+ buf->user_data = buf_local;
+
+ /* open file for output */
+ if(!trace_path) {
+ /* Only create the directory if using the default path, because
+ * of the risk of typo when using trace path override. We don't
+ * want to risk creating plenty of useless directories in that case.
+ */
+ result = create_dir_if_needed(USTD_DEFAULT_TRACE_PATH);
+ if(result == -1) {
+ ERR("could not create directory %s", USTD_DEFAULT_TRACE_PATH);
+ return 1;
+ }
+
+ trace_path = USTD_DEFAULT_TRACE_PATH;
+ }
+
+ asprintf(&tmp, "%s/%u_%lld", trace_path, buf->pid, buf->pidunique);
+ result = create_dir_if_needed(tmp);
+ if(result == -1) {
+ ERR("could not create directory %s", tmp);
+ free(tmp);
+ return 1;
+ }
+ free(tmp);
+
+ asprintf(&tmp, "%s/%u_%lld/%s", trace_path, buf->pid, buf->pidunique, buf->name);
+ result = fd = open(tmp, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, 00600);
+ if(result == -1) {
+ PERROR("open");
+ ERR("failed opening trace file %s", tmp);
+ return 1;
+ }
+ buf_local->file_fd = fd;
+ free(tmp);
+
+ return 0;
+}
+
+int on_close_buffer(struct libustd_callbacks *data, struct buffer_info *buf)
+{
+ struct buffer_info_local *buf_local = buf->user_data;
+ int result = close(buf_local->file_fd);
+ free(buf_local);
+ if(result == -1) {
+ PERROR("close");
+ }
+ return 0;
+}
+
+int on_put_error(struct libustd_callbacks *data, struct buffer_info *buf)
+{
+ unwrite_last_subbuffer(buf);
+}
+
+struct libustd_callbacks *new_callbacks()
+{
+ struct libustd_callbacks *callbacks =
+ malloc(sizeof(struct libustd_callbacks));
+
+ if(!callbacks)
+ return NULL;
+
+ callbacks->on_open_buffer = on_open_buffer;
+ callbacks->on_close_buffer = on_close_buffer;
+ callbacks->on_read_subbuffer = on_read_subbuffer;
+ callbacks->on_read_partial_subbuffer = on_read_partial_subbuffer;
+ callbacks->on_put_error = on_put_error;
+ callbacks->on_new_thread = NULL;
+ callbacks->on_close_thread = NULL;
+ callbacks->on_trace_end = NULL;
+
+ return callbacks;
+
+}
+
+int is_directory(const char *dir)
+{
+ int result;
+ struct stat st;
+
+ result = stat(dir, &st);
+ if(result == -1) {
+ PERROR("stat");
+ return 0;
+ }
+
+ if(!S_ISDIR(st.st_mode)) {
+ return 0;
+ }
+
+ return 1;
+}
+
+void usage(void)
+{
+ fprintf(stderr, "Usage:\nustd OPTIONS\n\nOptions:\n"
+ "\t-h\t\tDisplay this usage.\n"
+ "\t-o DIR\t\tSpecify the directory where to output the traces.\n"
+ "\t-s PATH\t\tSpecify the path to use for the daemon socket.\n"
+ "\t-d\t\tStart as a daemon.\n"
+ "\t--pidfile FILE\tWrite the PID in this file (when using -d).\n");
+}
+
+int parse_args(int argc, char **argv)
+{
+ int c;