]> wimlib.net Git - wimlib/blobdiff - programs/imagex.c
ntfs-apply.c: Tweak NTFS inode closing some more
[wimlib] / programs / imagex.c
index 61a93fbef260e509120f702d36b3f70b1472f156..30c2e3e8b289e9cd6b4995dfd0d9332e2a3f2814 100644 (file)
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "wimlib.h"
 #include "config.h"
+
+#include "wimlib.h"
+
+#include <errno.h>
 #include <getopt.h>
-#include <stdlib.h>
-#include <stdarg.h>
 #include <glob.h>
-#include <string.h>
-#include <errno.h>
+#include <inttypes.h>
 #include <libgen.h>
 #include <limits.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
 #include <sys/stat.h>
 #include <unistd.h>
-#include <inttypes.h>
 
 #define ARRAY_LEN(array) (sizeof(array) / sizeof(array[0]))
 
 #define for_opt(c, opts) while ((c = getopt_long_only(argc, (char**)argv, "", \
                                opts, NULL)) != -1)
 
-
 enum imagex_op_type {
        APPEND,
        APPLY,
@@ -97,13 +98,14 @@ static const char *usage_strings[] = {
 "                    [--ref=\"GLOB\"]\n",
 [MOUNTRW] =
 "imagex mountrw WIMFILE [IMAGE_NUM | IMAGE_NAME] DIRECTORY\n"
-"                      [--check] [--debug] [--streams-interface=INTERFACE]\n",
+"                      [--check] [--debug] [--streams-interface=INTERFACE]\n"
+"                      [--staging-dir=DIR]\n",
 [OPTIMIZE] =
-"imagex optimize WIMFILE [--check] [--recompress]\n",
+"imagex optimize WIMFILE [--check] [--recompress] [--compress=TYPE]\n",
 [SPLIT] =
 "imagex split WIMFILE SPLIT_WIMFILE PART_SIZE_MB [--check]\n",
 [UNMOUNT] =
-"imagex unmount DIRECTORY [--commit] [--check]\n",
+"imagex unmount DIRECTORY [--commit] [--check] [--rebuild]\n",
 };
 
 static const struct option common_options[] = {
@@ -165,10 +167,11 @@ static const struct option join_options[] = {
 };
 
 static const struct option mount_options[] = {
-       {"check", no_argument, NULL, 'c'},
-       {"debug", no_argument, NULL, 'd'},
+       {"check",             no_argument,       NULL, 'c'},
+       {"debug",             no_argument,       NULL, 'd'},
        {"streams-interface", required_argument, NULL, 's'},
-       {"ref",      required_argument, NULL, 'r'},
+       {"ref",               required_argument, NULL, 'r'},
+       {"staging-dir",       required_argument, NULL, 'D'},
        {NULL, 0, NULL, 0},
 };
 
@@ -184,8 +187,9 @@ static const struct option split_options[] = {
 };
 
 static const struct option unmount_options[] = {
-       {"commit", no_argument, NULL, 'c'},
-       {"check", no_argument, NULL, 'C'},
+       {"commit",  no_argument, NULL, 'c'},
+       {"check",   no_argument, NULL, 'C'},
+       {"rebuild", no_argument, NULL, 'R'},
        {NULL, 0, NULL, 0},
 };
 
@@ -357,7 +361,7 @@ static int imagex_progress_func(enum wimlib_progress_msg msg,
                       info->write_streams.completed_bytes >> 20,
                       info->write_streams.total_bytes >> 20,
                       percent_done);
-               if (info->write_streams.completed_bytes == info->write_streams.total_bytes)
+               if (info->write_streams.completed_bytes >= info->write_streams.total_bytes)
                        putchar('\n');
                break;
        case WIMLIB_PROGRESS_MSG_SCAN_BEGIN:
@@ -395,15 +399,14 @@ static int imagex_progress_func(enum wimlib_progress_msg msg,
                        putchar('\n');
                break;
        case WIMLIB_PROGRESS_MSG_EXTRACT_IMAGE_BEGIN:
-               /*printf("Applying image %d (%s) to `%s'\n",*/
-                      /*info->extract.image,*/
-                      /*info->extract.image_name,*/
-                      /*info->extract.target);*/
+               printf("Applying image %d (%s) from `%s' to %s `%s'\n",
+                      info->extract.image,
+                      info->extract.image_name,
+                      info->extract.wimfile_name,
+                      ((info->extract.extract_flags & WIMLIB_EXTRACT_FLAG_NTFS) ?
+                               "NTFS volume" : "directory"),
+                      info->extract.target);
                break;
-       /*case WIMLIB_PROGRESS_MSG_EXTRACT_IMAGE_END:*/
-               /*printf("Done applying image %d!\n",*/
-                      /*info->extract.image);*/
-               /*break;*/
        /*case WIMLIB_PROGRESS_MSG_EXTRACT_DIR_STRUCTURE_BEGIN:*/
                /*printf("Applying directory structure to %s\n",*/
                       /*info->extract.target);*/
@@ -416,12 +419,21 @@ static int imagex_progress_func(enum wimlib_progress_msg msg,
                       info->extract.completed_bytes >> 20,
                       info->extract.total_bytes >> 20,
                       percent_done);
-               if (info->extract.completed_bytes == info->extract.total_bytes)
+               if (info->extract.completed_bytes >= info->extract.total_bytes)
                        putchar('\n');
                break;
        case WIMLIB_PROGRESS_MSG_EXTRACT_DENTRY:
                puts(info->extract.cur_path);
                break;
+       case WIMLIB_PROGRESS_MSG_APPLY_TIMESTAMPS:
+               printf("Setting timestamps on all extracted files...\n");
+               break;
+       case WIMLIB_PROGRESS_MSG_EXTRACT_IMAGE_END:
+               if (info->extract.extract_flags & WIMLIB_EXTRACT_FLAG_NTFS) {
+                       printf("Unmounting NTFS volume `%s'...\n",
+                              info->extract.target);
+               }
+               break;
        case WIMLIB_PROGRESS_MSG_JOIN_STREAMS:
                percent_done = TO_PERCENT(info->join.completed_bytes,
                                          info->join.total_bytes);
@@ -610,16 +622,12 @@ static int imagex_apply(int argc, const char **argv)
                        goto out;
        }
 
-#ifdef WITH_NTFS_3G
        struct stat stbuf;
 
        ret = stat(target, &stbuf);
        if (ret == 0) {
-               if (S_ISBLK(stbuf.st_mode) || S_ISREG(stbuf.st_mode)) {
+               if (S_ISBLK(stbuf.st_mode) || S_ISREG(stbuf.st_mode))
                        extract_flags |= WIMLIB_EXTRACT_FLAG_NTFS;
-                       printf("Applying `%s' image %d to NTFS volume `%s'\n",
-                              wimfile, image, target);
-               }
        } else {
                if (errno != ENOENT) {
                        imagex_error_with_errno("Failed to stat `%s'", target);
@@ -627,11 +635,12 @@ static int imagex_apply(int argc, const char **argv)
                        goto out;
                }
        }
-#endif
 
        ret = wimlib_extract_image(w, image, target, extract_flags,
                                   additional_swms, num_additional_swms,
                                   imagex_progress_func);
+       if (ret == 0)
+               printf("Done applying WIM image.\n");
 out:
        wimlib_free(w);
        if (additional_swms) {
@@ -733,7 +742,6 @@ static int imagex_capture_or_append(int argc, const char **argv)
        if (ret != 0)
                goto out;
 
-#ifdef WITH_NTFS_3G
        struct stat stbuf;
 
        ret = stat(source, &stbuf);
@@ -750,7 +758,7 @@ static int imagex_capture_or_append(int argc, const char **argv)
                        goto out;
                }
        }
-#endif
+
        ret = wimlib_add_image(w, source, name, config_str, config_len,
                               add_image_flags, imagex_progress_func);
 
@@ -1097,6 +1105,7 @@ static int imagex_info(int argc, const char **argv)
        int open_flags = WIMLIB_OPEN_FLAG_SPLIT_OK;
        int part_number;
        int total_parts;
+       int num_images;
 
        for_opt(c, info_options) {
                switch (c) {
@@ -1162,7 +1171,7 @@ static int imagex_info(int argc, const char **argv)
        image = wimlib_resolve_image(w, image_num_or_name);
        if (image == WIMLIB_NO_IMAGE && strcmp(image_num_or_name, "0") != 0) {
                imagex_error("The image `%s' does not exist",
-                                               image_num_or_name);
+                            image_num_or_name);
                if (boot)
                        imagex_error("If you would like to set the boot "
                                     "index to 0, specify image \"0\" with "
@@ -1171,7 +1180,18 @@ static int imagex_info(int argc, const char **argv)
                goto out;
        }
 
-       if (image == WIMLIB_ALL_IMAGES && wimlib_get_num_images(w) > 1) {
+       num_images = wimlib_get_num_images(w);
+
+       if (num_images == 0) {
+               if (boot) {
+                       imagex_error("--boot is meaningless on a WIM with no "
+                                    "images");
+                       ret = WIMLIB_ERR_INVALID_IMAGE;
+                       goto out;
+               }
+       }
+
+       if (image == WIMLIB_ALL_IMAGES && num_images > 1) {
                if (boot) {
                        imagex_error("Cannot specify the --boot flag "
                                     "without specifying a specific "
@@ -1229,13 +1249,14 @@ static int imagex_info(int argc, const char **argv)
                                                        "file `%s' for "
                                                        "writing ",
                                                        xml_out_file);
+                               ret = -1;
                                goto out;
                        }
                        ret = wimlib_extract_xml_data(w, fp);
                        if (fclose(fp) != 0) {
                                imagex_error("Failed to close the file `%s'",
                                             xml_out_file);
-                               goto out;
+                               ret = -1;
                        }
 
                        if (ret != 0)
@@ -1255,7 +1276,8 @@ static int imagex_info(int argc, const char **argv)
                /* Modification operations */
                if (total_parts != 1) {
                        imagex_error("Modifying a split WIM is not supported.");
-                       return -1;
+                       ret = -1;
+                       goto out;
                }
                if (image == WIMLIB_ALL_IMAGES)
                        image = 1;
@@ -1263,7 +1285,8 @@ static int imagex_info(int argc, const char **argv)
                if (image == WIMLIB_NO_IMAGE && new_name) {
                        imagex_error("Cannot specify new_name (`%s') when "
                                     "using image 0", new_name);
-                       return -1;
+                       ret = -1;
+                       goto out;
                }
 
                if (boot) {
@@ -1311,18 +1334,18 @@ static int imagex_info(int argc, const char **argv)
                /* Only call wimlib_overwrite() if something actually needs to
                 * be changed. */
                if (boot || new_name || new_desc ||
-                               check != wimlib_has_integrity_table(w)) {
+                   (check && !wimlib_has_integrity_table(w)))
+               {
+                       int write_flags;
 
                        ret = file_writable(wimfile);
                        if (ret != 0)
                                return ret;
 
-                       int write_flags;
-                       if (check) {
+                       if (check)
                                write_flags = WIMLIB_WRITE_FLAG_CHECK_INTEGRITY;
-                       } else {
+                       else
                                write_flags = 0;
-                       }
 
                        ret = wimlib_overwrite(w, write_flags, 1,
                                               imagex_progress_func);
@@ -1330,7 +1353,7 @@ static int imagex_info(int argc, const char **argv)
                                ret = 0;
                } else {
                        printf("The file `%s' was not modified because nothing "
-                                       "needed to be done.\n", wimfile);
+                              "needed to be done.\n", wimfile);
                        ret = 0;
                }
        }
@@ -1388,6 +1411,7 @@ static int imagex_mount_rw_or_ro(int argc, const char **argv)
        const char *swm_glob = NULL;
        WIMStruct **additional_swms = NULL;
        unsigned num_additional_swms = 0;
+       const char *staging_dir = NULL;
 
        if (strcmp(argv[0], "mountrw") == 0)
                mount_flags |= WIMLIB_MOUNT_FLAG_READWRITE;
@@ -1415,6 +1439,9 @@ static int imagex_mount_rw_or_ro(int argc, const char **argv)
                case 'r':
                        swm_glob = optarg;
                        break;
+               case 'D':
+                       staging_dir = optarg;
+                       break;
                default:
                        goto mount_usage;
                }
@@ -1466,7 +1493,7 @@ static int imagex_mount_rw_or_ro(int argc, const char **argv)
        }
 
        ret = wimlib_mount_image(w, image, dir, mount_flags, additional_swms,
-                                num_additional_swms, NULL);
+                                num_additional_swms, staging_dir);
        if (ret != 0) {
                imagex_error("Failed to mount image %d from `%s' on `%s'",
                             image, wimfile, dir);
@@ -1535,19 +1562,21 @@ static int imagex_optimize(int argc, const char **argv)
 
        ret = wimlib_overwrite(w, write_flags, 0, imagex_progress_func);
 
-       new_size = file_get_size(argv[0]);
-       printf("`%s' optimized size: ", wimfile);
-       if (new_size == -1)
-               puts("Unknown");
-       else
-               printf("%"PRIu64" KiB\n", new_size >> 10);
+       if (ret == 0) {
+               new_size = file_get_size(argv[0]);
+               printf("`%s' optimized size: ", wimfile);
+               if (new_size == -1)
+                       puts("Unknown");
+               else
+                       printf("%"PRIu64" KiB\n", new_size >> 10);
 
-       fputs("Space saved: ", stdout);
-       if (new_size != -1 && old_size != -1) {
-               printf("%lld KiB\n",
-                      ((long long)old_size - (long long)new_size) >> 10);
-       } else {
-               puts("Unknown");
+               fputs("Space saved: ", stdout);
+               if (new_size != -1 && old_size != -1) {
+                       printf("%lld KiB\n",
+                              ((long long)old_size - (long long)new_size) >> 10);
+               } else {
+                       puts("Unknown");
+               }
        }
 
        wimlib_free(w);
@@ -1612,6 +1641,9 @@ static int imagex_unmount(int argc, const char **argv)
                case 'C':
                        unmount_flags |= WIMLIB_UNMOUNT_FLAG_CHECK_INTEGRITY;
                        break;
+               case 'R':
+                       unmount_flags |= WIMLIB_UNMOUNT_FLAG_REBUILD;
+                       break;
                default:
                        usage(UNMOUNT);
                        return -1;
@@ -1755,7 +1787,7 @@ int main(int argc, const char **argv)
                                imagex_error("Exiting with error code %d:\n"
                                             "       %s.", ret,
                                             wimlib_get_error_string(ret));
-                               if (ret == WIMLIB_ERR_NTFS_3G)
+                               if (ret == WIMLIB_ERR_NTFS_3G && errno != 0)
                                        imagex_error_with_errno("errno");
                        }
                        return ret;