Previous versions of wimlib had preliminary support for copying security data,
before it was removed. This version reintroduces this support, enabled by
default but configurable by the configure script.
Also various documentation fixes.
Allow reading WIMs with security data total length = 0 (it defaults to 8 if it
says 0)
18 files changed:
program if an assertion fails. An assertion failure should only occur
if there is a bug in wimlib.
program if an assertion fails. An assertion failure should only occur
if there is a bug in wimlib.
+--disable-security-data
+ Wimlib cannot create or modify WIM security data, but by default it will
+ copy existing security data when modifying a WIM or exporting an image.
+ Passing this flag will disable this support; then wimlib will always
+ write WIMs without security data.
+
--enable-debug
Include debugging messages. Only use this option if you have found a
bug in the library.
--enable-debug
Include debugging messages. Only use this option if you have found a
bug in the library.
Include more debugging messages. Only use this option if you have found
a bug in the library.
Include more debugging messages. Only use this option if you have found
a bug in the library.
-------------------------------------------------------------------------------
DEPENDENCIES
-------------------------------------------------------------------------------
DEPENDENCIES
/* Define to 1 if including even more debug messages. */
#undef ENABLE_MORE_DEBUG
/* 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 vectorized implementation of SHA1 */
#undef ENABLE_SSSE3_SHA1
# undef WORDS_BIGENDIAN
# endif
#endif
# undef WORDS_BIGENDIAN
# endif
#endif
-
-/* Define to `int' if <sys/types.h> does not define. */
-#undef ssize_t
enable_custom_memory_allocator
enable_assertions
enable_verify_compression
enable_custom_memory_allocator
enable_assertions
enable_verify_compression
with_fuse
enable_ssse3_sha1
with_libcrypto
with_fuse
enable_ssse3_sha1
with_libcrypto
--disable-verify-compression
disable checking if blocks we compress can be
correctly decompressed
--disable-verify-compression
disable checking if blocks we compress can be
correctly decompressed
+ --disable-security-data disable the ability to retain the security data of
+ existing WIMs
--enable-ssse3-sha1 use assembly language implementation of SHA1 from
Intel, accelerated with vector instructions
(SSSE3-enabled CPU required)
--enable-ssse3-sha1 use assembly language implementation of SHA1 from
Intel, accelerated with vector instructions
(SSSE3-enabled CPU required)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to include support for copying security data" >&5
+$as_echo_n "checking whether to include support for copying security data... " >&6; }
+# Check whether --enable-security_data was given.
+if test "${enable_security_data+set}" = set; then :
+ enableval=$enable_security_data; ENABLE_SECURITY_DATA=$enableval
+else
+ ENABLE_SECURITY_DATA=yes
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ENABLE_SECURITY_DATA" >&5
+$as_echo "$ENABLE_SECURITY_DATA" >&6; }
+if test "x$ENABLE_SECURITY_DATA" = "xyes"; then
+
+$as_echo "#define ENABLE_SECURITY_DATA 1" >>confdefs.h
+
+fi
+
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to include support for mounting WIMs" >&5
$as_echo_n "checking whether to include support for mounting WIMs... " >&6; }
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to include support for mounting WIMs" >&5
$as_echo_n "checking whether to include support for mounting WIMs... " >&6; }
+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_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])
+fi
+
AC_MSG_CHECKING([whether to include support for mounting WIMs])
AC_ARG_WITH([fuse],
AS_HELP_STRING([--without-fuse], [build without libfuse.
AC_MSG_CHECKING([whether to include support for mounting WIMs])
AC_ARG_WITH([fuse],
AS_HELP_STRING([--without-fuse], [build without libfuse.
Prints all the entries in the lookup table of the WIM.
.TP
\fB--metadata\fR
Prints all the entries in the lookup table of the WIM.
.TP
\fB--metadata\fR
-Prints the metadata for the directory tree for the specified image.
+Prints the metadata, including the security data and the directory entry tree,
+for the specified image.
.TP
\fB--xml\fR
Prints the XML data for the WIM.
.TP
\fB--xml\fR
Prints the XML data for the WIM.
-Splits \fIWIMFILE\fR into parts with size at most \fIPART_SIZE\fR megabytes,
+Splits \fIWIMFILE\fR into parts with size at most \fIPART_SIZE\fR mebibytes,
with the first part having the name \fISPLIT_WIMFILE\fR and the other parts
having names numbered in order of the parts.
with the first part having the name \fISPLIT_WIMFILE\fR and the other parts
having names numbered in order of the parts.
because the WIM file format provides no way to divide a single file resource in
the WIM among multiple split WIM parts. So if you, for example, have a file
inside the WIM that is 100 MiB, then an uncompressed split WIM will have at
because the WIM file format provides no way to divide a single file resource in
the WIM among multiple split WIM parts. So if you, for example, have a file
inside the WIM that is 100 MiB, then an uncompressed split WIM will have at
-least one part that is 100 MiB in size to contain that file. If the WIM
-resources are compressed then less space would be needed.
+least one part that is 100 MiB in size to contain that file. However, if the
+WIM resources are compressed then less space would be needed.
.SH SEE ALSO
.BR imagex (1)
.SH SEE ALSO
.BR imagex (1)
.SH UNSUPPORTED FEATURES
The following features are currently unsupported:
.IP \[bu] 2
.SH UNSUPPORTED FEATURES
The following features are currently unsupported:
.IP \[bu] 2
-File permissions and security descriptors are ignored. The information
-contained in them in an existing WIM will be lost when wimlib writes a WIM file.
-This does not seem to matter for Windows PE, but this means that you should not
-use this program to image a drive containing Windows Vista/7/8 and expect it to
-be applied with the correct file permissions.
+Wimlib cannot add security data when it captures a WIM file, although it will
+preserve security data for existing WIM files. New files added to a mounted
+WIM will be added without security data. This does not seem to matter for
+Windows PE, but this means that you should not use this program to image a drive
+containing Windows Vista/7/8 and expect it to be applied with the correct file
+permissions.
.IP \[bu] 2
Alternate file streams are unsupported and will be lost when wimlib writes a WIM
file. Note that you shouldn't really have these on your Windows system anyway
.IP \[bu] 2
Alternate file streams are unsupported and will be lost when wimlib writes a WIM
file. Note that you shouldn't really have these on your Windows system anyway
.IP \[bu] 2
The \fB--verify\fR option, for all commands that use it is unsupported. Without
this option, there theoretically could be a SHA1 hash collision between two
.IP \[bu] 2
The \fB--verify\fR option, for all commands that use it is unsupported. Without
this option, there theoretically could be a SHA1 hash collision between two
-files, although it's very unlikely.
+files, although it's very unlikely. You can still verify a WIM manually by
+capturing it, then applying it to a different location, then running a recursive
+diff on the two directory trees.
-The \fB--config\fR option, for all commands that use it
+The \fB--config\fR option, for all commands that use it.
-Different versions of the WIM file format (if different versions even exist)
+Different versions of the WIM file format (if different versions even exist).
Also see the Doxygen documentation for Wimlib.
Also see the Doxygen documentation for Wimlib.
The most important difference is that this version of \fBimagex\fR cannot
capture and restore Windows images losslessly because file permissions and
The most important difference is that this version of \fBimagex\fR cannot
capture and restore Windows images losslessly because file permissions and
-alternate file streams are ignored. This is because Microsoft designed the WIM
-format to be specific to their NTFS filesystem and the Windows security
-model/API, which is difficult to support in a non-Windows program. You can
-still create images of Windows PE, however.
+alternate file streams cannot be captured. This is because Microsoft designed
+the WIM format to be specific to their NTFS filesystem and the Windows security
+model/API, which is difficult to support in a non-Windows program. However, you
+can still create images of Windows PE, even from a directory tree on a non-NTFS
+filesystem.
See the documentation for each subcommand of \fBimagex\fR; in some cases they do
not do exactly the same thing as imagex.exe.
See the documentation for each subcommand of \fBimagex\fR; in some cases they do
not do exactly the same thing as imagex.exe.
modify.c \
mount.c \
resource.c \
modify.c \
mount.c \
resource.c \
sha1.c \
sha1.h \
split.c \
sha1.c \
sha1.h \
split.c \
am__objects_1 = comp.lo decomp.lo huffman.lo lz.lo lzx-common.lo \
lzx-comp.lo lzx-decomp.lo xpress-comp.lo xpress-decomp.lo
am__objects_2 = dentry.lo extract.lo header.lo integrity.lo join.lo \
am__objects_1 = comp.lo decomp.lo huffman.lo lz.lo lzx-common.lo \
lzx-comp.lo lzx-decomp.lo xpress-comp.lo xpress-decomp.lo
am__objects_2 = dentry.lo extract.lo header.lo integrity.lo join.lo \
- lookup_table.lo modify.lo mount.lo resource.lo sha1.lo \
- split.lo util.lo wim.lo write.lo xml.lo
+ lookup_table.lo modify.lo mount.lo resource.lo security.lo \
+ sha1.lo split.lo util.lo wim.lo write.lo xml.lo
am_libwim_la_OBJECTS = $(am__objects_1) $(am__objects_2)
libwim_la_OBJECTS = $(am_libwim_la_OBJECTS)
DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
am_libwim_la_OBJECTS = $(am__objects_1) $(am__objects_2)
libwim_la_OBJECTS = $(am_libwim_la_OBJECTS)
DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
modify.c \
mount.c \
resource.c \
modify.c \
mount.c \
resource.c \
sha1.c \
sha1.h \
split.c \
sha1.c \
sha1.h \
split.c \
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/modify.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mount.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/resource.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/modify.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mount.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/resource.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/security.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sha1.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/split.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/util.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sha1.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/split.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/util.Plo@am__quote@
int print_dentry(struct dentry *dentry, void *lookup_table)
{
struct lookup_table_entry *lte;
int print_dentry(struct dentry *dentry, void *lookup_table)
{
struct lookup_table_entry *lte;
printf("Length = %"PRIu64"\n", dentry->length);
printf("Attributes = 0x%x\n", dentry->attributes);
printf("Length = %"PRIu64"\n", dentry->length);
printf("Attributes = 0x%x\n", dentry->attributes);
- /*printf("Security ID = %d\n", dentry->security_id);*/
+#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("Subdir offset = %"PRIu64"\n", dentry->subdir_offset);
/*printf("Unused1 = %"PRIu64"\n", dentry->unused1);*/
/*printf("Unused2 = %"PRIu64"\n", dentry->unused2);*/
{
memset(dentry, 0, sizeof(struct dentry));
dentry->refcnt = 1;
{
memset(dentry, 0, sizeof(struct dentry));
dentry->refcnt = 1;
- /* We are currently ignoring the security data. */
- /*dentry->security_id = -1;*/
+#ifdef ENABLE_SECURITY_DATA
+ dentry->security_id = -1;
+#endif
}
p = get_u32(p, &dentry->attributes);
}
p = get_u32(p, &dentry->attributes);
- /* Currently ignoring security ID. */
+#ifdef ENABLE_SECURITY_DATA
+ p = get_u32(p, &dentry->security_id);
+#else
p = get_u64(p, &dentry->subdir_offset);
/* 2 unused fields */
p = get_u64(p, &dentry->subdir_offset);
/* 2 unused fields */
memset(p, 0, dentry->length);
p = put_u64(p, dentry->length);
p = put_u32(p, dentry->attributes);
memset(p, 0, dentry->length);
p = put_u64(p, dentry->length);
p = put_u32(p, dentry->attributes);
- p = put_u32(p, (u32)(-1)); /* security id */
+#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 */
p = put_u64(p, dentry->subdir_offset);
p = put_u64(p, 0); /* unused1 */
p = put_u64(p, 0); /* unused2 */
/* The index of the node in the security table that contains this file's
* security information. If -1, no security information exists for this
/* 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. Currently ignoring this field.*/
- //int32_t security_id;
+ * 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. */
/* The offset, from the start of the metadata section, of this directory
* entry's child files. 0 if the directory entry has no children. */
w->hdr.image_count++;
new_imd = &imd[w->hdr.image_count - 1];
w->hdr.image_count++;
new_imd = &imd[w->hdr.image_count - 1];
-
-#if 0
- init_security_data(&new_imd->security_data);
-#endif
new_imd->lookup_table_entry = imd_lookup_entry;
new_imd->modified = true;
new_imd->root_dentry = root_dentry;
new_imd->lookup_table_entry = imd_lookup_entry;
new_imd->modified = true;
new_imd->root_dentry = root_dentry;
wims.dest_wim = dest_wim;
for_dentry_in_tree(root, add_lookup_table_entry_to_dest_wim, &wims);
ret = add_new_dentry_tree(dest_wim, root);
wims.dest_wim = dest_wim;
for_dentry_in_tree(root, add_lookup_table_entry_to_dest_wim, &wims);
ret = add_new_dentry_tree(dest_wim, root);
+#ifdef ENABLE_SECURITY_DATA
+ struct wim_security_data *sd = wim_security_data(src_wim);
+ struct image_metadata *new_imd = wim_get_current_image_metadata(dest_wim);
+ new_imd->security_data = sd;
+ if (sd)
+ sd->refcnt++;
+#endif
if (ret != 0)
return ret;
if (ret != 0)
return ret;
* refcnt decremented to 0, and the security data. */
imd = wim_get_current_image_metadata(w);
free_dentry_tree(imd->root_dentry, w->lookup_table, true);
* refcnt decremented to 0, and the security data. */
imd = wim_get_current_image_metadata(w);
free_dentry_tree(imd->root_dentry, w->lookup_table, true);
-#if 0
- destroy_security_data(&imd->security_data);
+#ifdef ENABLE_SECURITY_DATA
+ free_security_data(imd->security_data);
#endif
/* Get rid of the lookup table entry for this image's metadata resource
#endif
/* Get rid of the lookup table entry for this image's metadata resource
* @return: True on success, false on failure.
*/
int read_metadata_resource(FILE *fp, const struct resource_entry *res_entry,
* @return: True on success, false on failure.
*/
int read_metadata_resource(FILE *fp, const struct resource_entry *res_entry,
- int wim_ctype, struct dentry **root_dentry_p)
+ int wim_ctype, struct image_metadata *image_metadata)
{
u8 *buf;
int ctype;
u32 dentry_offset;
int ret;
{
u8 *buf;
int ctype;
u32 dentry_offset;
int ret;
+ struct dentry *dentry = NULL;
DEBUG("Reading metadata resource: length = %lu, offset = %lu\n",
res_entry->original_size, res_entry->offset);
DEBUG("Reading metadata resource: length = %lu, offset = %lu\n",
res_entry->original_size, res_entry->offset);
DEBUG("Finished reading metadata resource into memory.\n");
DEBUG("Finished reading metadata resource into memory.\n");
-#if 0
- /* Read the security data into a WIMSecurityData structure. */
- if (!read_security_data(buf, res_entry->original_size, sd))
- goto err1;
-#endif
dentry = MALLOC(sizeof(struct dentry));
if (!dentry) {
dentry = MALLOC(sizeof(struct dentry));
if (!dentry) {
*
* The security data starts with a 4-byte integer giving its total
* length. */
*
* The security data starts with a 4-byte integer giving its total
* length. */
+
+ /* Read the security data into a WIMSecurityData structure. */
+#ifdef ENABLE_SECURITY_DATA
+ ret = read_security_data(buf, res_entry->original_size,
+ &image_metadata->security_data);
+ if (ret != 0)
+ goto err1;
+#endif
get_u32(buf, &dentry_offset);
get_u32(buf, &dentry_offset);
+ if (dentry_offset == 0)
+ dentry_offset = 8;
dentry_offset += (8 - dentry_offset % 8) % 8;
ret = read_dentry(buf, res_entry->original_size, dentry_offset, dentry);
dentry_offset += (8 - dentry_offset % 8) % 8;
ret = read_dentry(buf, res_entry->original_size, dentry_offset, dentry);
- *root_dentry_p = dentry;
+ image_metadata->root_dentry = dentry;
FREE(buf);
return ret;
err2:
FREE(buf);
return ret;
err2:
if (metadata_offset == -1)
return WIMLIB_ERR_WRITE;
if (metadata_offset == -1)
return WIMLIB_ERR_WRITE;
+ #ifdef ENABLE_SECURITY_DATA
+ subdir_offset = wim_security_data(w)->total_length + root->length + 8;
+ #else
subdir_offset = 8 + root->length + 8;
subdir_offset = 8 + root->length + 8;
calculate_subdir_offsets(root, &subdir_offset);
metadata_original_size = subdir_offset;
buf = MALLOC(metadata_original_size);
calculate_subdir_offsets(root, &subdir_offset);
metadata_original_size = subdir_offset;
buf = MALLOC(metadata_original_size);
"metadata resource\n", metadata_original_size);
return WIMLIB_ERR_NOMEM;
}
"metadata resource\n", metadata_original_size);
return WIMLIB_ERR_NOMEM;
}
+ #ifdef ENABLE_SECURITY_DATA
/* Write the security data. */
/* Write the security data. */
- p = write_security_data(wim_security_data(w), p);
+ p = write_security_data(wim_security_data(w), buf);
- p = put_u32(p, 8); /* Total length of security data. */
+ p = put_u32(buf, 8); /* Total length of security data. */
p = put_u32(p, 0); /* Number of security data entries. */
#endif
p = put_u32(p, 0); /* Number of security data entries. */
#endif
#include "io.h"
#include "security.h"
#include "io.h"
#include "security.h"
+#ifdef ENABLE_SECURITY_DATA
+
/*
* Reads the security data from the metadata resource.
*
* @metadata_resource: An array that contains the uncompressed metadata
* resource for the WIM file.
* @metadata_resource_len: The length of @metadata_resource.
/*
* Reads the security data from the metadata resource.
*
* @metadata_resource: An array that contains the uncompressed metadata
* resource for the WIM file.
* @metadata_resource_len: The length of @metadata_resource.
- * @sd: A pointer to a WIMSecurityData structure that is filled in with
- * the security data.
- * @return: True on success, false on failure.
+ * @sd_p: A pointer to a pointer wim_security_data structure that will be filled
+ * in with a pointer to a new wim_security_data structure on success.
*
* Note: There is no `offset' argument because the security data is located at
* the beginning of the metadata resource.
*/
*
* Note: There is no `offset' argument because the security data is located at
* the beginning of the metadata resource.
*/
-bool read_security_data(const u8 metadata_resource[],
- u64 metadata_resource_len, WIMSecurityData *sd)
+int read_security_data(const u8 metadata_resource[],
+ u64 metadata_resource_len, struct wim_security_data **sd_p)
- sd->num_entries = 0;
- sd->descriptors = NULL;
- sd->sizes = NULL;
+ struct wim_security_data *sd;
+ const u8 *p;
+ u64 sizes_size;
if (metadata_resource_len < 8) {
ERROR("Not enough space in %"PRIu64"-byte file resource for "
"security data!\n", metadata_resource_len);
if (metadata_resource_len < 8) {
ERROR("Not enough space in %"PRIu64"-byte file resource for "
"security data!\n", metadata_resource_len);
+ return WIMLIB_ERR_INVALID_RESOURCE_SIZE;
- const u8 *p = metadata_resource;
- p = get_u32(p, &sd->total_length);
+ sd = MALLOC(sizeof(struct wim_security_data));
+ if (!sd)
+ return WIMLIB_ERR_NOMEM;
+ p = get_u32(metadata_resource, &sd->total_length);
p = get_u32(p, &sd->num_entries);
/* Verify the listed total length of the security data is big enough to
* include the sizes array, verify that the file data is big enough to
* include it as well, then allocate the array of sizes. */
p = get_u32(p, &sd->num_entries);
/* Verify the listed total length of the security data is big enough to
* include the sizes array, verify that the file data is big enough to
* include it as well, then allocate the array of sizes. */
- u64 sizes_size = sd->num_entries * sizeof(u64);
+ sizes_size = sd->num_entries * sizeof(u64);
DEBUG("Reading security data with %u entries\n", sd->num_entries);
if (sd->num_entries == 0) {
DEBUG("Reading security data with %u entries\n", sd->num_entries);
if (sd->num_entries == 0) {
- sd->sizes = NULL;
- sd->descriptors = NULL;
- return true;
}
u64 size_no_descriptors = 8 + sizes_size;
if (size_no_descriptors > sd->total_length) {
}
u64 size_no_descriptors = 8 + sizes_size;
if (size_no_descriptors > sd->total_length) {
- ERROR("Security data total length of %"PRIu64" is too short "
- "because there must be at least %"PRIu64" bytes of security "
+ ERROR("Security data total length of %"PRIu64" is too short because\n"
+ "there must be at least %"PRIu64" bytes of security "
"data!\n", sd->total_length,
8 + sizes_size);
"data!\n", sd->total_length,
8 + sizes_size);
+ FREE(sd);
+ return WIMLIB_ERR_INVALID_RESOURCE_SIZE;
}
if (size_no_descriptors > metadata_resource_len) {
}
if (size_no_descriptors > metadata_resource_len) {
- ERROR("File resource of %"PRIu64" bytes is not big enough "
+ ERROR("File resource of %"PRIu64" bytes is not big enough\n"
"to hold security data of at least %"PRIu64" "
"bytes!\n", metadata_resource_len, size_no_descriptors);
"to hold security data of at least %"PRIu64" "
"bytes!\n", metadata_resource_len, size_no_descriptors);
+ FREE(sd);
+ return WIMLIB_ERR_INVALID_RESOURCE_SIZE;
+ }
+ sd->sizes = MALLOC(sizes_size);
+ if (!sd->sizes) {
+ FREE(sd);
+ return WIMLIB_ERR_NOMEM;
- sd->sizes = xmalloc(sizes_size);
/* Copy the sizes array in from the file data. */
p = get_bytes(p, sizes_size, sd->sizes);
array_to_le64(sd->sizes, sd->num_entries);
/* Allocate the array of pointers to descriptors, and read them in. */
/* Copy the sizes array in from the file data. */
p = get_bytes(p, sizes_size, sd->sizes);
array_to_le64(sd->sizes, sd->num_entries);
/* Allocate the array of pointers to descriptors, and read them in. */
- sd->descriptors = xmalloc(sd->num_entries * sizeof(u8*));
+ sd->descriptors = CALLOC(sd->num_entries, sizeof(u8*));
+ if (!sd->descriptors) {
+ FREE(sd);
+ FREE(sd->sizes);
+ return WIMLIB_ERR_NOMEM;
+ }
u64 total_len = size_no_descriptors;
for (uint i = 0; i < sd->num_entries; i++) {
u64 total_len = size_no_descriptors;
for (uint i = 0; i < sd->num_entries; i++) {
total_len += sd->sizes[i];
if (total_len > sd->total_length) {
ERROR("Security data total length of %"PRIu64" is too "
"short because there are at least %"PRIu64" "
"bytes of security data!\n",
sd->total_length, total_len);
total_len += sd->sizes[i];
if (total_len > sd->total_length) {
ERROR("Security data total length of %"PRIu64" is too "
"short because there are at least %"PRIu64" "
"bytes of security data!\n",
sd->total_length, total_len);
- sd->num_entries = i;
- return false;
+ free_security_data(sd);
+ return WIMLIB_ERR_INVALID_RESOURCE_SIZE;
}
if (total_len > metadata_resource_len) {
}
if (total_len > metadata_resource_len) {
ERROR("File resource of %"PRIu64" bytes is not big enough "
"to hold security data of at least %"PRIu64" "
"bytes!\n", metadata_resource_len, total_len);
ERROR("File resource of %"PRIu64" bytes is not big enough "
"to hold security data of at least %"PRIu64" "
"bytes!\n", metadata_resource_len, total_len);
+ free_security_data(sd);
+ return WIMLIB_ERR_INVALID_RESOURCE_SIZE;
+ }
+ sd->descriptors[i] = MALLOC(sd->sizes[i]);
+ if (!sd->descriptors[i]) {
+ free_security_data(sd);
+ return WIMLIB_ERR_NOMEM;
- sd->descriptors[i] = xmalloc(sd->sizes[i]);
p = get_bytes(p, sd->sizes[i], sd->descriptors[i]);
}
p = get_bytes(p, sd->sizes[i], sd->descriptors[i]);
}
-
- /* The total_length field seems to take into account padding for
- * quadword alignment of the dentry following it, so we can ignore the
- * case where the actual length read so far is less than the specified
- * total length of the security data. */
- #if 0
- if (total_len < sd->total_length) {
- /*ERROR("Warning: security data was actually %"PRIu64" bytes, but "*/
- /*"it says its length is %"PRIu64" bytes!\n",*/
- /*total_len, sd->total_length);*/
- }
- #endif
-
- return true;
+ sd->refcnt = 1;
+ *sd_p = sd;
+ return 0;
- * Writes the security data to the output file.
- *
- * @sd: The security data structure.
- * @out: The FILE* for the output file.
- * @return: True on success, false on failure.
+ * Writes security data to an in-memory buffer.
-u8 *write_security_data(const WIMSecurityData *sd, u8 *p)
+u8 *write_security_data(const struct wim_security_data *sd, u8 *p)
- DEBUG("Writing security data (total_length = %u, num_entries = %u)\n",
- sd->total_length, sd->num_entries);
- u8 *orig_p = p;
- p = put_u32(p, sd->total_length);
- p = put_u32(p, sd->num_entries);
+ if (sd) {
+ DEBUG("Writing security data (total_length = %u, "
+ "num_entries = %u)\n", sd->total_length,
+ sd->num_entries);
+ u8 *orig_p = p;
+ p = put_u32(p, sd->total_length);
+ p = put_u32(p, sd->num_entries);
+
+ for (uint i = 0; i < sd->num_entries; i++)
+ p = put_u64(p, sd->sizes[i]);
- for (uint i = 0; i < sd->num_entries; i++)
- p = put_u64(p, sd->sizes[i]);
+ for (uint i = 0; i < sd->num_entries; i++)
+ p = put_bytes(p, sd->sizes[i], sd->descriptors[i]);
- for (uint i = 0; i < sd->num_entries; i++)
- p = put_bytes(p, sd->sizes[i], sd->descriptors[i]);
+ wimlib_assert(p - orig_p <= sd->total_length);
- wimlib_assert(p - orig_p <= sd->total_length);
+ DEBUG("Successfully wrote security data.\n");
+ return orig_p + sd->total_length;
+ } else {
+ DEBUG("Writing security data (total_length = 8, "
+ "num_entries = 0)\n");
+ p = put_u32(p, 8);
+ return put_u32(p, 0);
- DEBUG("Successfully wrote security data.\n");
- return orig_p + sd->total_length;
}
/* XXX We don't actually do anything with the ACL's yet besides being able to
}
/* XXX We don't actually do anything with the ACL's yet besides being able to
/*
* Prints the security data for a WIM file.
/*
* Prints the security data for a WIM file.
- *
- * @sd: A pointer to the WIMSecurityData structure.
-void print_security_data(const WIMSecurityData *sd)
+void print_security_data(const struct wim_security_data *sd)
{
puts("[SECURITY DATA]");
{
puts("[SECURITY DATA]");
- printf("Length = %u bytes\n", sd->total_length);
- printf("Number of Entries = %u\n", sd->num_entries);
+ if (sd) {
+ printf("Length = %u bytes\n", sd->total_length);
+ printf("Number of Entries = %u\n", sd->num_entries);
- u64 num_entries = (u64)sd->num_entries;
- for (u64 i = 0; i < num_entries; i++) {
- printf("[SecurityDescriptor %"PRIu64", length = %"PRIu64"]\n", i,
- sd->sizes[i]);
- print_security_descriptor(sd->descriptors[i], sd->sizes[i]);
- putchar('\n');
+ u64 num_entries = (u64)sd->num_entries;
+ for (u64 i = 0; i < num_entries; i++) {
+ printf("[SecurityDescriptor %"PRIu64", "
+ "length = %"PRIu64"]\n",
+ i, sd->sizes[i]);
+ print_security_descriptor(sd->descriptors[i],
+ sd->sizes[i]);
+ putchar('\n');
+ }
+ } else {
+ puts("Length = 8 bytes\n"
+ "Number of Entries = 0");
+ return;
-void init_security_data(WIMSecurityData *sd)
+void free_security_data(struct wim_security_data *sd)
- sd->total_length = 8;
- sd->num_entries = 0;
- sd->sizes = NULL;
- sd->descriptors = NULL;
- /* XXX figure out what the security descriptors actually do */
-}
+ if (!sd)
+ return;
+ wimlib_assert(sd->refcnt >= 1);
+ if (sd->refcnt == 1) {
+ u8 **descriptors = sd->descriptors;
+ u32 num_entries = sd->num_entries;
-void destroy_security_data(WIMSecurityData *sd)
-{
- u8 **descriptors = sd->descriptors;
- u32 num_entries = sd->num_entries;
- while (num_entries--)
- FREE(*descriptors++);
- sd->num_entries = 0;
- FREE(sd->sizes);
- sd->sizes = NULL;
- FREE(sd->descriptors);
- sd->descriptors = NULL;
+ if (descriptors)
+ while (num_entries--)
+ FREE(*descriptors++);
+ FREE(sd->sizes);
+ FREE(sd->descriptors);
+ FREE(sd);
+ } else {
+ sd->refcnt--;
+ }
static int print_metadata(WIMStruct *w)
{
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,
print_security_data(wim_security_data(w));
#endif
return for_dentry_in_tree(wim_root_dentry(w), print_dentry,
DEBUG("Freeing image %u\n", w->current_image);
imd = wim_get_current_image_metadata(w);
free_dentry_tree(imd->root_dentry, NULL, false);
DEBUG("Freeing image %u\n", w->current_image);
imd = wim_get_current_image_metadata(w);
free_dentry_tree(imd->root_dentry, NULL, false);
-#if 0
- destroy_security_data(&imd->security_data);
-#endif
+#ifdef ENABLE_SECURITY_DATA
+ free_security_data(imd->security_data);
+ imd->security_data = NULL;
+#endif
}
w->current_image = image;
}
w->current_image = image;
return read_metadata_resource(w->fp,
wim_metadata_resource_entry(w),
wimlib_get_compression_type(w),
return read_metadata_resource(w->fp,
wim_metadata_resource_entry(w),
wimlib_get_compression_type(w),
- /*wim_security_data(w), */
- wim_root_dentry_p(w));
+ wim_get_current_image_metadata(w));
FREE(w->xml_data);
free_wim_info(w->wim_info);
if (w->image_metadata) {
FREE(w->xml_data);
free_wim_info(w->wim_info);
if (w->image_metadata) {
- for (i = 0; i < w->hdr.image_count; i++)
+ for (i = 0; i < w->hdr.image_count; i++) {
free_dentry_tree(w->image_metadata[i].root_dentry,
NULL, false);
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);
}
FREE(w);
FREE(w->image_metadata);
}
FREE(w);
*
* While wimlib supports the main features of WIM files, wimlib currently has
* the following limitations:
*
* While wimlib supports the main features of WIM files, wimlib currently has
* the following limitations:
- * - wimlib does not support "security data", which describes the access rights
- * of the files in the WIM. This data is very Windows-specific, and it would
- * be difficult to do anything with it. Microsoft's software can still read a
- * WIM without security data, including a boot.wim for Windows PE, but <b>do
- * not expect to be able to use wimlib to image a Windows installation and
- * preserve file attributes</b>.
+ * - wimlib does not support modifying or creating "security data", which
+ * describes the access rights of the files in the WIM. This data is very
+ * Windows-specific, and it would be difficult to do anything with it.
+ * Microsoft's software can still read a WIM without security data, including
+ * a boot.wim for Windows PE, but <b>do not expect to be able to use wimlib to
+ * image a Windows installation and preserve file attributes</b>. However, by
+ * default, wimlib will preserve security data for existing WIMs.
* - There is no way to directly extract or mount split WIMs.
* - There is not yet any code to verify that there are no collisions between
* different files that happen to have the same SHA1 message digest.
* - There is no way to directly extract or mount split WIMs.
* - There is not yet any code to verify that there are no collisions between
* different files that happen to have the same SHA1 message digest.
WIMLIB_ERR_INVALID_INTEGRITY_TABLE,
WIMLIB_ERR_INVALID_PARAM,
WIMLIB_ERR_INVALID_RESOURCE_SIZE,
WIMLIB_ERR_INVALID_INTEGRITY_TABLE,
WIMLIB_ERR_INVALID_PARAM,
WIMLIB_ERR_INVALID_RESOURCE_SIZE,
+ WIMLIB_ERR_INVALID_SECURITY_DATA,
WIMLIB_ERR_LINK,
WIMLIB_ERR_MKDIR,
WIMLIB_ERR_MQUEUE,
WIMLIB_ERR_LINK,
WIMLIB_ERR_MKDIR,
WIMLIB_ERR_MQUEUE,
#define WIM_HDR_FLAG_COMPRESS_LZX 0x00040000
#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. */
/* Structure for security data. Each image in the WIM file has its own security
* data. */
-typedef struct WIMSecurityData {
+struct wim_security_data {
/* The total length of the security data, in bytes. A typical size is
* 2048 bytes. If there is no security data, though (as in the WIMs
* that wimlib writes, currently), it will be 8 bytes. */
/* The total length of the security data, in bytes. A typical size is
* 2048 bytes. If there is no security data, though (as in the WIMs
* that wimlib writes, currently), it will be 8 bytes. */
/* Array of descriptors. */
u8 **descriptors;
/* Array of descriptors. */
u8 **descriptors;
+
+ /* keep track of how many WIMs reference this security data (used when
+ * exporting images between WIMs) */
+ u32 refcnt;
} WIMSecurityData;
#endif
/* Metadata resource for an image. */
struct image_metadata {
} WIMSecurityData;
#endif
/* Metadata resource for an image. */
struct image_metadata {
+ /* Pointer to the root dentry for the image. */
+ struct dentry *root_dentry;
-#if 0
- /* The security data for the image. */
- WIMSecurityData security_data;
+#ifdef ENABLE_SECURITY_DATA
+ /* Pointer to the security data for the image. */
+ struct wim_security_data *security_data;
-
- /* The root dentry for the image. */
- struct dentry *root_dentry;
+ /* A pointer to the lookup table entry for this image's metadata
+ * resource. */
+ struct lookup_table_entry *lookup_table_entry;
/* True if the filesystem of the image has been modified. If this is
* the case, the memory for the filesystem is not freed when switching
* to a different WIM image. */
bool modified;
/* True if the filesystem of the image has been modified. If this is
* the case, the memory for the filesystem is not freed when switching
* to a different WIM image. */
bool modified;
- /* A pointer to the lookup table entry for this image's metadata
- * resource. */
- struct lookup_table_entry *lookup_table_entry;
};
/* The opaque structure exposed to the wimlib API. */
};
/* The opaque structure exposed to the wimlib API. */
return &w->image_metadata[w->current_image - 1].root_dentry;
}
return &w->image_metadata[w->current_image - 1].root_dentry;
}
-#if 0
-static inline WIMSecurityData *wim_security_data(WIMStruct *w)
+#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;
+ return w->image_metadata[w->current_image - 1].security_data;
const struct resource_entry *entry,
int fd);
const struct resource_entry *entry,
int fd);
-extern int read_metadata_resource(FILE *fp, const struct resource_entry *metadata,
- int wim_ctype, /* WIMSecurityData *sd, */
- struct dentry **root_dentry_p);
+extern int read_metadata_resource(FILE *fp,
+ const struct resource_entry *metadata,
+ int wim_ctype,
+ struct image_metadata *image_metadata);
extern int resource_compression_type(int wim_ctype, int reshdr_flags);
extern int resource_compression_type(int wim_ctype, int reshdr_flags);
u64 *resource_size_ret);
extern int write_metadata_resource(WIMStruct *w);
u64 *resource_size_ret);
extern int write_metadata_resource(WIMStruct *w);
-#if 0
-/* security.c */
-bool read_security_data(const u8 metadata_resource[],
- u64 metadata_resource_len, WIMSecurityData *sd);
+#ifdef ENABLE_SECURITY_DATA
+int read_security_data(const u8 metadata_resource[],
+ u64 metadata_resource_len, struct wim_security_data **sd_p);
-void print_security_data(const WIMSecurityData *sd);
-u8 *write_security_data(const WIMSecurityData *sd, u8 *p);
-void init_security_data(WIMSecurityData *sd);
-void destroy_security_data(WIMSecurityData *sd);
+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);