/* Define to 1 if including even more debug messages. */
#undef ENABLE_MORE_DEBUG
-/* Define to 1 to enable support for copying security data */
-#undef ENABLE_SECURITY_DATA
-
/* Define to 1 if using vectorized implementation of SHA1 */
#undef ENABLE_SSSE3_SHA1
/* Define to 1 if using libcrypto SHA1 */
#undef WITH_LIBCRYPTO
+/* Define to 1 to enable support for NTFS-specific information */
+#undef WITH_NTFS_3G
+
/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
significant byte first (like Motorola and SPARC, unlike Intel). */
#if defined AC_APPLE_UNIVERSAL_BUILD
compressed data])
fi
-AC_MSG_CHECKING([whether to include support for copying security data])
-AC_ARG_ENABLE([security_data],
- AS_HELP_STRING([--disable-security-data], [disable
- the ability to retain the security data of
- existing WIMs]),
- [ENABLE_SECURITY_DATA=$enableval],
- [ENABLE_SECURITY_DATA=yes]
+AC_MSG_CHECKING([whether to include support for ntfs-3g])
+AC_ARG_WITH([ntfs-3g],
+ AS_HELP_STRING([--without-ntfs-3g], [build without NTFS-3g.
+ This will disable the ability to use NTFS-specific
+ information when capturing or applying WIMs to a
+ NTFS filesystem.])
+ [WITH_NTFS_3G=$enableval],
+ [WITH_NTFS_3G=yes]
)
-AC_MSG_RESULT([$ENABLE_SECURITY_DATA])
-if test "x$ENABLE_SECURITY_DATA" = "xyes"; then
- AC_DEFINE([ENABLE_SECURITY_DATA], [1], [Define to 1 to enable support
- for copying security data])
+AC_MSG_RESULT([$WITH_NTFS_3G])
+if test "x$WITH_NTFS_3G" = "xyes"; then
+ AC_DEFINE([WITH_NTFS_3G], [1], [Define to 1 to enable support for
+ NTFS-specific information])
fi
AC_MSG_CHECKING([whether to include support for mounting WIMs])
write an integrity table. If this option is not specified, no integrity table
is included in the new WIM file, even if there was one before.
.TP
-\fB--config\fR \fICONFIG_FILE\fR
-This option is currently unsupported.
-.TP
\fB--flags\fR \fIEDITIONID\fR
Specify a string to use in the <FLAGS> element of the XML data for the image.
-.TP
-\fB--verify\fR
-This option is currently unsupported.
.SH EXAMPLES
.IP
.TP
\fB--verbose\fR
Print the path to of each file or directory within the WIM image as it is extracted.
-.TP
-\fB--verify\fR
-This option is currently unsupported.
.SH EXAMPLES
.IP
is specified but \fITYPE\fR is not, the compression type is taken to be
"maximum", which is LZX compression. "fast" compression is XPRESS compression.
.TP
-\fB--config\fR \fICONFIG_FILE\fR
-This option is currently unsupported.
-.TP
\fB--flags\fR \fIEDITIONID\fR
Specify a string to use in the <FLAGS> element of the XML data for the image.
.TP
-\fB--norpfix
-This option is currently unsupported.
-.TP
-\fB--verify\fR
-This option is currently unsupported.
-.TP
\fB--verbose\fR
Print the names of files and directories as they are captured.
.SH SYNOPSIS
\fBimagex mount\fR \fIWIMFILE\fR (\fIIMAGE_NUM\fR | \fIIMAGE_NAME\fR) \
-\fIDIRECTORY\fR [--check]
+\fIDIRECTORY\fR [--check] [--stream-interface=\fIINTERFACE\fR]
.SH DESCRIPTION
.PP
.TP 6
\fB--check\fR
When reading \fIWIMFILE\fR, verify its integrity if the integrity table is
-present.
+present.
+.TP
+\fB--stream-interface\fR \fIINTERFACE\fR
+Specify the interface to alternate data streams (ADS) in the WIM that will be
+provided by the mounted filesystem. These are a NTFS feature that found their
+way into the WIM file format.
+
+If "none", it will be impossible to read or write the ADS.
+
+If "xattr" (default), the ADS will be accessible through extended attributes.
+Each ADS will be an extended attribute named "user.*", where the * is the name
+of the ADS. See \fBsetfattr\fR (1) and \fBgetfattr\fR (1).
+
+If "windows", the ADS will be accessible by specifing the filename, then a
+colon, then the name of the ADS; for example, "myfile:mystream".
+
.SH SEE ALSO
.BR imagex (1)
.SH SYNOPSIS
\fBimagex mountrw\fR \fIWIMFILE\fR (\fIIMAGE_NUM\fR | \fIIMAGE_NAME\fR) \
-\fIDIRECTORY\fR [--check]
+\fIDIRECTORY\fR [--check] [--stream-interface=\fIINTERFACE\fR]
.SH DESCRIPTION
.PP
\fB--check\fR
When reading \fIWIMFILE\fR, verify its integrity if the integrity table is
present.
+.TP
+\fB--stream-interface\fR \fIINTERFACE\fR
+Specify the interface to alternate data streams (ADS) in the WIM that will be
+provided by the mounted filesystem. These are a NTFS feature that found their
+way into the WIM file format.
+
+If "none", it will be impossible to read or write the ADS.
+
+If "xattr" (default), the ADS will be accessible through extended attributes.
+Each ADS will be an extended attribute named "user.*", where the * is the name
+of the ADS. See \fBsetfattr\fR (1) and \fBgetfattr\fR (1).
+
+If "windows", the ADS will be accessible by specifing the filename, then a
+colon, then the name of the ADS; for example, "myfile:mystream".
.SH SEE ALSO
.BR imagex (1)
static const char *usage_strings[] = {
[APPEND] =
" imagex append DIRECTORY WIMFILE [\"IMAGE_NAME\"] [\"DESCRIPTION\"] [--boot]\n"
-" [--check] [--config CONFIG_FILE] [--flags EDITIONID] [--verify]\n",
+" [--check] [--flags EDITIONID]\n",
[APPLY] =
" imagex apply WIMFILE [IMAGE_NUM | IMAGE_NAME | all] DIRECTORY [--check]\n"
-" [--verify] [--hardlink] [--symlink] [--verbose]\n",
+" [--hardlink] [--symlink] [--verbose]\n",
[CAPTURE] =
" imagex capture DIRECTORY WIMFILE [\"IMAGE_NAME\"] [\"DESCRIPTION\"]\n"
-" [--boot] [--check] [--compress[=TYPE]] [--config CONFIG_FILE]\n"
-" [--flags \"EditionID\"] [--norpfix] [--verify] [--verbose]\n",
+" l [--boot] [--check] [--compress[=TYPE]]\n"
+" [--flags \"EditionID\"] [--verbose]\n",
[DELETE] =
" imagex delete WIMFILE (IMAGE_NUM | IMAGE_NAME | all) [--check]\n",
[DIR] =
[EXPORT] =
" imagex export SRC_WIMFILE (SRC_IMAGE_NUM | SRC_IMAGE_NAME | all ) \n"
" DEST_WIMFILE [\"DEST_IMAGE_NAME\"] [\"DEST_IMAGE_DESCRIPTION\"]\n"
-" [--boot] [--check] [--compress[=TYPE]]\n",
+" [--boot] [--check] [--compress[=TYPE]]\n",
[INFO] =
" imagex info WIMFILE [IMAGE_NUM | IMAGE_NAME] [NEW_NAME]\n"
-" [NEW_DESC] [--boot] [--check] [--header] [--lookup-table]\n"
-" [--xml] [--extract-xml FILE] [--metadata]\n",
+" [NEW_DESC] [--boot] [--check] [--header] [--lookup-table]\n"
+" [--xml] [--extract-xml FILE] [--metadata]\n",
[JOIN] =
" imagex join [--check] WIMFILE SPLIT_WIM...\n",
[MOUNT] =
" imagex mount WIMFILE (IMAGE_NUM | IMAGE_NAME) DIRECTORY\n"
-" [--check] [--debug]\n",
+" [--check] [--debug] [--stream-interface=INTERFACE]\n",
[MOUNTRW] =
" imagex mountrw WIMFILE [IMAGE_NUM | IMAGE_NAME] DIRECTORY\n"
-" [--check] [--debug]\n",
+" [--check] [--debug] [--stream-interface=INTERFACE]\n",
[SPLIT] =
" imagex split WIMFILE SPLIT_WIMFILE PART_SIZE [--check]\n",
[UNMOUNT] =
static const struct option append_options[] = {
{"boot", no_argument, NULL, 'b'},
{"check", no_argument, NULL, 'c'},
- {"config", required_argument, NULL, 'C'},
{"flags", required_argument, NULL, 'f'},
- {"verify", no_argument, NULL, 'V'},
{NULL, 0, NULL, 0},
};
static const struct option apply_options[] = {
{"check", no_argument, NULL, 'c'},
- {"verify", no_argument, NULL, 'V'},
{"hardlink", no_argument, NULL, 'h'},
{"symlink", no_argument, NULL, 's'},
{"verbose", no_argument, NULL, 'v'},
+ {"ntfs", no_argument, NULL, 'N'},
{NULL, 0, NULL, 0},
};
static const struct option capture_options[] = {
{"boot", no_argument, NULL, 'b'},
{"check", no_argument, NULL, 'c'},
{"compress", optional_argument, NULL, 'x'},
- {"config", required_argument, NULL, 'C'},
{"flags", required_argument, NULL, 'f'},
- {"norpfix", no_argument, NULL, 'n'},
- {"verify", no_argument, NULL, 'V'},
- {"verbose", no_argument, NULL, 'v'},
+ {"verbose", no_argument, NULL,'v'},
+ {"ntfs", no_argument, NULL, 'N'},
{NULL, 0, NULL, 0},
};
static const struct option delete_options[] = {
static const struct option mount_options[] = {
{"check", no_argument, NULL, 'c'},
{"debug", no_argument, NULL, 'd'},
+ {"stream-interface", required_argument, NULL, 's'},
{NULL, 0, NULL, 0},
};
open_flags |= WIMLIB_OPEN_FLAG_CHECK_INTEGRITY;
write_flags |= WIMLIB_WRITE_FLAG_CHECK_INTEGRITY;
break;
- case 'C':
- /*config = optarg;*/
- break;
case 'f':
flags_element = optarg;
break;
- case 'V':
- /* verify */
- break;
default:
usage(APPEND);
return -1;
static int imagex_apply(int argc, const char **argv)
{
int c;
- int link_type = WIM_LINK_TYPE_NONE;
int open_flags = WIMLIB_OPEN_FLAG_SHOW_PROGRESS;
- bool verbose = false;
int image;
int num_images;
WIMStruct *w;
const char *wimfile;
const char *dir;
const char *image_num_or_name;
+ int extract_flags = 0;
for_opt(c, apply_options) {
switch (c) {
case 'c':
open_flags |= WIMLIB_OPEN_FLAG_CHECK_INTEGRITY;
break;
- case 'V':
- /* verify */
- break;
case 'h':
- link_type = WIM_LINK_TYPE_HARD;
+ extract_flags |= WIMLIB_EXTRACT_FLAG_HARDLINK;
break;
case 's':
- link_type = WIM_LINK_TYPE_SYMBOLIC;
+ extract_flags |= WIMLIB_EXTRACT_FLAG_SYMLINK;
break;
case 'v':
- verbose = true;
+ extract_flags |= WIMLIB_EXTRACT_FLAG_VERBOSE;
+ break;
+ case 'N':
+ extract_flags |= WIMLIB_EXTRACT_FLAG_NTFS;
break;
default:
usage(APPLY);
ret = -1;
goto done;
}
- ret = wimlib_set_output_dir(w, dir);
- if (ret != 0)
- goto done;
- wimlib_set_verbose(w, verbose);
- wimlib_set_link_type(w, link_type);
- ret = wimlib_extract_image(w, image);
+ ret = wimlib_extract_image(w, image, dir, extract_flags);
done:
wimlib_free(w);
return ret;
int add_image_flags = 0;
int write_flags = WIMLIB_WRITE_FLAG_SHOW_PROGRESS;
int compression_type = WIM_COMPRESSION_TYPE_NONE;
- const char *flags_element = NULL;
- bool verbose = false;
+ const char *flags_element = NULL;
const char *dir;
const char *wimfile;
const char *name;
if (compression_type == WIM_COMPRESSION_TYPE_INVALID)
return -1;
break;
- case 'C':
- /*config = optarg;*/
- break;
case 'f':
flags_element = optarg;
break;
- case 'n':
- /*norpfix = true;*/
- break;
case 'v':
- verbose = true;
+ add_image_flags |= WIMLIB_ADD_IMAGE_FLAG_VERBOSE;
break;
- case 'V':
- /*verify = true;*/
+ case 'N':
+ add_image_flags |= WIMLIB_ADD_IMAGE_FLAG_NTFS;
break;
default:
usage(CAPTURE);
if (ret != 0)
return ret;
- wimlib_set_verbose(w, verbose);
-
ret = wimlib_add_image(w, dir, name, desc, flags_element,
add_image_flags);
if (ret != 0) {
case 'd':
mount_flags |= WIMLIB_MOUNT_FLAG_DEBUG;
break;
+ case 's':
+ if (strcasecmp(optarg, "none") == 0)
+ mount_flags |= WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_NONE;
+ else if (strcasecmp(optarg, "xattr") == 0)
+ mount_flags |= WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_XATTR;
+ else if (strcasecmp(optarg, "windows") == 0)
+ mount_flags |= WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_WINDOWS;
+ else {
+ imagex_error("Unknown stream interface \"%s\"", optarg);
+ goto mount_usage;
+ }
+ break;
default:
- usage((mount_flags & WIMLIB_MOUNT_FLAG_READWRITE)
- ? MOUNTRW : MOUNT);
- return -1;
+ goto mount_usage;
}
}
argc -= optind;
argv += optind;
- if (argc != 2 && argc != 3) {
- usage((mount_flags & WIMLIB_MOUNT_FLAG_READWRITE)
- ? MOUNTRW : MOUNT);
- return -1;
- }
+ if (argc != 2 && argc != 3)
+ goto mount_usage;
wimfile = argv[0];
done:
wimlib_free(w);
return ret;
+mount_usage:
+ usage((mount_flags & WIMLIB_MOUNT_FLAG_READWRITE)
+ ? MOUNTRW : MOUNT);
+ return -1;
}
/* Split a WIM into a spanned set */
usage_all();
return 1;
}
+/*#ifndef WITH_NTFS_3G*/
+ /*ERROR("wimlib was not compiled with support for NTFS-3g, so we cannot extract");*/
+ /*ERROR("a WIM to a NTFS filesystem while preserving NTFS-specific metadata.");*/
+ /*ERROR("Please apply the WIM to a directory rather than a block device, ");*/
+ /*ERROR("and without the NTFS flag; or compile in support for NTFS-3g.");*/
+ /*return WIMLIB_ERR_UNSUPPORTED;*/
+/*#endif*/
if (file_attr_flags[i].flag & dentry->attributes)
printf(" WIM_FILE_ATTRIBUTE_%s is set\n",
file_attr_flags[i].name);
-#ifdef ENABLE_SECURITY_DATA
printf("Security ID = %d\n", dentry->security_id);
-#endif
printf("Subdir offset = %"PRIu64"\n", dentry->subdir_offset);
/*printf("Unused1 = %"PRIu64"\n", dentry->unused1);*/
/*printf("Unused2 = %"PRIu64"\n", dentry->unused2);*/
printf("Hash = ");
print_hash(dentry->hash);
putchar('\n');
- /*printf("Reparse Tag = %u\n", dentry->reparse_tag);*/
+ printf("Reparse Tag = %u\n", dentry->reparse_tag);
printf("Hard Link Group = %"PRIu64"\n", dentry->hard_link);
- /*printf("Number of Streams = %hu\n", dentry->streams);*/
+ printf("Number of Alternate Data Streams = %hu\n", dentry->num_ads);
printf("Filename = \"");
print_string(dentry->file_name, dentry->file_name_len);
puts("\"");
{
memset(dentry, 0, sizeof(struct dentry));
dentry->refcnt = 1;
+ dentry->security_id = -1;
}
/*
{
dentry->length = WIM_DENTRY_DISK_SIZE + dentry->file_name_len +
2 + dentry->short_name_len;
+ for (u16 i = 0; i < dentry->num_ads; i++)
+ dentry->length += ads_entry_length(&dentry->ads_entries[i]);
/* Must be multiple of 8. */
- dentry->length += (8 - dentry->length % 8) % 8;
+ dentry->length = (dentry->length + 7) & ~7;
}
/* Changes the name of a dentry to @new_name. Only changes the file_name and
for_dentry_in_tree(root, calculate_dentry_statistics, &stats);
}
+static int read_ads_entries(const u8 *p, struct dentry *dentry,
+ unsigned remaining_size)
+{
+ u16 num_ads = dentry->num_ads;
+ struct ads_entry *ads_entries = CALLOC(num_ads, sizeof(struct ads_entry));
+ int ret;
+ if (!ads_entries) {
+ ERROR("Could not allocate memory for %u alternate data stream "
+ "entries", num_ads);
+ return WIMLIB_ERR_NOMEM;
+ }
+ for (u16 i = 0; i < num_ads; i++) {
+ struct ads_entry *cur_entry = &ads_entries[i];
+ u64 length;
+ size_t utf8_len;
+ /* Read the base stream entry, excluding the stream name. */
+ if (remaining_size < WIM_ADS_ENTRY_DISK_SIZE) {
+ ERROR("Stream entries go past end of directory entry");
+ ret = WIMLIB_ERR_INVALID_DENTRY;
+ goto out_free_ads_entries;
+ }
+ remaining_size -= WIM_ADS_ENTRY_DISK_SIZE;
+
+ p = get_u64(p, &length); /* ADS entry length */
+ p += 8; /* Unused */
+ p = get_bytes(p, WIM_HASH_SIZE, (u8*)cur_entry->hash);
+ p = get_u16(p, &cur_entry->stream_name_len);
+ cur_entry->stream_name = NULL;
+ cur_entry->stream_name_utf8 = NULL;
+
+ if (remaining_size < cur_entry->stream_name_len) {
+ ERROR("Stream entries go past end of directory entry");
+ ret = WIMLIB_ERR_INVALID_DENTRY;
+ goto out_free_ads_entries;
+ }
+
+ cur_entry->stream_name = MALLOC(cur_entry->stream_name_len);
+ if (!cur_entry->stream_name) {
+ ret = WIMLIB_ERR_NOMEM;
+ goto out_free_ads_entries;
+ }
+ p = get_bytes(p, cur_entry->stream_name_len,
+ (u8*)cur_entry->stream_name);
+ cur_entry->stream_name_utf8 = utf16_to_utf8(cur_entry->stream_name,
+ cur_entry->stream_name_len,
+ &utf8_len);
+ cur_entry->stream_name_len_utf8 = utf8_len;
+
+ if (!cur_entry->stream_name_utf8) {
+ ret = WIMLIB_ERR_NOMEM;
+ goto out_free_ads_entries;
+ }
+ }
+ dentry->ads_entries = ads_entries;
+ return 0;
+out_free_ads_entries:
+ for (u16 i = 0; i < num_ads; i++) {
+ FREE(ads_entries[i].stream_name);
+ FREE(ads_entries[i].stream_name_utf8);
+ }
+ FREE(ads_entries);
+ return ret;
+}
+
/*
* Reads a directory entry from the metadata resource.
*/
u16 short_name_len;
u16 file_name_len;
size_t file_name_utf8_len;
+ int ret;
dentry_common_init(dentry);
}
p = get_u32(p, &dentry->attributes);
-#ifdef ENABLE_SECURITY_DATA
p = get_u32(p, (u32*)&dentry->security_id);
-#else
- p += sizeof(u32);
-#endif
p = get_u64(p, &dentry->subdir_offset);
/* 2 unused fields */
p = get_bytes(p, WIM_HASH_SIZE, dentry->hash);
- /* Currently ignoring reparse_tag. */
- p += sizeof(u32);
+ p = get_u32(p, &dentry->reparse_tag);
/* The reparse_reserved field does not actually exist. */
p = get_u64(p, &dentry->hard_link);
- /* Currently ignoring streams. */
- p += sizeof(u16);
+ p = get_u16(p, &dentry->num_ads);
p = get_u16(p, &short_name_len);
p = get_u16(p, &file_name_len);
if (!file_name_utf8) {
ERROR("Failed to allocate memory to convert UTF-16 "
"filename (%hu bytes) to UTF-8", file_name_len);
+ ret = WIMLIB_ERR_NOMEM;
goto out_free_file_name;
}
if (!short_name) {
ERROR("Failed to allocate %hu bytes for short filename",
short_name_len);
+ ret = WIMLIB_ERR_NOMEM;
goto out_free_file_name_utf8;
}
get_bytes(p, short_name_len, short_name);
+ if (dentry->num_ads != 0) {
+ ret = read_ads_entries(p, dentry,
+ dentry->length - calculated_size);
+ if (ret != 0)
+ goto out_free_short_name;
+ }
+
dentry->file_name = file_name;
dentry->file_name_utf8 = file_name_utf8;
dentry->short_name = short_name;
dentry->file_name_utf8_len = file_name_utf8_len;
dentry->short_name_len = short_name_len;
return 0;
+out_free_short_name:
+ FREE(short_name);
out_free_file_name_utf8:
- FREE(dentry->file_name_utf8);
+ FREE(file_name_utf8);
out_free_file_name:
- FREE(dentry->file_name);
- return WIMLIB_ERR_NOMEM;
+ FREE(file_name);
+ return ret;
}
/*
*
* @dentry: The dentry structure.
* @p: The memory location to write the data to.
- * @return: True on success, false on failure.
+ * @return: Pointer to the byte after the last byte we wrote as part of the
+ * dentry.
*/
static u8 *write_dentry(const struct dentry *dentry, u8 *p)
{
memset(p, 0, dentry->length);
p = put_u64(p, dentry->length);
p = put_u32(p, dentry->attributes);
-#ifdef ENABLE_SECURITY_DATA
p = put_u32(p, dentry->security_id);
-#else
- p = put_u32(p, (u32)(-1));
-#endif
p = put_u64(p, dentry->subdir_offset);
p = put_u64(p, 0); /* unused1 */
p = put_u64(p, 0); /* unused2 */
else
DEBUG("zero hash for %s\n", dentry->file_name_utf8);
p += WIM_HASH_SIZE;
- p = put_u32(p, 0); /* reparse_tag */
+ p = put_u32(p, dentry->reparse_tag);
p = put_u64(p, dentry->hard_link);
- p = put_u16(p, 0); /*streams */
+ p = put_u16(p, dentry->num_ads); /*streams */
p = put_u16(p, dentry->short_name_len);
p = put_u16(p, dentry->file_name_len);
p = put_bytes(p, dentry->file_name_len, (u8*)dentry->file_name);
p = put_u16(p, 0); /* filename padding, 2 bytes. */
p = put_bytes(p, dentry->short_name_len, (u8*)dentry->short_name);
+ for (u16 i = 0; i < dentry->num_ads; i++) {
+ p = put_u64(p, ads_entry_length(&dentry->ads_entries[i]));
+ p = put_u64(p, 0); /* Unused */
+ p = put_bytes(p, WIM_HASH_SIZE, dentry->ads_entries[i].hash);
+ p = put_u16(p, dentry->ads_entries[i].stream_name_len);
+ p = put_bytes(p, dentry->ads_entries[i].stream_name_len,
+ (u8*)dentry->ads_entries[i].stream_name);
+ }
return orig_p + dentry->length;
}
/* Size of the struct dentry up to and including the file_name_len. */
#define WIM_DENTRY_DISK_SIZE 102
+#define WIM_ADS_ENTRY_DISK_SIZE (2 * sizeof(u64) + WIM_HASH_SIZE + sizeof(u16))
+
+/* Alternate data stream entry */
+struct ads_entry {
+ /* SHA-1 message digest of stream contents */
+ u8 hash[WIM_HASH_SIZE];
+
+ /* Length of stream name (UTF-16) */
+ u16 stream_name_len;
+
+ /* Length of stream name (UTF-8) */
+ u16 stream_name_len_utf8;
+
+ /* Stream name (UTF-16) */
+ char *stream_name;
+
+ /* Stream name (UTF-8) */
+ char *stream_name_utf8;
+};
+
+static inline u64 ads_entry_length(const struct ads_entry *entry)
+{
+ return WIM_ADS_ENTRY_DISK_SIZE + entry->stream_name_len;
+}
+
/* In-memory structure for a directory entry. There is a directory tree for
* each image in the WIM. */
struct dentry {
/* The index of the node in the security table that contains this file's
* security information. If -1, no security information exists for this
* file. */
-#ifdef ENABLE_SECURITY_DATA
int32_t security_id;
-#endif
/* The offset, from the start of the metadata section, of this directory
* entry's child files. 0 if the directory entry has no children. */
/* A hash of the file's contents. */
u8 hash[WIM_HASH_SIZE];
- /* Identity of a reparse point (whatever that is). Currently ignoring
- * this field*/
- //u32 reparse_tag;
+ /* Identity of a reparse point. See
+ * http://msdn.microsoft.com/en-us/library/windows/desktop/aa365503(v=vs.85).aspx
+ * for what a reparse point is. */
+ u32 reparse_tag;
/* Although M$'s documentation does not tell you this, it seems that the
* reparse_reserved field does not actually exist. So the hard_link
* the set will share the same value for this field. */
u64 hard_link;
- /* Number of WIMStreamEntry structures that follow this struct dentry.
- * Currently ignoring this field. */
- //u16 streams;
+ /* Number of alternate data streams associated with this file. */
+ u16 num_ads;
/* Length of short filename, in bytes, not including the terminating
* zero wide-character. */
char *full_path_utf8;
u32 full_path_utf8_len;
- /* Stream entries for this dentry. Currently being ignored. */
- //struct WIMStreamEntry *stream_entries;
+ /* Alternate stream entries for this dentry. */
+ struct ads_entry *ads_entries;
/* Number of references to the dentry tree itself, as in multiple
* WIMStructs */
#include <string.h>
#include <errno.h>
+#ifdef WITH_NTFS_3G
+#include <ntfs-3g/volume.h>
+#endif
+
+/* Sets and creates the directory to which files are to be extracted when
+ * extracting files from the WIM. */
+static int set_output_dir(WIMStruct *w, const char *dir)
+{
+ char *p;
+ DEBUG("Setting output directory to `%s'", dir);
+
+ p = STRDUP(dir);
+ if (!p) {
+ ERROR("Out of memory");
+ return WIMLIB_ERR_NOMEM;
+ }
+
+ if (mkdir(dir, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) != 0) {
+ if (errno == EEXIST) {
+ DEBUG("`%s' already exists", dir);
+ goto done;
+ }
+ ERROR_WITH_ERRNO("Cannot create directory `%s'", dir);
+ FREE(p);
+ return WIMLIB_ERR_MKDIR;
+ } else {
+ DEBUG("Created directory `%s'", dir);
+ }
+done:
+ FREE(w->output_dir);
+ w->output_dir = p;
+ return 0;
+}
/*
* Extracts a regular file from the WIM archive.
const struct dentry *dentry,
const char *output_path)
{
- struct lookup_table *lookup_table;
- int link_type;
- bool is_multi_image_extraction;
struct lookup_table_entry *lte;
int ret;
int out_fd;
const struct resource_entry *res_entry;
- lookup_table = w->lookup_table;
- link_type = w->link_type;
- is_multi_image_extraction = w->is_multi_image_extraction;
- lte = lookup_resource(lookup_table, dentry->hash);
+ lte = lookup_resource(w->lookup_table, dentry->hash);
/* If we already extracted the same file or a hard link copy of it, we
* may be able to simply create a link. The exact action is specified
* by the current @link_type. */
- if (link_type != WIM_LINK_TYPE_NONE && lte && lte->out_refcnt != 0) {
+ if ((w->extract_flags & (WIMLIB_EXTRACT_FLAG_SYMLINK | WIMLIB_EXTRACT_FLAG_HARDLINK)) &&
+ lte && lte->out_refcnt != 0)
+ {
wimlib_assert(lte->file_on_disk);
- if (link_type == WIM_LINK_TYPE_HARD) {
+ if (w->extract_flags & WIMLIB_EXTRACT_FLAG_HARDLINK) {
if (link(lte->file_on_disk, output_path) != 0) {
ERROR_WITH_ERRNO("Failed to hard link "
"`%s' to `%s'",
num_output_dir_path_components =
get_num_path_components(w->output_dir);
- if (is_multi_image_extraction) {
+ if (w->is_multi_image_extraction) {
num_path_components++;
num_output_dir_path_components--;
}
size_t len = strlen(w->output_dir);
char output_path[len + dentry->full_path_utf8_len + 1];
- if (w->verbose)
+ if (w->extract_flags & WIMLIB_EXTRACT_FLAG_VERBOSE)
puts(dentry->full_path_utf8);
memcpy(output_path, w->output_dir, len);
memcpy(output_path + len, dentry->full_path_utf8, dentry->full_path_utf8_len);
output_path[len + dentry->full_path_utf8_len] = '\0';
-
if (dentry_is_regular_file(dentry)) {
return extract_regular_file(w, dentry, output_path);
} else {
/* Image name is empty. Use image number instead */
sprintf(buf + output_path_len + 1, "%d", image);
}
- ret = wimlib_set_output_dir(w, buf);
+ ret = set_output_dir(w, buf);
if (ret != 0)
goto done;
ret = extract_single_image(w, image);
done:
/* Restore original output directory */
buf[output_path_len + 1] = '\0';
- return wimlib_set_output_dir(w, buf);
+ return 0;
}
/* Extracts a single image or all images from a WIM file. */
-WIMLIBAPI int wimlib_extract_image(WIMStruct *w, int image)
+WIMLIBAPI int wimlib_extract_image(WIMStruct *w, int image,
+ const char *output_dir, int flags)
{
- if (!w->output_dir) {
- ERROR("No output directory selected.");
- return WIMLIB_ERR_NOTDIR;
+ int ret;
+ if (!output_dir)
+ return WIMLIB_ERR_INVALID_PARAM;
+ if ((flags & (WIMLIB_EXTRACT_FLAG_SYMLINK | WIMLIB_EXTRACT_FLAG_HARDLINK))
+ == (WIMLIB_EXTRACT_FLAG_SYMLINK | WIMLIB_EXTRACT_FLAG_HARDLINK))
+ return WIMLIB_ERR_INVALID_PARAM;
+
+ ret = set_output_dir(w, output_dir);
+ if (ret != 0)
+ return ret;
+
+ if ((flags & WIMLIB_EXTRACT_FLAG_NTFS)) {
+ #ifdef WITH_NTFS_3G
+ unsigned long mnt_flags;
+ ret = ntfs_check_if_mounted(output_dir, &mnt_flags);
+ if (ret != 0) {
+ ERROR_WITH_ERRNO("NTFS-3g: Cannot determine if `%s' "
+ "is mounted", output_dir);
+ return WIMLIB_ERR_NTFS_3G;
+ }
+ if (!(mnt_flags & NTFS_MF_MOUNTED)) {
+ ERROR("NTFS-3g: Filesystem on `%s' is not mounted ",
+ output_dir);
+ }
+ if (mnt_flags & NTFS_MF_READONLY) {
+ ERROR("NTFS-3g: Filesystem on `%s' is mounted "
+ "read-only", output_dir);
+ return WIMLIB_ERR_NTFS_3G;
+ }
+ #else
+ ERROR("wimlib was compiled without support for NTFS-3g, so");
+ ERROR("we cannot extract a WIM image while preserving NTFS-");
+ ERROR("specific information");
+ return WIMLIB_ERR_UNSUPPORTED;
+ #endif
}
+ w->extract_flags = flags;
if (image == WIM_ALL_IMAGES) {
w->is_multi_image_extraction = true;
- return extract_all_images(w);
+ ret = extract_all_images(w);
} else {
w->is_multi_image_extraction = false;
- return extract_single_image(w, image);
- }
-
-}
-
-/* Sets and creates the directory to which files are to be extracted when
- * extracting files from the WIM. */
-WIMLIBAPI int wimlib_set_output_dir(WIMStruct *w, const char *dir)
-{
- char *p;
- DEBUG("Setting output directory to `%s'", dir);
-
- if (!dir) {
- ERROR("Must specify a directory!");
- return WIMLIB_ERR_INVALID_PARAM;
- }
- p = STRDUP(dir);
- if (!p) {
- ERROR("Out of memory");
- return WIMLIB_ERR_NOMEM;
- }
-
- if (mkdir(dir, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) != 0) {
- if (errno == EEXIST) {
- DEBUG("`%s' already exists", dir);
- goto done;
- }
- ERROR_WITH_ERRNO("Cannot create directory `%s'", dir);
- FREE(p);
- return WIMLIB_ERR_MKDIR;
- } else {
- DEBUG("Created directory `%s'", dir);
+ ret = extract_single_image(w, image);
}
-done:
- FREE(w->output_dir);
- w->output_dir = p;
- return 0;
-}
+ return ret;
-WIMLIBAPI int wimlib_set_link_type(WIMStruct *w, int link_type)
-{
- switch (link_type) {
- case WIM_LINK_TYPE_NONE:
- case WIM_LINK_TYPE_HARD:
- case WIM_LINK_TYPE_SYMBOLIC:
- w->link_type = link_type;
- return 0;
- default:
- return WIMLIB_ERR_INVALID_PARAM;
- }
}
-
ERROR("Unexpected chunk size of %u! Ask the author to "
"implement support for other chunk sizes.",
chunk_size);
- ERROR("(Or it might just be that the WIM header is "
- "invalid.)", chunk_size);
+ ERROR("(Or it might just be that the WIM header is invalid.)");
return WIMLIB_ERR_INVALID_CHUNK_SIZE;
}
"the %"PRIu64" bytes from the end of the header to the",
expected_num_entries, bytes_to_check);
ERROR("end of the lookup table with a chunk size of %u, but "
- "there were only %u entries", expected_num_entries,
- bytes_to_check, chunk_size, num_entries);
+ "there were only %u entries", chunk_size, num_entries);
ret = WIMLIB_ERR_INVALID_INTEGRITY_TABLE;
goto out;
}
{
struct lookup_table_entry *lte;
- lte = MALLOC(sizeof(struct lookup_table_entry));
+ lte = CALLOC(1, sizeof(struct lookup_table_entry));
if (!lte) {
ERROR("Out of memory (tried to allocate %zu bytes for "
"lookup table entry)",
return NULL;
}
- lte->next = NULL;
- lte->file_on_disk = NULL;
- lte->other_wim_fp = NULL;
lte->part_number = 1;
lte->refcnt = 1;
- lte->staging_num_times_opened = 0;
return lte;
}
struct lookup_table *lt)
{
free_dentry_tree(imd->root_dentry, lt, true);
-#ifdef ENABLE_SECURITY_DATA
free_security_data(imd->security_data);
-#endif
/* Get rid of the lookup table entry for this image's metadata resource
* */
struct lookup_table_entry *metadata_lte;
struct image_metadata *imd;
struct image_metadata *new_imd;
-#ifdef ENABLE_SECURITY_DATA
struct wim_security_data *sd;
-#endif
DEBUG("Reallocating image metadata array for image_count = %u",
w->hdr.image_count + 1);
metadata_lte = new_lookup_table_entry();
if (!metadata_lte)
goto out_free_imd;
-#ifdef ENABLE_SECURITY_DATA
sd = CALLOC(1, sizeof(struct wim_security_data));
if (!sd)
goto out_free_metadata_lte;
sd->refcnt = 1;
sd->total_length = 8;
-#endif
metadata_lte->resource_entry.flags = WIM_RESHDR_FLAG_METADATA;
randomize_byte_array(metadata_lte->hash, WIM_HASH_SIZE);
new_imd->metadata_lte = metadata_lte;
new_imd->modified = true;
new_imd->root_dentry = root_dentry;
-#ifdef ENABLE_SECURITY_DATA
new_imd->security_data = sd;
-#endif
FREE(w->image_metadata);
w->image_metadata = imd;
ret = add_new_dentry_tree(dest_wim, root);
if (ret != 0)
return ret;
-#ifdef ENABLE_SECURITY_DATA
/* Bring over old security data */
struct wim_security_data *sd = wim_security_data(src_wim);
struct image_metadata *new_imd = wim_get_current_image_metadata(dest_wim);
free_security_data(new_imd->security_data);
new_imd->security_data = sd;
sd->refcnt++;
-#endif
if (flags & WIMLIB_EXPORT_FLAG_BOOT) {
DEBUG("Setting boot_idx to %d", dest_wim->hdr.image_count);
int num_images;
int i;
int ret;
- struct image_metadata *imd;
if (image == WIM_ALL_IMAGES) {
num_images = w->hdr.image_count;
/* Create a lookup table entry having the same hash value */
lte = new_lookup_table_entry();
- lte->staging_num_times_opened = 0;
- lte->resource_entry.original_size = 0;
memcpy(lte->hash, dentry->hash, WIM_HASH_SIZE);
fd = create_staging_file(&tmpfile_name);
if (flags & WIMLIB_MOUNT_FLAG_READWRITE)
wim_get_current_image_metadata(wim)->modified = true;
+ if (!(flags & (WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_NONE |
+ WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_XATTR |
+ WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_WINDOWS)))
+ flags |= WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_XATTR;
+
mount_dir = dir;
working_directory = getcwd(NULL, 0);
if (!working_directory) {
if (resource_size != resource_original_size) {
ERROR("Resource with original size %"PRIu64" bytes is "
"marked as uncompressed, but its actual size is "
- "%"PRIu64" bytes", resource_size);
+ "%"PRIu64" bytes",
+ resource_original_size, resource_size);
return WIMLIB_ERR_INVALID_RESOURCE_SIZE;
}
return read_uncompressed_resource(fp,
int ret;
const struct resource_entry *res_entry;
struct dentry *dentry;
-#ifdef ENABLE_SECURITY_DATA
struct wim_security_data *sd;
-#endif
res_entry = &imd->metadata_lte->resource_entry;
* The security data starts with a 4-byte integer giving its total
* length. */
-#ifdef ENABLE_SECURITY_DATA
/* Read the security data into a wim_security_data structure. */
ret = read_security_data(buf, res_entry->original_size, &sd);
if (ret != 0)
goto out_free_buf;
-#endif
dentry = MALLOC(sizeof(struct dentry));
if (!dentry) {
if (ret != 0)
goto out_free_dentry_tree;
-#ifdef ENABLE_SECURITY_DATA
imd->security_data = sd;
-#endif
imd->root_dentry = dentry;
goto out_free_buf;
out_free_security_data:
-#ifdef ENABLE_SECURITY_DATA
free_security_data(sd);
-#endif
out_free_dentry_tree:
free_dentry_tree(dentry, NULL, false);
out_free_buf:
if (metadata_offset == -1)
return WIMLIB_ERR_WRITE;
- #ifdef ENABLE_SECURITY_DATA
struct wim_security_data *sd = wim_security_data(w);
if (sd)
subdir_offset = sd->total_length + root->length + 8;
else
- #endif
subdir_offset = 8 + root->length + 8;
calculate_subdir_offsets(root, &subdir_offset);
metadata_original_size = subdir_offset;
"metadata resource", metadata_original_size);
return WIMLIB_ERR_NOMEM;
}
- #ifdef ENABLE_SECURITY_DATA
- /* Write the security data. */
+
p = write_security_data(sd, buf);
- #else
- p = put_u32(buf, 8); /* Total length of security data. */
- p = put_u32(p, 0); /* Number of security data entries. */
- #endif
DEBUG("Writing dentry tree.");
p = write_dentry_tree(root, p);
return WIMLIB_ERR_OPEN;
}
- if (w->verbose)
- puts(lte->file_on_disk);
-
ret = transfer_file_resource(in_fp, len, len, 0,
WIM_COMPRESSION_TYPE_NONE, out_fp,
out_wim_ctype, output_res_entry);
#include "io.h"
#include "security.h"
-#ifdef ENABLE_SECURITY_DATA
-
/*
* Reads the security data from the metadata resource.
*
sd->refcnt--;
}
}
-
-#endif
FILE *fp = fopen(p, "r+b");
if (!fp) {
- ERROR_WITH_ERRNO("Failed to open `%s'");
+ ERROR_WITH_ERRNO("Failed to open `%s'", p);
return WIMLIB_ERR_OPEN;
}
u8 buf[4];
"identify a WIM file",
[WIMLIB_ERR_NO_FILENAME]
= "The WIM is not identified with a filename",
+ [WIMLIB_ERR_NTFS_3G]
+ = "NTFS-3g encountered an error (check errno)",
[WIMLIB_ERR_OPEN]
= "Failed to open a file",
[WIMLIB_ERR_OPENDIR]
static int print_metadata(WIMStruct *w)
{
-#ifdef ENABLE_SECURITY_DATA
print_security_data(wim_security_data(w));
-#endif
return for_dentry_in_tree(wim_root_dentry(w), print_dentry,
w->lookup_table);
}
WIMStruct *new_wim_struct()
{
- WIMStruct *w;
-
- w = CALLOC(1, sizeof(WIMStruct));
- if (!w)
- return NULL;
- w->link_type = WIM_LINK_TYPE_NONE;
- w->current_image = WIM_NO_IMAGE;
- return w;
+ return CALLOC(1, sizeof(WIMStruct));
}
/*
WIMStruct *w = wim_p;
if (lte->resource_entry.flags & WIM_RESHDR_FLAG_METADATA) {
+ /*fprintf(stderr, "found mlte at %u\n", lte->resource_entry.offset);*/
if (w->current_image == w->hdr.image_count) {
ERROR("Expected only %u images, but found more",
w->hdr.image_count);
return resource_compression_type(wim_ctype, entry->flags);
}
-WIMLIBAPI void wimlib_set_verbose(WIMStruct *w, bool verbose)
-{
- w->verbose = verbose;
-}
-
/*
* Creates a WIMStruct for a new WIM file.
*/
DEBUG("Freeing image %u", w->current_image);
free_dentry_tree(imd->root_dentry, NULL, false);
imd->root_dentry = NULL;
-#ifdef ENABLE_SECURITY_DATA
free_security_data(imd->security_data);
imd->security_data = NULL;
-#endif
}
}
w->fp = fopen(in_wim_path, "rb");
if (!w->fp) {
- ERROR_WITH_ERRNO("Failed to open the file `%s' for reading");
+ ERROR_WITH_ERRNO("Failed to open the file `%s' for reading",
+ in_wim_path);
return WIMLIB_ERR_OPEN;
}
for (i = 0; i < w->hdr.image_count; i++) {
free_dentry_tree(w->image_metadata[i].root_dentry,
NULL, false);
- #ifdef ENABLE_SECURITY_DATA
free_security_data(w->image_metadata[i].security_data);
- #endif
}
FREE(w->image_metadata);
}
};
/** Mount the WIM read-write. */
-#define WIMLIB_MOUNT_FLAG_READWRITE 0x1
+#define WIMLIB_MOUNT_FLAG_READWRITE 0x00000001
/** For debugging only. (This passes the @c -d flag to @c fuse_main()).*/
-#define WIMLIB_MOUNT_FLAG_DEBUG 0x2
+#define WIMLIB_MOUNT_FLAG_DEBUG 0x00000002
+
+/** Do not allow accessing alternate data streams. */
+#define WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_NONE 0x00000010
+
+/** Access alternate data streams through extended file attributes. This is the
+ * default mode. */
+#define WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_XATTR 0x00000020
+
+/** Access alternate data streams by specifying the file name, a colon, then the
+ * alternate file stream name. */
+#define WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_WINDOWS 0x00000040
/** Include an integrity table in the new WIM being written during the unmount.
* Ignored for read-only mounts. */
-#define WIMLIB_UNMOUNT_FLAG_CHECK_INTEGRITY 0x1
+#define WIMLIB_UNMOUNT_FLAG_CHECK_INTEGRITY 0x00000001
/** Unless this flag is given, changes to a mounted WIM are discarded. Ignored
* for read-only mounts. */
-#define WIMLIB_UNMOUNT_FLAG_COMMIT 0x2
+#define WIMLIB_UNMOUNT_FLAG_COMMIT 0x00000002
/** Include an integrity table in the new WIM file. */
-#define WIMLIB_WRITE_FLAG_CHECK_INTEGRITY 0x1
+#define WIMLIB_WRITE_FLAG_CHECK_INTEGRITY 0x00000001
/** Print progress information when writing the integrity table. */
-#define WIMLIB_WRITE_FLAG_SHOW_PROGRESS 0x2
+#define WIMLIB_WRITE_FLAG_SHOW_PROGRESS 0x00000002
/** Mark the image being added as the bootable image of the WIM. */
-#define WIMLIB_ADD_IMAGE_FLAG_BOOT 0x1
+#define WIMLIB_ADD_IMAGE_FLAG_BOOT 0x00000001
+
+/** Print the name of each file or directory as it is scanned to be included in
+ * the WIM image. */
+#define WIMLIB_ADD_IMAGE_FLAG_VERBOSE 0x00000002
+
+/** Apply NTFS-specific information to the captured WIM image. This flag can
+ * only be specified if the directory being captured is on a NTFS filesystem
+ * mounted with NTFS-3g, and wimlib was compiled with support for NTFS-3g */
+#define WIMLIB_ADD_IMAGE_FLAG_NTFS 0x00000004
/** See documentation for wimlib_export_image(). */
-#define WIMLIB_EXPORT_FLAG_BOOT 0x1
+#define WIMLIB_EXPORT_FLAG_BOOT 0x00000001
/** Verify the integrity of the WIM if an integrity table is present. */
-#define WIMLIB_OPEN_FLAG_CHECK_INTEGRITY 0x1
+#define WIMLIB_OPEN_FLAG_CHECK_INTEGRITY 0x00000001
/** Print progress information when verifying integrity table. */
-#define WIMLIB_OPEN_FLAG_SHOW_PROGRESS 0x2
+#define WIMLIB_OPEN_FLAG_SHOW_PROGRESS 0x00000002
/** If this flag is not given, an error is issued if the WIM is part of a split
* WIM. */
-#define WIMLIB_OPEN_FLAG_SPLIT_OK 0x4
+#define WIMLIB_OPEN_FLAG_SPLIT_OK 0x00000004
+
+
+/** When identical files are extracted from the WIM, hard link them together. */
+#define WIMLIB_EXTRACT_FLAG_HARDLINK 0x00000001
+
+/** When identical files are extracted from the WIM, symlink them together. */
+#define WIMLIB_EXTRACT_FLAG_SYMLINK 0x00000002
+
+/** Apply NTFS-specific information when applying the WIM image. This flag can
+ * only be specified if the output directory is on a NTFS filesystem mounted
+ * with NTFS-3g, and wimlib was compiled with support for NTFS-3g */
+#define WIMLIB_EXTRACT_FLAG_NTFS 0x00000004
+
+/** Print the name of each file as it is extracted from the WIM image. */
+#define WIMLIB_EXTRACT_FLAG_VERBOSE 0x00000008
/**
* Possible values of the error code returned by many functions in wimlib.
WIMLIB_ERR_NOTDIR,
WIMLIB_ERR_NOT_A_WIM_FILE,
WIMLIB_ERR_NO_FILENAME,
+ WIMLIB_ERR_NTFS_3G,
WIMLIB_ERR_OPEN,
WIMLIB_ERR_OPENDIR,
WIMLIB_ERR_READ,
* @retval ::WIMLIB_ERR_WRITE
* Failed to write a file being extracted.
*/
-extern int wimlib_extract_image(WIMStruct *wim, int image);
+extern int wimlib_extract_image(WIMStruct *wim, int image,
+ const char *output_dir, int flags);
/**
* Extracts the XML data for a WIM file to a file stream. Every WIM file
*/
extern int wimlib_set_print_errors(bool show_messages);
-/**
- * Sets whether wimlib is to be verbose when extracting files from a WIM or when
- * creating an image from a directory (i.e. whether it will print all affected
- * files or not.) This is a per-WIM parameter.
- *
- * @param wim
- * Pointer to the ::WIMStruct for the WIM file.
- * @param verbose
- * Whether wimlib is to be verbose when extracting files from @a wim using
- * wimlib_extract_image() or when adding an image to @a wim using
- * wimlib_add_image().
- *
- * @return This function has no return value.
- */
-extern void wimlib_set_verbose(WIMStruct *wim, bool verbose);
-
-/**
- * Sets and creates the directory to which files are to be extracted when
- * extracting files from the WIM.
- *
- * @param wim
- * Pointer to the ::WIMStruct for the WIM file.
- * @param dir
- * The name of the directory to extract files to.
- *
- * @return 0 on success; nonzero on error.
- * @retval ::WIMLIB_ERR_INVALID_PARAM
- * @a dir was @c NULL.
- * @retval ::WIMLIB_ERR_MKDIR
- * @a dir does not already exist and it could not created.
- * @retval ::WIMLIB_ERR_NOMEM
- * Failed to allocate the memory needed to duplicate the @a dir string.
- */
-extern int wimlib_set_output_dir(WIMStruct *wim, const char *dir);
-
/**
* Splits a WIM into multiple parts.
*
#define WIM_HDR_FLAG_COMPRESS_LZX 0x00040000
-#ifdef ENABLE_SECURITY_DATA
/* Structure for security data. Each image in the WIM file has its own security
* data. */
struct wim_security_data {
* exporting images between WIMs) */
u32 refcnt;
} WIMSecurityData;
-#endif
/* Metadata resource for an image. */
struct image_metadata {
/* Pointer to the root dentry for the image. */
struct dentry *root_dentry;
-#ifdef ENABLE_SECURITY_DATA
/* Pointer to the security data for the image. */
struct wim_security_data *security_data;
-#endif
+
/* A pointer to the lookup table entry for this image's metadata
* resource. */
struct lookup_table_entry *metadata_lte;
/* The header of the WIM file. */
struct wim_header hdr;
- /* The type of links to create when extracting files (hard, symbolic, or
- * none.) */
- int link_type;
+ /* Temporary flags to use when extracting a WIM image or adding a WIM
+ * image. */
+ union {
+ int extract_flags;
+ int add_flags;
+ };
/* 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. */
- int current_image;
-
- /* True if files names are to be printed when doing extraction.
- * May be used for other things later. */
- bool verbose;
+ int current_image;
union {
/* Set to true when extracting multiple images */
return &w->image_metadata[w->current_image - 1].root_dentry;
}
-#ifdef ENABLE_SECURITY_DATA
static inline struct wim_security_data *wim_security_data(WIMStruct *w)
{
return w->image_metadata[w->current_image - 1].security_data;
}
-#endif
static inline struct lookup_table_entry*
wim_metadata_lookup_table_entry(WIMStruct *w)
u64 *resource_size_ret);
extern int write_metadata_resource(WIMStruct *w);
-#ifdef ENABLE_SECURITY_DATA
+/* security.c */
int read_security_data(const u8 metadata_resource[],
u64 metadata_resource_len, struct wim_security_data **sd_p);
void print_security_data(const struct wim_security_data *sd);
u8 *write_security_data(const struct wim_security_data *sd, u8 *p);
void free_security_data(struct wim_security_data *sd);
-#endif
/* wim.c */
extern WIMStruct *new_wim_struct();
cleanup() {
- if [ -d tmp ] && mountpoint tmp; then
+ if [ -d tmp ] && mountpoint tmp > /dev/null; then
fusermount -u tmp > /dev/null;
fi
rm -rf tmp* *.wim *.swm dir3