]> wimlib.net Git - wimlib/blobdiff - programs/imagex.c
wimlib-imagex: print version of library being used
[wimlib] / programs / imagex.c
index 8a0b48df08cff51944c47a904c41643575a2b094..28f0266356429b91879b6d1e59f421f435bcecf5 100644 (file)
@@ -6,7 +6,7 @@
  */
 
 /*
- * Copyright (C) 2012-2016 Eric Biggers
+ * Copyright (C) 2012-2017 Eric Biggers
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -131,14 +131,31 @@ enum {
 static void usage(int cmd, FILE *fp);
 static void usage_all(FILE *fp);
 static void recommend_man_page(int cmd, FILE *fp);
-static const tchar *get_cmd_string(int cmd, bool nospace);
+static const tchar *get_cmd_string(int cmd, bool only_short_form);
 
-static bool imagex_be_quiet = false;
 static FILE *imagex_info_file;
 
-#define imagex_printf(format, ...) \
+#define imagex_printf(format, ...)     \
+       if (imagex_info_file)           \
                tfprintf(imagex_info_file, format, ##__VA_ARGS__)
 
+static void imagex_suppress_output(void)
+{
+       imagex_info_file = NULL;
+}
+
+static void imagex_output_to_stderr(void)
+{
+       if (imagex_info_file)
+               imagex_info_file = stderr;
+}
+
+static void imagex_flush_output(void)
+{
+       if (imagex_info_file)
+               fflush(imagex_info_file);
+}
+
 enum {
        IMAGEX_ALLOW_OTHER_OPTION,
        IMAGEX_BLOBS_OPTION,
@@ -331,6 +348,7 @@ static const struct option join_options[] = {
        {NULL, 0, NULL, 0},
 };
 
+#if WIM_MOUNTING_SUPPORTED
 static const struct option mount_options[] = {
        {T("check"),             no_argument,       NULL, IMAGEX_CHECK_OPTION},
        {T("debug"),             no_argument,       NULL, IMAGEX_DEBUG_OPTION},
@@ -341,6 +359,7 @@ static const struct option mount_options[] = {
        {T("allow-other"),       no_argument,       NULL, IMAGEX_ALLOW_OTHER_OPTION},
        {NULL, 0, NULL, 0},
 };
+#endif
 
 static const struct option optimize_options[] = {
        {T("check"),       no_argument,       NULL, IMAGEX_CHECK_OPTION},
@@ -365,6 +384,7 @@ static const struct option split_options[] = {
        {NULL, 0, NULL, 0},
 };
 
+#if WIM_MOUNTING_SUPPORTED
 static const struct option unmount_options[] = {
        {T("commit"),  no_argument, NULL, IMAGEX_COMMIT_OPTION},
        {T("check"),   no_argument, NULL, IMAGEX_CHECK_OPTION},
@@ -374,6 +394,7 @@ static const struct option unmount_options[] = {
        {T("new-image"), no_argument, NULL, IMAGEX_NEW_IMAGE_OPTION},
        {NULL, 0, NULL, 0},
 };
+#endif
 
 static const struct option update_options[] = {
        /* Careful: some of the options here set the defaults for update
@@ -486,7 +507,7 @@ verify_image_exists_and_is_single(int image, const tchar *image_name,
 static void
 print_available_compression_types(FILE *fp)
 {
-       static const tchar *s =
+       static const tchar * const s =
        T(
        "Available compression types:\n"
        "\n"
@@ -1137,8 +1158,6 @@ imagex_progress_func(enum wimlib_progress_msg msg,
        unsigned unit_shift;
        const tchar *unit_name;
 
-       if (imagex_be_quiet)
-               return WIMLIB_PROGRESS_STATUS_CONTINUE;
        switch (msg) {
        case WIMLIB_PROGRESS_MSG_WRITE_STREAMS:
                {
@@ -1377,7 +1396,7 @@ imagex_progress_func(enum wimlib_progress_msg msg,
        default:
                break;
        }
-       fflush(imagex_info_file);
+       imagex_flush_output();
        return WIMLIB_PROGRESS_STATUS_CONTINUE;
 }
 
@@ -1982,11 +2001,6 @@ imagex_capture_or_append(int argc, tchar **argv, int cmd)
                        }
                        break;
                case IMAGEX_DELTA_FROM_OPTION:
-                       if (cmd != CMD_CAPTURE) {
-                               imagex_error(T("'--delta-from' is only "
-                                              "valid for capture!"));
-                               goto out_usage;
-                       }
                        ret = string_list_append(&base_wimfiles, optarg);
                        if (ret)
                                goto out;
@@ -2058,7 +2072,7 @@ imagex_capture_or_append(int argc, tchar **argv, int cmd)
                }
                wim_fd = STDOUT_FILENO;
                wimfile = NULL;
-               imagex_info_file = stderr;
+               imagex_output_to_stderr();
                set_fd_to_binary_mode(wim_fd);
        }
 
@@ -2500,21 +2514,21 @@ static const struct {
 #define TIMESTR_MAX 100
 
 static void
-timespec_to_string(const struct timespec *spec, tchar *buf)
+print_time(const tchar *type, const struct wimlib_timespec *wts,
+          int32_t high_part)
 {
-       time_t t = spec->tv_sec;
+       tchar timestr[TIMESTR_MAX];
+       time_t t;
        struct tm tm;
-       gmtime_r(&t, &tm);
-       tstrftime(buf, TIMESTR_MAX, T("%a %b %d %H:%M:%S %Y UTC"), &tm);
-       buf[TIMESTR_MAX - 1] = '\0';
-}
 
-static void
-print_time(const tchar *type, const struct timespec *spec)
-{
-       tchar timestr[TIMESTR_MAX];
+       if (sizeof(wts->tv_sec) == 4 && sizeof(t) > sizeof(wts->tv_sec))
+               t = (uint32_t)wts->tv_sec | ((uint64_t)high_part << 32);
+       else
+               t = wts->tv_sec;
 
-       timespec_to_string(spec, timestr);
+       gmtime_r(&t, &tm);
+       tstrftime(timestr, TIMESTR_MAX, T("%a %b %d %H:%M:%S %Y UTC"), &tm);
+       timestr[TIMESTR_MAX - 1] = '\0';
 
        tprintf(T("%-20"TS"= %"TS"\n"), type, timestr);
 }
@@ -2675,9 +2689,12 @@ print_dentry_detailed(const struct wimlib_dir_entry *dentry)
                                          dentry->security_descriptor_size);
        }
 
-       print_time(T("Creation Time"), &dentry->creation_time);
-       print_time(T("Last Write Time"), &dentry->last_write_time);
-       print_time(T("Last Access Time"), &dentry->last_access_time);
+       print_time(T("Creation Time"),
+                  &dentry->creation_time, dentry->creation_time_high);
+       print_time(T("Last Write Time"),
+                  &dentry->last_write_time, dentry->last_write_time_high);
+       print_time(T("Last Access Time"),
+                  &dentry->last_access_time, dentry->last_access_time_high);
 
 
        if (dentry->attributes & WIMLIB_FILE_ATTRIBUTE_REPARSE_POINT)
@@ -2964,7 +2981,7 @@ imagex_export(int argc, tchar **argv, int cmd)
        #endif
                dest_wimfile = NULL;
                dest_wim_fd = STDOUT_FILENO;
-               imagex_info_file = stderr;
+               imagex_output_to_stderr();
                set_fd_to_binary_mode(dest_wim_fd);
        }
        errno = ENOENT;
@@ -2972,9 +2989,9 @@ imagex_export(int argc, tchar **argv, int cmd)
                wim_is_new = false;
                /* Destination file exists. */
 
