produce an even better compression ratio at the cost of more time spent
compressing.
+ `wimlib-imagex optimize' now supports the '--compress=TYPE' option,
+ which recompresses the WIM file using the specified compression TYPE.
+ The new library API function used for this is
+ wimlib_set_output_compression_type().
+
Added the wimlib_get_xml_data() function to allow library clients to
easily retrieve the raw XML data from a WIM file if needed.
default \fB--recompress\fR, this will make compression about twice as slow and
will increase the compression ratio by maybe 1%, depending on the data.
.TP
+\fB--compress\fR=\fITYPE\fR
+Recompress the WIM file using the specified compression type. \fITYPE\fR may be
+"none", "fast", or "maximum". This implies \fB--recompress\fR.
+.TP
\fB--threads\fR=\fINUM_THREADS\fR
Number of threads to use for compressing data. Default: autodetect (number of
processors). This parameter is only meaningful when \fB--recompress\fR is also
.IP \[bu]
Split a standalone WIM into multiple parts (\fB@IMAGEX_PROGNAME@ split\fR)
.IP \[bu]
+Easily remove wasted space in a WIM file and optionally recompress it (\fB
+@IMAGEX_PROGNAME@ optimize\fR)
+.IP \[bu]
Support for all WIM compression types, both compression and decompression (LZX,
XPRESS, and none)
.IP \[bu]
WIM integrity table is supported (\fB--check\fR option to many commands)
.SH DIFFERENCES FROM MICROSOFT IMAGEX
Although \fB@IMAGEX_PROGNAME@\fR shares some similarities with Microsoft's
-implementation of ImageX, this section lists some noteworthy differences between
-the two programs:
+implementation of ImageX, this section lists some of the many noteworthy
+differences between the two programs:
.IP \[bu] 4
\fB@IMAGEX_PROGNAME@\fR is supported on both UNIX-like systems and Windows;
thus, some functionality was designed around this.
.IP \[bu]
\fB@IMAGEX_PROGNAME@\fR offers the extra command \fB@IMAGEX_PROGNAME@
optimize\fR, which lets you easily remove wasted space in a WIM (which can arise
-after a WIM image is appended or mounted read-write).
+after a WIM image is appended or mounted read-write). It also makes it easy to
+recompress a WIM file at the highest compression level.
.IP \[bu]
\fB@IMAGEX_PROGNAME@\fR also offers the command \fB@IMAGEX_PROGNAME@ join\fR,
which lets you easily join the parts of a split WIM.
mounting an image from a split WIM, but Microsoft's software does not. (Note:
this functionality is not available in Windows builds of wimlib and
\fB@IMAGEX_PROGNAME@\fR.)
-.IP \[bu]
-\fB@IMAGEX_PROGNAME@ capture\fR supports a special mode where UNIX file modes,
-owners, and groups are stored. (Note: this functionality is only available in
-builds of wimlib for UNIX-like systems.)
.SH LOCALES AND CHARACTER ENCODINGS
On Windows, wimlib works in UTF-16LE, and there should be no problems with
character encodings.
wimlib_set_image_descripton(WIMStruct *wim, int image,
const wimlib_tchar *description);
+/**
+ * @ingroup G_writing_and_overwriting_wims
+ *
+ * Set the compression type of a WIM to use in subsequent calls to
+ * wimlib_write() or wimlib_overwrite().
+ *
+ * @return 0 on success; nonzero on error.
+ *
+ * @param wim
+ * ::WIMStruct for a WIM.
+ * @param ctype
+ * The compression type to set (one of ::wimlib_compression_type).
+ *
+ * @return 0 on success; nonzero on error.
+ *
+ * @retval ::WIMLIB_ERR_INVALID_PARAM
+ * @p ctype did not specify a valid compression type.
+ */
+extern int
+wimlib_set_output_compression_type(WIMStruct *wim, int ctype);
+
/**
* @ingroup G_modifying_wims
*
/* One of WIMLIB_COMPRESSION_TYPE_*, cached from the header flags. */
u8 compression_type : 2;
+
+ /* Overwritten compression type for wimlib_overwrite() or
+ * wimlib_write(). Can be changed by
+ * wimlib_set_output_compression_type(); otherwise is the same as
+ * compression_type. */
+ u8 out_compression_type : 2;
};
static inline bool wim_is_pipable(const WIMStruct *wim)
extern void
wim_recalculate_refcnts(WIMStruct *wim);
+extern u32
+get_wim_hdr_cflags(int ctype);
+
extern int
init_wim_header(struct wim_header *hdr, int ctype);
{T("check"), no_argument, NULL, IMAGEX_CHECK_OPTION},
{T("nocheck"), no_argument, NULL, IMAGEX_NOCHECK_OPTION},
{T("no-check"), no_argument, NULL, IMAGEX_NOCHECK_OPTION},
+ {T("compress"), required_argument, NULL, IMAGEX_COMPRESS_OPTION},
{T("recompress"), no_argument, NULL, IMAGEX_RECOMPRESS_OPTION},
{T("compress-slow"), no_argument, NULL, IMAGEX_COMPRESS_SLOW_OPTION},
{T("recompress-slow"), no_argument, NULL, IMAGEX_COMPRESS_SLOW_OPTION},
}
}
-static void
+static int
set_compress_slow(void)
{
+ int ret;
static const struct wimlib_lzx_params slow_params = {
.size_of_this = sizeof(struct wimlib_lzx_params),
.algorithm = WIMLIB_LZX_ALGORITHM_SLOW,
},
},
};
- if (wimlib_lzx_set_default_params(&slow_params))
+ ret = wimlib_lzx_set_default_params(&slow_params);
+ if (ret)
imagex_error(T("Couldn't set slow compression parameters.!"));
+ return ret;
}
struct string_set {
goto out_err;
break;
case IMAGEX_COMPRESS_SLOW_OPTION:
- set_compress_slow();
+ ret = set_compress_slow();
+ if (ret)
+ goto out_err;
+ compression_type = WIMLIB_COMPRESSION_TYPE_LZX;
break;
case IMAGEX_FLAGS_OPTION:
flags_element = optarg;
int c;
int open_flags = WIMLIB_OPEN_FLAG_WRITE_ACCESS;
int write_flags = WIMLIB_WRITE_FLAG_REBUILD;
+ int compression_type = WIMLIB_COMPRESSION_TYPE_INVALID;
int ret;
WIMStruct *wim;
const tchar *wimfile;
case IMAGEX_NOCHECK_OPTION:
write_flags |= WIMLIB_WRITE_FLAG_NO_CHECK_INTEGRITY;
break;
+ case IMAGEX_COMPRESS_OPTION:
+ write_flags |= WIMLIB_WRITE_FLAG_RECOMPRESS;
+ compression_type = get_compression_type(optarg);
+ if (compression_type == WIMLIB_COMPRESSION_TYPE_INVALID)
+ goto out_err;
+ break;
case IMAGEX_RECOMPRESS_OPTION:
write_flags |= WIMLIB_WRITE_FLAG_RECOMPRESS;
break;
case IMAGEX_COMPRESS_SLOW_OPTION:
write_flags |= WIMLIB_WRITE_FLAG_RECOMPRESS;
- set_compress_slow();
+ ret = set_compress_slow();
+ if (ret)
+ goto out_err;
break;
case IMAGEX_THREADS_OPTION:
num_threads = parse_num_threads(optarg);
if (ret)
goto out;
+ if (compression_type != WIMLIB_COMPRESSION_TYPE_INVALID) {
+ ret = wimlib_set_output_compression_type(wim, compression_type);
+ if (ret)
+ goto out_wimlib_free;
+ }
+
old_size = file_get_size(wimfile);
tprintf(T("\"%"TS"\" original size: "), wimfile);
if (old_size == -1)
[CMD_OPTIMIZE] =
T(
" %"TS" WIMFILE [--check] [--nocheck] [--recompress]\n"
-" [--recompress-slow] [--threads=NUM_THREADS] [--pipable]\n"
-" [--not-pipable]\n"
+" [--recompress-slow] [--compress=TYPE]\n"
+" [--threads=NUM_THREADS] [--pipable] [--not-pipable]\n"
),
[CMD_SPLIT] =
T(
offsetof(struct wim_header_disk, wim_flags));
}
+u32
+get_wim_hdr_cflags(int ctype)
+{
+ switch (ctype) {
+ case WIMLIB_COMPRESSION_TYPE_NONE:
+ return 0;
+ case WIMLIB_COMPRESSION_TYPE_LZX:
+ return WIM_HDR_FLAG_COMPRESSION | WIM_HDR_FLAG_COMPRESS_LZX;
+ case WIMLIB_COMPRESSION_TYPE_XPRESS:
+ return WIM_HDR_FLAG_COMPRESSION | WIM_HDR_FLAG_COMPRESS_XPRESS;
+ case WIMLIB_COMPRESSION_TYPE_INVALID:
+ break;
+ }
+ return (u32)~0U;
+}
+
/*
* Initializes the header for a WIM file.
*/
init_wim_header(struct wim_header *hdr, int ctype)
{
memset(hdr, 0, sizeof(struct wim_header));
- switch (ctype) {
- case WIMLIB_COMPRESSION_TYPE_NONE:
- hdr->flags = 0;
- break;
- case WIMLIB_COMPRESSION_TYPE_LZX:
- hdr->flags = WIM_HDR_FLAG_COMPRESSION |
- WIM_HDR_FLAG_COMPRESS_LZX;
- break;
- case WIMLIB_COMPRESSION_TYPE_XPRESS:
- hdr->flags = WIM_HDR_FLAG_COMPRESSION |
- WIM_HDR_FLAG_COMPRESS_XPRESS;
- break;
- default:
+ hdr->flags = get_wim_hdr_cflags(ctype);
+ if (hdr->flags == (u32)~0U) {
ERROR("Invalid compression type specified (%d)", ctype);
return WIMLIB_ERR_INVALID_COMPRESSION_TYPE;
}
return true;
}
+/* API function documented in wimlib.h */
WIMLIBAPI int
wimlib_lzx_set_default_params(const struct wimlib_lzx_params * params)
{
* the metadata resource. */
ret = write_wim_resource_from_buffer(buf, len, WIM_RESHDR_FLAG_METADATA,
&wim->out_fd,
- wim->compression_type,
+ wim->out_compression_type,
&imd->metadata_lte->output_resource_entry,
imd->metadata_lte->hash,
write_resource_flags,
wim->lookup_table = table;
wim->refcnts_ok = 1;
wim->compression_type = ctype;
+ wim->out_compression_type = ctype;
*wim_ret = wim;
return 0;
out_free:
} else {
wim->compression_type = WIMLIB_COMPRESSION_TYPE_NONE;
}
+ wim->out_compression_type = wim->compression_type;
if (open_flags & WIMLIB_OPEN_FLAG_CHECK_INTEGRITY) {
ret = check_wim_integrity(wim, progress_func);
return write_stream_list(stream_list,
wim->lookup_table,
&wim->out_fd,
- wim->compression_type,
+ wim->out_compression_type,
&wim->lzx_context,
write_flags,
num_threads,
"metadata resource.", i);
ret = write_wim_resource(imd->metadata_lte,
&wim->out_fd,
- wim->compression_type,
+ wim->out_compression_type,
&imd->metadata_lte->output_resource_entry,
write_resource_flags,
&wim->lzx_context);
* finish_write(). */
}
+/* API function documented in wimlib.h */
+WIMLIBAPI int
+wimlib_set_output_compression_type(WIMStruct *wim, int ctype)
+{
+ switch (ctype) {
+ case WIMLIB_COMPRESSION_TYPE_INVALID:
+ break;
+ case WIMLIB_COMPRESSION_TYPE_NONE:
+ case WIMLIB_COMPRESSION_TYPE_LZX:
+ case WIMLIB_COMPRESSION_TYPE_XPRESS:
+ wim->out_compression_type = ctype;
+ return 0;
+ }
+ return WIMLIB_ERR_INVALID_PARAM;
+}
+
/* Write a standalone WIM or split WIM (SWM) part to a new file or to a file
* descriptor. */
int
wim->hdr.part_number = part_number;
wim->hdr.total_parts = total_parts;
+ /* Set compression type if different. */
+ if (wim->compression_type != wim->out_compression_type)
+ wim->hdr.flags = get_wim_hdr_cflags(wim->out_compression_type);
+
/* Use GUID if specified; otherwise generate a new one. */
if (guid)
memcpy(wim->hdr.guid, guid, WIMLIB_GUID_LEN);
if ((!wim->deletion_occurred || (write_flags & WIMLIB_WRITE_FLAG_SOFT_DELETE))
&& !(write_flags & (WIMLIB_WRITE_FLAG_REBUILD |
WIMLIB_WRITE_FLAG_PIPABLE))
- && !(wim_is_pipable(wim)))
+ && !(wim_is_pipable(wim))
+ && wim->compression_type == wim->out_compression_type)
{
ret = overwrite_wim_inplace(wim, write_flags, num_threads,
progress_func);