the LZX documentation is not entirely correct, and the WIM documentation itself
is very incomplete and is of unacceptable quality.
+A WIM file may be either stand-alone or split into multiple parts.
+
WINDOWS PE
A major use for this library is to create customized images of Windows PE, the
specifies a regular file or block device, it is interpreted as a NTFS volume to
which the WIM image is to be extracted.
+\fBimagex apply\fR supports applying images from stand-alone WIMs as well as
+split WIM. See \fBSPLIT WIMS\fR.
+
.SH NORMAL MODE
The normal extraction mode is entered when \fITARGET\fR is a directory or
bootable flag on it, and have a master boot record that loads the bootable
partition (Windows' MBR does, and SYSLINUX provides an equivalent MBR).
+.SH SPLIT WIMS
+
+You may use \fBimagex apply\fR to apply images from a split WIM. The
+\fIWIMFILE\fR argument is used to specify the first part of the split WIM, and
+the \fB--refs\fR="\fIGLOB\fR" option is used to provide a shell-style file glob
+that specifies the additional parts of the split WIM. \fIGLOB\fR is expected to
+be a single string on the command line, so \fIGLOB\fR must be quoted so that it
+is protected against shell expansion. \fIGLOB\fR must expand to all parts of
+the split WIM, except optionally the first part which may either omitted or
+included in the glob (but the first part MUST be specified as \fIWIMFILE\fR as
+well).
+
+Here's an example. The names for the split WIMs usually go something like:
+
+.RS
+.PP
+.nf
+mywim.swm
+mywim2.swm
+mywim3.swm
+mywim4.swm
+mywim5.swm
+\. ... etc.
+.RE
+
+To apply the first image of this split WIM to the directory "dir", we would do:
+.PP
+.RS
+imagex apply mywim.swm 1 dir --ref="mywim*.swm"
+.RE
+.PP
+
.SH OPTIONS
.TP 6
\fB--check\fR
\fB--verbose\fR
Print the path to of each file or directory within the WIM image as it is
extracted, and some additional informational messages.
+.TP
+\fB--ref\fR="\fIGLOB\fR"
+File glob of additional split WIM parts that are part of the split WIM being
+applied. See \fBSPLIT_WIMS\fR.
.SH NOTES
-\fBimagex apply\fR does not yet support split WIMs.
-
\fBimagex apply\fR calculates the SHA1 message digest of every file stream it
extracts and verifies that it is the same as the SHA1 message digest provided in
the WIM file. It is an error if the message digests don't match. It's also
.SH SYNOPSIS
\fBimagex mount\fR \fIWIMFILE\fR \fIIMAGE\fR \fIDIRECTORY\fR [--check]
-[--streams-interface=\fIINTERFACE\fR]
+[--streams-interface=\fIINTERFACE\fR] [--ref="\fIGLOB\fR"]
.br
\fBimagex mountrw\fR \fIWIMFILE\fR \fIIMAGE\fR \fIDIRECTORY\fR [--check]
[--streams-interface=\fIINTERFACE\fR]
made to a WIM mounted read-write will be discarded unless the \fB--commit\fR
flag is provided to \fBimagex unmount\fR.
+.SH SPLIT WIMS
+
+You may use \fBimagex mount\fR to mount an image from a split WIM read-only.
+However, you may not mount an image from a split WIM read-write.
+
+The \fIWIMFILE\fR argument is used to specify the first part of the split WIM, and
+the \fB--refs\fR="\fIGLOB\fR" option is used to provide a shell-style file glob
+that specifies the additional parts of the split WIM. \fIGLOB\fR is expected to
+be a single string on the command line, so \fIGLOB\fR must be quoted so that it
+is protected against shell expansion. \fIGLOB\fR must expand to all parts of
+the split WIM, except optionally the first part which may either omitted or
+included in the glob (but the first part MUST be specified as \fIWIMFILE\fR as
+well).
+
+Here's an example. The names for the split WIMs usually go something like:
+
+.RS
+.PP
+.nf
+mywim.swm
+mywim2.swm
+mywim3.swm
+mywim4.swm
+mywim5.swm
+\. ... etc.
+.RE
+
+To mount the first image of this split WIM to the directory "dir", we would do:
+.PP
+.RS
+imagex mount mywim.swm 1 dir --ref="mywim*.swm"
+.RE
+.PP
+
.SH NOTES
If wimlib was configured using the --without-fuse flag, then the \fBimagex
All files in the mounted WIM will be accessible regardless of whether there is a
security descriptor in the WIM associated with the file or not. New files or
directories created in a read-write mounted WIM will be created with no security
-descriptor.
-
-Mounting split WIMs is not yet supported.
+descriptor. Although there is support for accessing named data streams (see the
+\fB--streams-interface\fR option), it is currently not possible
+to set or get DOS names, file attributes, or security
+descriptors in a mounted WIM.
.SH MOUNT OPTIONS
.TP
Turn on debugging information printed by the FUSE library, and do not fork into
the background.
+.TP
+\fB--ref\fR="\fIGLOB\fR"
+File glob of additional split WIM parts that are part of the split WIM being
+mounted. This option is valid for \fBimagex mount\fR but not \fBimagex
+mountrw\fR. See \fBSPLIT_WIMS\fR.
+
.SH UNMOUNT OPTIONS
.TP
\fB--commit\fR
The following features are currently supported:
-.IP \[bu] 2
-Mount an image in a WIM read-only (\fBimagex mount\fR)
-.IP \[bu] 2
-Mount an image in a WIM read-write (\fBimagex mountrw\fR)
-.IP \[bu] 2
-Create a WIM from a directory or NTFS volume (\fBimagex capture\fR)
-.IP \[bu] 2
-Append a directory or NTFS volume onto a WIM as a new image (\fBimagex
+.IP \[bu] 3
+Create a stand-alone WIM from a directory or NTFS volume (\fBimagex capture\fR)
+.IP \[bu]
+Append a directory or NTFS volume onto a stand-alone WIM as a new image (\fBimagex
append\fR)
-.IP \[bu] 2
-Delete image(s) from a WIM (\fBimagex delete\fR)
-.IP \[bu] 2
-Export image(s) from a WIM (\fBimagex export\fR)
-.IP \[bu] 2
+.IP \[bu]
+Apply an image from a stand-alone or split WIM to a directory or NTFS volume
+(\fBimagex apply\fR)
+.IP \[bu]
+Mount an image from a stand-alone or split WIM read-only (\fBimagex mount\fR)
+.IP \[bu]
+Mount an image from a stand-alone WIM read-write (\fBimagex mountrw\fR)
+.IP \[bu]
+Delete image(s) from a stand-alone WIM (\fBimagex delete\fR)
+.IP \[bu]
+Export image(s) from a stand-alone WIM (\fBimagex export\fR)
+.IP \[bu]
Display information about a WIM file (\fBimagex info\fR, \fBimagex dir\fR)
-.IP \[bu] 2
+.IP \[bu]
Change the name or description of an image in the WIM (\fBimagex info\fR)
-.IP \[bu] 2
+.IP \[bu]
Change which image in a WIM is bootable (\fBimagex info\fR)
-.IP \[bu] 2
-Combine split WIMs into one WIM (\fBimage join\fR)
-.IP \[bu] 2
-Split a WIM into multiple parts (\fBimage split\fR)
-.IP \[bu] 2
+.IP \[bu]
+Combine split WIMs into one stand-alone WIM (\fBimage join\fR)
+.IP \[bu]
+Split a stand-alone WIM into multiple parts (\fBimage split\fR)
+.IP \[bu]
Support for all WIM compression types, both compression and decompression (LZX,
XPRESS, and none)
-.IP \[bu] 2
-Integrity table
-.IP \[bu] 2
-XML data (parsed and written using \fBlibxml\fR(3))
+.IP \[bu]
+WIM integrity table is supported (\fB--check\fR option to many commands)
+.IP \[bu]
+WIM XML data (parsed and written using \fBlibxml\fR(3))
.SH UNSUPPORTED FEATURES
As of version 1.0.0, wimlib supports capturing and applying WIMs directly from
-NTFS and has much improved support for hard links and symbolic links. I don't
-think there are many other features that would be worth it to implement; the
-only significant thing missing (in my opinion) is that split WIMs need to be
-handled better (e.g. it should be possible to apply a split WIM using \fBimagex
-apply\fR). And if Microsoft updates the WIM format, I'd need to support it, but
-it looks like the format for Windows 8 is the same as that of Windows 7.
+NTFS and has much improved support for hard links and symbolic links. In
+addition, you may now apply split WIMs and mount them read-only. I don't think
+there are many other features that would be worth it to implement. Besides
+porting the library to Windows (which I'm not really interested in), the main
+thing that could use improvement (in my opinion) is that the LZX compression
+ratio still isn't quite as good as Microsoft's version. Also, exporting an
+image from a split WIM could be supported. Furthermore, if Microsoft updates
+the WIM format, I'd need to support it, but it looks like the format for Windows
+8 is the same as that of Windows 7.
.SH DIFFERENCES FROM MICROSOFT IMAGEX
when they are extracted from a WIM, are not available in Microsoft's version of
imagex. Also, doesn't seem to be an equivalent of \fBimagex join\fR in
Microsoft's version; you would have to use \fBimagex.exe /export\fR, but that
-doesn't let you export all images at once.
+doesn't let you export all images at once. Furthermore, this version of
+\fBimagex\fR lets you mount an image from a split WIM read-only, while
+Microsoft's version does not.
Microsoft's version has some weird limitations, like it won't let you extract a
WIM on a shared folder, and it requires some commands to be run only from
UNMOUNT,
};
-static const char *path_basename(const char *path)
-{
- const char *p = path;
- while (*p)
- p++;
- p--;
-
- /* Trailing slashes. */
- while ((p != path - 1) && *p == '/')
- p--;
-
- while ((p != path - 1) && *p != '/')
- p--;
-
- return p + 1;
-}
-
+static void usage(int cmd_type);
+static void usage_all();
static const char *usage_strings[] = {
[APPEND] =
[APPLY] =
" imagex apply WIMFILE [IMAGE_NUM | IMAGE_NAME | all]\n"
" (DIRECTORY | NTFS_VOLUME) [--check] [--hardlink]\n"
-" [--symlink] [--verbose]\n",
+" [--symlink] [--verbose] [--ref=\"GLOB\"]\n",
[CAPTURE] =
" imagex capture (DIRECTORY | NTFS_VOLUME) WIMFILE [IMAGE_NAME]\n"
" [DESCRIPTION] [--boot] [--check] [--compress=TYPE]\n"
" imagex join [--check] WIMFILE SPLIT_WIM...\n",
[MOUNT] =
" imagex mount WIMFILE (IMAGE_NUM | IMAGE_NAME) DIRECTORY\n"
-" [--check] [--debug] [--streams-interface=INTERFACE]\n",
+" [--check] [--debug] [--streams-interface=INTERFACE]\n"
+" [--ref=\"GLOB\"]\n",
[MOUNTRW] =
" imagex mountrw WIMFILE [IMAGE_NUM | IMAGE_NAME] DIRECTORY\n"
" [--check] [--debug] [--streams-interface=INTERFACE]\n",
{"check", no_argument, NULL, 'c'},
{"debug", no_argument, NULL, 'd'},
{"streams-interface", required_argument, NULL, 's'},
+ {"ref", required_argument, NULL, 'r'},
{NULL, 0, NULL, 0},
};
};
+
/* Print formatted error message to stderr. */
static void imagex_error(const char *format, ...)
{
va_end(va);
}
-
-static inline void version()
+static const char *path_basename(const char *path)
{
- static const char *s =
- "imagex (" PACKAGE ") " PACKAGE_VERSION "\n"
- "Copyright (C) 2012 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";
- fputs(s, stdout);
-}
+ const char *p = path;
+ while (*p)
+ p++;
+ p--;
-static inline void usage(int cmd)
-{
- puts("IMAGEX: Usage:");
- fputs(usage_strings[cmd], stdout);
-}
+ /* Trailing slashes. */
+ while ((p != path - 1) && *p == '/')
+ p--;
-static void usage_all()
-{
- puts("IMAGEX: Usage:");
- for (int i = 0; i < ARRAY_LEN(usage_strings); i++)
- fputs(usage_strings[i], stdout);
- static const char *extra =
-" imagex --help\n"
-" imagex --version\n"
-"\n"
-" The compression TYPE may be \"maximum\", \"fast\", or \"none\".\n"
- ;
- fputs(extra, stdout);
+ while ((p != path - 1) && *p != '/')
+ p--;
+
+ return p + 1;
}
+
static int verify_image_exists(int image)
{
if (image == WIM_NO_IMAGE) {
return NULL;
}
+static int open_swms_from_glob(const char *swm_glob,
+ const char *first_part,
+ int open_flags,
+ WIMStruct ***additional_swms_ret,
+ unsigned *num_additional_swms_ret)
+{
+ unsigned num_additional_swms = 0;
+ WIMStruct **additional_swms = NULL;
+ glob_t globbuf;
+ int ret;
+
+ ret = glob(swm_glob, GLOB_ERR | GLOB_NOSORT, NULL, &globbuf);
+ if (ret != 0) {
+ if (ret == GLOB_NOMATCH) {
+ imagex_error("Found no files for glob \"%s\"",
+ swm_glob);
+ } else {
+ imagex_error_with_errno("Failed to process glob "
+ "\"%s\"", swm_glob);
+ }
+ ret = -1;
+ goto out;
+ }
+ num_additional_swms = globbuf.gl_pathc;
+ additional_swms = calloc(num_additional_swms, sizeof(additional_swms[0]));
+ if (!additional_swms) {
+ imagex_error("Out of memory");
+ ret = -1;
+ goto out_globfree;
+ }
+ size_t offset = 0;
+ for (size_t i = 0; i < num_additional_swms; i++) {
+ if (strcmp(globbuf.gl_pathv[i], first_part) == 0) {
+ offset++;
+ continue;
+ }
+ ret = wimlib_open_wim(globbuf.gl_pathv[i],
+ open_flags | WIMLIB_OPEN_FLAG_SPLIT_OK,
+ &additional_swms[i - offset]);
+ if (ret != 0)
+ goto out_close_swms;
+ }
+ *additional_swms_ret = additional_swms;
+ *num_additional_swms_ret = num_additional_swms - offset;
+ ret = 0;
+ goto out_globfree;
+out_close_swms:
+ for (unsigned i = 0; i < num_additional_swms; i++)
+ wimlib_free(additional_swms[i]);
+ free(additional_swms);
+out_globfree:
+ globfree(&globbuf);
+out:
+ return ret;
+}
+
static int imagex_append(int argc, const char **argv)
{
int c;
const char *swm_glob = NULL;
WIMStruct **additional_swms = NULL;
- size_t num_additional_swms = 0;
- glob_t globbuf;
+ unsigned num_additional_swms = 0;
for_opt(c, apply_options) {
switch (c) {
}
if (swm_glob) {
- ret = glob(swm_glob, GLOB_ERR | GLOB_NOSORT, NULL, &globbuf);
- if (ret != 0) {
- imagex_error_with_errno("Failed to process glob "
- "\"%s\"", swm_glob);
- ret = -1;
- goto out;
- }
- num_additional_swms = globbuf.gl_pathc;
- additional_swms = calloc(num_additional_swms, sizeof(additional_swms[0]));
- if (!additional_swms) {
- imagex_error("Out of memory");
- ret = -1;
+ ret = open_swms_from_glob(swm_glob, wimfile, open_flags,
+ &additional_swms,
+ &num_additional_swms);
+ if (ret != 0)
goto out;
- }
- size_t offset = 0;
- for (size_t i = 0; i < num_additional_swms; i++) {
- if (strcmp(globbuf.gl_pathv[i], wimfile) == 0) {
- offset++;
- continue;
- }
- ret = wimlib_open_wim(globbuf.gl_pathv[i],
- open_flags | WIMLIB_OPEN_FLAG_SPLIT_OK,
- &additional_swms[i - offset]);
- if (ret != 0)
- goto out;
- }
- num_additional_swms -= offset;
}
#ifdef WITH_NTFS_3G
{
int c;
int mount_flags = 0;
- int open_flags = WIMLIB_OPEN_FLAG_SHOW_PROGRESS;
+ int open_flags = WIMLIB_OPEN_FLAG_SHOW_PROGRESS |
+ WIMLIB_OPEN_FLAG_SPLIT_OK;
const char *wimfile;
const char *dir;
WIMStruct *w;
int image;
int num_images;
int ret;
+ const char *swm_glob = NULL;
+ WIMStruct **additional_swms = NULL;
+ unsigned num_additional_swms = 0;
if (strcmp(argv[0], "mountrw") == 0)
mount_flags |= WIMLIB_MOUNT_FLAG_READWRITE;
goto mount_usage;
}
break;
+ case 'r':
+ swm_glob = optarg;
+ break;
default:
goto mount_usage;
}
if (ret != 0)
return ret;
+ if (swm_glob) {
+ ret = open_swms_from_glob(swm_glob, wimfile, open_flags,
+ &additional_swms,
+ &num_additional_swms);
+ if (ret != 0)
+ goto out;
+ }
+
if (argc == 2) {
image = 1;
num_images = wimlib_get_num_images(w);
usage((mount_flags & WIMLIB_MOUNT_FLAG_READWRITE)
? MOUNTRW : MOUNT);
ret = WIMLIB_ERR_INVALID_IMAGE;
- goto done;
+ goto out;
}
dir = argv[1];
} else {
ret = verify_image_exists_and_is_single(image);
if (ret != 0)
- goto done;
+ goto out;
- ret = wimlib_mount(w, image, dir, mount_flags);
+ ret = wimlib_mount(w, image, dir, mount_flags, additional_swms,
+ num_additional_swms);
if (ret != 0) {
imagex_error("Failed to mount image %d from `%s' on `%s'",
image, wimfile, dir);
}
-done:
+out:
wimlib_free(w);
+ if (additional_swms)
+ for (unsigned i = 0; i < num_additional_swms; i++)
+ wimlib_free(additional_swms[i]);
return ret;
mount_usage:
usage((mount_flags & WIMLIB_MOUNT_FLAG_READWRITE)
int cmd;
};
+
+#define for_imagex_command(p) for (p = &imagex_commands[0]; \
+ p != &imagex_commands[ARRAY_LEN(imagex_commands)]; p++)
+
static struct imagex_command imagex_commands[] = {
{"append", imagex_append, APPEND},
{"apply", imagex_apply, APPLY},
{"unmount", imagex_unmount, UNMOUNT},
};
-#define for_imagex_command(p) for (p = &imagex_commands[0]; \
- p != &imagex_commands[ARRAY_LEN(imagex_commands)]; p++)
+static void version()
+{
+ static const char *s =
+ "imagex (" PACKAGE ") " PACKAGE_VERSION "\n"
+ "Copyright (C) 2012 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";
+ fputs(s, stdout);
+}
+
static void help_or_version(int argc, const char **argv)
{
}
+static void usage(int cmd_type)
+{
+ struct imagex_command *cmd;
+ puts("IMAGEX: Usage:");
+ fputs(usage_strings[cmd_type], stdout);
+ for_imagex_command(cmd)
+ if (cmd->cmd == cmd_type)
+ printf("\nTry `man imagex-%s' for more details.\n",
+ cmd->name);
+}
+
+static void usage_all()
+{
+ puts("IMAGEX: Usage:");
+ for (int i = 0; i < ARRAY_LEN(usage_strings); i++)
+ fputs(usage_strings[i], stdout);
+ static const char *extra =
+" imagex --help\n"
+" imagex --version\n"
+"\n"
+" The compression TYPE may be \"maximum\", \"fast\", or \"none\".\n"
+"\n"
+" Try `man imagex' for more information.\n"
+ ;
+ fputs(extra, stdout);
+}
+
+
int main(int argc, const char **argv)
{
struct imagex_command *cmd;
static int copy_lte_to_table(struct lookup_table_entry *lte, void *table)
{
struct lookup_table_entry *copy;
- copy = new_lookup_table_entry();
+ copy = MALLOC(sizeof(struct lookup_table_entry));
if (!copy)
return WIMLIB_ERR_NOMEM;
memcpy(copy, lte, sizeof(struct lookup_table_entry));
+ INIT_LIST_HEAD(©->lte_group_list);
lookup_table_insert(table, copy);
return 0;
}
/* Mounts a WIM file. */
WIMLIBAPI int wimlib_mount(WIMStruct *wim, int image, const char *dir,
- int flags)
+ int flags, WIMStruct **additional_swms,
+ unsigned num_additional_swms)
{
int argc = 0;
char *argv[16];
int ret;
char *p;
+ struct lookup_table *joined_tab, *wim_tab_save;
DEBUG("Mount: wim = %p, image = %d, dir = %s, flags = %d, ",
wim, image, dir, flags);
- if (!dir)
+ if (!wim || !dir)
return WIMLIB_ERR_INVALID_PARAM;
+ ret = verify_swm_set(wim, additional_swms, num_additional_swms);
+ if (ret != 0)
+ return ret;
+
+ if (num_additional_swms) {
+ ret = new_joined_lookup_table(wim, additional_swms,
+ num_additional_swms,
+ &joined_tab);
+ if (ret != 0)
+ return ret;
+ wim_tab_save = wim->lookup_table;
+ wim->lookup_table = joined_tab;
+ }
+
ret = wimlib_select_image(wim, image);
if (ret != 0)
- return ret;
+ goto out;
DEBUG("Selected image %d", image);
next_link_group_id = assign_link_group_ids(wim->image_metadata[image - 1].lgt);
+ DEBUG("Resolving lookup table entries");
/* Resolve all the lookup table entries of the dentry tree */
for_dentry_in_tree(wim_root_dentry(wim), dentry_resolve_ltes,
wim->lookup_table);
+ DEBUG("Checking lookup table entry reference counts");
+
ret = for_lookup_table_entry(wim->lookup_table, check_lte_refcnt, NULL);
if (ret != 0)
- return ret;
+ goto out;
if (flags & WIMLIB_MOUNT_FLAG_READWRITE)
wim_get_current_image_metadata(wim)->modified = true;
WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_WINDOWS)))
flags |= WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_XATTR;
+ DEBUG("Getting current directory");
+
mount_dir = dir;
working_directory = getcwd(NULL, 0);
if (!working_directory) {
ERROR_WITH_ERRNO("Could not determine current directory");
- return WIMLIB_ERR_NOTDIR;
+ ret = WIMLIB_ERR_NOTDIR;
+ goto out;
}
+ DEBUG("Closing POSIX message queues");
+ /* XXX hack to get rid of the message queues if they already exist for
+ * some reason (maybe left over from a previous mount that wasn't
+ * unmounted correctly) */
+ ret = open_message_queues(true);
+ if (ret != 0)
+ goto out;
+ close_message_queues();
+
+ DEBUG("Preparing arguments to fuse_main()");
+
+
p = STRDUP(dir);
- if (!p)
- return WIMLIB_ERR_NOMEM;
+ if (!p) {
+ ret = WIMLIB_ERR_NOMEM;
+ goto out;
+ }
argv[argc++] = "imagex";
argv[argc++] = p;
make_staging_dir();
if (!staging_dir_name) {
FREE(p);
- return WIMLIB_ERR_MKDIR;
+ ret = WIMLIB_ERR_MKDIR;
+ goto out;
}
} else {
/* Read-only mount */
mount_flags = flags;
ret = fuse_main(argc, argv, &wimfs_operations, NULL);
-
- return (ret == 0) ? 0 : WIMLIB_ERR_FUSE;
+ if (ret)
+ ret = WIMLIB_ERR_FUSE;
+out:
+ if (num_additional_swms) {
+ free_lookup_table(wim->lookup_table);
+ wim->lookup_table = wim_tab_save;
+ }
+ return ret;
}
}
WIMLIBAPI int wimlib_mount(WIMStruct *wim_p, int image, const char *dir,
- int flags)
+ int flags, WIMStruct **additional_swms,
+ unsigned num_additional_swms)
{
return mount_unsupported_error();
}
* but the LZX documentation is not entirely correct, and the WIM documentation
* itself is very incomplete and is of unacceptable quality.
*
+ * A WIM file may be either stand-alone or split into multiple parts.
+ *
* \section winpe Windows PE
*
* A major use for this library is to create customized images of Windows PE, the
* @param num_additional_swms
* Number of additional WIM parts provided in the @a additional_swms array.
* This number should be one less than the total number of parts in the
- * split WIM.
+ * split WIM. Set to 0 if the WIM is a standalone WIM.
*
* @return 0 on success; nonzero on error.
* @retval ::WIMLIB_ERR_DECOMPRESSION
* ::WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_XATTR, or
* ::WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_WINDOWS. The default interface is
* the XATTR interface.
+ * @param additional_swms
+ * Array of pointers to the ::WIMStruct for each additional part in the
+ * split WIM. Ignored if @a num_additional_swms is 0. The pointers do not
+ * need to be in any particular order, but they must include all parts of
+ * the split WIM other than the first part, which must be provided in the
+ * @a wim parameter.
+ * @param num_additional_swms
+ * Number of additional WIM parts provided in the @a additional_swms array.
+ * This number should be one less than the total number of parts in the
+ * split WIM. Set to 0 if the WIM is a standalone WIM.
*
* @return 0 on success; nonzero on error.
* @retval ::WIMLIB_ERR_DECOMPRESSION
* @retval ::WIMLIB_ERR_READ
* An unexpected end-of-file or read error occurred when trying to read
* data from the WIM file associated with @a wim.
+ * @retval ::WIMLIB_ERR_SPLIT_INVALID
+ * The WIM is a split WIM, but the parts specified do not form a complete
+ * split WIM because they do not include all the parts of the original WIM,
+ * there are duplicate parts, or not all the parts have the same GUID and
+ * compression type.
+ * @retval ::WIMLIB_ERR_SPLIT_UNSUPPORTED
+ * The WIM is a split WIM and a read-write mount was requested. We only
+ * support mounting a split WIM read-only.
*/
-extern int wimlib_mount(WIMStruct *wim, int image, const char *dir, int flags);
+extern int wimlib_mount(WIMStruct *wim, int image, const char *dir, int flags,
+ WIMStruct **additional_swms,
+ unsigned num_additional_swms);
/**
* Opens a WIM file and creates a ::WIMStruct for it.