-               if (!S_ISREG(stbuf.st_mode)) {
-                       imagex_error(T("\"%"TS"\" is not a regular file"),
-                                    dest_wimfile);
+               if (!S_ISREG(stbuf.st_mode) && !S_ISBLK(stbuf.st_mode)) {
+                       imagex_error(T("\"%"TS"\" is not a regular file "
+                                      "or block device"), dest_wimfile);
                        ret = -1;
                        goto out_free_src_wim;
                }
@@ -3178,8 +3195,7 @@ imagex_extract(int argc, tchar **argv, int cmd)
                        break;
                case IMAGEX_TO_STDOUT_OPTION:
                        extract_flags |= WIMLIB_EXTRACT_FLAG_TO_STDOUT;
-                       imagex_info_file = stderr;
-                       imagex_be_quiet = true;
+                       imagex_suppress_output();
                        set_fd_to_binary_mode(STDOUT_FILENO);
                        break;
                case IMAGEX_INCLUDE_INVALID_NAMES_OPTION:
@@ -3275,8 +3291,7 @@ imagex_extract(int argc, tchar **argv, int cmd)
        }
 
        if (ret == 0) {
-               if (!imagex_be_quiet)
-                       imagex_printf(T("Done extracting files.\n"));
+               imagex_printf(T("Done extracting files.\n"));
        } else if (ret == WIMLIB_ERR_PATH_DOES_NOT_EXIST) {
                if ((extract_flags & (WIMLIB_EXTRACT_FLAG_STRICT_GLOB |
                                      WIMLIB_EXTRACT_FLAG_GLOB_PATHS))
@@ -4374,14 +4389,15 @@ static const struct imagex_command imagex_commands[] = {
 
 #endif
 
-static const tchar *usage_strings[] = {
+static const tchar * const usage_strings[] = {
 [CMD_APPEND] =
 T(
 "    %"TS" " SOURCE_STR " WIMFILE [IMAGE_NAME [IMAGE_DESC]]\n"
 "                    [--boot] [--check] [--nocheck] [--config=FILE]\n"
 "                    [--threads=NUM_THREADS] [--no-acls] [--strict-acls]\n"
 "                    [--rpfix] [--norpfix] [--update-of=[WIMFILE:]IMAGE]\n"
-"                    [--wimboot] [--unix-data] [--dereference] [--snapshot]\n"
+"                    [--delta-from=WIMFILE] [--wimboot] [--unix-data]\n"
+"                    [--dereference] [--snapshot]\n"
 ),
 [CMD_APPLY] =
 T(
@@ -4407,7 +4423,7 @@ T(
 ),
 [CMD_DIR] =
 T(
-"    %"TS" WIMFILE IMAGE [--path=PATH] [--detailed]\n"
+"    %"TS" WIMFILE [IMAGE] [--path=PATH] [--detailed]\n"
 ),
 [CMD_EXPORT] =
 T(
@@ -4485,21 +4501,18 @@ T(
 static const tchar *invocation_name;
 static int invocation_cmd = CMD_NONE;
 
-static const tchar *get_cmd_string(int cmd, bool nospace)
+static const tchar *get_cmd_string(int cmd, bool only_short_form)
 {
        static tchar buf[50];
-       if (cmd == CMD_NONE) {
+
+       if (cmd == CMD_NONE)
                return T("wimlib-imagex");
-       } else if (invocation_cmd != CMD_NONE) {
+
+       if (only_short_form || invocation_cmd != CMD_NONE) {
                tsprintf(buf, T("wim%"TS), imagex_commands[cmd].name);
        } else {
-               const tchar *format;
-
-               if (nospace)
-                       format = T("%"TS"-%"TS"");
-               else
-                       format = T("%"TS" %"TS"");
-               tsprintf(buf, format, invocation_name, imagex_commands[cmd].name);
+               tsprintf(buf, T("%"TS" %"TS), invocation_name,
+                        imagex_commands[cmd].name);
        }
        return buf;
 }
@@ -4507,23 +4520,27 @@ static const tchar *get_cmd_string(int cmd, bool nospace)
 static void
 version(void)
 {
-       static const tchar *s =
+       uint32_t vers = wimlib_get_version();
+
+       static const tchar * const fmt =
        T(
-"wimlib-imagex (distributed with " PACKAGE " " PACKAGE_VERSION ")\n"
-"Copyright (C) 2012-2016 Eric Biggers\n"
+"wimlib-imagex " PACKAGE_VERSION " (using wimlib %u.%u.%u)\n"
+"Copyright (C) 2012-2017 Eric Biggers\n"
 "License GPLv3+; GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.\n"
 "This is free software: you are free to change and redistribute it.\n"
 "There is NO WARRANTY, to the extent permitted by law.\n"
 "\n"
 "Report bugs to "PACKAGE_BUGREPORT".\n"
        );
-       tfputs(s, stdout);
+       tfprintf(stdout, fmt,
+                vers >> 20, (vers >> 10) & 0x3ff, vers & 0x3ff);
 }
 
 
 static void
-help_or_version(int argc, tchar **argv, int cmd)
+do_common_options(int *argc_p, tchar **argv, int cmd)
 {
+       int argc = *argc_p;
        int i;
        const tchar *p;
 
@@ -4540,9 +4557,18 @@ help_or_version(int argc, tchar **argv, int cmd)
                        } else if (!tstrcmp(p, T("version"))) {
                                version();
                                exit(0);
-                       }
+                       } else if (!tstrcmp(p, T("quiet"))) {
+                               imagex_suppress_output();
+                               memmove(&argv[i], &argv[i + 1],
+                                       (argc - i) * sizeof(argv[i]));
+                               argc--;
+                               i--;
+                       } else if (!*p) /* reached "--", no more options */
+                               break;
                }
        }
+
+       *argc_p = argc;
 }
 
 static void
@@ -4559,8 +4585,7 @@ recommend_man_page(int cmd, FILE *fp)
        format_str = T("Some uncommon options are not listed;\n"
                       "See %"TS".pdf in the doc directory for more details.\n");
 #else
-       format_str = T("Some uncommon options are not listed;\n"
-                      "Try `man %"TS"' for more details.\n");
+       format_str = T("Some uncommon options are not listed; see `man %"TS"' for more details.\n");
 #endif
        tfprintf(fp, format_str, get_cmd_string(cmd, true));
 }
@@ -4582,7 +4607,7 @@ usage_all(FILE *fp)
                print_usage_string(cmd, fp);
                tfprintf(fp, T("\n"));
        }
-       static const tchar *extra =
+       static const tchar * const extra =
        T(
 "    %"TS" --help\n"
 "    %"TS" --version\n"
@@ -4616,31 +4641,6 @@ main(int argc, tchar **argv)
        imagex_info_file = stdout;
        invocation_name = tbasename(argv[0]);
 
-#ifndef __WIN32__
-       if (getenv("WIMLIB_IMAGEX_USE_UTF8")) {
-               init_flags |= WIMLIB_INIT_FLAG_ASSUME_UTF8;
-       } else {
-               char *codeset;
-
-               setlocale(LC_ALL, "");
-               codeset = nl_langinfo(CODESET);
-               if (!strstr(codeset, "UTF-8") &&
-                   !strstr(codeset, "UTF8") &&
-                   !strstr(codeset, "utf-8") &&
-                   !strstr(codeset, "utf8"))
-               {
-                       fprintf(stderr,
-"WARNING: Running %"TS" in a UTF-8 locale is recommended!\n"
-"         Maybe try: `export LANG=en_US.UTF-8'?\n"
-"         Alternatively, set the environmental variable WIMLIB_IMAGEX_USE_UTF8\n"
-"         to any value to force wimlib to use UTF-8.\n",
-                       invocation_name);
-
-               }
-       }
-
-#endif /* !__WIN32__ */
-
        {
                tchar *igcase = tgetenv(T("WIMLIB_IMAGEX_IGNORE_CASE"));
                if (igcase != NULL) {
@@ -4693,11 +4693,8 @@ main(int argc, tchar **argv)
                }
        }
 
-       /* Handle --help and --version.  --help can be either for the program as
-        * a whole (cmd == CMD_NONE) or just for a specific command (cmd !=
-        * CMD_NONE).  Note: help_or_version() will not return if a --help or
-        * --version argument was found.  */
-       help_or_version(argc, argv, cmd);
+       /* Handle common options.  May exit early (for --help or --version).  */
+       do_common_options(&argc, argv, cmd);
 
        /* Bail if a valid command was not specified.  */
        if (cmd == CMD_NONE) {