Cleanup: do not overwrite const argv parameters
[babeltrace.git] / converter / babeltrace.c
index 11c10cf8aa488657ac9fae1fcd0ac9e98d01525e..db8c8d65b0e94975f3f9544e122a4845e8af9f2a 100644 (file)
 #include <unistd.h>
 #include <inttypes.h>
 #include <fts.h>
+#include <string.h>
 
 #include <babeltrace/ctf-ir/metadata.h>        /* for clocks */
 
 #define DEFAULT_FILE_ARRAY_SIZE        1
-static char *opt_input_format;
-static char *opt_output_format;
+static char *opt_input_format, *opt_output_format;
+/* Pointer into const argv */
+static const char *opt_input_format_arg, *opt_output_format_arg;
 
 static const char *opt_input_path;
 static const char *opt_output_path;
 
 static struct format *fmt_read;
 
+static
 void strlower(char *str)
 {
        while (*str) {
@@ -79,8 +82,8 @@ enum {
 
 static struct poptOption long_options[] = {
        /* longName, shortName, argInfo, argPtr, value, descrip, argDesc */
-       { "input-format", 'i', POPT_ARG_STRING, &opt_input_format, OPT_NONE, NULL, NULL },
-       { "output-format", 'o', POPT_ARG_STRING, &opt_output_format, OPT_NONE, NULL, NULL },
+       { "input-format", 'i', POPT_ARG_STRING, &opt_input_format_arg, OPT_NONE, NULL, NULL },
+       { "output-format", 'o', POPT_ARG_STRING, &opt_output_format_arg, OPT_NONE, NULL, NULL },
        { "help", 'h', POPT_ARG_NONE, NULL, OPT_HELP, NULL, NULL },
        { "list", 'l', POPT_ARG_NONE, NULL, OPT_LIST, NULL, NULL },
        { "verbose", 'v', POPT_ARG_NONE, NULL, OPT_VERBOSE, NULL, NULL },
@@ -321,9 +324,10 @@ end:
  * path, and add them to the context. The packet_seek parameter can be
  * NULL: this specify to use the default format packet_seek.
  *
- * Return: 0 on success, nonzero on failure.
+ * Return: 0 on success, < 0 on failure, > 0 on partial failure.
  * Unable to open toplevel: failure.
- * Unable to open some subdirectory or file: warn and continue;
+ * Unable to open some subdirectory or file: warn and continue (partial
+ * failure);
  */
 int bt_context_add_traces_recursive(struct bt_context *ctx, const char *path,
                const char *format_str,
@@ -335,7 +339,7 @@ int bt_context_add_traces_recursive(struct bt_context *ctx, const char *path,
        GArray *trace_ids;
        char lpath[PATH_MAX];
        char * const paths[2] = { lpath, NULL };
-       int ret = -1;
+       int ret = 0;
 
        /*
         * Need to copy path, because fts_open can change it.
@@ -355,6 +359,7 @@ int bt_context_add_traces_recursive(struct bt_context *ctx, const char *path,
 
        while ((node = fts_read(tree))) {
                int dirfd, metafd;
+               int closeret;
 
                if (!(node->fts_info & FTS_D))
                        continue;
@@ -363,27 +368,31 @@ int bt_context_add_traces_recursive(struct bt_context *ctx, const char *path,
                if (dirfd < 0) {
                        fprintf(stderr, "[error] [Context] Unable to open trace "
                                "directory file descriptor.\n");
-                       ret = dirfd;
+                       ret = 1;        /* partial error */
                        goto error;
                }
                metafd = openat(dirfd, "metadata", O_RDONLY);
                if (metafd < 0) {
-                       ret = close(dirfd);
-                       if (ret < 0) {
+                       closeret = close(dirfd);
+                       if (closeret < 0) {
                                perror("close");
+                               ret = -1;       /* failure */
                                goto error;
                        }
+                       continue;
                } else {
                        int trace_id;
 
-                       ret = close(metafd);
-                       if (ret < 0) {
+                       closeret = close(metafd);
+                       if (closeret < 0) {
                                perror("close");
+                               ret = -1;       /* failure */
                                goto error;
                        }
-                       ret = close(dirfd);
-                       if (ret < 0) {
+                       closeret = close(dirfd);
+                       if (closeret < 0) {
                                perror("close");
+                               ret = -1;       /* failure */
                                goto error;
                        }
 
@@ -394,16 +403,22 @@ int bt_context_add_traces_recursive(struct bt_context *ctx, const char *path,
                                fprintf(stderr, "[warning] [Context] opening trace \"%s\" from %s "
                                        "for reading.\n", node->fts_accpath, path);
                                /* Allow to skip erroneous traces. */
+                               ret = 1;        /* partial error */
                                continue;
                        }
                        g_array_append_val(trace_ids, trace_id);
                }
        }
 
-       g_array_free(trace_ids, TRUE);
-       return ret;
-
 error:
+       /*
+        * Return an error if no trace can be opened.
+        */
+       if (trace_ids->len == 0) {
+               fprintf(stderr, "[error] Cannot open any trace for reading.\n\n");
+               ret = -ENOENT;          /* failure */
+       }
+       g_array_free(trace_ids, TRUE);
        return ret;
 }
 
@@ -447,7 +462,7 @@ error_iter:
 
 int main(int argc, char **argv)
 {
-       int ret;
+       int ret, partial_error = 0;
        struct format *fmt_write;
        struct trace_descriptor *td_write;
        struct bt_context *ctx;
@@ -463,10 +478,22 @@ int main(int argc, char **argv)
        printf_verbose("Verbose mode active.\n");
        printf_debug("Debug mode active.\n");
 
-       if (opt_input_format)
+       if (opt_input_format_arg) {
+               opt_input_format = strdup(opt_input_format_arg);
+               if (!opt_input_format) {
+                       partial_error = 1;
+                       goto end;
+               }
                strlower(opt_input_format);
-       if (opt_output_format)
+       }
+       if (opt_output_format) {
+               opt_output_format = strdup(opt_output_format_arg);
+               if (!opt_output_format) {
+                       partial_error = 1;
+                       goto end;
+               }
                strlower(opt_output_format);
+       }
 
        printf_verbose("Converting from directory: %s\n", opt_input_path);
        printf_verbose("Converting from format: %s\n",
@@ -476,31 +503,47 @@ int main(int argc, char **argv)
        printf_verbose("Converting to format: %s\n",
                opt_output_format ? : "text <default>");
 
-       if (!opt_input_format)
-               opt_input_format = "ctf";
-       if (!opt_output_format)
-               opt_output_format = "text";
+       if (!opt_input_format) {
+               opt_input_format = strdup("ctf");
+               if (!opt_input_format) {
+                       partial_error = 1;
+                       goto end;
+               }
+       }
+       if (!opt_output_format) {
+               opt_output_format = strdup("text");
+               if (!opt_output_format) {
+                       partial_error = 1;
+                       goto end;
+               }
+       }
        fmt_read = bt_lookup_format(g_quark_from_static_string(opt_input_format));
        if (!fmt_read) {
                fprintf(stderr, "[error] Format \"%s\" is not supported.\n\n",
                        opt_input_format);
-               exit(EXIT_FAILURE);
+               partial_error = 1;
+               goto end;
        }
        fmt_write = bt_lookup_format(g_quark_from_static_string(opt_output_format));
        if (!fmt_write) {
                fprintf(stderr, "[error] format \"%s\" is not supported.\n\n",
                        opt_output_format);
-               exit(EXIT_FAILURE);
+               partial_error = 1;
+               goto end;
        }
 
        ctx = bt_context_create();
 
        ret = bt_context_add_traces_recursive(ctx, opt_input_path,
                        opt_input_format, NULL);
-       if (ret) {
+       if (ret < 0) {
                fprintf(stderr, "[error] opening trace \"%s\" for reading.\n\n",
                        opt_input_path);
                goto error_td_read;
+       } else if (ret > 0) {
+               fprintf(stderr, "[warning] errors occurred when opening trace \"%s\" for reading, continuing anyway.\n\n",
+                       opt_input_path);
+               partial_error = 1;
        }
 
        td_write = fmt_write->open_trace(opt_output_path, O_RDWR, NULL, NULL);
@@ -521,7 +564,7 @@ int main(int argc, char **argv)
        bt_context_put(ctx);
        printf_verbose("finished converting. Output written to:\n%s\n",
                        opt_output_path ? : "<stdout>");
-       exit(EXIT_SUCCESS);
+       goto end;
 
        /* Error handling */
 error_copy_trace:
@@ -529,5 +572,14 @@ error_copy_trace:
 error_td_write:
        bt_context_put(ctx);
 error_td_read:
-       exit(EXIT_FAILURE);
+       partial_error = 1;
+
+       /* teardown and exit */
+end:
+       free(opt_input_format);
+       free(opt_output_format);
+       if (partial_error)
+               exit(EXIT_FAILURE);
+       else
+               exit(EXIT_SUCCESS);
 }
This page took 0.025664 seconds and 4 git commands to generate.