src/security.c \
src/sha1.c \
src/split.c \
- src/swm.c \
src/reparse.c \
src/timestamp.c \
src/update_image.c \
include/wimlib/endianness.h \
include/wimlib/error.h \
include/wimlib/file_io.h \
+ include/wimlib/glob.h \
include/wimlib/header.h \
include/wimlib/integrity.h \
include/wimlib/list.h \
include/wimlib/resource.h \
include/wimlib/security.h \
include/wimlib/sha1.h \
- include/wimlib/swm.h \
include/wimlib/timestamp.h \
include/wimlib/types.h \
include/wimlib/util.h \
to standard output and applying images from standard input, but they are
not compatible with Microsoft's software and are not created by default.
See the documentation for --pipable flag of `wimlib-imagex capture' for
- more information. Two new functions have been added to the library to
- fully support this: wimlib_write_to_fd() and
- wimlib_extract_image_from_pipe().
+ more information.
- wimlib now preserve WIM integrity tables by default, even if
+ To better support incremental backups, added support for declaring an
+ image as a modified form of a prior image. See the documentation for
+ the '--delta-from' option of `wimlib-imagex append'.
+
+ The library support for managing split WIMs has been changed to support
+ other arrangements, such as delta WIMs, and be easier to use. This
+ change is visible in `wimlib-imagex', which also can now accept the
+ '--ref' option multiple times.
+
+ wimlib now preserves WIM integrity tables by default, even if
WIMLIB_WRITE_FLAG_CHECK_INTEGRITY is not specified. This changes the
behavior of `wimlib-imagex' whenever the WIM being operated on contains
an integrity table and the '--check' option is not specified.
ratio by default, which is usually what is desired, at a cost of some
speed.
- For convenience, `wimlib-imagex' now supports being invoked as
- wimCOMMAND, where COMMAND is the command as in `wimlib-imagex COMMAND';
- for example, it can be invoked as `wimapply' as an alternative to
- `wimlib-imagex apply'. The appropriate hard links are created in UNIX
- installations of `wimlib-imagex', while for the Windows distribution of
- `wimlib-imagex', batch files that emulate this behavior are generated.
-
- `wimlib-imagex' no longer recognizes the 'mount', 'mountrw', and
- 'unmount' commands on Windows, since they didn't work on Windows anyway.
+ `wimlib-imagex' now supports being invoked as wimCOMMAND, where COMMAND
+ is the command as in `wimlib-imagex COMMAND'; for example, it can be
+ invoked as `wimapply' as an alternative to `wimlib-imagex apply'. The
+ appropriate hard links are created in UNIX installations of
+ `wimlib-imagex', while for the Windows distribution of `wimlib-imagex',
+ batch files that emulate this behavior are generated.
Security descriptors are now extracted correctly on Windows.
- `mkwinpeimg' now supports grabbing files from the WAIK supplement rather
- than the WAIK itself.
-
- The test suite no longer fails when run in a locale where the decimal
- separator is not a period.
-
- From the library, WIMLIB_PROGRESS_MSG_EXTRACT_DENTRY has been removed
- and WIMLIB_EXTRACT_FLAG_VERBOSE re-reserved for future use. Also,
- WIMLIB_PROGRESS_MSG_JOIN_STREAMS has been removed, but
- WIMLIB_PROGRESS_MSG_WRITE_STREAMS will be received instead and now
- provides WIM part numbers.
+ Fixed archiving DOS names in NTFS-3g capture mode.
The extraction code has been rewritten and it will now be easier to
support new features on all supported backends (currently Win32, UNIX,
and NTFS-3g). For example, hard-linked extraction mode (--hardlink) is
now supported on all backends, not just UNIX.
- The LZX compression and decompression code now compiles correctly on the
- ARM architecture (where 'char' is unsigned).
-
- wimlib_split() progress messages now report the total number of parts
- being written.
-
- Fixed storing DOS names in NTFS-3g capture mode.
-
- A few changes were made to the error codes returned by library routines.
+ `mkwinpeimg' now supports grabbing files from the WAIK supplement rather
+ than the WAIK itself.
- To make wimlib easier to use on Windows, wimlib_global_init() now
- automatically attempts to acquire additional privileges on Windows, so
- library clients need not do this (although they can provide a flag to
- get the old behavior and manage privileges themselves).
+ wimlib_global_init() now, by default, attempts to acquire additional
+ privileges on Windows, so library clients need not do this.
- This update bumps the shared library version number up to 9, since it
- doesn't quite maintain binary compatibility with previous releases.
+ This update bumps the shared library version number up to 9, since it is
+ not binary compatibible with previous releases.
Version 1.4.2:
Fixed bug in `wimlib-imagex export' that made it impossible to export an
most Windows software and may not be able to be deleted easily.
.SH SPLIT WIMS
You may use \fB@IMAGEX_PROGNAME@ 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).
-.PP
-Here's an example. The names for the split WIMs usually go something like:
+\fIWIMFILE\fR argument must specify the first part of the split WIM, while the
+additional parts of the split WIM must be specified in one or more
+\fB--ref\fR="\fIGLOB\fR" options. Since globbing is built into the \fB--ref\fR
+option, typically only one \fB--ref\fR option is necessary. For example, the
+names for the split WIM parts usually go something like:
.RS
.PP
.nf
present.
.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.
+File glob of additional WIMs or split WIM parts to reference resources from.
+See \fBSPLIT_WIMS\fR. This option can be specified multiple times. Note:
+\fIGLOB\fR is listed in quotes because it is interpreted by
+\fB@IMAGEX_PROGNAME@\fR and may need to be quoted to protect against shell
+expansion.
.TP
\fB--rpfix\fR, \fB--norpfix\fR
Set whether to fix targets of absolute symbolic links (reparse points in Windows
\fB@IMAGEX_PROGNAME@ optimize\fR.
.TP
\fB--ref\fR="\fIGLOB\fR"
-File glob of additional split WIM parts that are part of the split WIM being
-exported. See \fBSPLIT_WIMS\fR.
+File glob of additional WIMs or split WIM parts to reference resources from.
+See \fBSPLIT_WIMS\fR. This option can be specified multiple times. Note:
+\fIGLOB\fR is listed in quotes because it is interpreted by
+\fB@IMAGEX_PROGNAME@\fR and may need to be quoted to protect against shell
+expansion.
.TP
\fB--pipable\fR
Build, or rebuild, \fIDEST_WIMFILE\fR as a "pipable WIM" so that it can be
default behavior, unless \fIDEST_WIMFILE\fR already existed and was already
pipable, or if \fIDEST_WIMFILE\fR was "-" (standard output).
.SH SPLIT WIMS
-You may use \fB@IMAGEX_PROGNAME@ export\fR to export images from a split WIM. The
-\fISRC_WIMFILE\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 \fISRC_WIMFILE\fR as
-well).
-.PP
-Here's an example. The names for the split WIMs usually go something like:
+You may use \fB@IMAGEX_PROGNAME@ export\fR to export images from a split WIM.
+The \fISRC_WIMFILE\fR argument must specify the first part of the split WIM,
+while the additional parts of the split WIM must be specified in one or more
+\fB--ref\fR="\fIGLOB\fR" options. Since globbing is built into the \fB--ref\fR
+option, typically only one \fB--ref\fR option is necessary. For example, the
+names for the split WIM parts usually go something like:
.PP
.RS
.nf
present.
.TP
\fB--ref\fR="\fIGLOB\fR"
-File glob of additional split WIM parts that are part of the split WIM. See
-\fBSPLIT_WIMS\fR.
+File glob of additional WIMs or split WIM parts to reference resources from.
+See \fBSPLIT_WIMS\fR. Note: since \fIGLOB\fR is listed in quotes because it is
+interpreted by \fB@IMAGEX_PROGNAME@\fR and may need to be quoted to protect
+against shell expansion.
.TP
\fB--verbose\fR
This option no longer does anything but is reserved for future use.
made to a WIM mounted read-write will be discarded unless the \fB--commit\fR
flag is provided to \fB@IMAGEX_PROGNAME@ unmount\fR.
.SH SPLIT WIMS
-You may use \fB@IMAGEX_PROGNAME@ 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.
+You may use \fB@IMAGEX_PROGNAME@ 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.
.PP
-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).
+The \fIWIMFILE\fR argument must specify the first part of the split WIM, while
+the additional parts of the split WIM must be specified in one or more
+\fB--ref\fR="\fIGLOB\fR" options. Since globbing is built into the \fB--ref\fR
+option, typically only one \fB--ref\fR option is necessary. For example, the
+names for the split WIM parts usually go something like:
.PP
-Here's an example. The names for the split WIMs usually go something like:
.RS
-.PP
.nf
mywim.swm
mywim2.swm
mywim5.swm
.RE
.PP
-To mount the first image of this split WIM to the directory "dir", we would do:
+To mount the first image of this split WIM to the directory "dir", run:
.PP
.RS
@IMAGEX_PROGNAME@ mount mywim.swm 1 dir --ref="mywim*.swm"
If wimlib was configured using the \fB--without-fuse\fR flag, then the
\fB@IMAGEX_PROGNAME@ mount\fR, \fB@IMAGEX_PROGNAME@ mountrw\fR, and
\fB@IMAGEX_PROGNAME@ unmount\fR commands will not work. Also, these commands
-are not available in the Windows builds of wimlib.
+are not available in the Windows builds of \fB@IMAGEX_PROGNAME@\fR.
.PP
You can mount multiple images from a WIM file read-only at the same time, but
you can only mount one image at a time from a WIM read-write.
file attributes, unless this support was disabled when compiling wimlib. The
named data streams may be accessed through extended attributes named "user.*",
where the * is the name of the named data stream. See \fBsetfattr\fR (1) and
-\fBgetfattr\fR (1).
+\fBgetfattr\fR (1). Note that this is not an ideal interface, since named data
+streams may be larger than the maximum allowed extended attribute size.
.IP ""
If "windows", the named data streams will be accessible by specifying the
filename, then a colon, then the name of the named data stream; for example,
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 \fB@IMAGEX_PROGNAME@ mount\fR but not \fB@IMAGEX_PROGNAME@
-mountrw\fR. See \fBSPLIT_WIMS\fR.
+File glob of additional WIMs or split WIM parts to reference resources from.
+See \fBSPLIT_WIMS\fR. This option can be specified multiple times. Note:
+\fIGLOB\fR is listed in quotes because it is interpreted by
+\fB@IMAGEX_PROGNAME@\fR and may need to be quoted to protect against shell
+expansion.
.TP
\fB--staging-dir\fR=\fIDIR\fR
Store temporary staging files in a subdirectory of the directory \fIDIR\fR.
.PP
\fB@IMAGEX_PROGNAME@ unmount\fR runs in a separate process from the process that previously
ran \fB@IMAGEX_PROGNAME@ mount\fR, and these two processes communicate using POSIX message
-queues. See \fIsrc/mount_image.c\fR in the sources for details. Note: As of
-wimlib v1.2.1, \fB@IMAGEX_PROGNAME@ unmount\fR correctly fails with an error within a
-reasonable amount of time (1 second) if the filesystem daemon is abnormally
-terminated.
+queues. See \fIsrc/mount_image.c\fR in the sources for details.
.SH SEE ALSO
.BR @IMAGEX_PROGNAME@ (1)
typedef int (*wimlib_iterate_lookup_table_callback_t)(const struct wimlib_resource_entry *resource,
void *user_ctx);
+/**
+ * @name Directory tree iteration flags
+ *
+ * The following flags can be passed to wimlib_iterate_dir_tree().
+ *
+ * @{
+ */
+
/** For wimlib_iterate_dir_tree(): Iterate recursively on children rather than
* just on the specified path. */
#define WIMLIB_ITERATE_DIR_TREE_FLAG_RECURSIVE 0x00000001
-/*****************************
- * WIMLIB_ADD_FLAG_*
- *****************************/
+/**
+ * @name Add flags
+ *
+ * The following flags can be passed to wimlib_add_image(),
+ * wimlib_add_image_multisource(), and add commands passed to
+ * wimlib_update_image().
+ *
+ * @{
+ */
/** Directly capture a NTFS volume rather than a generic directory. This flag
* cannot be combined with ::WIMLIB_ADD_FLAG_DEREFERENCE or
WIMLIB_ADD_FLAG_NO_UNSUPPORTED_EXCLUDE
#define WIMLIB_ADD_IMAGE_FLAG_WINCONFIG WIMLIB_ADD_FLAG_WINCONFIG
-/******************************
- * WIMLIB_DELETE_FLAG_*
- ******************************/
+/**
+ * @name Delete flags
+ *
+ * The following flags can be specified in delete commands passed to
+ * wimlib_update_image().
+ *
+ * @{
+ */
/** Do not issue an error if the path to delete does not exist. */
#define WIMLIB_DELETE_FLAG_FORCE 0x00000001
* issued if the path to delete is a directory. */
#define WIMLIB_DELETE_FLAG_RECURSIVE 0x00000002
-/******************************
- * WIMLIB_EXPORT_FLAG_*
- ******************************/
+/**
+ * @name Export flags
+ *
+ * The following flags can be passed to wimlib_export_image().
+ *
+ * @{
+ */
-/** See documentation for wimlib_export_image(). */
+/**
+ * If a single image is being exported, mark it bootable in the destination WIM.
+ * Alternatively, if ::WIMLIB_ALL_IMAGES is specified as the image to export,
+ * the image in the source WIM (if any) that is marked as bootable is also
+ * marked as bootable in the destination WIM.
+ */
#define WIMLIB_EXPORT_FLAG_BOOT 0x00000001
-/******************************
- * WIMLIB_EXTRACT_FLAG_*
- ******************************/
+/** Give the exported image(s) no names. Avoids problems with image name
+ * collisions.
+ */
+#define WIMLIB_EXPORT_FLAG_NO_NAMES 0x00000002
+
+/** Give the exported image(s) no descriptions. */
+#define WIMLIB_EXPORT_FLAG_NO_DESCRIPTIONS 0x00000004
+
+/**
+ * @name Extract flags
+ *
+ * The following flags can be passed to wimlib_extract_image(),
+ * wimlib_extract_files(), and wimlib_extract_image_from_pipe().
+ *
+ * @{
+ */
/** Extract the image directly to a NTFS volume rather than a generic directory.
* This mode is only available if wimlib was compiled with libntfs-3g support;
* behavior is currently less than satisfactory. Do not use (yet). */
#define WIMLIB_EXTRACT_FLAG_RESUME 0x00010000
-/******************************
- * WIMLIB_MOUNT_FLAG_*
- ******************************/
+/**
+ * @name Mount flags
+ *
+ * The following flags can be passed to wimlib_mount_image().
+ *
+ * @{
+ */
/** Mount the WIM image read-write rather than the default of read-only. */
#define WIMLIB_MOUNT_FLAG_READWRITE 0x00000001
* allow_other option to FUSE mount) */
#define WIMLIB_MOUNT_FLAG_ALLOW_OTHER 0x00000040
-/******************************
- * WIMLIB_OPEN_FLAG_*
- ******************************/
+/**
+ * @name Open flags
+ *
+ * The following flags can be passed to wimlib_open_wim() and several other
+ * functions such as wimlib_join().
+ * @{
+ */
/** Verify the WIM contents against the WIM's integrity table, if present. This
* causes the raw data of the WIM file, divided into 10 MB chunks, to be
* an error sooner rather than later. */
#define WIMLIB_OPEN_FLAG_WRITE_ACCESS 0x00000004
-/******************************
- * WIMLIB_UNMOUNT_FLAG_*
- ******************************/
+/**
+ * @name Unmount flags
+ *
+ * The following flags can be passed to wimlib_unmount_image().
+ * @{
+ */
/** See ::WIMLIB_WRITE_FLAG_CHECK_INTEGRITY. */
#define WIMLIB_UNMOUNT_FLAG_CHECK_INTEGRITY 0x00000001
/** Do a "lazy" unmount (detach filesystem immediately, even if busy). */
#define WIMLIB_UNMOUNT_FLAG_LAZY 0x00000010
-/******************************
- * WIMLIB_UPDATE_FLAG_*
- ******************************/
+/**
+ * @name Update flags
+ *
+ * The following flags can be passed to wimlib_update_image().
+ * @{
+ */
/** Send ::WIMLIB_PROGRESS_MSG_UPDATE_BEGIN_COMMAND and
* ::WIMLIB_PROGRESS_MSG_UPDATE_END_COMMAND messages. */
#define WIMLIB_UPDATE_FLAG_SEND_PROGRESS 0x00000001
-/******************************
- * WIMLIB_WRITE_FLAG_*
- ******************************/
+/**
+ * @name Write flags
+ *
+ * The following flags can be passed to wimlib_write(), wimlib_overwrite(),
+ * wimlib_write_to_fd(), and several other functions such as wimlib_join().
+ * @{
+ */
/** Include an integrity table in the WIM.
*
* set the readonly flag on the on-disk WIM file. */
#define WIMLIB_WRITE_FLAG_IGNORE_READONLY_FLAG 0x00000100
-/******************************
- * WIMLIB_INIT_FLAG_*
- ******************************/
+/**
+ * @name Init flags
+ *
+ * The following flags can be passed to wimlib_global_init().
+ */
/** Assume that strings are represented in UTF-8, even if this is not the
* locale's character encoding. This flag is ignored on Windows, where wimlib
*/
#define WIMLIB_INIT_FLAG_STRICT_APPLY_PRIVILEGES 0x00000008
+/**
+ * @name Resource reference flags
+ *
+ * The following flags can be passed to wimlib_reference_resource_files() and
+ * wimlib_reference_resources().
+ */
+
+/** wimlib_reference_resource_files() only: Enable shell-style filename
+ * globbing. */
+#define WIMLIB_REF_FLAG_GLOB_ENABLE 0x00000001
+
+/** wimlib_reference_resource_files() only: Issue an error
+ * (::WIMLIB_ERR_GLOB_HAD_NO_MATCHES) if a glob did not match any files. The
+ * default behavior without this flag is to issue no error at that point, but
+ * then attempt to open the glob as a literal path, which of course will fail
+ * anyway if no file exists at that path. No effect if
+ * ::WIMLIB_REF_FLAG_GLOB_ENABLE is not also specified. */
+#define WIMLIB_REF_FLAG_GLOB_ERR_ON_NOMATCH 0x00000002
+
+/**
+ * @}
+ */
+
/** Specification of an update to perform on a WIM image. */
struct wimlib_update_command {
WIMLIB_ERR_FORK,
WIMLIB_ERR_FUSE,
WIMLIB_ERR_FUSERMOUNT,
+ WIMLIB_ERR_GLOB_HAD_NO_MATCHES,
WIMLIB_ERR_ICONV_NOT_AVAILABLE,
WIMLIB_ERR_IMAGE_COUNT,
WIMLIB_ERR_IMAGE_NAME_COLLISION,
WIMLIB_ERR_INVALID_PIPABLE_WIM,
WIMLIB_ERR_INVALID_REPARSE_DATA,
WIMLIB_ERR_INVALID_RESOURCE_HASH,
- WIMLIB_ERR_INVALID_SECURITY_DATA,
WIMLIB_ERR_INVALID_UNMOUNT_MESSAGE,
WIMLIB_ERR_INVALID_UTF16_STRING,
WIMLIB_ERR_INVALID_UTF8_STRING,
WIMLIB_ERR_IS_DIRECTORY,
WIMLIB_ERR_LIBXML_UTF16_HANDLER_NOT_AVAILABLE,
WIMLIB_ERR_LINK,
+ WIMLIB_ERR_METADATA_NOT_FOUND,
WIMLIB_ERR_MKDIR,
WIMLIB_ERR_MQUEUE,
WIMLIB_ERR_NOMEM,
* flag.
*
* This function can additionally return ::WIMLIB_ERR_DECOMPRESSION,
- * ::WIMLIB_ERR_INVALID_METADATA_RESOURCE, ::WIMLIB_ERR_NOMEM,
- * ::WIMLIB_ERR_READ, or ::WIMLIB_ERR_UNEXPECTED_END_OF_FILE, all of which
- * indicate failure (for different reasons) to read the metadata resource for an
- * image that needed to be deleted.
+ * ::WIMLIB_ERR_INVALID_METADATA_RESOURCE, ::WIMLIB_ERR_METADATA_NOT_FOUND,
+ * ::WIMLIB_ERR_NOMEM, ::WIMLIB_ERR_READ, or
+ * ::WIMLIB_ERR_UNEXPECTED_END_OF_FILE, all of which indicate failure (for
+ * different reasons) to read the metadata resource for an image that needed to
+ * be deleted.
*/
extern int
wimlib_delete_image(WIMStruct *wim, int image);
* Pointer to the ::WIMStruct for a stand-alone WIM or part 1 of a split
* WIM that contains the image(s) being exported.
* @param src_image
- * The image to export from @p src_wim. Can be the number of an image, or
- * ::WIMLIB_ALL_IMAGES to export all images.
+ * The image to export from @p src_wim, as either a 1-based image index to
+ * export a single image, or ::WIMLIB_ALL_IMAGES to export all images.
* @param dest_wim
- * Pointer to the ::WIMStruct for a WIM file that will receive the images
- * being exported.
+ * Pointer to the ::WIMStruct for a WIM that will receive the images being
+ * exported.
* @param dest_name
- * The name to give the exported image in the new WIM file. If left @c
- * NULL, the name from @p src_wim is used. This parameter must be left @c
- * NULL if @p src_image is ::WIMLIB_ALL_IMAGES and @p src_wim contains more
- * than one image; in that case, the names are all taken from the @p
- * src_wim. (This is allowed even if one or more images being exported has
- * no name.)
+ * For single-image exports, the name to give the exported image in @p
+ * dest_wim. If left @c NULL, the name from @p src_wim is used. For
+ * ::WIMLIB_ALL_IMAGES exports, this parameter must be left @c NULL; in
+ * that case, the names are all taken from @p src_wim. This parameter is
+ * overridden by ::WIMLIB_EXPORT_FLAG_NO_NAMES.
* @param dest_description
- * The description to give the exported image in the new WIM file. If left
- * @c NULL, the description from the @p src_wim is used. This parameter must
- * be left @c NULL if @p src_image is ::WIMLIB_ALL_IMAGES and @p src_wim contains
- * more than one image; in that case, the descriptions are all taken from
- * @p src_wim. (This is allowed even if one or more images being exported
- * has no description.)
+ * For single-image exports, the description to give the exported image in
+ * the new WIM file. If left @c NULL, the description from @p src_wim is
+ * used. For ::WIMLIB_ALL_IMAGES exports, this parameter must be left @c
+ * NULL; in that case, the description are all taken from @p src_wim. This
+ * parameter is overridden by ::WIMLIB_EXPORT_FLAG_NO_DESCRIPTIONS.
* @param export_flags
- * ::WIMLIB_EXPORT_FLAG_BOOT if the image being exported is to be made
- * bootable, or 0 if which image is marked as bootable in the destination
- * WIM is to be left unchanged. If @p src_image is ::WIMLIB_ALL_IMAGES and
- * there are multiple images in @p src_wim, specifying
- * ::WIMLIB_EXPORT_FLAG_BOOT is valid only if one of the exported images is
- * currently marked as bootable in @p src_wim; if that is the case, then
- * that image is marked as bootable in the destination WIM.
- * @param additional_swms
- * Array of pointers to the ::WIMStruct for each additional part in the
- * split WIM. Ignored if @p 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
- * @p wim parameter.
- * @param num_additional_swms
- * Number of additional WIM parts provided in the @p 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.
+ * Bitwise OR of flags prefixed with WIMLIB_EXPORT_FLAG.
* @param progress_func
- * If non-NULL, a function that will be called periodically with the
- * progress of the current operation.
+ * Currently ignored, but reserved for a function that will be called with
+ * information about the operation. Use NULL if no additional information
+ * is desired.
*
* @return 0 on success; nonzero on error.
* @retval ::WIMLIB_ERR_IMAGE_NAME_COLLISION
* One or more of the names being given to an exported image was already in
* use in the destination WIM.
* @retval ::WIMLIB_ERR_INVALID_IMAGE
- * @p src_image does not exist in @p src_wim.
+ * @p src_image does not exist in @p src_wim and was not
+ * ::WIMLIB_ALL_IMAGES.
* @retval ::WIMLIB_ERR_INVALID_PARAM
- * ::WIMLIB_EXPORT_FLAG_BOOT was specified in @p flags, @p src_image was
- * ::WIMLIB_ALL_IMAGES, @p src_wim contains multiple images, and no images in
- * @p src_wim are marked as bootable; or @p dest_name and/or @p
- * dest_description were non-<code>NULL</code>, @p src_image was
- * ::WIMLIB_ALL_IMAGES, and @p src_wim contains multiple images.
+ * @p src_wim and/or @p dest_wim were @c NULL; or @p src_image was
+ * ::WIMLIB_ALL_IMAGES but @p dest_name and/or @p dest_description were not
+ * @c NULL.
+ * @retval ::WIMLIB_ERR_METADATA_NOT_FOUND
+ * Either @p src_wim or @p dest_wim did not contain metadata resources; for
+ * example, one of them was a non-first part of a split WIM.
* @retval ::WIMLIB_ERR_NOMEM
* Failed to allocate needed memory.
- * @retval ::WIMLIB_ERR_SPLIT_INVALID
- * The source 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
- * split WIM, there are duplicate parts, or not all the parts are in fact
- * from the same split WIM.
+ * @retval ::WIMLIB_ERR_RESOURCE_NOT_FOUND
+ * A resource that needed to be exported could not be found in either the
+ * source or destination WIMs. This error can occur if, for example, @p
+ * src_wim is part of a split WIM but resources from the other split WIM
+ * parts were not referenced with wimlib_reference_resources() or
+ * wimlib_reference_resource_files().
* @retval ::WIMLIB_ERR_WIM_IS_READONLY
* @p dest_wim is considered read-only because of any of the reasons
* mentioned in the documentation for the ::WIMLIB_OPEN_FLAG_WRITE_ACCESS
* flag.
*
* This function can additionally return ::WIMLIB_ERR_DECOMPRESSION,
- * ::WIMLIB_ERR_INVALID_METADATA_RESOURCE, ::WIMLIB_ERR_NOMEM,
- * ::WIMLIB_ERR_READ, or ::WIMLIB_ERR_UNEXPECTED_END_OF_FILE, all of which
- * indicate failure (for different reasons) to read the metadata resource for an
- * image in @p src_wim that needed to be exported.
+ * ::WIMLIB_ERR_INVALID_METADATA_RESOURCE, ::WIMLIB_ERR_METADATA_NOT_FOUND,
+ * ::WIMLIB_ERR_NOMEM, ::WIMLIB_ERR_READ, or
+ * ::WIMLIB_ERR_UNEXPECTED_END_OF_FILE, all of which indicate failure (for
+ * different reasons) to read the metadata resource for an image in @p src_wim
+ * that needed to be exported.
*/
extern int
wimlib_export_image(WIMStruct *src_wim, int src_image,
const wimlib_tchar *dest_name,
const wimlib_tchar *dest_description,
int export_flags,
- WIMStruct **additional_swms,
- unsigned num_additional_swms,
wimlib_progress_func_t progress_func);
/**
* been specified in the ::wimlib_extract_command.extract_flags member in
* each extraction command, in combination with any flags already present.
*
- * @param additional_swms
- * Array of pointers to the ::WIMStruct for each additional part in the
- * split WIM. Ignored if @p 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
- * @p wim parameter.
- *
- * @param num_additional_swms
- * Number of additional WIM parts provided in the @p 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.
- *
* @param progress_func
* If non-NULL, a function that will be called periodically with the
* progress of the current operation.
const struct wimlib_extract_command *cmds,
size_t num_cmds,
int default_extract_flags,
- WIMStruct **additional_swms,
- unsigned num_additional_swms,
wimlib_progress_func_t progress_func);
/**
* path to the unmounted NTFS volume to extract the image to.
* @param extract_flags
* Bitwise OR of the flags prefixed with WIMLIB_EXTRACT_FLAG.
- * @param additional_swms
- * Array of pointers to the ::WIMStruct for each additional part in the
- * split WIM. Ignored if @p 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
- * @p wim parameter.
- * @param num_additional_swms
- * Number of additional WIM parts provided in the @p 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.
- *
* @param progress_func
* If non-NULL, a function that will be called periodically with the
* progress of the current operation.
*
* @return 0 on success; nonzero on error.
* @retval ::WIMLIB_ERR_DECOMPRESSION
- * Failed to decompress a resource to be extracted, or failed to decompress
- * a needed metadata resource.
+ * Failed to decompress a resource to be extracted.
* @retval ::WIMLIB_ERR_INVALID_PARAM
* Both ::WIMLIB_EXTRACT_FLAG_HARDLINK and ::WIMLIB_EXTRACT_FLAG_SYMLINK
* were specified in @p extract_flags; or both
* ::WIMLIB_EXTRACT_FLAG_RESUME was specified in @p extract_flags; or if
* ::WIMLIB_EXTRACT_FLAG_NTFS was specified in @p extract_flags and
* @p image was ::WIMLIB_ALL_IMAGES.
- * @retval ::WIMLIB_ERR_INVALID_METADATA_RESOURCE
- * The metadata resource for an image being extracted was invalid.
* @retval ::WIMLIB_ERR_INVALID_RESOURCE_HASH
* The SHA1 message digest of an extracted stream did not match the SHA1
* message digest given in the WIM file.
* @retval ::WIMLIB_ERR_SET_TIMESTAMPS
* Failed to set timestamps on a file (only if
* ::WIMLIB_EXTRACT_FLAG_STRICT_TIMESTAMPS was specified in @p extract_flags).
- * @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_UNEXPECTED_END_OF_FILE
* Unexpected end-of-file occurred when reading data from the WIM file
* associated with @p wim.
* ::WIMLIB_EXTRACT_FLAG_NTFS was not specified in @p extract_flags.
* @retval ::WIMLIB_ERR_WRITE
* Failed to write data to a file being extracted.
+ *
+ * This function can additionally return ::WIMLIB_ERR_DECOMPRESSION,
+ * ::WIMLIB_ERR_INVALID_METADATA_RESOURCE, ::WIMLIB_ERR_METADATA_NOT_FOUND,
+ * ::WIMLIB_ERR_NOMEM, ::WIMLIB_ERR_READ, or
+ * ::WIMLIB_ERR_UNEXPECTED_END_OF_FILE, all of which indicate failure (for
+ * different reasons) to read the metadata resource for an image that needed to
+ * be extracted.
*/
extern int
wimlib_extract_image(WIMStruct *wim, int image,
const wimlib_tchar *target,
int extract_flags,
- WIMStruct **additional_swms,
- unsigned num_additional_swms,
wimlib_progress_func_t progress_func);
/**
* Failed to allocate memory needed to create a ::wimlib_dir_entry.
*
* This function can additionally return ::WIMLIB_ERR_DECOMPRESSION,
- * ::WIMLIB_ERR_INVALID_METADATA_RESOURCE, ::WIMLIB_ERR_NOMEM,
- * ::WIMLIB_ERR_READ, or ::WIMLIB_ERR_UNEXPECTED_END_OF_FILE, all of which
- * indicate failure (for different reasons) to read the metadata resource for an
- * image over which iteration needed to be done.
+ * ::WIMLIB_ERR_INVALID_METADATA_RESOURCE, ::WIMLIB_ERR_METADATA_NOT_FOUND,
+ * ::WIMLIB_ERR_NOMEM, ::WIMLIB_ERR_READ, or
+ * ::WIMLIB_ERR_UNEXPECTED_END_OF_FILE, all of which indicate failure (for
+ * different reasons) to read the metadata resource for an image over which
+ * iteration needed to be done.
*/
extern int
wimlib_iterate_dir_tree(WIMStruct *wim, int image, const wimlib_tchar *path,
* The path to an existing empty directory to mount the image on.
* @param mount_flags
* Bitwise OR of the flags prefixed with WIMLIB_MOUNT_FLAG.
- * @param additional_swms
- * Array of pointers to the ::WIMStruct for each additional part in the
- * split WIM. Ignored if @p 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
- * @p wim parameter.
- * @param num_additional_swms
- * Number of additional WIM parts provided in the @p 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.
* @param staging_dir
* If non-NULL, the name of a directory in which the staging directory will
* be created. Ignored if ::WIMLIB_MOUNT_FLAG_READWRITE is not specified
* the on-disk WIM file could not be acquired because another thread or
* process has mounted an image from the WIM read-write or is currently
* modifying the WIM in-place.
- * @retval ::WIMLIB_ERR_DECOMPRESSION
- * Could not decompress the metadata resource for @p image in @p wim.
* @retval ::WIMLIB_ERR_FUSE
* A non-zero status was returned by @c fuse_main().
* @retval ::WIMLIB_ERR_INVALID_IMAGE
* @p image does not specify an existing, single image in @p wim.
- * @retval ::WIMLIB_ERR_INVALID_METADATA_RESOURCE
- * The metadata resource for @p image is invalid.
* @retval ::WIMLIB_ERR_INVALID_PARAM
* @p image is shared among multiple ::WIMStruct's as a result of a call to
* wimlib_export_image(), or @p image has been added with
* @retval ::WIMLIB_ERR_MKDIR
* ::WIMLIB_MOUNT_FLAG_READWRITE was specified in @p mount_flags, but the
* staging directory could not be created.
- * @retval ::WIMLIB_ERR_NOMEM
- * Failed to allocate needed memory.
* @retval ::WIMLIB_ERR_NOTDIR
* Could not determine the current working directory.
- * @retval ::WIMLIB_ERR_READ
- * Failed to read data from the WIM file associated with @p wim.
* @retval ::WIMLIB_ERR_RESOURCE_NOT_FOUND
* One of the dentries in the image referenced a stream not present in the
* WIM's lookup table (or in any of the lookup tables of the split WIM
* parts).
- * @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_WIM_IS_READONLY
* ::WIMLIB_MOUNT_FLAG_READWRITE was specified in @p mount_flags, but @p
* wim is considered read-only because of any of the reasons mentioned in
* the documentation for the ::WIMLIB_OPEN_FLAG_WRITE_ACCESS flag.
- * @retval ::WIMLIB_ERR_UNEXPECTED_END_OF_FILE
- * Unexpected end-of-file occurred while reading data from the WIM file
- * associated with @p wim.
* @retval ::WIMLIB_ERR_UNSUPPORTED
* Mounting is not supported, either because the platform is Windows, or
* because the platform is UNIX-like and wimlib was compiled with @c
* --without-fuse.
+ *
+ * This function can additionally return ::WIMLIB_ERR_DECOMPRESSION,
+ * ::WIMLIB_ERR_INVALID_METADATA_RESOURCE, ::WIMLIB_ERR_METADATA_NOT_FOUND,
+ * ::WIMLIB_ERR_NOMEM, ::WIMLIB_ERR_READ, or
+ * ::WIMLIB_ERR_UNEXPECTED_END_OF_FILE, all of which indicate failure (for
+ * different reasons) to read the metadata resource for the image to mount.
*/
extern int
wimlib_mount_image(WIMStruct *wim,
int image,
const wimlib_tchar *dir,
int mount_flags,
- WIMStruct **additional_swms,
- unsigned num_additional_swms,
const wimlib_tchar *staging_dir);
/**
extern int
wimlib_print_metadata(WIMStruct *wim, int image) _wimlib_deprecated;
+/**
+ * Reference resources from other WIM files or split WIM parts. This function
+ * can be used on WIMs that are not standalone, such as split or "delta" WIMs,
+ * to load needed resources (that is, "streams" keyed by SHA1 message digest)
+ * from other files, before calling a function such as wimlib_extract_image()
+ * that requires the resources to be present.
+ *
+ * @param wim
+ * The ::WIMStruct for a WIM that contains metadata resources, but is not
+ * necessarily "standalone". In the case of split WIMs, this should be the
+ * first part, since only the first part contains the metadata resources.
+ * In the case of delta WIMs, this should be the delta WIM rather than the
+ * WIM on which it is based.
+ * @param resource_wimfiles_or_globs
+ * Array of paths to WIM files and/or split WIM parts to reference.
+ * Alternatively, when ::WIMLIB_REF_FLAG_GLOB_ENABLE is specified in @p
+ * ref_flags, these are treated as globs rather than literal paths. That
+ * is, using this function you can specify zero or more globs, each of
+ * which expands to one or more literal paths.
+ * @param count
+ * Number of entries in @p resource_wimfiles_or_globs.
+ * @param ref_flags
+ * Bitwise OR of ::WIMLIB_REF_FLAG_GLOB_ENABLE and/or
+ * ::WIMLIB_REF_FLAG_GLOB_ERR_ON_NOMATCH.
+ * @param open_flags
+ * Additional open flags, such as ::WIMLIB_OPEN_FLAG_CHECK_INTEGRITY, to
+ * pass to internal calls to wimlib_open_wim() on the reference files.
+ * Note: ::WIMLIB_OPEN_FLAG_SPLIT_OK will be supplied regardless of this
+ * parameter.
+ * @param progress_func
+ * Passed to internal calls to wimlib_open_wim() on the reference files.
+ *
+ * @return 0 on success; nonzero on error.
+ *
+ * @retval ::WIMLIB_ERR_GLOB_HAD_NO_MATCHES
+ * One of the specified globs did not match any paths (only with both
+ * ::WIMLIB_REF_FLAG_GLOB_ENABLE and ::WIMLIB_REF_FLAG_GLOB_ERR_ON_NOMATCH
+ * specified in @p ref_flags).
+ * @retval ::WIMLIB_ERR_NOMEM
+ * Failed to allocate memory.
+ * @retval ::WIMLIB_ERR_READ
+ * I/O or permissions error while processing a file glob.
+ *
+ * This function can additionally return most values that can be returned by
+ * wimlib_open_wim().
+ */
+extern int
+wimlib_reference_resource_files(WIMStruct *wim,
+ const wimlib_tchar * const *resource_wimfiles_or_globs,
+ unsigned count,
+ int ref_flags,
+ int open_flags,
+ wimlib_progress_func_t progress_func);
+
+/**
+ * Similar to wimlib_reference_resource_files(), but operates at a lower level
+ * where the caller must open the ::WIMStruct for each referenced file itself.
+ *
+ * @param wim
+ * The ::WIMStruct for a WIM that contains metadata resources, but is not
+ * necessarily "standalone". In the case of split WIMs, this should be the
+ * first part, since only the first part contains the metadata resources.
+ * @param resource_wims
+ * Array of pointers to the ::WIMStruct's for additional resource WIMs or
+ * split WIM parts to reference.
+ * @param num_resource_wims
+ * Number of entries in @p resource_wims.
+ * @param ref_flags
+ * Currently ignored (set to 0).
+ *
+ * @return 0 on success; nonzero on error. On success, the ::WIMStruct's
+ * specified in @p resource_wims should be considered "don't touch" until either
+ * wimlib_free() is called on @p wim, or wimlib_unreference_resources() is
+ * called to unreference them.
+ *
+ * @retval ::WIMLIB_ERR_INVALID_PARAM
+ * @p wim was @c NULL, or @p num_resource_wims was nonzero but @p
+ * resource_wims was @c NULL, or @p wim did not contain metadata resources,
+ * or an entry in @p resource_wims was @p NULL, or an entry in @p
+ * resource_wims was already referenced by a call to this function without
+ * a corresponding call to wimlib_free() on the metadata WIM, or
+ * wimlib_unreference_resources().
+ */
+extern int
+wimlib_reference_resources(WIMStruct *wim, WIMStruct **resource_wims,
+ unsigned num_resource_wims, int ref_flags);
+
/**
* Declares that a newly added image is mostly the same as a prior image, but
* captured at a later point in time, possibly with some modifications in the
* wimlib_add_image()), but before writing the updated WIM file (e.g. with
* wimlib_overwrite()).
*
- * @p wim
+ * @param wim
* Pointer to the ::WIMStruct for a WIM.
- * @p new_image
+ * @param new_image
* 1-based index in the WIM of the newly added image. This image can have
* been added with wimlib_add_image() or wimlib_add_image_multisource(), or
* wimlib_add_empty_image() followed by wimlib_update_image().
- * @p template_image
+ * @param template_image
* 1-based index in the WIM of a template image that reflects a prior state
* of the directory tree being captured.
- * @p flags
+ * @param flags
* Reserved; must be 0.
- * @p progress_func
+ * @param progress_func
* Currently ignored, but reserved for a function that will be called with
* information about the operation. Use NULL if no additional information
* is desired.
* @retval ::WIMLIB_ERR_INVALID_IMAGE
* @p new_image and/or @p template_image were not a valid image indices in
* the WIM.
+ * @retval ::WIMLIB_ERR_METADATA_NOT_FOUND
+ * The specified ::WIMStruct did not actually contain the metadata resource
+ * for the new or template image; for example, it was a non-first part of a
+ * split WIM.
* @retval ::WIMLIB_ERR_NOMEM
* Failed to allocate needed memory.
* @retval ::WIMLIB_ERR_INVALID_PARAM
* an image that had not been modified since opening the WIM.
*
* This function can additionally return ::WIMLIB_ERR_DECOMPRESSION,
- * ::WIMLIB_ERR_INVALID_METADATA_RESOURCE, ::WIMLIB_ERR_NOMEM,
- * ::WIMLIB_ERR_READ, or ::WIMLIB_ERR_UNEXPECTED_END_OF_FILE, all of which
- * indicate failure (for different reasons) to read the metadata resource for
- * the template image.
+ * ::WIMLIB_ERR_INVALID_METADATA_RESOURCE, ::WIMLIB_ERR_METADATA_NOT_FOUND,
+ * ::WIMLIB_ERR_NOMEM, ::WIMLIB_ERR_READ, or
+ * ::WIMLIB_ERR_UNEXPECTED_END_OF_FILE, all of which indicate failure (for
+ * different reasons) to read the metadata resource for the template image.
*/
extern int
wimlib_reference_template_image(WIMStruct *wim, int new_image,
* @p wim is considered read-only because of any of the reasons mentioned
* in the documentation for the ::WIMLIB_OPEN_FLAG_WRITE_ACCESS flag.
*/
-extern int wimlib_set_image_name(WIMStruct *wim, int image,
- const wimlib_tchar *name);
+extern int
+wimlib_set_image_name(WIMStruct *wim, int image, const wimlib_tchar *name);
/**
* Set the functions that wimlib uses to allocate and free memory.
* codes that can be returned by wimlib_write() as well as the following error
* codes:
*
- * @retval ::WIMLIB_ERR_SPLIT_UNSUPPORTED
- * @p wim was not part 1 of a stand-alone WIM.
* @retval ::WIMLIB_ERR_INVALID_PARAM
* @p swm_name was not a nonempty string, or @p part_size was 0.
*
int unmount_flags,
wimlib_progress_func_t progress_func);
+/**
+ * Unreferences resources previously referenced with
+ * wimlib_reference_resources().
+ *
+ * Calling this is not necessary (or even possible) if the higher-level function
+ * wimlib_reference_resource_files() is used.
+ *
+ * @param wim
+ * See corresponding parameter to wimlib_reference_resources().
+ * @param resource_wims
+ * See corresponding parameter to wimlib_reference_resources().
+ * @param num_resource_wims
+ * See corresponding parameter to wimlib_reference_resources().
+ *
+ * @return 0 on success; nonzero on error.
+ *
+ * @retval ::WIMLIB_ERR_INVALID_PARAM
+ * Not all entries in @p resource_wims specify valid ::WIMStruct's that are
+ * referenced by @p wim.
+ */
+extern int
+wimlib_unreference_resources(WIMStruct *wim, WIMStruct **resource_wims,
+ unsigned num_resource_wims);
+
/**
* Update a WIM image by adding, deleting, and/or renaming files or directories.
*
* update commands may have been executed. No individual update command will
* have been partially executed. Possible error codes include:
*
- * @retval ::WIMLIB_ERR_DECOMPRESSION
- * Failed to decompress the metadata resource from @p image in @p wim.
* @retval ::WIMLIB_ERR_INVALID_CAPTURE_CONFIG
* The capture configuration structure specified for an add command was
* invalid.
* @retval ::WIMLIB_ERR_INVALID_REPARSE_DATA
* (Windows only): While executing an add command, tried to capture a
* reparse point with invalid data.
- * @retval ::WIMLIB_ERR_INVALID_RESOURCE_SIZE
- * The metadata resource for @p image in @p wim is invalid.
- * @retval ::WIMLIB_ERR_INVALID_SECURITY_DATA
- * The security data for image @p image in @p wim is invalid.
* @retval ::WIMLIB_ERR_IS_DIRECTORY
* A delete command without ::WIMLIB_DELETE_FLAG_RECURSIVE specified was
* for a WIM path that corresponded to a directory; or, a rename command
* WIM path that did not exist; or, a rename command attempted to rename a
* file that does not exist.
* @retval ::WIMLIB_ERR_READ
- * Failed to read the metadata resource for @p image in @p wim; or, while
- * executing an add command, failed to read data from a file or directory
- * to be captured.
+ * While executing an add command, failed to read data from a file or
+ * directory to be captured.
* @retval ::WIMLIB_ERR_READLINK
* While executing an add command, failed to read the target of a symbolic
* link or junction point.
* @retval ::WIMLIB_ERR_REPARSE_POINT_FIXUP_FAILED
* (Windows only) Failed to perform a reparse point fixup because of
* problems with the data of a reparse point.
- * @retval ::WIMLIB_ERR_UNSUPPORTED_FILE
- * While executing an add command, attempted to capture a file that was not
- * a supported file type (e.g. a device file). Only if
- * ::WIMLIB_ADD_FLAG_NO_UNSUPPORTED_EXCLUDE specified in @p the add_flags
- * for an update command.
* @retval ::WIMLIB_ERR_STAT
* While executing an add command, failed to get attributes for a file or
* directory.
* or, the platform is Windows and either the ::WIMLIB_ADD_FLAG_UNIX_DATA
* or the ::WIMLIB_ADD_FLAG_DEREFERENCE flags were specified in the @p
* add_flags for an update command.
+ * @retval ::WIMLIB_ERR_UNSUPPORTED_FILE
+ * While executing an add command, attempted to capture a file that was not
+ * a supported file type (e.g. a device file). Only if
+ * ::WIMLIB_ADD_FLAG_NO_UNSUPPORTED_EXCLUDE specified in @p the add_flags
+ * for an update command.
* @retval ::WIMLIB_ERR_WIM_IS_READONLY
* The WIM file is considered read-only because of any of the reasons
* mentioned in the documentation for the ::WIMLIB_OPEN_FLAG_WRITE_ACCESS
* flag.
+ *
+ * This function can additionally return ::WIMLIB_ERR_DECOMPRESSION,
+ * ::WIMLIB_ERR_INVALID_METADATA_RESOURCE, ::WIMLIB_ERR_METADATA_NOT_FOUND,
+ * ::WIMLIB_ERR_NOMEM, ::WIMLIB_ERR_READ, or
+ * ::WIMLIB_ERR_UNEXPECTED_END_OF_FILE, all of which indicate failure (for
+ * different reasons) to read the metadata resource for an image that needed to
+ * be updated.
*/
extern int
wimlib_update_image(WIMStruct *wim,
*
* @return 0 on success; nonzero on error.
*
- * @retval ::WIMLIB_ERR_DECOMPRESSION
- * Failed to decompress a metadata or file resource in @p wim.
* @retval ::WIMLIB_ERR_INVALID_IMAGE
* @p image does not specify a single existing image in @p wim, and is not
* ::WIMLIB_ALL_IMAGES.
* message digest check.
* @retval ::WIMLIB_ERR_INVALID_PARAM
* @p path was @c NULL.
- * @retval ::WIMLIB_ERR_INVALID_METADATA_RESOURCE
- * The metadata resource for @p image in @p wim is invalid.
* @retval ::WIMLIB_ERR_NOMEM
* Failed to allocate needed memory.
* @retval ::WIMLIB_ERR_OPEN
* files.
* @retval ::WIMLIB_ERR_WRITE
* An error occurred when trying to write data to the new WIM file.
+ *
+ * This function can additionally return ::WIMLIB_ERR_DECOMPRESSION,
+ * ::WIMLIB_ERR_INVALID_METADATA_RESOURCE, ::WIMLIB_ERR_METADATA_NOT_FOUND,
+ * ::WIMLIB_ERR_NOMEM, ::WIMLIB_ERR_READ, or
+ * ::WIMLIB_ERR_UNEXPECTED_END_OF_FILE, all of which indicate failure (for
+ * different reasons) to read the metadata resource for an image that needed to
+ * be written.
*/
extern int
wimlib_write(WIMStruct *wim,
--- /dev/null
+#ifndef _WIMLIB_GLOB_H
+#define _WIMLIB_GLOB_H
+
+#ifndef __WIN32__
+# include <glob.h>
+#else
+
+#include <wchar.h>
+#include <stddef.h>
+
+typedef struct {
+ size_t gl_pathc;
+ wchar_t **gl_pathv;
+ size_t gl_offs;
+} glob_t;
+
+/* WARNING: this is a reduced functionality replacement */
+extern int
+win32_wglob(const wchar_t *pattern, int flags,
+ int (*errfunc)(const wchar_t *epath, int eerrno),
+ glob_t *pglob);
+
+extern void globfree(glob_t *pglob);
+
+#define GLOB_ERR 0x1 /* Return on read errors. */
+#define GLOB_NOSORT 0x2 /* Don't sort the names. */
+
+/* Error returns from `glob'. */
+#define GLOB_NOSPACE 1 /* Ran out of memory. */
+#define GLOB_ABORTED 2 /* Read error. */
+#define GLOB_NOMATCH 3 /* No matches found. */
+
+#endif /* __WIN32__ */
+
+#endif /* _WIMLIB_GLOB_H */
inode_resolve_ltes(struct wim_inode *inode, struct wim_lookup_table *table,
bool force);
+extern int
+resource_not_found_error(struct wim_inode *inode, const u8 *hash);
+
extern void
inode_unresolve_ltes(struct wim_inode *inode);
+++ /dev/null
-#ifndef _WIMLIB_SWM_H
-#define _WIMLIB_SWM_H
-
-#include "wimlib/types.h"
-
-extern int
-verify_swm_set(WIMStruct *wim,
- WIMStruct **additional_swms, unsigned num_additional_swms);
-
-extern void
-merge_lookup_tables(WIMStruct *wim,
- WIMStruct **additional_swms, unsigned num_additional_swms);
-
-extern void
-unmerge_lookup_table(WIMStruct *wim);
-
-#endif
#include "wimlib/header.h"
#include "wimlib/types.h"
#include "wimlib/file_io.h"
+#include "wimlib/list.h"
struct wim_info;
struct wim_lookup_table;
/* Temporary field */
void *private;
+ WIMStruct *master_wim;
+
+ struct list_head resource_wims;
+
+ struct list_head resource_wim_node;
+
/* The currently selected image, indexed starting at 1. If not 0,
* subtract 1 from this to get the index of the current image in the
* image_metadata array. */
u8 wim_locked : 1;
+ u8 being_unmerged : 1;
+
+ u8 is_owned_by_master : 1;
+
/* One of WIMLIB_COMPRESSION_TYPE_*, cached from the header flags. */
u8 compression_type : 2;
};
return (wim->hdr.integrity.offset != 0);
}
+static inline bool wim_has_metadata(const WIMStruct *wim)
+{
+ return (wim->image_metadata != NULL || wim->hdr.image_count == 0);
+}
+
extern void
wim_recalculate_refcnts(WIMStruct *wim);
# define tmempcpy wmempcpy
# define tstrcpy wcscpy
# define tprintf wprintf
-# define tsprintf swprintf
+# define tsprintf _swprintf
# define tfprintf fwprintf
# define tvfprintf vfwprintf
# define istalpha iswalpha
# define tstrerror_r win32_strerror_r_replacement
# define trename win32_rename_replacement
# define ttruncate win32_truncate_replacement
+# define tglob win32_wglob
#else /* __WIN32__ */
/* For non-Windows builds, the "tchar" type will be one byte and will specify a
* string in the locale-dependent multibyte encoding. However, only UTF-8 is
# define trename rename
# define ttruncate truncate
# define taccess access
+# define tglob glob
#endif /* !__WIN32__ */
#endif /* _WIMLIB_TCHAR_H */
#endif
#include "imagex-win32.h"
-#include <assert.h>
-#include <errno.h>
#include <fcntl.h>
#include <io.h>
#include <stdio.h>
-#include <string.h>
#include <windows.h>
-/* Replacement for glob() in Windows native builds that operates on wide
- * characters. */
-int
-win32_wglob(const wchar_t *pattern, int flags,
- int (*errfunc)(const wchar_t *epath, int eerrno),
- glob_t *pglob)
-{
- WIN32_FIND_DATAW dat;
- DWORD err;
- HANDLE hFind;
- int ret;
- size_t nspaces;
-
- const wchar_t *backslash, *end_slash;
- size_t prefix_len;
-
- backslash = wcsrchr(pattern, L'\\');
- end_slash = wcsrchr(pattern, L'/');
-
- if (backslash > end_slash)
- end_slash = backslash;
-
- if (end_slash)
- prefix_len = end_slash - pattern + 1;
- else
- prefix_len = 0;
-
- /* This function does not support all functionality of the POSIX glob(),
- * so make sure the parameters are consistent with supported
- * functionality. */
- assert(errfunc == NULL);
- assert((flags & GLOB_ERR) == GLOB_ERR);
- assert((flags & ~(GLOB_NOSORT | GLOB_ERR)) == 0);
-
- hFind = FindFirstFileW(pattern, &dat);
- if (hFind == INVALID_HANDLE_VALUE) {
- err = GetLastError();
- if (err == ERROR_FILE_NOT_FOUND) {
- errno = 0;
- return GLOB_NOMATCH;
- } else {
- /* The other possible error codes for FindFirstFile()
- * are undocumented. */
- errno = EIO;
- return GLOB_ABORTED;
- }
- }
- pglob->gl_pathc = 0;
- pglob->gl_pathv = NULL;
- nspaces = 0;
- do {
- wchar_t *path;
- if (pglob->gl_pathc == nspaces) {
- size_t new_nspaces;
- wchar_t **pathv;
-
- new_nspaces = nspaces * 2 + 1;
- pathv = realloc(pglob->gl_pathv,
- new_nspaces * sizeof(pglob->gl_pathv[0]));
- if (!pathv)
- goto oom;
- pglob->gl_pathv = pathv;
- nspaces = new_nspaces;
- }
- size_t filename_len = wcslen(dat.cFileName);
- size_t len_needed = prefix_len + filename_len;
-
- path = malloc((len_needed + 1) * sizeof(wchar_t));
- if (!path)
- goto oom;
-
- wmemcpy(path, pattern, prefix_len);
- wmemcpy(path + prefix_len, dat.cFileName, filename_len + 1);
- pglob->gl_pathv[pglob->gl_pathc++] = path;
- } while (FindNextFileW(hFind, &dat));
- err = GetLastError();
- CloseHandle(hFind);
- if (err == ERROR_NO_MORE_FILES) {
- errno = 0;
- return 0;
- } else {
- /* Other possible error codes for FindNextFile() are
- * undocumented */
- errno = EIO;
- ret = GLOB_ABORTED;
- goto fail_globfree;
- }
-oom:
- CloseHandle(hFind);
- errno = ENOMEM;
- ret = GLOB_NOSPACE;
-fail_globfree:
- globfree(pglob);
- return ret;
-}
-
-void
-globfree(glob_t *pglob)
-{
- size_t i;
- for (i = 0; i < pglob->gl_pathc; i++)
- free(pglob->gl_pathv[i]);
- free(pglob->gl_pathv);
-}
-
/* Convert a string from the "current Windows codepage" to UTF-16LE. */
wchar_t *
win32_mbs_to_wcs(const char *mbs, size_t mbs_nbytes, size_t *num_wchars_ret)
#include <stdbool.h>
#include <wchar.h>
-typedef struct {
- size_t gl_pathc;
- wchar_t **gl_pathv;
- size_t gl_offs;
-} glob_t;
-
-/* WARNING: this is a reduced functionality replacement */
-extern int
-win32_wglob(const wchar_t *pattern, int flags,
- int (*errfunc)(const wchar_t *epath, int eerrno),
- glob_t *pglob);
-
-extern void globfree(glob_t *pglob);
-
-#define GLOB_ERR 0x1 /* Return on read errors. */
-#define GLOB_NOSORT 0x2 /* Don't sort the names. */
-
-/* Error returns from `glob'. */
-#define GLOB_NOSPACE 1 /* Ran out of memory. */
-#define GLOB_ABORTED 2 /* Read error. */
-#define GLOB_NOMATCH 3 /* No matches found. */
-
-extern void
-win32_acquire_capture_privileges(void);
-
-extern void
-win32_release_capture_privileges(void);
-
-extern void
-win32_acquire_restore_privileges(void);
-
-extern void
-win32_release_restore_privileges(void);
-
extern wchar_t *
win32_mbs_to_wcs(const char *mbs, size_t mbs_nbytes, size_t *num_wchars_ret);
#ifdef __WIN32__
# include "imagex-win32.h"
# define tbasename win32_wbasename
-# define tglob win32_wglob
# define OS_PREFERRED_PATH_SEPARATOR L'\\'
# define OS_PREFERRED_PATH_SEPARATOR_STRING L"\\"
#else /* __WIN32__ */
# include <getopt.h>
# include <langinfo.h>
# define tbasename basename
-# define tglob glob
# define OS_PREFERRED_PATH_SEPARATOR '/'
# define OS_PREFERRED_PATH_SEPARATOR_STRING "/"
static inline void set_fd_to_binary_mode(int fd)
#define for_opt(c, opts) while ((c = getopt_long_only(argc, (tchar**)argv, T(""), \
opts, NULL)) != -1)
-
enum {
CMD_NONE = -1,
CMD_APPEND = 0,
static void recommend_man_page(int cmd, FILE *fp);
static const tchar *get_cmd_string(int cmd, bool nospace);
+static int imagex_progress_func(enum wimlib_progress_msg msg,
+ const union wimlib_progress_info *info);
+
static bool imagex_be_quiet = false;
static FILE *imagex_info_file;
}
}
+struct refglob_set {
+ const tchar **globs;
+ unsigned num_globs;
+ unsigned num_alloc_globs;
+};
+
+#define REFGLOB_SET_INITIALIZER \
+ { .globs = NULL, .num_globs = 0, .num_alloc_globs = 0, }
+
+#define REFGLOB_SET(_refglobs) \
+ struct refglob_set _refglobs = REFGLOB_SET_INITIALIZER
+
+static int
+refglob_set_append(struct refglob_set *set, const tchar *glob)
+{
+ unsigned num_alloc_globs = set->num_alloc_globs;
+
+ if (set->num_globs == num_alloc_globs) {
+ const tchar **new_globs;
+
+ num_alloc_globs += 4;
+ new_globs = realloc(set->globs, sizeof(set->globs[0]) * num_alloc_globs);
+ if (!new_globs) {
+ imagex_error(T("Out of memory!"));
+ return -1;
+ }
+ set->globs = new_globs;
+ set->num_alloc_globs = num_alloc_globs;
+ }
+ set->globs[set->num_globs++] = glob;
+ return 0;
+}
+
+static int
+wim_reference_globs(WIMStruct *wim, struct refglob_set *set, int open_flags)
+{
+ return wimlib_reference_resource_files(wim, set->globs, set->num_globs,
+ WIMLIB_REF_FLAG_GLOB_ENABLE,
+ open_flags,
+ imagex_progress_func);
+}
+
+static void
+refglob_set_destroy(struct refglob_set *set)
+{
+ free(set->globs);
+}
+
+static void
+do_resource_not_found_warning(const tchar *wimfile,
+ const struct wimlib_wim_info *info,
+ const struct refglob_set *refglobs)
+{
+ if (info->total_parts > 1) {
+ if (refglobs->num_globs == 0) {
+ imagex_error(T("\"%"TS"\" is part of a split WIM. "
+ "Use --ref to specify the other parts."),
+ wimfile);
+ } else {
+ imagex_error(T("Perhaps the '--ref' argument did not "
+ "specify all other parts of the split "
+ "WIM?"));
+ }
+ } else {
+ imagex_error(T("If this is a delta WIM, use the --ref argument "
+ "to specify the WIM on which it is based."));
+ }
+}
+
/* Returns the size of a file given its name, or -1 if the file does not exist
* or its size cannot be determined. */
static off_t
return 0;
}
-/* Open all the split WIM parts that correspond to a file glob.
- *
- * @first_part specifies the first part of the split WIM and it may be either
- * included or omitted from the glob. */
-static int
-open_swms_from_glob(const tchar *swm_glob,
- const tchar *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;
-
- /* Warning: glob() is replaced in Windows native builds */
- ret = tglob(swm_glob, GLOB_ERR | GLOB_NOSORT, NULL, &globbuf);
- if (ret) {
- if (ret == GLOB_NOMATCH) {
- imagex_error(T("Found no files for glob \"%"TS"\""),
- swm_glob);
- } else {
- imagex_error_with_errno(T("Failed to process glob \"%"TS"\""),
- 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(T("Out of memory"));
- ret = -1;
- goto out_globfree;
- }
- unsigned offset = 0;
- for (unsigned i = 0; i < num_additional_swms; i++) {
- if (tstrcmp(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],
- imagex_progress_func);
- if (ret)
- 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 unsigned
parse_num_threads(const tchar *optarg)
{
int open_flags = WIMLIB_OPEN_FLAG_SPLIT_OK;
int image;
WIMStruct *wim;
+ struct wimlib_wim_info info;
int ret;
const tchar *wimfile;
const tchar *target;
const tchar *image_num_or_name;
int extract_flags = WIMLIB_EXTRACT_FLAG_SEQUENTIAL;
- const tchar *swm_glob = NULL;
- WIMStruct **additional_swms;
- unsigned num_additional_swms;
+ REFGLOB_SET(refglobs);
for_opt(c, apply_options) {
switch (c) {
extract_flags |= WIMLIB_EXTRACT_FLAG_VERBOSE;
break;
case IMAGEX_REF_OPTION:
- swm_glob = optarg;
+ ret = refglob_set_append(&refglobs, optarg);
+ if (ret)
+ goto out_free_refglobs;
break;
case IMAGEX_UNIX_DATA_OPTION:
extract_flags |= WIMLIB_EXTRACT_FLAG_UNIX_DATA;
target = argv[2];
}
wim = NULL;
- num_additional_swms = 0;
- additional_swms = NULL;
} else {
ret = wimlib_open_wim(wimfile, open_flags, &wim,
imagex_progress_func);
if (ret)
- goto out;
+ goto out_free_refglobs;
+
+ wimlib_get_wim_info(wim, &info);
if (argc >= 3) {
/* Image explicitly specified. */
} else {
/* No image specified; default to image 1, but only if the WIM
* contains exactly one image. */
- struct wimlib_wim_info info;
- wimlib_get_wim_info(wim, &info);
if (info.image_count != 1) {
imagex_error(T("\"%"TS"\" contains %d images; "
"Please select one (or all)."),
image = 1;
target = argv[1];
}
+ }
- if (swm_glob) {
- ret = open_swms_from_glob(swm_glob, wimfile, open_flags,
- &additional_swms,
- &num_additional_swms);
- if (ret)
- goto out_wimlib_free;
- } else {
- additional_swms = NULL;
- num_additional_swms = 0;
+ if (refglobs.num_globs) {
+ if (wim == NULL) {
+ imagex_error(T("Can't specify --ref when applying from stdin!"));
+ ret = -1;
+ goto out_wimlib_free;
}
+ ret = wim_reference_globs(wim, &refglobs, open_flags);
+ if (ret)
+ goto out_wimlib_free;
}
#ifndef __WIN32__
imagex_error_with_errno(T("Failed to stat \"%"TS"\""),
target);
ret = -1;
- goto out_free_swms;
+ goto out_wimlib_free;
}
} else {
if (S_ISBLK(stbuf.st_mode) || S_ISREG(stbuf.st_mode))
if (wim) {
ret = wimlib_extract_image(wim, image, target, extract_flags,
- additional_swms, num_additional_swms,
imagex_progress_func);
} else {
set_fd_to_binary_mode(STDIN_FILENO);
target, extract_flags,
imagex_progress_func);
}
- if (ret == 0)
+ if (ret == 0) {
imagex_printf(T("Done applying WIM image.\n"));
-out_free_swms:
- for (unsigned i = 0; i < num_additional_swms; i++)
- wimlib_free(additional_swms[i]);
- free(additional_swms);
+ } else if (ret == WIMLIB_ERR_RESOURCE_NOT_FOUND) {
+ if (wim) {
+ do_resource_not_found_warning(wimfile, &info, &refglobs);
+ } else {
+ imagex_error(T( "If you are applying an image "
+ "from a split pipable WIM,\n"
+ " make sure you have "
+ "concatenated together all parts."));
+ }
+ }
out_wimlib_free:
wimlib_free(wim);
-out:
+out_free_refglobs:
+ refglob_set_destroy(&refglobs);
return ret;
out_usage:
usage(CMD_APPLY, stderr);
ret = -1;
- goto out;
+ goto out_free_refglobs;
}
/* Create a WIM image from a directory tree, NTFS volume, or multiple files or
const tchar *dest_name;
const tchar *dest_desc;
WIMStruct *src_wim;
+ struct wimlib_wim_info src_info;
WIMStruct *dest_wim;
int ret;
int image;
struct stat stbuf;
bool wim_is_new;
- const tchar *swm_glob = NULL;
- WIMStruct **additional_swms;
- unsigned num_additional_swms;
+ REFGLOB_SET(refglobs);
unsigned num_threads = 0;
for_opt(c, export_options) {
goto out_err;
break;
case IMAGEX_REF_OPTION:
- swm_glob = optarg;
+ ret = refglob_set_append(&refglobs, optarg);
+ if (ret)
+ goto out_free_refglobs;
break;
case IMAGEX_THREADS_OPTION:
num_threads = parse_num_threads(optarg);
open_flags | WIMLIB_OPEN_FLAG_SPLIT_OK, &src_wim,
imagex_progress_func);
if (ret)
- goto out;
+ goto out_free_refglobs;
+
+ wimlib_get_wim_info(src_wim, &src_info);
/* Determine if the destination is an existing file or not. If so, we
* try to append the exported image(s) to it; otherwise, we create a new
/* The user did not specify a compression type; default
* to that of the source WIM. */
- struct wimlib_wim_info src_info;
-
- wimlib_get_wim_info(src_wim, &src_info);
compression_type = src_info.compression_type;
}
ret = wimlib_create_new_wim(compression_type, &dest_wim);
if (ret)
goto out_free_dest_wim;
- if (swm_glob) {
- ret = open_swms_from_glob(swm_glob, src_wimfile, open_flags,
- &additional_swms,
- &num_additional_swms);
+ if (refglobs.num_globs) {
+ ret = wim_reference_globs(src_wim, &refglobs, open_flags);
if (ret)
goto out_free_dest_wim;
- } else {
- additional_swms = NULL;
- num_additional_swms = 0;
+ }
+
+ if ((export_flags & WIMLIB_EXPORT_FLAG_BOOT) &&
+ image == WIMLIB_ALL_IMAGES && src_info.boot_index == 0)
+ {
+ imagex_error(T("--boot specified for all-images export, but source WIM "
+ "has no bootable image."));
+ ret = -1;
+ goto out_free_dest_wim;
}
ret = wimlib_export_image(src_wim, image, dest_wim, dest_name,
- dest_desc, export_flags, additional_swms,
- num_additional_swms, imagex_progress_func);
- if (ret)
- goto out_free_swms;
+ dest_desc, export_flags, imagex_progress_func);
+ if (ret) {
+ if (ret == WIMLIB_ERR_RESOURCE_NOT_FOUND) {
+ do_resource_not_found_warning(src_wimfile,
+ &src_info, &refglobs);
+ }
+ goto out_free_dest_wim;
+ }
if (!wim_is_new)
ret = wimlib_overwrite(dest_wim, write_flags, num_threads,
ret = wimlib_write_to_fd(dest_wim, dest_wim_fd,
WIMLIB_ALL_IMAGES, write_flags,
num_threads, imagex_progress_func);
- if (ret)
- imagex_error(T("Export failed."));
-out_free_swms:
- for (unsigned i = 0; i < num_additional_swms; i++)
- wimlib_free(additional_swms[i]);
- free(additional_swms);
out_free_dest_wim:
wimlib_free(dest_wim);
out_free_src_wim:
wimlib_free(src_wim);
-out:
+out_free_refglobs:
+ refglob_set_destroy(&refglobs);
return ret;
out_usage:
usage(CMD_EXPORT, stderr);
out_err:
ret = -1;
- goto out;
+ goto out_free_refglobs;
}
static bool
tchar *dest_dir = T(".");
int extract_flags = WIMLIB_EXTRACT_FLAG_SEQUENTIAL | WIMLIB_EXTRACT_FLAG_NORPFIX;
- const tchar *swm_glob = NULL;
- WIMStruct **additional_swms;
- unsigned num_additional_swms;
+ REFGLOB_SET(refglobs);
struct wimlib_extract_command *cmds;
size_t num_cmds;
extract_flags |= WIMLIB_EXTRACT_FLAG_VERBOSE;
break;
case IMAGEX_REF_OPTION:
- swm_glob = optarg;
+ ret = refglob_set_append(&refglobs, optarg);
+ if (ret)
+ goto out_free_refglobs;
break;
case IMAGEX_UNIX_DATA_OPTION:
extract_flags |= WIMLIB_EXTRACT_FLAG_UNIX_DATA;
if (ret)
goto out_wimlib_free;
- if (swm_glob) {
- ret = open_swms_from_glob(swm_glob, wimfile, open_flags,
- &additional_swms,
- &num_additional_swms);
+ if (refglobs.num_globs) {
+ ret = wim_reference_globs(wim, &refglobs, open_flags);
if (ret)
goto out_wimlib_free;
- } else {
- additional_swms = NULL;
- num_additional_swms = 0;
}
ret = wimlib_extract_files(wim, image, cmds, num_cmds, 0,
- additional_swms, num_additional_swms,
imagex_progress_func);
if (ret == 0) {
if (!imagex_be_quiet)
"files and directories\n"
" are in the WIM image.\n"),
get_cmd_string(CMD_INFO, false));
+ } else if (ret == WIMLIB_ERR_RESOURCE_NOT_FOUND) {
+ struct wimlib_wim_info info;
+
+ wimlib_get_wim_info(wim, &info);
+ do_resource_not_found_warning(wimfile, &info, &refglobs);
}
- for (unsigned i = 0; i < num_additional_swms; i++)
- wimlib_free(additional_swms[i]);
- free(additional_swms);
out_wimlib_free:
wimlib_free(wim);
out_free_cmds:
free_extract_commands(cmds, num_cmds, dest_dir);
-out:
+out_free_refglobs:
+ refglob_set_destroy(&refglobs);
return ret;
out_usage:
usage(CMD_EXTRACT, stderr);
out_err:
ret = -1;
- goto out;
+ goto out_free_refglobs;
}
static void print_byte_field(const uint8_t field[], size_t len)
int c;
int mount_flags = 0;
int open_flags = WIMLIB_OPEN_FLAG_SPLIT_OK;
- const tchar *swm_glob = NULL;
const tchar *staging_dir = NULL;
const tchar *wimfile;
const tchar *dir;
WIMStruct *wim;
+ struct wimlib_wim_info info;
int image;
int ret;
- WIMStruct **additional_swms;
- unsigned num_additional_swms;
+
+ REFGLOB_SET(refglobs);
if (cmd == CMD_MOUNTRW) {
mount_flags |= WIMLIB_MOUNT_FLAG_READWRITE;
}
break;
case IMAGEX_REF_OPTION:
- swm_glob = optarg;
+ ret = refglob_set_append(&refglobs, optarg);
+ if (ret)
+ goto out_free_refglobs;
break;
case IMAGEX_STAGING_DIR_OPTION:
staging_dir = optarg;
ret = wimlib_open_wim(wimfile, open_flags, &wim, imagex_progress_func);
if (ret)
- goto out;
+ goto out_free_refglobs;
+
+ wimlib_get_wim_info(wim, &info);
if (argc >= 3) {
/* Image explicitly specified. */
} else {
/* No image specified; default to image 1, but only if the WIM
* contains exactly one image. */
- struct wimlib_wim_info info;
- wimlib_get_wim_info(wim, &info);
if (info.image_count != 1) {
imagex_error(T("\"%"TS"\" contains %d images; Please "
"select one."), wimfile, info.image_count);
dir = argv[1];
}
- if (swm_glob) {
- ret = open_swms_from_glob(swm_glob, wimfile, open_flags,
- &additional_swms,
- &num_additional_swms);
+ if (refglobs.num_globs) {
+ ret = wim_reference_globs(wim, &refglobs, open_flags);
if (ret)
goto out_free_wim;
- } else {
- additional_swms = NULL;
- num_additional_swms = 0;
}
- ret = wimlib_mount_image(wim, image, dir, mount_flags, additional_swms,
- num_additional_swms, staging_dir);
+ ret = wimlib_mount_image(wim, image, dir, mount_flags, staging_dir);
if (ret) {
imagex_error(T("Failed to mount image %d from \"%"TS"\" "
"on \"%"TS"\""),
image, wimfile, dir);
}
- for (unsigned i = 0; i < num_additional_swms; i++)
- wimlib_free(additional_swms[i]);
- free(additional_swms);
out_free_wim:
wimlib_free(wim);
-out:
+out_free_refglobs:
+ refglob_set_destroy(&refglobs);
return ret;
out_usage:
usage(cmd, stderr);
ret = -1;
- goto out;
+ goto out_free_refglobs;
}
#endif /* WIM_MOUNTING_SUPPORTED */
int ret;
struct wim_image_metadata *new_imd;
- if (wim->hdr.part_number != 1)
- return WIMLIB_ERR_SPLIT_UNSUPPORTED;
-
if (new_image < 1 || new_image > wim->hdr.image_count)
return WIMLIB_ERR_INVALID_IMAGE;
if (new_image == template_image)
return WIMLIB_ERR_INVALID_PARAM;
+ if (!wim_has_metadata(wim))
+ return WIMLIB_ERR_METADATA_NOT_FOUND;
+
new_imd = wim->image_metadata[new_image - 1];
if (!new_imd->modified)
return WIMLIB_ERR_INVALID_PARAM;
#include "wimlib/error.h"
#include "wimlib/lookup_table.h"
#include "wimlib/metadata.h"
-#include "wimlib/swm.h"
#include "wimlib/xml.h"
+#include <stdlib.h>
static int
-inode_allocate_needed_ltes(struct wim_inode *inode,
- struct wim_lookup_table *src_lookup_table,
- struct wim_lookup_table *dest_lookup_table,
- struct list_head *lte_list_head)
+inode_export_streams(struct wim_inode *inode,
+ const struct wim_lookup_table *src_lookup_table,
+ struct wim_lookup_table *dest_lookup_table)
{
- struct wim_lookup_table_entry *src_lte, *dest_lte;
unsigned i;
+ const u8 *hash;
+ struct wim_lookup_table_entry *src_lte, *dest_lte;
inode_unresolve_ltes(inode);
for (i = 0; i <= inode->i_num_ads; i++) {
- src_lte = inode_stream_lte_unresolved(inode, i,
- src_lookup_table);
- if (src_lte && src_lte->out_refcnt == 0) {
- src_lte->out_refcnt = 1;
- dest_lte = inode_stream_lte_unresolved(inode, i,
- dest_lookup_table);
- if (!dest_lte) {
- dest_lte = clone_lookup_table_entry(src_lte);
- if (!dest_lte)
- return WIMLIB_ERR_NOMEM;
- list_add_tail(&dest_lte->export_stream_list,
- lte_list_head);
- }
+
+ /* Retrieve SHA1 message digest of stream to export. */
+ hash = inode_stream_hash(inode, i);
+ if (is_zero_hash(hash)) /* Empty stream? */
+ continue;
+
+ /* Search for the stream (via SHA1 message digest) in the
+ * destination WIM. */
+ dest_lte = __lookup_resource(dest_lookup_table, hash);
+ if (!dest_lte) {
+ /* Stream not yet present in destination WIM. Search
+ * for it in the source WIM, then export it into the
+ * destination WIM. */
+ src_lte = __lookup_resource(src_lookup_table, hash);
+ if (!src_lte)
+ return resource_not_found_error(inode, hash);
+
+ dest_lte = clone_lookup_table_entry(src_lte);
+ if (!dest_lte)
+ return WIMLIB_ERR_NOMEM;
+ dest_lte->refcnt = 0;
+ dest_lte->out_refcnt = 0;
+ lookup_table_insert(dest_lookup_table, dest_lte);
}
+
+ /* Stream is present in destination WIM (either pre-existing,
+ * already exported, or just exported above). Increment its
+ * reference count appropriately. Note: we use 'refcnt' for
+ * the raw reference count, but 'out_refcnt' for references
+ * arising just from the export operation; this is used to roll
+ * back a failed export if needed. */
+ dest_lte->refcnt += inode->i_nlink;
+ dest_lte->out_refcnt += inode->i_nlink;
}
return 0;
}
-static void
-inode_move_ltes_to_table(struct wim_inode *inode,
- struct wim_lookup_table *src_lookup_table,
- struct wim_lookup_table *dest_lookup_table,
- struct list_head *lte_list_head)
+static int
+lte_unexport(struct wim_lookup_table_entry *lte, void *_lookup_table)
{
- struct wim_lookup_table_entry *src_lte, *dest_lte;
- unsigned i;
+ struct wim_lookup_table *lookup_table = _lookup_table;
- for (i = 0; i <= inode->i_num_ads; i++) {
- src_lte = inode_stream_lte_unresolved(inode, i, src_lookup_table);
- if (src_lte) {
- dest_lte = inode_stream_lte_unresolved(inode, i,
- dest_lookup_table);
- if (!dest_lte) {
- struct list_head *next;
-
- wimlib_assert(!list_empty(lte_list_head));
- next = lte_list_head->next;
- list_del(next);
- dest_lte = container_of(next,
- struct wim_lookup_table_entry,
- export_stream_list);
- dest_lte->part_number = 1;
- dest_lte->refcnt = 0;
- wimlib_assert(hashes_equal(dest_lte->hash, src_lte->hash));
- lookup_table_insert(dest_lookup_table, dest_lte);
- }
- dest_lte->refcnt += inode->i_nlink;
- }
+ lte->refcnt -= lte->out_refcnt;
+ if (lte->refcnt == 0) {
+ lookup_table_unlink(lookup_table, lte);
+ free_lookup_table_entry(lte);
}
+ return 0;
}
/* API function documented in wimlib.h */
const tchar *dest_name,
const tchar *dest_description,
int export_flags,
- WIMStruct **additional_swms,
- unsigned num_additional_swms,
wimlib_progress_func_t progress_func)
{
int ret;
- struct wim_image_metadata *src_imd;
- struct list_head lte_list_head;
- struct wim_inode *inode;
+ int start_image;
+ int end_image;
+ int image;
+ u32 orig_dest_boot_idx;
+ u32 orig_dest_image_count;
+
+ /* Check for sane parameters. */
+ if (src_wim == NULL || dest_wim == NULL)
+ return WIMLIB_ERR_INVALID_PARAM;
+
+ if (!wim_has_metadata(src_wim) || !wim_has_metadata(dest_wim))
+ return WIMLIB_ERR_METADATA_NOT_FOUND;
+ /* Destination WIM must be writable. */
ret = can_modify_wim(dest_wim);
if (ret)
return ret;
if (src_image == WIMLIB_ALL_IMAGES) {
- if (src_wim->hdr.image_count > 1) {
-
- /* multi-image export. */
-
- if ((export_flags & WIMLIB_EXPORT_FLAG_BOOT) &&
- (src_wim->hdr.boot_idx == 0))
- {
- /* Specifying the boot flag on a multi-image
- * source WIM makes the boot index default to
- * the bootable image in the source WIM. It is
- * an error if there is no such bootable image.
- * */
- ERROR("Cannot specify `boot' flag when "
- "exporting multiple images from a WIM "
- "with no bootable images");
- return WIMLIB_ERR_INVALID_PARAM;
- }
- if (dest_name || dest_description) {
- ERROR("Image name or image description was "
- "specified, but we are exporting "
- "multiple images");
- return WIMLIB_ERR_INVALID_PARAM;
- }
- for (int i = 1; i <= src_wim->hdr.image_count; i++) {
- int new_flags = export_flags;
-
- if (i != src_wim->hdr.boot_idx)
- new_flags &= ~WIMLIB_EXPORT_FLAG_BOOT;
-
- ret = wimlib_export_image(src_wim, i, dest_wim,
- NULL, NULL,
- new_flags,
- additional_swms,
- num_additional_swms,
- progress_func);
- if (ret)
- return ret;
- }
- return 0;
- } else if (src_wim->hdr.image_count == 1) {
- src_image = 1;
- } else {
- return 0;
+ /* Multi-image export. */
+ if ((!(export_flags & WIMLIB_EXPORT_FLAG_NO_NAMES) &&
+ dest_name) ||
+ (!(export_flags & WIMLIB_EXPORT_FLAG_NO_DESCRIPTIONS) &&
+ dest_description))
+ {
+ ERROR("Image name or image description was "
+ "specified, but we are exporting "
+ "multiple images");
+ return WIMLIB_ERR_INVALID_PARAM;
}
+ start_image = 1;
+ end_image = src_wim->hdr.image_count;
+ } else {
+ start_image = src_image;
+ end_image = src_image;
}
- if (!dest_name) {
- dest_name = wimlib_get_image_name(src_wim, src_image);
- DEBUG("Using name `%"TS"' for source image %d",
- dest_name, src_image);
- }
-
- if (!dest_description) {
- dest_description = wimlib_get_image_description(src_wim,
- src_image);
- DEBUG("Using description `%"TS"' for source image %d",
- dest_description, src_image);
- }
-
- DEBUG("Exporting image %d from `%"TS"'", src_image, src_wim->filename);
-
- if (wimlib_image_name_in_use(dest_wim, dest_name)) {
- ERROR("There is already an image named `%"TS"' in the "
- "destination WIM", dest_name);
- return WIMLIB_ERR_IMAGE_NAME_COLLISION;
- }
-
- ret = verify_swm_set(src_wim, additional_swms, num_additional_swms);
- if (ret)
- return ret;
-
+ /* Stream checksums must be known before proceeding. */
ret = wim_checksum_unhashed_streams(src_wim);
if (ret)
return ret;
if (ret)
return ret;
- if (num_additional_swms)
- merge_lookup_tables(src_wim, additional_swms, num_additional_swms);
+ /* Zero 'out_refcnt' in all lookup table entries in the destination WIM;
+ * this tracks the number of references found from the source WIM
+ * image(s). */
+ for_lookup_table_entry(dest_wim->lookup_table, lte_zero_out_refcnt,
+ NULL);
- ret = select_wim_image(src_wim, src_image);
- if (ret) {
- ERROR("Could not select image %d from the WIM `%"TS"' "
- "to export it", src_image, src_wim->filename);
- goto out;
- }
+ /* Save the original count of images in the destination WIM and the boot
+ * index (used if rollback necessary). */
+ orig_dest_image_count = dest_wim->hdr.image_count;
+ orig_dest_boot_idx = dest_wim->hdr.boot_idx;
+
+ /* Export each requested image. */
+ for (image = start_image; image <= end_image; image++) {
+ const tchar *next_dest_name, *next_dest_description;
+ struct wim_image_metadata *src_imd;
+ struct wim_inode *inode;
+
+ DEBUG("Exporting image %d from \"%"TS"\"",
+ image, src_wim->filename);
- /* Pre-allocate the new lookup table entries that will be needed. This
- * way, it's not possible to run out of memory part-way through
- * modifying the lookup table of the destination WIM. */
- for_lookup_table_entry(src_wim->lookup_table, lte_zero_out_refcnt, NULL);
- src_imd = wim_get_current_image_metadata(src_wim);
- INIT_LIST_HEAD(<e_list_head);
- image_for_each_inode(inode, src_imd) {
- ret = inode_allocate_needed_ltes(inode,
- src_wim->lookup_table,
- dest_wim->lookup_table,
- <e_list_head);
+ /* Determine destination image name and description. */
+
+ if (export_flags & WIMLIB_EXPORT_FLAG_NO_NAMES) {
+ next_dest_name = NULL;
+ } else if (dest_name) {
+ next_dest_name = dest_name;
+ } else {
+ next_dest_name = wimlib_get_image_name(src_wim,
+ image);
+ }
+
+ DEBUG("Using name \"%"TS"\"", next_dest_name);
+
+ if (export_flags & WIMLIB_EXPORT_FLAG_NO_DESCRIPTIONS) {
+ next_dest_description = NULL;
+ } if (dest_description) {
+ next_dest_description = dest_description;
+ } else {
+ next_dest_description = wimlib_get_image_description(
+ src_wim, image);
+ }
+
+ DEBUG("Using description \"%"TS"\"", next_dest_description);
+
+ /* Check for name conflict. */
+ if (wimlib_image_name_in_use(dest_wim, next_dest_name)) {
+ ERROR("There is already an image named \"%"TS"\" "
+ "in the destination WIM", next_dest_name);
+ ret = WIMLIB_ERR_IMAGE_NAME_COLLISION;
+ goto out_rollback;
+ }
+
+ /* Load metadata for source image into memory. */
+ ret = select_wim_image(src_wim, image);
if (ret)
- goto out_free_ltes;
- }
+ goto out_rollback;
- ret = xml_export_image(src_wim->wim_info, src_image,
- &dest_wim->wim_info, dest_name,
- dest_description);
- if (ret)
- goto out_free_ltes;
+ src_imd = wim_get_current_image_metadata(src_wim);
- ret = append_image_metadata(dest_wim, src_imd);
- if (ret)
- goto out_xml_delete_image;
-
- /* The `struct image_metadata' is now referenced by both the @src_wim
- * and the @dest_wim. */
- src_imd->refcnt++;
- src_imd->modified = 1;
-
- /* All memory allocations have been taken care of, so it's no longer
- * possible for this function to fail. Go ahead and update the lookup
- * table of the destination WIM and the boot index, if needed. */
- image_for_each_inode(inode, src_imd) {
- inode_move_ltes_to_table(inode,
- src_wim->lookup_table,
- dest_wim->lookup_table,
- <e_list_head);
- }
+ /* Iterate through inodes in the source image and export their
+ * streams into the destination WIM. */
+ image_for_each_inode(inode, src_imd) {
+ ret = inode_export_streams(inode,
+ src_wim->lookup_table,
+ dest_wim->lookup_table);
+ if (ret)
+ goto out_rollback;
+ }
+
+ /* Export XML information into the destination WIM. */
+ ret = xml_export_image(src_wim->wim_info, image,
+ &dest_wim->wim_info, next_dest_name,
+ next_dest_description);
+ if (ret)
+ goto out_rollback;
+
+ /* Reference the source image metadata from the destination WIM.
+ */
+ ret = append_image_metadata(dest_wim, src_imd);
+ if (ret)
+ goto out_rollback;
+ src_imd->refcnt++;
+
+ /* Lock the metadata into memory. XXX: need better solution for
+ * this. */
+ src_imd->modified = 1;
- if (export_flags & WIMLIB_EXPORT_FLAG_BOOT)
- dest_wim->hdr.boot_idx = dest_wim->hdr.image_count;
+ /* Set boot index in destination WIM. */
+ if ((export_flags & WIMLIB_EXPORT_FLAG_BOOT) &&
+ (src_image != WIMLIB_ALL_IMAGES ||
+ image == src_wim->hdr.boot_idx))
+ {
+ DEBUG("Marking destination image %u as bootable.",
+ dest_wim->hdr.image_count);
+ dest_wim->hdr.boot_idx = dest_wim->hdr.image_count;
+ }
+
+ }
+ /* Set the reparse point fixup flag on the destination WIM if the flag
+ * is set on the source WIM. */
if (src_wim->hdr.flags & WIM_HDR_FLAG_RP_FIX)
- {
- /* Set the reparse point fixup flag on the destination WIM if
- * the flag is set on the source WIM. */
dest_wim->hdr.flags |= WIM_HDR_FLAG_RP_FIX;
+ DEBUG("Export operation successful.");
+ return 0;
+
+out_rollback:
+ while ((image = wim_info_get_num_images(dest_wim->wim_info))
+ > orig_dest_image_count)
+ {
+ xml_delete_image(&dest_wim->wim_info, image);
}
- DEBUG("Successfully exported image.");
- ret = 0;
- goto out;
-out_xml_delete_image:
- xml_delete_image(&dest_wim->wim_info, dest_wim->hdr.image_count + 1);
-out_free_ltes:
+ while (dest_wim->hdr.image_count > orig_dest_image_count)
{
- struct wim_lookup_table_entry *lte, *tmp;
- list_for_each_entry_safe(lte, tmp, <e_list_head, export_stream_list)
- free_lookup_table_entry(lte);
+ put_image_metadata(dest_wim->image_metadata[
+ --dest_wim->hdr.image_count], NULL);
}
-out:
- if (num_additional_swms)
- unmerge_lookup_table(src_wim);
+ for_lookup_table_entry(dest_wim->lookup_table, lte_unexport,
+ dest_wim->lookup_table);
+ dest_wim->hdr.boot_idx = orig_dest_boot_idx;
return ret;
}
#include "wimlib/reparse.h"
#include "wimlib/resource.h"
#include "wimlib/security.h"
-#include "wimlib/swm.h"
#ifdef __WIN32__
# include "wimlib/win32.h" /* for realpath() equivalent */
#endif
const struct wimlib_extract_command *cmds,
size_t num_cmds,
int default_extract_flags,
- WIMStruct **additional_swms,
- unsigned num_additional_swms,
wimlib_progress_func_t progress_func)
{
int ret;
default_extract_flags &= WIMLIB_EXTRACT_MASK_PUBLIC;
- ret = verify_swm_set(wim, additional_swms, num_additional_swms);
- if (ret)
- goto out;
-
if (num_cmds == 0)
- goto out;
-
- if (num_additional_swms)
- merge_lookup_tables(wim, additional_swms, num_additional_swms);
+ return 0;
cmds_copy = CALLOC(num_cmds, sizeof(cmds[0]));
- if (!cmds_copy) {
- ret = WIMLIB_ERR_NOMEM;
- goto out_restore_lookup_table;
- }
+ if (!cmds_copy)
+ return WIMLIB_ERR_NOMEM;
for (size_t i = 0; i < num_cmds; i++) {
cmds_copy[i].extract_flags = (default_extract_flags |
FREE(cmds_copy[i].fs_dest_path);
}
FREE(cmds_copy);
-out_restore_lookup_table:
- if (num_additional_swms)
- unmerge_lookup_table(wim);
-out:
return ret;
}
int image,
const tchar *target,
int extract_flags,
- WIMStruct **additional_swms,
- unsigned num_additional_swms,
wimlib_progress_func_t progress_func)
{
int ret;
- if (extract_flags & WIMLIB_EXTRACT_FLAG_FROM_PIPE) {
- wimlib_assert(wim->hdr.part_number == 1);
- wimlib_assert(num_additional_swms == 0);
- } else {
- ret = verify_swm_set(wim, additional_swms, num_additional_swms);
- if (ret)
- return ret;
-
- if (num_additional_swms)
- merge_lookup_tables(wim, additional_swms, num_additional_swms);
- }
-
if (image == WIMLIB_ALL_IMAGES) {
ret = extract_all_images(wim, target, extract_flags,
progress_func);
lte_free_extracted_file,
NULL);
}
- if (num_additional_swms)
- unmerge_lookup_table(wim);
return ret;
}
/* Extract the image. */
extract_flags |= WIMLIB_EXTRACT_FLAG_FROM_PIPE;
ret = do_wimlib_extract_image(pwm, image, target,
- extract_flags, NULL, 0, progress_func);
+ extract_flags, progress_func);
/* Clean up and return. */
out_wimlib_free:
wimlib_free(pwm);
int image,
const tchar *target,
int extract_flags,
- WIMStruct **additional_swms,
- unsigned num_additional_swms,
wimlib_progress_func_t progress_func)
{
extract_flags &= WIMLIB_EXTRACT_MASK_PUBLIC;
return do_wimlib_extract_image(wim, image, target, extract_flags,
- additional_swms, num_additional_swms,
progress_func);
}
struct integrity_table *old_table;
struct integrity_table *new_table;
int ret;
- off_t cur_offset;
u32 new_table_size;
wimlib_assert(old_lookup_table_end <= new_lookup_table_end);
- cur_offset = wim->out_fd.offset;
-
if (wim->hdr.integrity.offset == 0 || old_lookup_table_end == 0) {
old_table = NULL;
} else {
#endif
#include "wimlib.h"
+#include "wimlib/error.h"
#include "wimlib/types.h"
-#include "wimlib/swm.h"
#include "wimlib/util.h"
#include "wimlib/wim.h"
+/*
+ * verify_swm_set: - Sanity checks to make sure a set of WIMs correctly
+ * correspond to a spanned set.
+ *
+ * @wim:
+ * Part 1 of the set.
+ *
+ * @additional_swms:
+ * All parts of the set other than part 1.
+ *
+ * @num_additional_swms:
+ * Number of WIMStructs in @additional_swms. Or, the total number of parts
+ * in the set minus 1.
+ *
+ * @return:
+ * 0 on success; WIMLIB_ERR_SPLIT_INVALID if the set is not valid.
+ */
+static int
+verify_swm_set(WIMStruct *wim, WIMStruct **additional_swms,
+ unsigned num_additional_swms)
+{
+ unsigned total_parts = wim->hdr.total_parts;
+ int ctype;
+ const u8 *guid;
+
+ if (total_parts != num_additional_swms + 1) {
+ ERROR("`%"TS"' says there are %u parts in the spanned set, "
+ "but %"TS"%u part%"TS" provided",
+ wim->filename, total_parts,
+ (num_additional_swms + 1 < total_parts) ? T("only ") : T(""),
+ num_additional_swms + 1,
+ (num_additional_swms) ? T("s were") : T(" was"));
+ return WIMLIB_ERR_SPLIT_INVALID;
+ }
+ if (wim->hdr.part_number != 1) {
+ ERROR("WIM `%"TS"' is not the first part of the split WIM.",
+ wim->filename);
+ return WIMLIB_ERR_SPLIT_INVALID;
+ }
+ for (unsigned i = 0; i < num_additional_swms; i++) {
+ if (additional_swms[i]->hdr.total_parts != total_parts) {
+ ERROR("WIM `%"TS"' says there are %u parts in the "
+ "spanned set, but %u parts were provided",
+ additional_swms[i]->filename,
+ additional_swms[i]->hdr.total_parts,
+ total_parts);
+ return WIMLIB_ERR_SPLIT_INVALID;
+ }
+ }
+
+ /* keep track of ctype and guid just to make sure they are the same for
+ * all the WIMs. */
+ ctype = wim->compression_type;
+ guid = wim->hdr.guid;
+
+ {
+ /* parts_to_swms is not allocated at function scope because it
+ * should only be allocated after num_additional_swms was
+ * checked to be the same as wim->hdr.total_parts. Otherwise, it
+ * could be unexpectedly high and cause a stack overflow. */
+ WIMStruct *parts_to_swms[num_additional_swms];
+ ZERO_ARRAY(parts_to_swms);
+ for (unsigned i = 0; i < num_additional_swms; i++) {
+
+ WIMStruct *swm = additional_swms[i];
+
+ if (swm->compression_type != ctype) {
+ ERROR("The split WIMs do not all have the same "
+ "compression type");
+ return WIMLIB_ERR_SPLIT_INVALID;
+ }
+ if (memcmp(guid, swm->hdr.guid, WIM_GID_LEN) != 0) {
+ ERROR("The split WIMs do not all have the same "
+ "GUID");
+ return WIMLIB_ERR_SPLIT_INVALID;
+ }
+ if (swm->hdr.part_number == 1) {
+ ERROR("WIMs `%"TS"' and `%"TS"' both are marked "
+ "as the first WIM in the spanned set",
+ wim->filename, swm->filename);
+ return WIMLIB_ERR_SPLIT_INVALID;
+ }
+ if (swm->hdr.part_number == 0 ||
+ swm->hdr.part_number > total_parts)
+ {
+ ERROR("WIM `%"TS"' says it is part %u in the "
+ "spanned set, but the part number must "
+ "be in the range [1, %u]",
+ swm->filename, swm->hdr.part_number, total_parts);
+ return WIMLIB_ERR_SPLIT_INVALID;
+ }
+ if (parts_to_swms[swm->hdr.part_number - 2])
+ {
+ ERROR("`%"TS"' and `%"TS"' are both marked as "
+ "part %u of %u in the spanned set",
+ parts_to_swms[swm->hdr.part_number - 2]->filename,
+ swm->filename,
+ swm->hdr.part_number,
+ total_parts);
+ return WIMLIB_ERR_SPLIT_INVALID;
+ } else {
+ parts_to_swms[swm->hdr.part_number - 2] = swm;
+ }
+ }
+ }
+ return 0;
+}
+
/* API function documented in wimlib.h */
WIMLIBAPI int
wimlib_join(const tchar * const *swm_names,
if (ret)
goto out_free_swms;
- merge_lookup_tables(swm0, additional_swms, num_additional_swms);
+ ret = wimlib_reference_resources(swm0, additional_swms,
+ num_additional_swms, 0);
+ if (ret)
+ goto out_free_swms;
ret = wimlib_write(swm0, output_path, WIMLIB_ALL_IMAGES,
wim_write_flags, 1, progress_func);
+ wimlib_unreference_resources(swm0, additional_swms,
+ num_additional_swms);
out_free_swms:
for (i = 0; i < num_additional_swms; i++)
wimlib_free(additional_swms[i]);
#include "wimlib/endianness.h"
#include "wimlib/error.h"
#include "wimlib/file_io.h"
+#include "wimlib/glob.h"
#include "wimlib/lookup_table.h"
#include "wimlib/metadata.h"
#include "wimlib/paths.h"
}
#endif
+int
+resource_not_found_error(struct wim_inode *inode, const u8 *hash)
+{
+ if (wimlib_print_errors) {
+ ERROR("\"%"TS"\": resource not found", inode_first_full_path(inode));
+ tfprintf(stderr, T(" SHA-1 message digest of missing resource:\n "));
+ print_hash(hash, stderr);
+ tputc(T('\n'), stderr);
+ }
+ return WIMLIB_ERR_RESOURCE_NOT_FOUND;
+}
+
/*
* Resolve an inode's lookup table entries.
*
inode->i_resolved = 1;
}
return 0;
+
resource_not_found:
- if (wimlib_print_errors) {
- ERROR("\"%"TS"\": resource not found", inode_first_full_path(inode));
- tfprintf(stderr, T(" SHA-1 message digest of missing resource:\n "));
- print_hash(hash, stderr);
- tputc(T('\n'), stderr);
- }
- return WIMLIB_ERR_RESOURCE_NOT_FOUND;
+ return resource_not_found_error(inode, hash);
}
void
*lte_ret = lte;
return 0;
}
+
+static int
+move_lte_to_table(struct wim_lookup_table_entry *lte, void *_combined_table)
+{
+ struct wim_lookup_table *combined_table = _combined_table;
+
+ hlist_del(<e->hash_list);
+ lookup_table_insert(combined_table, lte);
+ return 0;
+}
+
+static void
+lookup_table_join(struct wim_lookup_table *combined_table,
+ struct wim_lookup_table *part_table)
+{
+ for_lookup_table_entry(part_table, move_lte_to_table, combined_table);
+ part_table->num_entries = 0;
+}
+
+static void
+merge_lookup_tables(WIMStruct *wim, WIMStruct **resource_wims,
+ unsigned num_resource_wims)
+{
+ for (unsigned i = 0; i < num_resource_wims; i++) {
+ lookup_table_join(wim->lookup_table, resource_wims[i]->lookup_table);
+ list_add(&resource_wims[i]->resource_wim_node, &wim->resource_wims);
+ resource_wims[i]->master_wim = wim;
+ }
+}
+
+static int
+move_lte_to_orig_table(struct wim_lookup_table_entry *lte, void *_wim)
+{
+ WIMStruct *wim = _wim;
+
+ if (lte->resource_location == RESOURCE_IN_WIM &&
+ lte->wim->being_unmerged)
+ {
+ move_lte_to_table(lte, lte->wim->lookup_table);
+ wim->lookup_table->num_entries--;
+ }
+ return 0;
+}
+
+static int
+check_reference_params(WIMStruct *wim,
+ WIMStruct **resource_wims, unsigned num_resource_wims,
+ WIMStruct *expected_master)
+{
+ if (wim == NULL)
+ return WIMLIB_ERR_INVALID_PARAM;
+
+ if (wim->hdr.part_number != 1)
+ return WIMLIB_ERR_INVALID_PARAM;
+
+ if (num_resource_wims != 0 && resource_wims == NULL)
+ return WIMLIB_ERR_INVALID_PARAM;
+
+ for (unsigned i = 0; i < num_resource_wims; i++) {
+ if (resource_wims[i] == NULL)
+ return WIMLIB_ERR_INVALID_PARAM;
+ if (resource_wims[i]->master_wim != expected_master)
+ return WIMLIB_ERR_INVALID_PARAM;
+ }
+ return 0;
+}
+
+/* API function documented in wimlib.h */
+WIMLIBAPI int
+wimlib_reference_resources(WIMStruct *wim,
+ WIMStruct **resource_wims, unsigned num_resource_wims,
+ int ref_flags)
+{
+ int ret;
+
+ ret = check_reference_params(wim, resource_wims,
+ num_resource_wims, NULL);
+ if (ret)
+ return ret;
+
+ merge_lookup_tables(wim, resource_wims, num_resource_wims);
+ return 0;
+}
+
+static int
+reference_resource_paths(WIMStruct *wim,
+ const tchar * const *resource_wimfiles,
+ unsigned num_resource_wimfiles,
+ int ref_flags,
+ int open_flags,
+ wimlib_progress_func_t progress_func)
+{
+ WIMStruct **resource_wims;
+ unsigned i;
+ int ret;
+
+ open_flags |= WIMLIB_OPEN_FLAG_SPLIT_OK;
+
+ resource_wims = CALLOC(num_resource_wimfiles, sizeof(resource_wims[0]));
+ if (!resource_wims)
+ return WIMLIB_ERR_NOMEM;
+
+ for (i = 0; i < num_resource_wimfiles; i++) {
+ ret = wimlib_open_wim(resource_wimfiles[i], open_flags,
+ &resource_wims[i], progress_func);
+ if (ret)
+ goto out_free_resource_wims;
+ }
+
+ ret = wimlib_reference_resources(wim, resource_wims,
+ num_resource_wimfiles, ref_flags);
+ if (ret)
+ goto out_free_resource_wims;
+
+ for (i = 0; i < num_resource_wimfiles; i++)
+ resource_wims[i]->is_owned_by_master = 1;
+
+ ret = 0;
+ goto out_free_array;
+
+out_free_resource_wims:
+ for (i = 0; i < num_resource_wimfiles; i++)
+ wimlib_free(resource_wims[i]);
+out_free_array:
+ FREE(resource_wims);
+ return ret;
+}
+
+static int
+reference_resource_glob(WIMStruct *wim, const tchar *refglob,
+ int ref_flags, int open_flags,
+ wimlib_progress_func_t progress_func)
+{
+ glob_t globbuf;
+ int ret;
+
+ /* Note: glob() is replaced in Windows native builds. */
+ ret = tglob(refglob, GLOB_ERR | GLOB_NOSORT, NULL, &globbuf);
+ if (ret) {
+ if (ret == GLOB_NOMATCH) {
+ if (ref_flags & WIMLIB_REF_FLAG_GLOB_ERR_ON_NOMATCH) {
+ ERROR("Found no files for glob \"%"TS"\"", refglob);
+ return WIMLIB_ERR_GLOB_HAD_NO_MATCHES;
+ } else {
+ return reference_resource_paths(wim,
+ &refglob,
+ 1,
+ ref_flags,
+ open_flags,
+ progress_func);
+ }
+ } else {
+ ERROR_WITH_ERRNO("Failed to process glob \"%"TS"\"", refglob);
+ if (ret == GLOB_NOSPACE)
+ return WIMLIB_ERR_NOMEM;
+ else
+ return WIMLIB_ERR_READ;
+ }
+ }
+
+ ret = reference_resource_paths(wim,
+ (const tchar * const *)globbuf.gl_pathv,
+ globbuf.gl_pathc,
+ ref_flags,
+ open_flags,
+ progress_func);
+ globfree(&globbuf);
+ return ret;
+}
+
+/* API function documented in wimlib.h */
+WIMLIBAPI int
+wimlib_reference_resource_files(WIMStruct *wim,
+ const tchar * const * resource_wimfiles_or_globs,
+ unsigned count,
+ int ref_flags,
+ int open_flags,
+ wimlib_progress_func_t progress_func)
+{
+ unsigned i;
+ int ret;
+
+ if (ref_flags & WIMLIB_REF_FLAG_GLOB_ENABLE) {
+ for (i = 0; i < count; i++) {
+ ret = reference_resource_glob(wim,
+ resource_wimfiles_or_globs[i],
+ ref_flags,
+ open_flags,
+ progress_func);
+ if (ret)
+ return ret;
+ }
+ return 0;
+ } else {
+ return reference_resource_paths(wim, resource_wimfiles_or_globs,
+ count, ref_flags,
+ open_flags, progress_func);
+ }
+}
+
+/* API function documented in wimlib.h */
+WIMLIBAPI int
+wimlib_unreference_resources(WIMStruct *wim,
+ WIMStruct **resource_wims, unsigned num_resource_wims)
+{
+ int ret;
+ unsigned i;
+
+ ret = check_reference_params(wim, resource_wims, num_resource_wims, wim);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < num_resource_wims; i++)
+ resource_wims[i]->being_unmerged = 1;
+
+ for_lookup_table_entry(wim->lookup_table, move_lte_to_orig_table, wim);
+
+ for (i = 0; i < num_resource_wims; i++) {
+ resource_wims[i]->being_unmerged = 0;
+ list_del(&resource_wims[i]->resource_wim_node);
+ resource_wims[i]->master_wim = NULL;
+ }
+ return 0;
+}
#include "wimlib/paths.h"
#include "wimlib/reparse.h"
#include "wimlib/resource.h"
-#include "wimlib/swm.h"
#include "wimlib/timestamp.h"
#include "wimlib/version.h"
#include "wimlib/write.h"
/* API function documented in wimlib.h */
WIMLIBAPI int
wimlib_mount_image(WIMStruct *wim, int image, const char *dir,
- int mount_flags, WIMStruct **additional_swms,
- unsigned num_additional_swms,
- const char *staging_dir)
+ int mount_flags, const char *staging_dir)
{
int argc;
char *argv[16];
DEBUG("Mount: wim = %p, image = %d, dir = %s, flags = %d, ",
wim, image, dir, mount_flags);
- if (!wim || !dir) {
- ret = WIMLIB_ERR_INVALID_PARAM;
- goto out;
- }
-
- ret = verify_swm_set(wim, additional_swms, num_additional_swms);
- if (ret)
- goto out;
+ if (!wim || !dir)
+ return WIMLIB_ERR_INVALID_PARAM;
if (mount_flags & WIMLIB_MOUNT_FLAG_READWRITE) {
ret = can_delete_from_wim(wim);
if (ret)
- goto out;
+ return ret;
}
- if (num_additional_swms)
- merge_lookup_tables(wim, additional_swms, num_additional_swms);
-
ret = select_wim_image(wim, image);
if (ret)
- goto out_restore_lookup_table;
+ return ret;
DEBUG("Selected image %d", image);
if (imd->refcnt != 1) {
ERROR("Cannot mount image that was just exported with "
"wimlib_export_image()");
- ret = WIMLIB_ERR_INVALID_PARAM;
- goto out_restore_lookup_table;
+ return WIMLIB_ERR_INVALID_PARAM;
}
if (imd->modified) {
ERROR("Cannot mount image that was added "
"with wimlib_add_image()");
- ret = WIMLIB_ERR_INVALID_PARAM;
- goto out_restore_lookup_table;
+ return WIMLIB_ERR_INVALID_PARAM;
}
if (mount_flags & WIMLIB_MOUNT_FLAG_READWRITE) {
ret = lock_wim(wim, wim->in_fd.fd);
if (ret)
- goto out_restore_lookup_table;
+ return ret;
}
/* Use default stream interface if one was not specified */
wim->wim_locked = 0;
out_free_message_queue_names:
free_message_queue_names(&ctx);
-out_restore_lookup_table:
- if (num_additional_swms)
- unmerge_lookup_table(wim);
-out:
return ret;
}
WIMLIBAPI int
wimlib_mount_image(WIMStruct *wim, int image, const tchar *dir,
- int mount_flags, WIMStruct **additional_swms,
- unsigned num_additional_swms,
- const tchar *staging_dir)
+ int mount_flags, const tchar *staging_dir)
{
return mount_unsupported_error();
}
if (swm_name == NULL || swm_name[0] == T('\0') || part_size == 0)
return WIMLIB_ERR_INVALID_PARAM;
- if (wim->hdr.total_parts != 1)
- return WIMLIB_ERR_SPLIT_UNSUPPORTED;
+ if (!wim_has_metadata(wim))
+ return WIMLIB_ERR_INVALID_PARAM;
memset(&swm_info, 0, sizeof(swm_info));
swm_info.max_part_size = part_size;
+++ /dev/null
-/*
- * swm.c
- *
- * Functions to help handle split WIMs.
- */
-
-/*
- * Copyright (C) 2012, 2013 Eric Biggers
- *
- * This file is part of wimlib, a library for working with WIM files.
- *
- * wimlib is free software; you can redistribute it and/or modify it under the
- * terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 3 of the License, or (at your option)
- * any later version.
- *
- * wimlib is distributed in the hope that it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- * A PARTICULAR PURPOSE. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with wimlib; if not, see http://www.gnu.org/licenses/.
- */
-
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-
-#include "wimlib/error.h"
-#include "wimlib/lookup_table.h"
-#include "wimlib/swm.h"
-#include "wimlib/wim.h"
-
-static int
-move_lte_to_table(struct wim_lookup_table_entry *lte, void *combined_table)
-{
- hlist_del(<e->hash_list);
- lookup_table_insert((struct wim_lookup_table*)combined_table, lte);
- return 0;
-}
-
-static void
-lookup_table_join(struct wim_lookup_table *combined_table,
- struct wim_lookup_table *part_table)
-{
- for_lookup_table_entry(part_table, move_lte_to_table, combined_table);
- part_table->num_entries = 0;
-}
-
-/*
- * merge_lookup_tables() - Merge lookup tables from the parts of a split WIM.
- *
- * @wim specifies the first part, while @additional_swms and @num_additional_swms
- * specify an array of pointers to the WIMStruct's for additional split WIM parts.
- *
- * The reason we join the lookup tables is so we only have to search one lookup
- * table to find the location of a resource in the entire WIM.
- */
-void
-merge_lookup_tables(WIMStruct *wim,
- WIMStruct **additional_swms,
- unsigned num_additional_swms)
-{
- for (unsigned i = 0; i < num_additional_swms; i++)
- lookup_table_join(wim->lookup_table, additional_swms[i]->lookup_table);
-}
-
-static int
-move_lte_to_orig_table(struct wim_lookup_table_entry *lte, void *_wim)
-{
- WIMStruct *wim = _wim;
- if (lte->wim != wim) {
- move_lte_to_table(lte, lte->wim->lookup_table);
- wim->lookup_table->num_entries--;
- }
- return 0;
-}
-
-/* Undo merge_lookup_tables(), given the first WIM part that contains the merged
- * lookup table. */
-void
-unmerge_lookup_table(WIMStruct *wim)
-{
- for_lookup_table_entry(wim->lookup_table, move_lte_to_orig_table, wim);
-}
-
-/*
- * verify_swm_set: - Sanity checks to make sure a set of WIMs correctly
- * correspond to a spanned set.
- *
- * @wim:
- * Part 1 of the set.
- *
- * @additional_swms:
- * All parts of the set other than part 1.
- *
- * @num_additional_swms:
- * Number of WIMStructs in @additional_swms. Or, the total number of parts
- * in the set minus 1.
- *
- * @return:
- * 0 on success; WIMLIB_ERR_SPLIT_INVALID if the set is not valid.
- */
-int
-verify_swm_set(WIMStruct *wim, WIMStruct **additional_swms,
- unsigned num_additional_swms)
-{
- unsigned total_parts = wim->hdr.total_parts;
- int ctype;
- const u8 *guid;
-
- if (total_parts != num_additional_swms + 1) {
- ERROR("`%"TS"' says there are %u parts in the spanned set, "
- "but %"TS"%u part%"TS" provided",
- wim->filename, total_parts,
- (num_additional_swms + 1 < total_parts) ? T("only ") : T(""),
- num_additional_swms + 1,
- (num_additional_swms) ? T("s were") : T(" was"));
- return WIMLIB_ERR_SPLIT_INVALID;
- }
- if (wim->hdr.part_number != 1) {
- ERROR("WIM `%"TS"' is not the first part of the split WIM.",
- wim->filename);
- return WIMLIB_ERR_SPLIT_INVALID;
- }
- for (unsigned i = 0; i < num_additional_swms; i++) {
- if (additional_swms[i]->hdr.total_parts != total_parts) {
- ERROR("WIM `%"TS"' says there are %u parts in the "
- "spanned set, but %u parts were provided",
- additional_swms[i]->filename,
- additional_swms[i]->hdr.total_parts,
- total_parts);
- return WIMLIB_ERR_SPLIT_INVALID;
- }
- }
-
- /* keep track of ctype and guid just to make sure they are the same for
- * all the WIMs. */
- ctype = wim->compression_type;
- guid = wim->hdr.guid;
-
- {
- /* parts_to_swms is not allocated at function scope because it
- * should only be allocated after num_additional_swms was
- * checked to be the same as wim->hdr.total_parts. Otherwise, it
- * could be unexpectedly high and cause a stack overflow. */
- WIMStruct *parts_to_swms[num_additional_swms];
- ZERO_ARRAY(parts_to_swms);
- for (unsigned i = 0; i < num_additional_swms; i++) {
-
- WIMStruct *swm = additional_swms[i];
-
- if (swm->compression_type != ctype) {
- ERROR("The split WIMs do not all have the same "
- "compression type");
- return WIMLIB_ERR_SPLIT_INVALID;
- }
- if (memcmp(guid, swm->hdr.guid, WIM_GID_LEN) != 0) {
- ERROR("The split WIMs do not all have the same "
- "GUID");
- return WIMLIB_ERR_SPLIT_INVALID;
- }
- if (swm->hdr.part_number == 1) {
- ERROR("WIMs `%"TS"' and `%"TS"' both are marked "
- "as the first WIM in the spanned set",
- wim->filename, swm->filename);
- return WIMLIB_ERR_SPLIT_INVALID;
- }
- if (swm->hdr.part_number == 0 ||
- swm->hdr.part_number > total_parts)
- {
- ERROR("WIM `%"TS"' says it is part %u in the "
- "spanned set, but the part number must "
- "be in the range [1, %u]",
- swm->filename, swm->hdr.part_number, total_parts);
- return WIMLIB_ERR_SPLIT_INVALID;
- }
- if (parts_to_swms[swm->hdr.part_number - 2])
- {
- ERROR("`%"TS"' and `%"TS"' are both marked as "
- "part %u of %u in the spanned set",
- parts_to_swms[swm->hdr.part_number - 2]->filename,
- swm->filename,
- swm->hdr.part_number,
- total_parts);
- return WIMLIB_ERR_SPLIT_INVALID;
- } else {
- parts_to_swms[swm->hdr.part_number - 2] = swm;
- }
- }
- }
- return 0;
-}
[WIMLIB_ERR_FUSERMOUNT]
= T("Could not execute the `fusermount' program, or it exited "
"with a failure status"),
+ [WIMLIB_ERR_GLOB_HAD_NO_MATCHES]
+ = T("The provided file glob did not match any files"),
[WIMLIB_ERR_ICONV_NOT_AVAILABLE]
= T("The iconv() function does not seem to work. "
"Maybe check to make sure the directory /usr/lib/gconv exists"),
[WIMLIB_ERR_LINK]
= T("Failed to create a hard or symbolic link when extracting "
"a file from the WIM"),
+ [WIMLIB_ERR_METADATA_NOT_FOUND]
+ = T("A required metadata resource could not be located"),
[WIMLIB_ERR_MKDIR]
= T("Failed to create a directory"),
[WIMLIB_ERR_MQUEUE]
wim->in_fd.fd = -1;
wim->out_fd.fd = -1;
}
+ INIT_LIST_HEAD(&wim->resource_wims);
return wim;
}
return WIMLIB_ERR_INVALID_IMAGE;
}
- if (wim->hdr.part_number != 1) {
- ERROR("Cannot select an image from a non-first part of a split WIM");
- return WIMLIB_ERR_SPLIT_UNSUPPORTED;
+ if (!wim_has_metadata(wim)) {
+ ERROR("\"%"TS"\" does not contain metadata resources!", wim->filename);
+ if (wim->hdr.part_number != 1)
+ ERROR("Specify the first part of the split WIM instead.");
+ return WIMLIB_ERR_METADATA_NOT_FOUND;
}
/* If a valid image is currently selected, it can be freed if it is not
WIMLIBAPI int
wimlib_print_metadata(WIMStruct *wim, int image)
{
- if (wim->hdr.part_number != 1) {
- ERROR("Cannot show the metadata from part %hu of a %hu-part split WIM!",
- wim->hdr.part_number, wim->hdr.total_parts);
- ERROR("Select the first part of the split WIM to see the metadata.");
- return WIMLIB_ERR_SPLIT_UNSUPPORTED;
- }
return for_image(wim, image, image_print_metadata);
}
if (!wim)
return;
+
+ while (!list_empty(&wim->resource_wims)) {
+ WIMStruct *resource_wim;
+
+ resource_wim = list_entry(wim->resource_wims.next,
+ WIMStruct, resource_wim_node);
+ if (resource_wim->is_owned_by_master) {
+ list_del(&resource_wim->resource_wim_node);
+ wimlib_free(resource_wim);
+ } else {
+ wimlib_unreference_resources(wim, &resource_wim, 1);
+ }
+ }
+
if (filedes_valid(&wim->in_fd))
filedes_close(&wim->in_fd);
if (filedes_valid(&wim->out_fd))
filedes_close(&wim->out_fd);
+
free_lookup_table(wim->lookup_table);
FREE(wim->filename);
stream_path = alloca(sizeof(wchar_t) *
(wcslen(path) + 1 +
wcslen(stream_name) + 1));
- swprintf(stream_path, L"%ls:%ls", path, stream_name);
+ tsprintf(stream_path, L"%ls:%ls", path, stream_name);
}
h = CreateFile(stream_path, FILE_WRITE_DATA, 0, NULL,
spath_buf_nbytes = (spath_nchars + 1) * sizeof(wchar_t);
spath = MALLOC(spath_buf_nbytes);
- swprintf(spath, L"%ls%ls%ls%ls",
+ tsprintf(spath, L"%ls%ls%ls%ls",
relpath_prefix, path, colonchar, stream_name);
/* Make a new wim_lookup_table_entry */
# include "config.h"
#endif
+#include <errno.h>
#include <pthread.h>
#include <shlwapi.h> /* for PathMatchSpecW() */
#include "wimlib/win32_common.h"
#include "wimlib/assert.h"
#include "wimlib/file_io.h"
+#include "wimlib/glob.h"
#include "wimlib/error.h"
#include "wimlib/util.h"
return ret;
}
+/* Replacement for glob() in Windows native builds that operates on wide
+ * characters. */
+int
+win32_wglob(const wchar_t *pattern, int flags,
+ int (*errfunc)(const wchar_t *epath, int eerrno),
+ glob_t *pglob)
+{
+ WIN32_FIND_DATAW dat;
+ DWORD err;
+ HANDLE hFind;
+ int ret;
+ size_t nspaces;
+
+ const wchar_t *backslash, *end_slash;
+ size_t prefix_len;
+
+ backslash = wcsrchr(pattern, L'\\');
+ end_slash = wcsrchr(pattern, L'/');
+
+ if (backslash > end_slash)
+ end_slash = backslash;
+
+ if (end_slash)
+ prefix_len = end_slash - pattern + 1;
+ else
+ prefix_len = 0;
+
+ /* This function does not support all functionality of the POSIX glob(),
+ * so make sure the parameters are consistent with supported
+ * functionality. */
+ wimlib_assert(errfunc == NULL);
+ wimlib_assert((flags & GLOB_ERR) == GLOB_ERR);
+ wimlib_assert((flags & ~(GLOB_NOSORT | GLOB_ERR)) == 0);
+
+ hFind = FindFirstFileW(pattern, &dat);
+ if (hFind == INVALID_HANDLE_VALUE) {
+ err = GetLastError();
+ if (err == ERROR_FILE_NOT_FOUND) {
+ errno = 0;
+ return GLOB_NOMATCH;
+ } else {
+ /* The other possible error codes for FindFirstFile()
+ * are undocumented. */
+ errno = EIO;
+ return GLOB_ABORTED;
+ }
+ }
+ pglob->gl_pathc = 0;
+ pglob->gl_pathv = NULL;
+ nspaces = 0;
+ do {
+ wchar_t *path;
+ if (pglob->gl_pathc == nspaces) {
+ size_t new_nspaces;
+ wchar_t **pathv;
+
+ new_nspaces = nspaces * 2 + 1;
+ pathv = REALLOC(pglob->gl_pathv,
+ new_nspaces * sizeof(pglob->gl_pathv[0]));
+ if (!pathv)
+ goto oom;
+ pglob->gl_pathv = pathv;
+ nspaces = new_nspaces;
+ }
+ size_t filename_len = wcslen(dat.cFileName);
+ size_t len_needed = prefix_len + filename_len;
+
+ path = MALLOC((len_needed + 1) * sizeof(wchar_t));
+ if (!path)
+ goto oom;
+
+ wmemcpy(path, pattern, prefix_len);
+ wmemcpy(path + prefix_len, dat.cFileName, filename_len + 1);
+ pglob->gl_pathv[pglob->gl_pathc++] = path;
+ } while (FindNextFileW(hFind, &dat));
+ err = GetLastError();
+ CloseHandle(hFind);
+ if (err == ERROR_NO_MORE_FILES) {
+ errno = 0;
+ return 0;
+ } else {
+ /* Other possible error codes for FindNextFile() are
+ * undocumented */
+ errno = EIO;
+ ret = GLOB_ABORTED;
+ goto fail_globfree;
+ }
+oom:
+ CloseHandle(hFind);
+ errno = ENOMEM;
+ ret = GLOB_NOSPACE;
+fail_globfree:
+ globfree(pglob);
+ return ret;
+}
+
+void
+globfree(glob_t *pglob)
+{
+ size_t i;
+ for (i = 0; i < pglob->gl_pathc; i++)
+ free(pglob->gl_pathv[i]);
+ free(pglob->gl_pathv);
+}
#endif /* __WIN32__ */
(image < 1 || image > wim->hdr.image_count))
return WIMLIB_ERR_INVALID_IMAGE;
- /* @wim must specify a standalone WIM, or at least the first part of a
- * split WIM. */
- if (wim->hdr.part_number != 1)
- return WIMLIB_ERR_SPLIT_UNSUPPORTED;
+ /* If we need to write metadata resources, make sure the ::WIMStruct has
+ * the needed information attached (e.g. is not a resource-only WIM,
+ * such as a non-first part of a split WIM). */
+ if (!wim_has_metadata(wim) &&
+ !(write_flags & WIMLIB_WRITE_FLAG_NO_METADATA))
+ return WIMLIB_ERR_METADATA_NOT_FOUND;
/* Check for contradictory flags. */
if ((write_flags & (WIMLIB_WRITE_FLAG_CHECK_INTEGRITY |
u64
wim_info_get_total_bytes(const struct wim_info *info)
{
- if (!info)
+ if (info)
+ return info->total_bytes;
+ else
return 0;
- return info->total_bytes;
}
u64
wim_info_get_image_hard_link_bytes(const struct wim_info *info, int image)
{
- return info->images[image - 1].hard_link_bytes;
+ if (info)
+ return info->images[image - 1].hard_link_bytes;
+ else
+ return 0;
}
u64
wim_info_get_image_total_bytes(const struct wim_info *info, int image)
{
- return info->images[image - 1].total_bytes;
+ if (info)
+ return info->images[image - 1].total_bytes;
+ else
+ return 0;
}
unsigned
wim_info_get_num_images(const struct wim_info *info)
{
- return info->num_images;
+ if (info)
+ return info->num_images;
+ else
+ return 0;
}
/* Returns a statically allocated string that is a string representation of the