X-Git-Url: https://wimlib.net/git/?a=blobdiff_plain;f=programs%2Fimagex.c;h=ed0f24dce3bc853c4f3c60151152ae74c051138a;hb=5ed5a1ef610700e463abd0c07aed377cce5eef47;hp=61a93fbef260e509120f702d36b3f70b1472f156;hpb=3cf06a471de65b5e69b44c41b95b1bbfb49ab55f;p=wimlib
diff --git a/programs/imagex.c b/programs/imagex.c
index 61a93fbe..ed0f24dc 100644
--- a/programs/imagex.c
+++ b/programs/imagex.c
@@ -22,26 +22,27 @@
* along with this program. If not, see .
*/
-#include "wimlib.h"
#include "config.h"
+
+#include "wimlib.h"
+
+#include
#include
-#include
-#include
#include
-#include
-#include
+#include
#include
#include
+#include
+#include
+#include
#include
#include
-#include
#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,
@@ -66,16 +67,16 @@ static const char *usage_strings[] = {
"imagex append (DIRECTORY | NTFS_VOLUME) WIMFILE [IMAGE_NAME]\n"
" [DESCRIPTION] [--boot] [--check] [--flags EDITION_ID]\n"
" [--verbose] [--dereference] [--config=FILE]\n"
-" [--threads=NUM_THREADS] [--rebuild]\n",
+" [--threads=NUM_THREADS] [--rebuild] [--unix-data]\n",
[APPLY] =
"imagex apply WIMFILE [IMAGE_NUM | IMAGE_NAME | all]\n"
" (DIRECTORY | NTFS_VOLUME) [--check] [--hardlink]\n"
-" [--symlink] [--verbose] [--ref=\"GLOB\"]\n",
+" [--symlink] [--verbose] [--ref=\"GLOB\"] [--unix-data]\n",
[CAPTURE] =
"imagex capture (DIRECTORY | NTFS_VOLUME) WIMFILE [IMAGE_NAME]\n"
" [DESCRIPTION] [--boot] [--check] [--compress=TYPE]\n"
" [--flags EDITION_ID] [--verbose] [--dereference]\n"
-" [--config=FILE] [--threads=NUM_THREADS]\n",
+" [--config=FILE] [--threads=NUM_THREADS] [--unix-data]\n",
[DELETE] =
"imagex delete WIMFILE (IMAGE_NUM | IMAGE_NAME | all) [--check] [--soft]\n",
[DIR] =
@@ -94,16 +95,17 @@ static const char *usage_strings[] = {
[MOUNT] =
"imagex mount WIMFILE (IMAGE_NUM | IMAGE_NAME) DIRECTORY\n"
" [--check] [--debug] [--streams-interface=INTERFACE]\n"
-" [--ref=\"GLOB\"]\n",
+" [--ref=\"GLOB\"] [--unix-data] [--allow-other]\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] [--unix-data] [--allow-other]\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[] = {
@@ -113,11 +115,12 @@ static const struct option common_options[] = {
};
static const struct option apply_options[] = {
- {"check", no_argument, NULL, 'c'},
- {"hardlink", no_argument, NULL, 'h'},
- {"symlink", no_argument, NULL, 's'},
- {"verbose", no_argument, NULL, 'v'},
- {"ref", required_argument, NULL, 'r'},
+ {"check", no_argument, NULL, 'c'},
+ {"hardlink", no_argument, NULL, 'h'},
+ {"symlink", no_argument, NULL, 's'},
+ {"verbose", no_argument, NULL, 'v'},
+ {"ref", required_argument, NULL, 'r'},
+ {"unix-data", no_argument, NULL, 'U'},
{NULL, 0, NULL, 0},
};
static const struct option capture_or_append_options[] = {
@@ -130,6 +133,7 @@ static const struct option capture_or_append_options[] = {
{"verbose", no_argument, NULL, 'v'},
{"threads", required_argument, NULL, 't'},
{"rebuild", no_argument, NULL, 'R'},
+ {"unix-data", no_argument, NULL, 'U'},
{NULL, 0, NULL, 0},
};
static const struct option delete_options[] = {
@@ -165,10 +169,13 @@ 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'},
+ {"unix-data", no_argument, NULL, 'U'},
+ {"allow-other", no_argument, NULL, 'A'},
{NULL, 0, NULL, 0},
};
@@ -184,8 +191,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},
};
@@ -272,6 +280,21 @@ static off_t file_get_size(const char *filename)
return (off_t)-1;
}
+static const char *default_capture_config =
+"[ExclusionList]\n"
+"\\$ntfs.log\n"
+"\\hiberfil.sys\n"
+"\\pagefile.sys\n"
+"\\System Volume Information\n"
+"\\RECYCLER\n"
+"\\Windows\\CSC\n"
+"\n"
+"[CompressionExclusionList]\n"
+"*.mp3\n"
+"*.zip\n"
+"*.cab\n"
+"\\WINDOWS\\inf\\*.pnf\n";
+
static char *file_get_contents(const char *filename, size_t *len_ret)
{
struct stat stbuf;
@@ -314,7 +337,7 @@ out_fclose:
static int file_writable(const char *path)
{
int ret;
- ret = access(path, F_OK | W_OK);
+ ret = access(path, W_OK);
if (ret != 0)
imagex_error_with_errno("Can't modify `%s'", path);
return ret;
@@ -357,7 +380,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 +418,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 +438,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);
@@ -563,6 +594,9 @@ static int imagex_apply(int argc, const char **argv)
case 'r':
swm_glob = optarg;
break;
+ case 'U':
+ extract_flags |= WIMLIB_EXTRACT_FLAG_UNIX_DATA;
+ break;
default:
usage(APPLY);
return -1;
@@ -610,16 +644,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 +657,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) {
@@ -698,6 +729,9 @@ static int imagex_capture_or_append(int argc, const char **argv)
case 'R':
write_flags |= WIMLIB_WRITE_FLAG_REBUILD;
break;
+ case 'U':
+ add_image_flags |= WIMLIB_ADD_IMAGE_FLAG_UNIX_DATA;
+ break;
default:
usage(cmd);
return -1;
@@ -733,7 +767,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,9 +783,11 @@ 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);
+
+ ret = wimlib_add_image(w, source, name,
+ config_str ? config_str : default_capture_config,
+ config_len, add_image_flags,
+ imagex_progress_func);
if (ret != 0)
goto out;
@@ -1003,7 +1038,7 @@ static int imagex_export(int argc, const char **argv)
ret = file_writable(dest_wimfile);
if (ret != 0)
- return ret;
+ goto out;
dest_ctype = wimlib_get_compression_type(dest_w);
if (compression_type_specified
@@ -1015,7 +1050,6 @@ static int imagex_export(int argc, const char **argv)
ret = -1;
goto out;
}
- compression_type = dest_ctype;
} else {
wim_is_new = true;
/* dest_wimfile is not an existing file, so create a new WIM. */
@@ -1097,6 +1131,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 +1197,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 +1206,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 +1275,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 +1302,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 +1311,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 +1360,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 +1379,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,12 +1437,16 @@ 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;
for_opt(c, mount_options) {
switch (c) {
+ case 'A':
+ mount_flags |= WIMLIB_MOUNT_FLAG_ALLOW_OTHER;
+ break;
case 'c':
open_flags |= WIMLIB_OPEN_FLAG_CHECK_INTEGRITY;
break;
@@ -1415,6 +1468,12 @@ static int imagex_mount_rw_or_ro(int argc, const char **argv)
case 'r':
swm_glob = optarg;
break;
+ case 'D':
+ staging_dir = optarg;
+ break;
+ case 'U':
+ mount_flags |= WIMLIB_MOUNT_FLAG_UNIX_DATA;
+ break;
default:
goto mount_usage;
}
@@ -1462,11 +1521,11 @@ static int imagex_mount_rw_or_ro(int argc, const char **argv)
if (mount_flags & WIMLIB_MOUNT_FLAG_READWRITE) {
ret = file_writable(wimfile);
if (ret != 0)
- return ret;
+ goto out;
}
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 +1594,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 +1673,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;
@@ -1747,22 +1811,28 @@ int main(int argc, const char **argv)
argv++;
wimlib_set_print_errors(true);
+ ret = wimlib_global_init();
+ if (ret)
+ goto out;
for_imagex_command(cmd) {
if (strcmp(cmd->name, *argv) == 0) {
ret = cmd->func(argc, argv);
- if (ret > 0) {
- imagex_error("Exiting with error code %d:\n"
- " %s.", ret,
- wimlib_get_error_string(ret));
- if (ret == WIMLIB_ERR_NTFS_3G)
- imagex_error_with_errno("errno");
- }
- return ret;
+ goto out;
}
}
imagex_error("Unrecognized command: `%s'", argv[0]);
usage_all();
return 1;
+out:
+ if (ret > 0) {
+ imagex_error("Exiting with error code %d:\n"
+ " %s.", ret,
+ wimlib_get_error_string(ret));
+ if (ret == WIMLIB_ERR_NTFS_3G && errno != 0)
+ imagex_error_with_errno("errno");
+ }
+ wimlib_global_cleanup();
+ return ret;
}