From 26fdf3f709adf52521e1cf962095987a3e0e2e00 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Fri, 26 Oct 2012 16:31:30 -0500 Subject: [PATCH] Various cleanups --- src/dentry.c | 82 ++++++------- src/header.c | 8 +- src/integrity.c | 6 + src/lookup_table.c | 15 ++- src/modify.c | 50 ++++---- src/resource.c | 13 ++ src/security.c | 2 + src/util.c | 96 +++++++-------- src/wim.c | 143 +++++++++++----------- src/wimlib.h | 4 +- src/xml.c | 294 +++++++++++++++++++++++---------------------- 11 files changed, 373 insertions(+), 340 deletions(-) diff --git a/src/dentry.c b/src/dentry.c index fa7ff56b..bca9f35e 100644 --- a/src/dentry.c +++ b/src/dentry.c @@ -68,7 +68,7 @@ static u64 dentry_correct_length(const struct dentry *dentry) * Returns true if @dentry has the UTF-8 file name @name that has length * @name_len. */ -static bool dentry_has_name(const struct dentry *dentry, const char *name, +static bool dentry_has_name(const struct dentry *dentry, const char *name, size_t name_len) { if (dentry->file_name_utf8_len != name_len) @@ -199,7 +199,7 @@ void stbuf_to_inode(const struct stat *stbuf, struct inode *inode) } #ifdef WITH_FUSE -/* Transfers file attributes from a struct inode to a `stat' buffer. +/* Transfers file attributes from a struct inode to a `stat' buffer. * * The lookup table entry tells us which stream in the inode we are statting. * For a named data stream, everything returned is the same as the unnamed data @@ -244,11 +244,11 @@ int inode_to_stbuf(const struct inode *inode, struct lookup_table_entry *lte, } #endif -/* +/* * Calls a function on all directory entries in a directory tree. It is called * on a parent before its children. */ -int for_dentry_in_tree(struct dentry *root, +int for_dentry_in_tree(struct dentry *root, int (*visitor)(struct dentry*, void*), void *arg) { int ret; @@ -273,11 +273,11 @@ int for_dentry_in_tree(struct dentry *root, return 0; } -/* +/* * Like for_dentry_in_tree(), but the visitor function is always called on a * dentry's children before on itself. */ -int for_dentry_in_tree_depth(struct dentry *root, +int for_dentry_in_tree_depth(struct dentry *root, int (*visitor)(struct dentry*, void*), void *arg) { int ret; @@ -297,9 +297,9 @@ int for_dentry_in_tree_depth(struct dentry *root, return visitor(root, arg); } -/* +/* * Calculate the full path of @dentry, based on its parent's full path and on - * its UTF-8 file name. + * its UTF-8 file name. */ int calculate_dentry_full_path(struct dentry *dentry, void *ignore) { @@ -347,12 +347,12 @@ oom: return WIMLIB_ERR_NOMEM; } -/* - * Recursively calculates the subdir offsets for a directory tree. +/* + * Recursively calculates the subdir offsets for a directory tree. * * @dentry: The root of the directory tree. * @subdir_offset_p: The current subdirectory offset; i.e., the subdirectory - * offset for @dentry. + * offset for @dentry. */ void calculate_subdir_offsets(struct dentry *dentry, u64 *subdir_offset_p) { @@ -389,14 +389,14 @@ void calculate_subdir_offsets(struct dentry *dentry, u64 *subdir_offset_p) } } -/* Returns the child of @dentry that has the file name @name. +/* Returns the child of @dentry that has the file name @name. * Returns NULL if no child has the name. */ -struct dentry *get_dentry_child_with_name(const struct dentry *dentry, +struct dentry *get_dentry_child_with_name(const struct dentry *dentry, const char *name) { struct dentry *child; size_t name_len; - + child = dentry->d_inode->children; if (child) { name_len = strlen(name); @@ -557,7 +557,7 @@ int print_dentry(struct dentry *dentry, void *lookup_table) } else { hash = inode_stream_hash(inode, 0); if (hash) { - printf("Hash = 0x"); + printf("Hash = 0x"); print_hash(hash); putchar('\n'); putchar('\n'); @@ -570,7 +570,7 @@ int print_dentry(struct dentry *dentry, void *lookup_table) inode->ads_entries[i].stream_name_len); hash = inode_stream_hash(inode, i + 1); if (hash) { - printf("Hash = 0x"); + printf("Hash = 0x"); print_hash(hash); putchar('\n'); } @@ -613,7 +613,7 @@ static struct inode *new_inode() return inode; } -/* +/* * Creates an unlinked directory entry. * * @name: The UTF-8 filename of the new dentry. @@ -623,7 +623,7 @@ static struct inode *new_inode() struct dentry *new_dentry(const char *name) { struct dentry *dentry; - + dentry = MALLOC(sizeof(struct dentry)); if (!dentry) goto err; @@ -724,7 +724,7 @@ static void put_inode(struct inode *inode) } } -/* Frees a WIM dentry. +/* Frees a WIM dentry. * * The inode is freed only if its link count is decremented to 0. */ @@ -751,7 +751,7 @@ void put_dentry(struct dentry *dentry) free_dentry(dentry); } -/* +/* * This function is passed as an argument to for_dentry_in_tree_depth() in order * to free a directory tree. __args is a pointer to a `struct free_dentry_args'. */ @@ -775,7 +775,7 @@ static int do_free_dentry(struct dentry *dentry, void *__lookup_table) return 0; } -/* +/* * Unlinks and frees a dentry tree. * * @root: The root of the tree. @@ -797,7 +797,7 @@ int increment_dentry_refcnt(struct dentry *dentry, void *ignore) return 0; } -/* +/* * Links a dentry into the directory tree. * * @dentry: The dentry to link. @@ -823,8 +823,8 @@ void link_dentry(struct dentry *dentry, struct dentry *parent) #ifdef WITH_FUSE -/* - * Unlink a dentry from the directory tree. +/* + * Unlink a dentry from the directory tree. * * Note: This merely removes it from the in-memory tree structure. */ @@ -928,7 +928,7 @@ static int verify_inode(struct inode *inode, const WIMStruct *w) num_unnamed_streams++; } if (num_unnamed_streams > 1) { - ERROR("Dentry `%s' has multiple (%u) un-named streams", + ERROR("Dentry `%s' has multiple (%u) un-named streams", first_dentry->full_path_utf8, num_unnamed_streams); goto out; } @@ -1010,7 +1010,7 @@ struct ads_entry *inode_get_ads_entry(struct inode *inode, #endif #if defined(WITH_FUSE) || defined(WITH_NTFS_3G) -/* +/* * Add an alternate stream entry to an inode and return a pointer to it, or NULL * if memory could not be allocated. */ @@ -1076,7 +1076,7 @@ void inode_remove_ads(struct inode *inode, u16 idx, -/* +/* * Reads the alternate data stream entries for a dentry. * * @p: Pointer to buffer that starts with the first alternate stream entry. @@ -1092,7 +1092,7 @@ void inode_remove_ads(struct inode *inode, u16 idx, * * struct ads_entry_on_disk { * u64 length; // Length of the entry, in bytes. This includes - * all fields (including the stream name and + * all fields (including the stream name and * null terminator if present, AND the padding!). * u64 reserved; // Seems to be unused * u8 hash[20]; // SHA1 message digest of the uncompressed stream @@ -1240,7 +1240,7 @@ out_free_ads_entries: return ret; } -/* +/* * Reads a directory entry, including all alternate data stream entries that * follow it, from the WIM image's metadata resource. * @@ -1255,7 +1255,7 @@ out_free_ads_entries: * special "end of directory" dentry and not a real dentry. If nonzero, this * was a real dentry. */ -int read_dentry(const u8 metadata_resource[], u64 metadata_resource_len, +int read_dentry(const u8 metadata_resource[], u64 metadata_resource_len, u64 offset, struct dentry *dentry) { const u8 *p; @@ -1330,7 +1330,7 @@ int read_dentry(const u8 metadata_resource[], u64 metadata_resource_len, p = get_u64(p, &inode->last_write_time); p = get_bytes(p, SHA1_HASH_SIZE, inode->hash); - + /* * I don't know what's going on here. It seems like M$ screwed up the * reparse points, then put the fields in the same place and didn't @@ -1349,14 +1349,14 @@ int read_dentry(const u8 metadata_resource[], u64 metadata_resource_len, /* By the way, the reparse_reserved field does not actually exist (at * least when the file is not a reparse point) */ - + p = get_u16(p, &inode->num_ads); p = get_u16(p, &short_name_len); p = get_u16(p, &file_name_len); /* We now know the length of the file name and short name. Make sure - * the length of the dentry is large enough to actually hold them. + * the length of the dentry is large enough to actually hold them. * * The calculated length here is unaligned to allow for the possibility * that the dentry->length names an unaligned length, although this @@ -1367,7 +1367,7 @@ int read_dentry(const u8 metadata_resource[], u64 metadata_resource_len, if (dentry->length < calculated_size) { ERROR("Unexpected end of directory entry! (Expected " "at least %"PRIu64" bytes, got %"PRIu64" bytes. " - "short_name_len = %hu, file_name_len = %hu)", + "short_name_len = %hu, file_name_len = %hu)", calculated_size, dentry->length, short_name_len, file_name_len); return WIMLIB_ERR_INVALID_DENTRY; @@ -1385,7 +1385,7 @@ int read_dentry(const u8 metadata_resource[], u64 metadata_resource_len, p = get_bytes(p, file_name_len, file_name); /* Convert filename to UTF-8. */ - file_name_utf8 = utf16_to_utf8(file_name, file_name_len, + file_name_utf8 = utf16_to_utf8(file_name, file_name_len, &file_name_utf8_len); if (!file_name_utf8) { @@ -1450,7 +1450,7 @@ int read_dentry(const u8 metadata_resource[], u64 metadata_resource_len, p += 2; } - /* + /* * Read the alternate data streams, if present. dentry->num_ads tells * us how many they are, and they will directly follow the dentry * on-disk. @@ -1520,7 +1520,7 @@ int read_dentry_tree(const u8 metadata_resource[], u64 metadata_resource_len, struct dentry cur_child; int ret; - /* + /* * If @dentry has no child dentries, nothing more needs to be done for * this branch. This is the case for regular files, symbolic links, and * *possibly* empty directories (although an empty directory may also @@ -1533,7 +1533,7 @@ int read_dentry_tree(const u8 metadata_resource[], u64 metadata_resource_len, while (1) { /* Read next child of @dentry into @cur_child. */ - ret = read_dentry(metadata_resource, metadata_resource_len, + ret = read_dentry(metadata_resource, metadata_resource_len, cur_offset, &cur_child); if (ret != 0) break; @@ -1567,7 +1567,7 @@ int read_dentry_tree(const u8 metadata_resource[], u64 metadata_resource_len, /* If there are children of this child, call this procedure * recursively. */ if (child->subdir_offset != 0) { - ret = read_dentry_tree(metadata_resource, + ret = read_dentry_tree(metadata_resource, metadata_resource_len, child); if (ret != 0) break; @@ -1591,7 +1591,7 @@ int read_dentry_tree(const u8 metadata_resource[], u64 metadata_resource_len, return ret; } -/* +/* * Writes a WIM dentry to an output buffer. * * @dentry: The dentry structure. @@ -1681,7 +1681,7 @@ static u8 *write_dentry_tree_recursive(const struct dentry *parent, u8 *p) if (parent->subdir_offset == 0) return p; - /* Write child dentries and end-of-directory entry. + /* Write child dentries and end-of-directory entry. * * Note: we need to write all of this dentry's children before * recursively writing the directory trees rooted at each of the child diff --git a/src/header.c b/src/header.c index 68ea0526..5563d705 100644 --- a/src/header.c +++ b/src/header.c @@ -32,7 +32,7 @@ static const u8 wim_magic_chars[WIM_MAGIC_LEN] = { 'M', 'S', 'W', 'I', 'M', '\0', '\0', '\0' }; /* Reads the header for a WIM file. */ -int read_header(FILE *fp, struct wim_header *hdr, int split_ok) +int read_header(FILE *fp, struct wim_header *hdr, int open_flags) { size_t bytes_read; u8 buf[WIM_HEADER_DISK_SIZE]; @@ -66,7 +66,7 @@ int read_header(FILE *fp, struct wim_header *hdr, int split_ok) /* Byte 12 */ if (hdr_size != WIM_HEADER_DISK_SIZE) { - DEBUG("ERROR: Header is size %u (expected %u)", + ERROR("Header is %u bytes (expected %u bytes)", hdr_size, WIM_HEADER_DISK_SIZE); return WIMLIB_ERR_INVALID_HEADER_SIZE; } @@ -104,7 +104,9 @@ int read_header(FILE *fp, struct wim_header *hdr, int split_ok) p = get_u16(p, &hdr->part_number); p = get_u16(p, &hdr->total_parts); - if (!split_ok && (hdr->part_number != 1 || hdr->total_parts != 1)) { + if (!(open_flags & WIMLIB_OPEN_FLAG_SPLIT_OK) + && (hdr->part_number != 1 || hdr->total_parts != 1)) + { ERROR("This WIM is part %u of a %u-part WIM", hdr->part_number, hdr->total_parts); return WIMLIB_ERR_SPLIT_UNSUPPORTED; diff --git a/src/integrity.c b/src/integrity.c index 70ff7ffe..f94b7436 100644 --- a/src/integrity.c +++ b/src/integrity.c @@ -201,6 +201,12 @@ int check_wim_integrity(WIMStruct *w, int show_progress, int *status) end_lookup_table_offset = w->hdr.lookup_table_res_entry.offset + w->hdr.lookup_table_res_entry.size; + if (end_lookup_table_offset < WIM_HEADER_DISK_SIZE) { + ERROR("WIM lookup table ends before WIM header ends???"); + ret = WIMLIB_ERR_INVALID_INTEGRITY_TABLE; + goto out; + } + bytes_to_check = end_lookup_table_offset - WIM_HEADER_DISK_SIZE; expected_num_entries = (bytes_to_check + chunk_size - 1) / chunk_size; diff --git a/src/lookup_table.c b/src/lookup_table.c index 02125aeb..1226488a 100644 --- a/src/lookup_table.c +++ b/src/lookup_table.c @@ -61,15 +61,14 @@ struct lookup_table_entry *new_lookup_table_entry() struct lookup_table_entry *lte; lte = CALLOC(1, sizeof(struct lookup_table_entry)); - if (!lte) { + if (lte) { + lte->part_number = 1; + lte->refcnt = 1; + } else { ERROR("Out of memory (tried to allocate %zu bytes for " "lookup table entry)", sizeof(struct lookup_table_entry)); - return NULL; } - - lte->part_number = 1; - lte->refcnt = 1; return lte; } @@ -278,7 +277,8 @@ int read_lookup_table(WIMStruct *w) w->hdr.lookup_table_res_entry.offset, w->hdr.lookup_table_res_entry.original_size); - if (fseeko(w->fp, w->hdr.lookup_table_res_entry.offset, SEEK_SET) != 0) { + if (fseeko(w->fp, w->hdr.lookup_table_res_entry.offset, SEEK_SET) != 0) + { ERROR_WITH_ERRNO("Failed to seek to byte %"PRIu64" to read " "lookup table", w->hdr.lookup_table_res_entry.offset); @@ -323,7 +323,6 @@ int read_lookup_table(WIMStruct *w) w->hdr.part_number, cur_entry->part_number); ret = WIMLIB_ERR_INVALID_LOOKUP_TABLE_ENTRY; goto out_free_cur_entry; - } if (is_zero_hash(cur_entry->hash)) { @@ -347,7 +346,7 @@ int read_lookup_table(WIMStruct *w) if (!(cur_entry->resource_entry.flags & WIM_RESHDR_FLAG_COMPRESSED) && (cur_entry->resource_entry.size != - cur_entry->resource_entry.original_size)) + cur_entry->resource_entry.original_size)) { ERROR("Found uncompressed resource with original size " "not the same as compressed size"); diff --git a/src/modify.c b/src/modify.c index b0da749b..775312c6 100644 --- a/src/modify.c +++ b/src/modify.c @@ -55,7 +55,7 @@ void destroy_image_metadata(struct image_metadata *imd, struct lookup_table *lt) lookup_table_remove(lt, imd->metadata_lte); } -/* +/* * Recursively builds a dentry tree from a directory tree on disk, outside the * WIM file. * @@ -63,10 +63,10 @@ void destroy_image_metadata(struct image_metadata *imd, struct lookup_table *lt) * modified if successful. NULL if the file or directory was * excluded from capture. * - * @root_disk_path: The path to the root of the directory tree on disk. + * @root_disk_path: The path to the root of the directory tree on disk. * * @lookup_table: The lookup table for the WIM file. For each file added to the - * dentry tree being built, an entry is added to the lookup table, + * dentry tree being built, an entry is added to the lookup table, * unless an identical stream is already in the lookup table. * These lookup table entries that are added point to the path of * the file on disk. @@ -128,7 +128,7 @@ static int build_dentry_tree(struct dentry **root_ret, return WIMLIB_ERR_STAT; } - if ((add_flags & WIMLIB_ADD_IMAGE_FLAG_ROOT) && + if ((add_flags & WIMLIB_ADD_IMAGE_FLAG_ROOT) && !S_ISDIR(root_stbuf.st_mode)) { ERROR("`%s' is not a directory", root_disk_path); return WIMLIB_ERR_NOTDIR; @@ -202,7 +202,7 @@ static int build_dentry_tree(struct dentry **root_ret, } else if (dentry_is_symlink(root)) { /* Archiving a symbolic link */ char deref_name_buf[4096]; ssize_t deref_name_len; - + deref_name_len = readlink(root_disk_path, deref_name_buf, sizeof(deref_name_buf) - 1); if (deref_name_len >= 0) { @@ -307,7 +307,7 @@ static int allocate_lte_if_needed(struct dentry *dentry, void *arg) return 0; } -/* +/* * This function takes in a dentry that was previously located only in image(s) * in @src_wim, but now is being added to @dest_wim. For each stream associated * with the dentry, if there is already a lookup table entry for that stream in @@ -362,7 +362,7 @@ static int add_lte_to_dest_wim(struct dentry *dentry, void *arg) /* * Adds an image (given by its dentry tree) to the image metadata array of a WIM * file, adds an entry to the lookup table for the image metadata, updates the - * image count in the header, and selects the new image. + * image count in the header, and selects the new image. * * Does not update the XML data. * @@ -392,9 +392,9 @@ static int add_new_dentry_tree(WIMStruct *w, struct dentry *root_dentry, return WIMLIB_ERR_NOMEM; } - memcpy(imd, w->image_metadata, + memcpy(imd, w->image_metadata, w->hdr.image_count * sizeof(struct image_metadata)); - + metadata_lte = new_lookup_table_entry(); if (!metadata_lte) goto out_free_imd; @@ -431,11 +431,11 @@ out_free_imd: /* * Copies an image, or all the images, from a WIM file, into another WIM file. */ -WIMLIBAPI int wimlib_export_image(WIMStruct *src_wim, - int src_image, - WIMStruct *dest_wim, - const char *dest_name, - const char *dest_description, +WIMLIBAPI int wimlib_export_image(WIMStruct *src_wim, + int src_image, + WIMStruct *dest_wim, + const char *dest_name, + const char *dest_description, int flags, WIMStruct **additional_swms, unsigned num_additional_swms) @@ -461,7 +461,7 @@ WIMLIBAPI int wimlib_export_image(WIMStruct *src_wim, /* multi-image export. */ - if ((flags & WIMLIB_EXPORT_FLAG_BOOT) && + if ((flags & WIMLIB_EXPORT_FLAG_BOOT) && (src_wim->hdr.boot_idx == 0)) { /* Specifying the boot flag on a multi-image @@ -486,7 +486,7 @@ WIMLIBAPI int wimlib_export_image(WIMStruct *src_wim, if (i != src_wim->hdr.boot_idx) export_flags &= ~WIMLIB_EXPORT_FLAG_BOOT; - ret = wimlib_export_image(src_wim, i, dest_wim, + ret = wimlib_export_image(src_wim, i, dest_wim, NULL, NULL, export_flags, additional_swms, @@ -495,8 +495,10 @@ WIMLIBAPI int wimlib_export_image(WIMStruct *src_wim, return ret; } return 0; + } else if (src_wim->hdr.image_count == 1) { + src_image = 1; } else { - src_image = 1; + return 0; } } @@ -600,8 +602,8 @@ out: return ret; } -/* - * Deletes an image from the WIM. +/* + * Deletes an image from the WIM. */ WIMLIBAPI int wimlib_delete_image(WIMStruct *w, int image) { @@ -742,7 +744,7 @@ static int init_capture_config(const char *_config_str, size_t config_len, FREE(config_str); return WIMLIB_ERR_NOMEM; } - + memcpy(config_str, _config_str, config_len); next_p = config_str; config->config_str = config_str; @@ -758,7 +760,7 @@ static int init_capture_config(const char *_config_str, size_t config_len, ret = WIMLIB_ERR_INVALID_CAPTURE_CONFIG; goto out_destroy; } - + next_p = eol + 1; bytes_remaining -= (next_p - p); if (eol == p) @@ -887,7 +889,7 @@ bool exclude_path(const char *path, const struct capture_config *config, && path[config->prefix_len] == '/') path += config->prefix_len; } - return match_pattern(path, basename, &config->exclusion_list) && + return match_pattern(path, basename, &config->exclusion_list) && !match_pattern(path, basename, &config->exclusion_exception); } @@ -910,7 +912,7 @@ int do_add_image(WIMStruct *w, const char *dir, const char *name, const char *config_str, size_t config_len, int flags, int (*capture_tree)(struct dentry **, const char *, - struct lookup_table *, + struct lookup_table *, struct wim_security_data *, const struct capture_config *, int, void *), @@ -1027,7 +1029,7 @@ out_destroy_config: /* * Adds an image to a WIM file from a directory tree on disk. */ -WIMLIBAPI int wimlib_add_image(WIMStruct *w, const char *dir, +WIMLIBAPI int wimlib_add_image(WIMStruct *w, const char *dir, const char *name, const char *config_str, size_t config_len, int flags) { diff --git a/src/resource.c b/src/resource.c index d35d936a..be9bd7ce 100644 --- a/src/resource.c +++ b/src/resource.c @@ -390,8 +390,21 @@ const u8 *get_resource_entry(const u8 *p, struct resource_entry *entry) p = get_u8(p, &flags); entry->size = size; entry->flags = flags; + + /* offset and original_size are truncated to 62 bits to avoid possible + * overflows, when converting to a signed 64-bit integer (off_t) or when + * adding size or original_size. This is okay since no one would ever + * actually have a WIM bigger than 4611686018427387903 bytes... */ p = get_u64(p, &entry->offset); + if (entry->offset & 0xc000000000000000ULL) { + WARNING("Truncating offset in resource entry"); + entry->offset &= 0x3fffffffffffffffULL; + } p = get_u64(p, &entry->original_size); + if (entry->original_size & 0xc000000000000000ULL) { + WARNING("Truncating original_size in resource entry"); + entry->original_size &= 0x3fffffffffffffffULL; + } return p; } diff --git a/src/security.c b/src/security.c index 63ab5ba0..c05dd06f 100644 --- a/src/security.c +++ b/src/security.c @@ -285,6 +285,8 @@ static void print_security_descriptor(const u8 *p, u64 size) */ void print_security_data(const struct wim_security_data *sd) { + wimlib_assert(sd != NULL); + puts("[SECURITY DATA]"); printf("Length = %"PRIu32" bytes\n", sd->total_length); printf("Number of Entries = %"PRIu32"\n", sd->num_entries); diff --git a/src/util.c b/src/util.c index 1df757fa..b68db910 100644 --- a/src/util.c +++ b/src/util.c @@ -106,97 +106,97 @@ WIMLIBAPI int wimlib_set_print_errors(bool show_error_messages) } static const char *error_strings[] = { - [WIMLIB_ERR_SUCCESS] + [WIMLIB_ERR_SUCCESS] = "Success", - [WIMLIB_ERR_COMPRESSED_LOOKUP_TABLE] + [WIMLIB_ERR_COMPRESSED_LOOKUP_TABLE] = "Lookup table is compressed", - [WIMLIB_ERR_DECOMPRESSION] + [WIMLIB_ERR_DECOMPRESSION] = "Failed to decompress compressed data", - [WIMLIB_ERR_DELETE_STAGING_DIR] + [WIMLIB_ERR_DELETE_STAGING_DIR] = "Failed to delete staging directory", - [WIMLIB_ERR_FORK] + [WIMLIB_ERR_FORK] = "Failed to fork another process", - [WIMLIB_ERR_FUSE] + [WIMLIB_ERR_FUSE] = "An error was returned by fuse_main()", - [WIMLIB_ERR_FUSERMOUNT] + [WIMLIB_ERR_FUSERMOUNT] = "Could not execute the `fusermount' program, or it exited " "with a failure status", - [WIMLIB_ERR_IMAGE_COUNT] + [WIMLIB_ERR_IMAGE_COUNT] = "Inconsistent image count among the metadata " "resources, the WIM header, and/or the XML data", - [WIMLIB_ERR_IMAGE_NAME_COLLISION] + [WIMLIB_ERR_IMAGE_NAME_COLLISION] = "Tried to add an image with a name that is already in use", - [WIMLIB_ERR_INTEGRITY] + [WIMLIB_ERR_INTEGRITY] = "The WIM failed an integrity check", [WIMLIB_ERR_INVALID_CAPTURE_CONFIG] = "The capture configuration string was invalid", - [WIMLIB_ERR_INVALID_CHUNK_SIZE] + [WIMLIB_ERR_INVALID_CHUNK_SIZE] = "The WIM is compressed but does not have a chunk " "size of 32768", - [WIMLIB_ERR_INVALID_COMPRESSION_TYPE] + [WIMLIB_ERR_INVALID_COMPRESSION_TYPE] = "The WIM is compressed, but is not marked as having LZX or " "XPRESS compression", - [WIMLIB_ERR_INVALID_DENTRY] + [WIMLIB_ERR_INVALID_DENTRY] = "A directory entry in the WIM was invalid", - [WIMLIB_ERR_INVALID_HEADER_SIZE] + [WIMLIB_ERR_INVALID_HEADER_SIZE] = "The WIM header was not 208 bytes", - [WIMLIB_ERR_INVALID_IMAGE] + [WIMLIB_ERR_INVALID_IMAGE] = "Tried to select an image that does not exist in the WIM", - [WIMLIB_ERR_INVALID_INTEGRITY_TABLE] + [WIMLIB_ERR_INVALID_INTEGRITY_TABLE] = "The WIM's integrity table is invalid", [WIMLIB_ERR_INVALID_LOOKUP_TABLE_ENTRY] = "An entry in the WIM's lookup table is invalid", - [WIMLIB_ERR_INVALID_PARAM] + [WIMLIB_ERR_INVALID_PARAM] = "An invalid parameter was given", [WIMLIB_ERR_INVALID_RESOURCE_HASH] = "The SHA1 message digest of a WIM resource did not match the expected value", - [WIMLIB_ERR_INVALID_RESOURCE_SIZE] - = "A resource entry in the WIM is invalid", - [WIMLIB_ERR_LINK] + [WIMLIB_ERR_INVALID_RESOURCE_SIZE] + = "A resource entry in the WIM has an invalid size", + [WIMLIB_ERR_LINK] = "Failed to create a hard or symbolic link when extracting " "a file from the WIM", - [WIMLIB_ERR_MKDIR] + [WIMLIB_ERR_MKDIR] = "Failed to create a directory", - [WIMLIB_ERR_MQUEUE] + [WIMLIB_ERR_MQUEUE] = "Failed to create or use a POSIX message queue", - [WIMLIB_ERR_NOMEM] + [WIMLIB_ERR_NOMEM] = "Ran out of memory", - [WIMLIB_ERR_NOTDIR] + [WIMLIB_ERR_NOTDIR] = "Expected a directory", - [WIMLIB_ERR_NOT_A_WIM_FILE] + [WIMLIB_ERR_NOT_A_WIM_FILE] = "The file did not begin with the magic characters that " "identify a WIM file", - [WIMLIB_ERR_NO_FILENAME] + [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] + [WIMLIB_ERR_OPEN] = "Failed to open a file", - [WIMLIB_ERR_OPENDIR] + [WIMLIB_ERR_OPENDIR] = "Failed to open a directory", - [WIMLIB_ERR_READ] + [WIMLIB_ERR_READ] = "Could not read data from a file", [WIMLIB_ERR_READLINK] = "Could not read the target of a symbolic link", - [WIMLIB_ERR_RENAME] + [WIMLIB_ERR_RENAME] = "Could not rename a file", [WIMLIB_ERR_SPECIAL_FILE] = "Encountered a special file that cannot be archived", - [WIMLIB_ERR_SPLIT_INVALID] + [WIMLIB_ERR_SPLIT_INVALID] = "The WIM is part of an invalid split WIM", - [WIMLIB_ERR_SPLIT_UNSUPPORTED] + [WIMLIB_ERR_SPLIT_UNSUPPORTED] = "The WIM is part of a split WIM, which is not supported for this operation", - [WIMLIB_ERR_STAT] + [WIMLIB_ERR_STAT] = "Could not read the metadata for a file or directory", - [WIMLIB_ERR_TIMEOUT] + [WIMLIB_ERR_TIMEOUT] = "Timed out", - [WIMLIB_ERR_UNKNOWN_VERSION] + [WIMLIB_ERR_UNKNOWN_VERSION] = "The WIM file is marked with an unknown version number", - [WIMLIB_ERR_UNSUPPORTED] + [WIMLIB_ERR_UNSUPPORTED] = "The requested operation is unsupported", - [WIMLIB_ERR_WRITE] + [WIMLIB_ERR_WRITE] = "Failed to write data to a file", - [WIMLIB_ERR_XML] + [WIMLIB_ERR_XML] = "The XML data of the WIM is invalid", }; @@ -228,8 +228,8 @@ char *wimlib_strdup(const char *str) { size_t size; char *p; - - size = strlen(str); + + size = strlen(str); p = MALLOC(size + 1); if (p) memcpy(p, str, size + 1); @@ -250,7 +250,7 @@ WIMLIBAPI int wimlib_set_memory_allocator(void *(*malloc_func)(size_t), wimlib_free_func = free_func ? free_func : free; wimlib_realloc_func = realloc_func ? realloc_func : realloc; - xml_set_memory_allocator(wimlib_malloc_func, wimlib_free_func, + xml_set_memory_allocator(wimlib_malloc_func, wimlib_free_func, wimlib_realloc_func); return 0; #else @@ -287,7 +287,7 @@ char *utf16_to_utf8(const char *utf16_str, size_t utf16_len, char *orig_utf8_str = utf8_str; - size_t num_chars_converted = iconv(cd_utf16_to_utf8, (char**)&utf16_str, + size_t num_chars_converted = iconv(cd_utf16_to_utf8, (char**)&utf16_str, &utf16_bytes_left, &utf8_str, &utf8_bytes_left); if (num_chars_converted == (size_t)(-1)) { @@ -330,7 +330,7 @@ char *utf8_to_utf16(const char *utf8_str, size_t utf8_len, char *orig_utf16_str = utf16_str; - size_t num_chars_converted = iconv(cd_utf8_to_utf16, (char**)&utf8_str, + size_t num_chars_converted = iconv(cd_utf8_to_utf16, (char**)&utf8_str, &utf8_bytes_left, &utf16_str, &utf16_bytes_left); if (num_chars_converted == (size_t)(-1)) { @@ -444,7 +444,7 @@ const char *path_basename(const char *path) return p + 1; } -/* +/* * Returns a pointer to the part of @path following the first colon in the last * path component, or NULL if the last path component does not contain a colon. */ @@ -458,7 +458,7 @@ const char *path_stream_name(const char *path) return stream_name + 1; } -/* +/* * Splits a file path into the part before the first '/', or the entire name if * there is no '/', and the part after the first sequence of '/' characters. * @@ -466,7 +466,7 @@ const char *path_stream_name(const char *path) * @first_part_len_ret: A pointer to a `size_t' into which the length of the * first part of the path will be returned. * @return: A pointer to the next part of the path, after the first - * sequence of '/', or a pointer to the terminating + * sequence of '/', or a pointer to the terminating * null byte in the case of a path without any '/'. */ const char *path_next_part(const char *path, size_t *first_part_len_ret) @@ -501,9 +501,9 @@ int get_num_path_components(const char *path) } -/* +/* * Prints a string. Printable characters are printed as-is, while unprintable - * characters are printed as their octal escape codes. + * characters are printed as their octal escape codes. */ void print_string(const void *string, size_t len) { diff --git a/src/wim.c b/src/wim.c index fe216495..2883b6a7 100644 --- a/src/wim.c +++ b/src/wim.c @@ -6,7 +6,7 @@ * Copyright (C) 2010 Carl Thijssen * Copyright (C) 2012 Eric Biggers * - * wimlib - Library for working with WIM files + * wimlib - Library for working with WIM files * * This file is part of wimlib, a library for working with WIM files. * @@ -40,15 +40,16 @@ static int print_metadata(WIMStruct *w) { + DEBUG("Printing metadata for image %d", w->current_image); print_security_data(wim_security_data(w)); - return for_dentry_in_tree(wim_root_dentry(w), print_dentry, + return for_dentry_in_tree(wim_root_dentry(w), print_dentry, w->lookup_table); } static int print_files(WIMStruct *w) { - return for_dentry_in_tree(wim_root_dentry(w), print_dentry_full_path, + return for_dentry_in_tree(wim_root_dentry(w), print_dentry_full_path, NULL); } @@ -57,7 +58,7 @@ WIMStruct *new_wim_struct() return CALLOC(1, sizeof(WIMStruct)); } -/* +/* * Calls a function on images in the WIM. If @image is WIM_ALL_IMAGES, @visitor * is called on the WIM once for each image, with each image selected as the * current image in turn. If @image is a certain image, @visitor is called on @@ -66,19 +67,20 @@ WIMStruct *new_wim_struct() int for_image(WIMStruct *w, int image, int (*visitor)(WIMStruct *)) { int ret; - int i; + int start; int end; + int i; if (image == WIM_ALL_IMAGES) { - i = 1; + start = 1; end = w->hdr.image_count; - } else { - if (image < 1 || image > w->hdr.image_count) - return WIMLIB_ERR_INVALID_IMAGE; - i = image; + } else if (image >= 1 && image <= w->hdr.image_count) { + start = image; end = image; + } else { + return WIMLIB_ERR_INVALID_IMAGE; } - for (; i <= end; i++) { + for (i = start; i <= end; i++) { ret = select_wim_image(w, i); if (ret != 0) return ret; @@ -91,10 +93,10 @@ int for_image(WIMStruct *w, int image, int (*visitor)(WIMStruct *)) static int sort_image_metadata_by_position(const void *p1, const void *p2) { - struct image_metadata *bmd1 = (struct image_metadata*)p1; - struct image_metadata *bmd2 = (struct image_metadata*)p2; - u64 offset1 = bmd1->metadata_lte->resource_entry.offset; - u64 offset2 = bmd2->metadata_lte->resource_entry.offset; + const struct image_metadata *imd1 = p1; + const struct image_metadata *imd2 = p2; + u64 offset1 = imd1->metadata_lte->resource_entry.offset; + u64 offset2 = imd2->metadata_lte->resource_entry.offset; if (offset1 < offset2) return -1; else if (offset1 > offset2) @@ -103,31 +105,31 @@ static int sort_image_metadata_by_position(const void *p1, const void *p2) return 0; } -/* +/* * If @lte points to a metadata resource, append it to the list of metadata * resources in the WIMStruct. Otherwise, do nothing. */ -static int append_metadata_resource_entry(struct lookup_table_entry *lte, +static int append_metadata_resource_entry(struct lookup_table_entry *lte, void *wim_p) { WIMStruct *w = wim_p; + int ret = 0; 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 WIMLIB_ERR_IMAGE_COUNT; + ret = WIMLIB_ERR_IMAGE_COUNT; } else { DEBUG("Found metadata resource for image %u at " "offset %"PRIu64".", - w->current_image + 1, + w->current_image + 1, lte->resource_entry.offset); w->image_metadata[ w->current_image++].metadata_lte = lte; } } - return 0; + return ret; } /* Returns the compression type given in the flags of a WIM header. */ @@ -285,7 +287,7 @@ WIMLIBAPI int wimlib_resolve_image(WIMStruct *w, const char *image_name_or_num) WIMLIBAPI void wimlib_print_wim_information(const WIMStruct *w) { const struct wim_header *hdr; - + hdr = &w->hdr; puts("WIM Information:"); puts("----------------"); @@ -298,7 +300,7 @@ WIMLIBAPI void wimlib_print_wim_information(const WIMStruct *w) wimlib_get_compression_type(w))); printf("Part Number: %d/%d\n", hdr->part_number, hdr->total_parts); printf("Boot Index: %d\n", hdr->boot_idx); - printf("Size: %"PRIu64" bytes\n", + printf("Size: %"PRIu64" bytes\n", wim_info_get_total_bytes(w->wim_info)); printf("Integrity Info: %s\n", (w->hdr.integrity.size != 0) ? "yes" : "no"); putchar('\n'); @@ -311,20 +313,28 @@ WIMLIBAPI bool wimlib_has_integrity_table(const WIMStruct *w) WIMLIBAPI void wimlib_print_available_images(const WIMStruct *w, int image) { + int first; + int last; + int i; + int n; if (image == WIM_ALL_IMAGES) { - puts("Available Images:"); - puts("-----------------"); - } else { - int n; - int i; - + n = printf("Available Images:\n"); + first = 1; + last = w->hdr.image_count; + } else if (image >= 1 && image <= w->hdr.image_count) { n = printf("Information for Image %d\n", image); - for (i = 0; i < n - 1; i++) - putchar('-'); - putchar('\n'); - + first = image; + last = image; + } else { + printf("wimlib_print_available_images(): Invalid image %d", + image); + return; } - print_image_info(w->wim_info, image); + for (i = 0; i < n - 1; i++) + putchar('-'); + putchar('\n'); + for (i = first; i <= last; i++) + print_image_info(w->wim_info, i); } @@ -335,15 +345,11 @@ WIMLIBAPI int wimlib_print_metadata(WIMStruct *w, int image) if (!w) return WIMLIB_ERR_INVALID_PARAM; if (w->hdr.part_number != 1) { - ERROR("We cannot show the metadata from part %hu of a %hu-part split WIM.", + ERROR("Cannot show the metadata from part %hu of a %hu-part split WIM!", w->hdr.part_number, w->hdr.total_parts); ERROR("Select the first part of the split WIM to see the metadata."); return WIMLIB_ERR_SPLIT_UNSUPPORTED; } - if (image == WIM_ALL_IMAGES) - DEBUG("Printing metadata for all images"); - else - DEBUG("Printing metadata for image %d", image); return for_image(w, image, print_metadata); } @@ -352,7 +358,7 @@ WIMLIBAPI int wimlib_print_files(WIMStruct *w, int image) if (!w) return WIMLIB_ERR_INVALID_PARAM; if (w->hdr.part_number != 1) { - ERROR("We cannot list the files from part %hu of a %hu-part split WIM", + ERROR("Cannot list the files from part %hu of a %hu-part split WIM!", w->hdr.part_number, w->hdr.total_parts); ERROR("Select the first part of the split WIM if you'd like to list the files."); return WIMLIB_ERR_SPLIT_UNSUPPORTED; @@ -366,21 +372,12 @@ WIMLIBAPI int wimlib_set_boot_idx(WIMStruct *w, int boot_idx) if (!w) return WIMLIB_ERR_INVALID_PARAM; if (w->hdr.total_parts != 1) { - ERROR("We cannot modify the boot index of a split WIM"); + ERROR("Cannot modify the boot index of a split WIM!"); return WIMLIB_ERR_SPLIT_UNSUPPORTED; } if (boot_idx < 0 || boot_idx > w->hdr.image_count) return WIMLIB_ERR_INVALID_IMAGE; w->hdr.boot_idx = boot_idx; - if (boot_idx == 0) { - memset(&w->hdr.boot_metadata_res_entry, 0, - sizeof(struct resource_entry)); - } else { - memcpy(&w->hdr.boot_metadata_res_entry, - &w->image_metadata[ - boot_idx - 1].metadata_lte->resource_entry, - sizeof(struct resource_entry)); - } return 0; } @@ -390,18 +387,18 @@ WIMLIBAPI int wimlib_get_part_number(const WIMStruct *w, int *total_parts_ret) *total_parts_ret = w->hdr.total_parts; return w->hdr.part_number; } - + WIMLIBAPI int wimlib_get_boot_idx(const WIMStruct *w) { return w->hdr.boot_idx; } -/* +/* * Begins the reading of a WIM file; opens the file and reads its header and * lookup table, and optionally checks the integrity. */ -static int begin_read(WIMStruct *w, const char *in_wim_path, int flags) +static int begin_read(WIMStruct *w, const char *in_wim_path, int open_flags) { int ret; uint xml_num_images; @@ -422,7 +419,7 @@ static int begin_read(WIMStruct *w, const char *in_wim_path, int flags) return WIMLIB_ERR_OPEN; } - ret = read_header(w->fp, &w->hdr, flags & WIMLIB_OPEN_FLAG_SPLIT_OK); + ret = read_header(w->fp, &w->hdr, open_flags); if (ret != 0) return ret; @@ -431,8 +428,8 @@ static int begin_read(WIMStruct *w, const char *in_wim_path, int flags) /* If the boot index is invalid, print a warning and set it to 0 */ if (w->hdr.boot_idx > w->hdr.image_count) { WARNING("In `%s', image %u is marked as bootable, " - "but there are only %u images", - in_wim_path, w->hdr.boot_idx, w->hdr.image_count); + "but there are only %u images in the WIM", + in_wim_path, w->hdr.boot_idx, w->hdr.image_count); w->hdr.boot_idx = 0; } @@ -443,15 +440,13 @@ static int begin_read(WIMStruct *w, const char *in_wim_path, int flags) } - if (flags & WIMLIB_OPEN_FLAG_CHECK_INTEGRITY) { + if (open_flags & WIMLIB_OPEN_FLAG_CHECK_INTEGRITY) { int integrity_status; - ret = check_wim_integrity(w, - flags & WIMLIB_OPEN_FLAG_SHOW_PROGRESS, + ret = check_wim_integrity(w, + open_flags & WIMLIB_OPEN_FLAG_SHOW_PROGRESS, &integrity_status); - if (ret != 0) { - ERROR("Error in check_wim_integrity()"); + if (ret != 0) return ret; - } if (integrity_status == WIM_INTEGRITY_NONEXISTENT) { WARNING("No integrity information for `%s'; skipping " "integrity check.", w->filename); @@ -471,7 +466,7 @@ static int begin_read(WIMStruct *w, const char *in_wim_path, int flags) if (ret != 0) return ret; - w->image_metadata = CALLOC(w->hdr.image_count, + w->image_metadata = CALLOC(w->hdr.image_count, sizeof(struct image_metadata)); if (!w->image_metadata) { @@ -484,7 +479,7 @@ static int begin_read(WIMStruct *w, const char *in_wim_path, int flags) DEBUG("Looking for metadata resources in the lookup table."); /* Find the images in the WIM by searching the lookup table. */ - ret = for_lookup_table_entry(w->lookup_table, + ret = for_lookup_table_entry(w->lookup_table, append_metadata_resource_entry, w); if (ret != 0) @@ -492,7 +487,9 @@ static int begin_read(WIMStruct *w, const char *in_wim_path, int flags) /* Make sure all the expected images were found. (We already have * returned false if *extra* images were found) */ - if (w->current_image != w->hdr.image_count && w->hdr.part_number == 1) { + if (w->current_image != w->hdr.image_count && + w->hdr.part_number == 1) + { ERROR("Only found %u images in WIM, but expected %u", w->current_image, w->hdr.image_count); return WIMLIB_ERR_IMAGE_COUNT; @@ -509,7 +506,7 @@ static int begin_read(WIMStruct *w, const char *in_wim_path, int flags) w->current_image = WIM_NO_IMAGE; /* Read the XML data. */ - ret = read_xml_data(w->fp, &w->hdr.xml_res_entry, + ret = read_xml_data(w->fp, &w->hdr.xml_res_entry, &w->xml_data, &w->wim_info); if (ret != 0) { @@ -534,27 +531,27 @@ static int begin_read(WIMStruct *w, const char *in_wim_path, int flags) /* * Opens a WIM file and creates a WIMStruct for it. */ -WIMLIBAPI int wimlib_open_wim(const char *wim_file, int flags, +WIMLIBAPI int wimlib_open_wim(const char *wim_file, int open_flags, WIMStruct **w_ret) { WIMStruct *w; int ret; - DEBUG("wim_file = `%s', flags = %#x", wim_file, flags); + DEBUG("wim_file = `%s', open_flags = %#x", wim_file, open_flags); w = new_wim_struct(); if (!w) { ERROR("Failed to allocate memory for WIMStruct"); return WIMLIB_ERR_NOMEM; } - ret = begin_read(w, wim_file, flags); - if (ret != 0) { + ret = begin_read(w, wim_file, open_flags); + if (ret == 0) { + *w_ret = w; + } else { DEBUG("Could not begin reading the WIM file `%s'", wim_file); wimlib_free(w); - return ret; } - *w_ret = w; - return 0; + return ret; } /* Frees the memory for the WIMStruct, including all internal memory; also diff --git a/src/wimlib.h b/src/wimlib.h index ad8db225..5ed6c684 100644 --- a/src/wimlib.h +++ b/src/wimlib.h @@ -1129,7 +1129,9 @@ extern int wimlib_overwrite_xml_and_header(WIMStruct *wim, int flags); * image, or ::WIM_ALL_IMAGES to print information about all images in the * WIM. * - * @return This function has no return value. + * @return This function has no return value. No error checking is done when + * printing the information. If @a image is invalid, an error message is + * printed. */ extern void wimlib_print_available_images(const WIMStruct *wim, int image); diff --git a/src/xml.c b/src/xml.c index 44039895..89d08e0e 100644 --- a/src/xml.c +++ b/src/xml.c @@ -246,7 +246,7 @@ void free_wim_info(struct wim_info *info) /* Reads the information from a element inside the element. * */ -static void xml_read_windows_version(const xmlNode *version_node, +static void xml_read_windows_version(const xmlNode *version_node, struct windows_version* windows_version) { xmlNode *child; @@ -268,8 +268,8 @@ static void xml_read_windows_version(const xmlNode *version_node, /* Reads the information from a element inside a element. * */ -static int xml_read_languages(const xmlNode *languages_node, - char ***languages_ret, +static int xml_read_languages(const xmlNode *languages_node, + char ***languages_ret, u64 *num_languages_ret, char **default_language_ret) { @@ -309,7 +309,7 @@ static int xml_read_languages(const xmlNode *languages_node, } /* Reads the information from a element inside an element. */ -static int xml_read_windows_info(const xmlNode *windows_node, +static int xml_read_windows_info(const xmlNode *windows_node, struct windows_info *windows_info) { xmlNode *child; @@ -321,27 +321,27 @@ static int xml_read_windows_info(const xmlNode *windows_node, if (node_name_is(child, "ARCH")) { windows_info->arch = node_get_u64(child); } else if (node_name_is(child, "PRODUCTNAME")) { - ret = node_get_string(child, + ret = node_get_string(child, &windows_info->product_name); } else if (node_name_is(child, "EDITIONID")) { - ret = node_get_string(child, + ret = node_get_string(child, &windows_info->edition_id); } else if (node_name_is(child, "INSTALLATIONTYPE")) { - ret = node_get_string(child, + ret = node_get_string(child, &windows_info->installation_type); } else if (node_name_is(child, "PRODUCTTYPE")) { - ret = node_get_string(child, + ret = node_get_string(child, &windows_info->product_type); } else if (node_name_is(child, "PRODUCTSUITE")) { - ret = node_get_string(child, + ret = node_get_string(child, &windows_info->product_suite); } else if (node_name_is(child, "LANGUAGES")) { - ret = xml_read_languages(child, + ret = xml_read_languages(child, &windows_info->languages, &windows_info->num_languages, &windows_info->default_language); } else if (node_name_is(child, "VERSION")) { - xml_read_windows_version(child, + xml_read_windows_version(child, &windows_info->windows_version); windows_info->windows_version_exists = true; } else if (node_name_is(child, "SYSTEMROOT")) { @@ -357,13 +357,13 @@ static int xml_read_windows_info(const xmlNode *windows_node, } /* Reads the information from an element. */ -static int xml_read_image_info(xmlNode *image_node, +static int xml_read_image_info(xmlNode *image_node, struct image_info *image_info) { xmlNode *child; xmlChar *index_prop; int ret; - + index_prop = xmlGetProp(image_node, "INDEX"); if (index_prop) { char *tmp; @@ -470,7 +470,7 @@ static int xml_read_wim_info(const xmlNode *wim_node, } /* Sort the array of struct image_infos by image index. */ - qsort(wim_info->images, wim_info->num_images, + qsort(wim_info->images, wim_info->num_images, sizeof(struct image_info), sort_by_index); done: *wim_info_ret = wim_info; @@ -487,33 +487,52 @@ static void print_windows_info(const struct windows_info *windows_info) const struct windows_version *windows_version; printf("Architecture: %s\n", get_arch(windows_info->arch)); - printf("Product Name: %s\n", windows_info->product_name); - printf("Edition ID: %s\n", windows_info->edition_id); - printf("Installation Type: %s\n", windows_info->installation_type); + + if (windows_info->product_name) + printf("Product Name: %s\n", + windows_info->product_name); + + if (windows_info->edition_id) + printf("Edition ID: %s\n", + windows_info->edition_id); + + if (windows_info->installation_type) + printf("Installation Type: %s\n", + windows_info->installation_type); + if (windows_info->hal) printf("HAL: %s\n", windows_info->hal); - printf("Product Type: %s\n", windows_info->product_type); + + if (windows_info->product_type) + printf("Product Type: %s\n", + windows_info->product_type); + if (windows_info->product_suite) - printf("Product Suite: %s\n", windows_info->product_suite); + printf("Product Suite: %s\n", + windows_info->product_suite); printf("Languages: "); for (i = 0; i < windows_info->num_languages; i++) { fputs(windows_info->languages[i], stdout); putchar(' '); } putchar('\n'); - printf("Default Language: %s\n", windows_info->default_language); - printf("System Root: %s\n", windows_info->system_root); + if (windows_info->default_language) + printf("Default Language: %s\n", + windows_info->default_language); + if (windows_info->system_root) + printf("System Root: %s\n", + windows_info->system_root); if (windows_info->windows_version_exists) { windows_version = &windows_info->windows_version; - printf("Major Version: %"PRIu64"\n", + printf("Major Version: %"PRIu64"\n", windows_version->major); - printf("Minor Version: %"PRIu64"\n", + printf("Minor Version: %"PRIu64"\n", windows_version->minor); - printf("Build: %"PRIu64"\n", + printf("Build: %"PRIu64"\n", windows_version->build); - printf("Service Pack Build: %"PRIu64"\n", + printf("Service Pack Build: %"PRIu64"\n", windows_version->sp_build); - printf("Service Pack Level: %"PRIu64"\n", + printf("Service Pack Level: %"PRIu64"\n", windows_version->sp_level); } } @@ -522,35 +541,35 @@ static void print_windows_info(const struct windows_info *windows_info) /* Writes the information contained in a struct windows_version structure to the XML * document being constructed in memory. This is the element inside * the element. */ -static int xml_write_windows_version(xmlTextWriter *writer, - const struct windows_version *version) +static int xml_write_windows_version(xmlTextWriter *writer, + const struct windows_version *version) { int rc; rc = xmlTextWriterStartElement(writer, "VERSION"); if (rc < 0) return rc; - rc = xmlTextWriterWriteFormatElement(writer, "MAJOR", "%"PRIu64, + rc = xmlTextWriterWriteFormatElement(writer, "MAJOR", "%"PRIu64, version->major); if (rc < 0) return rc; - rc = xmlTextWriterWriteFormatElement(writer, "MINOR", "%"PRIu64, + rc = xmlTextWriterWriteFormatElement(writer, "MINOR", "%"PRIu64, version->minor); if (rc < 0) return rc; - rc = xmlTextWriterWriteFormatElement(writer, "BUILD", "%"PRIu64, + rc = xmlTextWriterWriteFormatElement(writer, "BUILD", "%"PRIu64, version->build); if (rc < 0) return rc; - rc = xmlTextWriterWriteFormatElement(writer, "SPBUILD", "%"PRIu64, + rc = xmlTextWriterWriteFormatElement(writer, "SPBUILD", "%"PRIu64, version->sp_build); if (rc < 0) return rc; - rc = xmlTextWriterWriteFormatElement(writer, "SPLEVEL", "%"PRIu64, + rc = xmlTextWriterWriteFormatElement(writer, "SPLEVEL", "%"PRIu64, version->sp_level); if (rc < 0) return rc; @@ -560,8 +579,8 @@ static int xml_write_windows_version(xmlTextWriter *writer, /* Writes the information contained in a struct windows_info structure to the XML * document being constructed in memory. This is the element. */ -static int xml_write_windows_info(xmlTextWriter *writer, - const struct windows_info *windows_info) +static int xml_write_windows_info(xmlTextWriter *writer, + const struct windows_info *windows_info) { int rc; rc = xmlTextWriterStartElement(writer, "WINDOWS"); @@ -569,55 +588,55 @@ static int xml_write_windows_info(xmlTextWriter *writer, return rc; - rc = xmlTextWriterWriteFormatElement(writer, "ARCH", "%"PRIu64, + rc = xmlTextWriterWriteFormatElement(writer, "ARCH", "%"PRIu64, windows_info->arch); if (rc < 0) return rc; - + if (windows_info->product_name) { - rc = xmlTextWriterWriteElement(writer, "PRODUCTNAME", + rc = xmlTextWriterWriteElement(writer, "PRODUCTNAME", windows_info->product_name); if (rc < 0) return rc; } if (windows_info->edition_id) { - rc = xmlTextWriterWriteElement(writer, "EDITIONID", + rc = xmlTextWriterWriteElement(writer, "EDITIONID", windows_info->edition_id); if (rc < 0) return rc; } if (windows_info->installation_type) { - rc = xmlTextWriterWriteElement(writer, "INSTALLATIONTYPE", + rc = xmlTextWriterWriteElement(writer, "INSTALLATIONTYPE", windows_info->installation_type); if (rc < 0) return rc; } if (windows_info->hal) { - rc = xmlTextWriterWriteElement(writer, "HAL", + rc = xmlTextWriterWriteElement(writer, "HAL", windows_info->hal); if (rc < 0) return rc; } if (windows_info->system_root) { - rc = xmlTextWriterWriteElement(writer, "SYSTEMROOT", + rc = xmlTextWriterWriteElement(writer, "SYSTEMROOT", windows_info->system_root); if (rc < 0) return rc; } if (windows_info->product_type) { - rc = xmlTextWriterWriteElement(writer, "PRODUCTTYPE", + rc = xmlTextWriterWriteElement(writer, "PRODUCTTYPE", windows_info->product_type); if (rc < 0) return rc; } if (windows_info->product_suite) { - rc = xmlTextWriterWriteElement(writer, "PRODUCTSUITE", + rc = xmlTextWriterWriteElement(writer, "PRODUCTSUITE", windows_info->product_suite); if (rc < 0) return rc; @@ -629,12 +648,12 @@ static int xml_write_windows_info(xmlTextWriter *writer, return rc; for (int i = 0; i < windows_info->num_languages; i++) { - rc = xmlTextWriterWriteElement(writer, "LANGUAGE", + rc = xmlTextWriterWriteElement(writer, "LANGUAGE", windows_info->languages[i]); if (rc < 0) return rc; } - rc = xmlTextWriterWriteElement(writer, "DEFAULT", + rc = xmlTextWriterWriteElement(writer, "DEFAULT", windows_info->default_language); if (rc < 0) return rc; @@ -654,15 +673,15 @@ static int xml_write_windows_info(xmlTextWriter *writer, } /* Writes a time element to the XML document being constructed in memory. */ -static int xml_write_time(xmlTextWriter *writer, const char *element_name, - u64 time) +static int xml_write_time(xmlTextWriter *writer, const char *element_name, + u64 time) { int rc; rc = xmlTextWriterStartElement(writer, element_name); if (rc < 0) return rc; - rc = xmlTextWriterWriteFormatElement(writer, "HIGHPART", + rc = xmlTextWriterWriteFormatElement(writer, "HIGHPART", "0x%"PRIX32, (u32)(time >> 32)); if (rc < 0) return rc; @@ -680,7 +699,7 @@ static int xml_write_time(xmlTextWriter *writer, const char *element_name, /* Writes an element to the XML document. */ -static int xml_write_image_info(xmlTextWriter *writer, +static int xml_write_image_info(xmlTextWriter *writer, const struct image_info *image_info) { int rc; @@ -688,37 +707,37 @@ static int xml_write_image_info(xmlTextWriter *writer, if (rc < 0) return rc; - rc = xmlTextWriterWriteFormatAttribute(writer, "INDEX", "%"PRIu64, + rc = xmlTextWriterWriteFormatAttribute(writer, "INDEX", "%"PRIu64, image_info->index); if (rc < 0) return rc; - rc = xmlTextWriterWriteFormatElement(writer, "DIRCOUNT", "%"PRIu64, + rc = xmlTextWriterWriteFormatElement(writer, "DIRCOUNT", "%"PRIu64, image_info->dir_count); if (rc < 0) return rc; - rc = xmlTextWriterWriteFormatElement(writer, "FILECOUNT", "%"PRIu64, + rc = xmlTextWriterWriteFormatElement(writer, "FILECOUNT", "%"PRIu64, image_info->file_count); if (rc < 0) return rc; - rc = xmlTextWriterWriteFormatElement(writer, "TOTALBYTES", "%"PRIu64, + rc = xmlTextWriterWriteFormatElement(writer, "TOTALBYTES", "%"PRIu64, image_info->total_bytes); if (rc < 0) return rc; - rc = xmlTextWriterWriteFormatElement(writer, "HARDLINKBYTES", "%"PRIu64, + rc = xmlTextWriterWriteFormatElement(writer, "HARDLINKBYTES", "%"PRIu64, image_info->hard_link_bytes); if (rc < 0) return rc; - rc = xml_write_time(writer, "CREATIONTIME", + rc = xml_write_time(writer, "CREATIONTIME", image_info->creation_time); if (rc < 0) return rc; - rc = xml_write_time(writer, "LASTMODIFICATIONTIME", + rc = xml_write_time(writer, "LASTMODIFICATIONTIME", image_info->last_modification_time); if (rc < 0) return rc; @@ -737,19 +756,19 @@ static int xml_write_image_info(xmlTextWriter *writer, return rc; } if (image_info->description) { - rc = xmlTextWriterWriteElement(writer, "DESCRIPTION", + rc = xmlTextWriterWriteElement(writer, "DESCRIPTION", image_info->description); if (rc < 0) return rc; } if (image_info->display_name) { - rc = xmlTextWriterWriteElement(writer, "DISPLAYNAME", + rc = xmlTextWriterWriteElement(writer, "DISPLAYNAME", image_info->display_name); if (rc < 0) return rc; } if (image_info->display_description) { - rc = xmlTextWriterWriteElement(writer, "DISPLAYDESCRIPTION", + rc = xmlTextWriterWriteElement(writer, "DISPLAYDESCRIPTION", image_info->display_description); if (rc < 0) return rc; @@ -784,7 +803,7 @@ static struct image_info *add_image_info_struct(struct wim_info *wim_info) return &images[wim_info->num_images - 1]; } -static int clone_windows_info(const struct windows_info *old, +static int clone_windows_info(const struct windows_info *old, struct windows_info *new) { uint i; @@ -793,7 +812,7 @@ static int clone_windows_info(const struct windows_info *old, return WIMLIB_ERR_NOMEM; if (old->edition_id && !(new->edition_id = STRDUP(old->edition_id))) return WIMLIB_ERR_NOMEM; - if (old->installation_type && !(new->installation_type = + if (old->installation_type && !(new->installation_type = STRDUP(old->installation_type))) return WIMLIB_ERR_NOMEM; if (old->hal && !(new->hal = STRDUP(old->hal))) @@ -816,7 +835,7 @@ static int clone_windows_info(const struct windows_info *old, return WIMLIB_ERR_NOMEM; } } - if (old->default_language && + if (old->default_language && !(new->default_language = STRDUP(old->default_language))) return WIMLIB_ERR_NOMEM; if (old->system_root && !(new->system_root = STRDUP(old->system_root))) @@ -859,13 +878,13 @@ static int clone_image_info(const struct image_info *old, struct image_info *new if (old->windows_info_exists) { new->windows_info_exists = true; - return clone_windows_info(&old->windows_info, + return clone_windows_info(&old->windows_info, &new->windows_info); } return 0; } -/* Copies the XML information for an image between WIM files. +/* Copies the XML information for an image between WIM files. * * @dest_image_name and @dest_image_description are ignored if they are NULL; * otherwise, they are used to override the image name and/or image description @@ -874,10 +893,10 @@ static int clone_image_info(const struct image_info *old, struct image_info *new * On failure, WIMLIB_ERR_NOMEM is returned and no changes are made. Otherwise, * 0 is returned and the WIM information at *new_wim_info_p is modified. */ -int xml_export_image(const struct wim_info *old_wim_info, - int image, - struct wim_info **new_wim_info_p, - const char *dest_image_name, +int xml_export_image(const struct wim_info *old_wim_info, + int image, + struct wim_info **new_wim_info_p, + const char *dest_image_name, const char *dest_image_description) { struct wim_info *new_wim_info; @@ -933,7 +952,7 @@ void xml_delete_image(struct wim_info **wim_info_p, int image) int i; DEBUG("Deleting image %d from the XML data.", image); - + wim_info = *wim_info_p; wimlib_assert(wim_info); @@ -974,7 +993,7 @@ void xml_set_memory_allocator(void *(*malloc_func)(size_t), static int calculate_dentry_statistics(struct dentry *dentry, void *arg) { - struct image_info *info = arg; + struct image_info *info = arg; struct lookup_table *lookup_table = info->lookup_table; const struct inode *inode = dentry->d_inode; struct lookup_table_entry *lte; @@ -996,7 +1015,7 @@ static int calculate_dentry_statistics(struct dentry *dentry, void *arg) else info->file_count++; - /* + /* * Update total bytes and hard link bytes. * * Unfortunately there are some inconsistencies/bugs in the way this is @@ -1046,7 +1065,7 @@ static int calculate_dentry_statistics(struct dentry *dentry, void *arg) void xml_update_image_info(WIMStruct *w, int image) { struct image_info *image_info; - struct dentry *root; + struct dentry *root; char *flags_save; DEBUG("Updating the image info for image %d", image); @@ -1064,7 +1083,7 @@ void xml_update_image_info(WIMStruct *w, int image) for_dentry_in_tree(w->image_metadata[image - 1].root_dentry, calculate_dentry_statistics, image_info); - + image_info->lookup_table = NULL; image_info->flags = flags_save; image_info->last_modification_time = get_wim_timestamp(); @@ -1117,85 +1136,76 @@ out_free_wim_info: return WIMLIB_ERR_NOMEM; } -/* Prints information about the specified image from struct wim_info structure. - * @image may be WIM_ALL_IMAGES. */ +/* Prints information about the specified image from struct wim_info structure. + * */ void print_image_info(const struct wim_info *wim_info, int image) { uint i; const struct image_info *image_info; const char *desc; + int start; + int end; + time_t time; + char *p; + wimlib_assert(image >= 1 && image <= wim_info->num_images); - if (image == WIM_ALL_IMAGES) { - for (i = 1; i <= wim_info->num_images; i++) - print_image_info(wim_info, i); - } else { - time_t time; - char *p; + image_info = &wim_info->images[image - 1]; - image_info = &wim_info->images[image - 1]; + printf("Index: %"PRIu64"\n", image_info->index); + printf("Name: %s\n", image_info->name); - printf("Index: %"PRIu64"\n", - image_info->index); - printf("Name: %s\n", - image_info->name); - - /* Always print the Description: part even if there is no - * description. */ - if (image_info->description) - desc = image_info->description; - else - desc = ""; - printf("Description: %s\n", desc); - - if (image_info->display_name) - printf("Display Name: %s\n", - image_info->display_name); - - if (image_info->display_description) - printf("Display Description: %s\n", - image_info->display_description); - - printf("Directory Count: %"PRIu64"\n", - image_info->dir_count); - printf("File Count: %"PRIu64"\n", - image_info->file_count); - printf("Total Bytes: %"PRIu64"\n", - image_info->total_bytes); - printf("Hard Link Bytes: %"PRIu64"\n", - image_info->hard_link_bytes); - - time = wim_timestamp_to_unix(image_info->creation_time); - p = asctime(gmtime(&time)); - *(strrchr(p, '\n')) = '\0'; - - printf("Creation Time: %s UTC\n", p); - - time = wim_timestamp_to_unix(image_info->last_modification_time); - p = asctime(gmtime(&time)); - *(strrchr(p, '\n')) = '\0'; - - printf("Last Modification Time: %s UTC\n", p); - if (image_info->windows_info_exists) - print_windows_info(&image_info->windows_info); - if (image_info->flags) - printf("Flags: %s\n", image_info->flags); - putchar('\n'); - } + /* Always print the Description: part even if there is no + * description. */ + if (image_info->description) + desc = image_info->description; + else + desc = ""; + printf("Description: %s\n", desc); + + if (image_info->display_name) + printf("Display Name: %s\n", + image_info->display_name); + + if (image_info->display_description) + printf("Display Description: %s\n", + image_info->display_description); + + printf("Directory Count: %"PRIu64"\n", image_info->dir_count); + printf("File Count: %"PRIu64"\n", image_info->file_count); + printf("Total Bytes: %"PRIu64"\n", image_info->total_bytes); + printf("Hard Link Bytes: %"PRIu64"\n", image_info->hard_link_bytes); + + time = wim_timestamp_to_unix(image_info->creation_time); + p = asctime(gmtime(&time)); + *(strrchr(p, '\n')) = '\0'; + + printf("Creation Time: %s UTC\n", p); + + time = wim_timestamp_to_unix(image_info->last_modification_time); + p = asctime(gmtime(&time)); + *(strrchr(p, '\n')) = '\0'; + + printf("Last Modification Time: %s UTC\n", p); + if (image_info->windows_info_exists) + print_windows_info(&image_info->windows_info); + if (image_info->flags) + printf("Flags: %s\n", image_info->flags); + putchar('\n'); } -/* +/* * Reads the XML data from a WIM file. */ -int read_xml_data(FILE *fp, const struct resource_entry *res, u8 **xml_data_ret, - struct wim_info **info_ret) +int read_xml_data(FILE *fp, const struct resource_entry *res, + u8 **xml_data_ret, struct wim_info **info_ret) { u8 *xml_data; xmlDoc *doc; xmlNode *root; int ret; - DEBUG("XML data is %"PRIu64" bytes at offset %"PRIu64"", + DEBUG("XML data is %"PRIu64" bytes at offset %"PRIu64"", (u64)res->size, res->offset); if (resource_is_compressed(res)) { @@ -1273,14 +1283,14 @@ out_cleanup_parser: goto err2; \ } }) -/* +/* * Writes XML data to a WIM file. * * If @total_bytes is non-zero, it specifies what to write to the TOTALBYTES * element in the XML data. If zero, TOTALBYTES is given the default value of * the offset of the XML data. */ -int write_xml_data(const struct wim_info *wim_info, int image, FILE *out, +int write_xml_data(const struct wim_info *wim_info, int image, FILE *out, u64 total_bytes) { xmlBuffer *buf; @@ -1294,8 +1304,8 @@ int write_xml_data(const struct wim_info *wim_info, int image, FILE *out, size_t utf16_len; size_t bytes_written; - wimlib_assert(image == WIM_ALL_IMAGES || - (wim_info != NULL && image >= 1 && + wimlib_assert(image == WIM_ALL_IMAGES || + (wim_info != NULL && image >= 1 && image <= wim_info->num_images)); /* The contents of the element in the XML data, under the @@ -1373,7 +1383,7 @@ int write_xml_data(const struct wim_info *wim_info, int image, FILE *out, goto err2; } - if ((putc(0xff, out)) == EOF || (putc(0xfe, out) == EOF) || + if ((putc(0xff, out)) == EOF || (putc(0xfe, out) == EOF) || ((bytes_written = fwrite(utf16_str, 1, utf16_len, out)) != utf16_len)) { ERROR_WITH_ERRNO("Error writing XML data"); @@ -1405,7 +1415,7 @@ WIMLIBAPI const char *wimlib_get_image_name(const WIMStruct *w, int image) } /* Returns the description of the specified image. */ -WIMLIBAPI const char *wimlib_get_image_description(const WIMStruct *w, +WIMLIBAPI const char *wimlib_get_image_description(const WIMStruct *w, int image) { DEBUG("Getting the description of image %d", image); @@ -1433,7 +1443,7 @@ WIMLIBAPI bool wimlib_image_name_in_use(const WIMStruct *w, const char *name) WIMLIBAPI int wimlib_extract_xml_data(WIMStruct *w, FILE *fp) { DEBUG("Extracting the XML data."); - if (fwrite(w->xml_data, 1, w->hdr.xml_res_entry.size, fp) != + if (fwrite(w->xml_data, 1, w->hdr.xml_res_entry.size, fp) != w->hdr.xml_res_entry.size) { ERROR_WITH_ERRNO("Failed to extract XML data"); return WIMLIB_ERR_WRITE; @@ -1482,7 +1492,7 @@ WIMLIBAPI int wimlib_set_image_name(WIMStruct *w, int image, const char *name) } /* Sets the description of an image in the WIM. */ -WIMLIBAPI int wimlib_set_image_descripton(WIMStruct *w, int image, +WIMLIBAPI int wimlib_set_image_descripton(WIMStruct *w, int image, const char *description) { char *p; -- 2.43.0