From 36a737d734cdc6c6eb0ce9da3183a1f8fa4288e6 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 16 Dec 2012 21:50:12 -0600 Subject: [PATCH] extract_wim_resource() refactor --- src/extract_image.c | 2 +- src/ntfs-apply.c | 45 ++++++++---------------- src/resource.c | 81 ++++++++++++++++++++++++++----------------- src/util.c | 25 ------------- src/util.h | 2 -- src/wimlib_internal.h | 32 +++++++++++++---- 6 files changed, 89 insertions(+), 98 deletions(-) diff --git a/src/extract_image.c b/src/extract_image.c index 470469a0..ba9b8c67 100644 --- a/src/extract_image.c +++ b/src/extract_image.c @@ -174,7 +174,7 @@ static int extract_regular_file_unlinked(struct dentry *dentry, goto out; } - ret = extract_full_wim_resource_to_fd(lte, out_fd); + ret = extract_wim_resource_to_fd(lte, out_fd, wim_resource_size(lte)); if (ret != 0) { ERROR("Failed to extract resource to `%s'", output_path); goto out; diff --git a/src/ntfs-apply.c b/src/ntfs-apply.c index dc732d8c..f1ff0dd1 100644 --- a/src/ntfs-apply.c +++ b/src/ntfs-apply.c @@ -44,6 +44,18 @@ #include #include +static int extract_wim_chunk_to_ntfs_attr(const u8 *buf, size_t len, + u64 offset, void *arg) +{ + ntfs_attr *na = arg; + if (ntfs_attr_pwrite(na, offset, len, buf) == len) { + return 0; + } else { + ERROR_WITH_ERRNO("Error extracting WIM resource to NTFS attribute"); + return WIMLIB_ERR_WRITE; + } +} + /* * Extracts a WIM resource to a NTFS attribute. */ @@ -51,37 +63,8 @@ static int extract_wim_resource_to_ntfs_attr(const struct lookup_table_entry *lte, ntfs_attr *na) { - u64 bytes_remaining = wim_resource_size(lte); - u8 buf[min(WIM_CHUNK_SIZE, bytes_remaining)]; - u64 offset = 0; - int ret = 0; - u8 hash[SHA1_HASH_SIZE]; - - SHA_CTX ctx; - sha1_init(&ctx); - - while (bytes_remaining) { - u64 to_read = min(bytes_remaining, WIM_CHUNK_SIZE); - ret = read_wim_resource(lte, buf, to_read, offset, 0); - if (ret != 0) - break; - sha1_update(&ctx, buf, to_read); - if (ntfs_attr_pwrite(na, offset, to_read, buf) != to_read) { - ERROR_WITH_ERRNO("Error extracting WIM resource"); - return WIMLIB_ERR_WRITE; - } - bytes_remaining -= to_read; - offset += to_read; - } - sha1_final(hash, &ctx); - if (!hashes_equal(hash, lte->hash)) { - ERROR("Invalid checksum on a WIM resource " - "(detected when extracting to NTFS stream)"); - ERROR("The following WIM resource is invalid:"); - print_lookup_table_entry(lte); - return WIMLIB_ERR_INVALID_RESOURCE_HASH; - } - return 0; + return extract_wim_resource(lte, wim_resource_size(lte), + extract_wim_chunk_to_ntfs_attr, na); } /* Writes the data streams to a NTFS file diff --git a/src/resource.c b/src/resource.c index 66360130..9d6fe2dc 100644 --- a/src/resource.c +++ b/src/resource.c @@ -22,21 +22,18 @@ * wimlib; if not, see http://www.gnu.org/licenses/. */ -#include "config.h" - -#include -#include - -#include "dentry.h" - #include "wimlib_internal.h" +#include "dentry.h" #include "lookup_table.h" #include "buffer_io.h" #include "lzx.h" #include "xpress.h" #include "sha1.h" -#include + #include +#include +#include +#include #ifdef WITH_NTFS_3G #include @@ -45,7 +42,6 @@ #include #endif - /* * Reads all or part of a compressed resource into an in-memory buffer. * @@ -375,9 +371,6 @@ int read_uncompressed_resource(FILE *fp, u64 offset, u64 len, return 0; } - - - /* Reads the contents of a struct resource_entry, as represented in the on-disk * format, from the memory pointed to by @p, and fills in the fields of @entry. * A pointer to the byte after the memory read at @p is returned. */ @@ -609,14 +602,10 @@ int read_full_wim_resource(const struct lookup_table_entry *lte, u8 buf[], return read_wim_resource(lte, buf, wim_resource_size(lte), 0, flags); } -/* - * Extracts the first @size bytes of the WIM resource specified by @lte to the - * open file descriptor @fd. - * - * Returns 0 on success; nonzero on failure. - */ -int extract_wim_resource_to_fd(const struct lookup_table_entry *lte, int fd, - u64 size) +int extract_wim_resource(const struct lookup_table_entry *lte, + u64 size, + extract_chunk_func_t extract_chunk, + void *extract_chunk_arg) { u64 bytes_remaining = size; u8 buf[min(WIM_CHUNK_SIZE, bytes_remaining)]; @@ -628,37 +617,65 @@ int extract_wim_resource_to_fd(const struct lookup_table_entry *lte, int fd, sha1_init(&ctx); while (bytes_remaining) { - u64 to_read = min(bytes_remaining, WIM_CHUNK_SIZE); + u64 to_read = min(bytes_remaining, sizeof(buf)); ret = read_wim_resource(lte, buf, to_read, offset, 0); if (ret != 0) break; sha1_update(&ctx, buf, to_read); - if (full_write(fd, buf, to_read) < to_read) { + ret = extract_chunk(buf, to_read, offset, extract_chunk_arg); + if (ret != 0) { ERROR_WITH_ERRNO("Error extracting WIM resource"); - return WIMLIB_ERR_WRITE; + return ret; } bytes_remaining -= to_read; offset += to_read; } sha1_final(hash, &ctx); if (!hashes_equal(hash, lte->hash)) { - ERROR("Invalid checksum on a WIM resource " - "(detected when extracting to external file)"); - ERROR("The following WIM resource is invalid:"); + #ifdef ENABLE_ERROR_MESSAGES + ERROR("Invalid checksum on the following WIM resource:"); print_lookup_table_entry(lte); + #endif return WIMLIB_ERR_INVALID_RESOURCE_HASH; } return 0; } -/* - * Extracts the WIM resource specified by @lte to the open file descriptor @fd. +/* Write @n bytes from @buf to the file descriptor @fd, retrying on interupt and + * on short writes. * - * Returns 0 on success; nonzero on failure. - */ -int extract_full_wim_resource_to_fd(const struct lookup_table_entry *lte, int fd) + * Returns short count and set errno on failure. */ +static ssize_t full_write(int fd, const void *buf, size_t n) +{ + const char *p = buf; + ssize_t ret; + ssize_t total = 0; + + while (total != n) { + ret = write(fd, p, n); + if (ret < 0) { + if (errno == EINTR) + continue; + else + break; + } + total += ret; + p += ret; + } + return total; +} + +int extract_wim_chunk_to_fd(const u8 *buf, size_t len, + u64 offset, void *arg) { - return extract_wim_resource_to_fd(lte, fd, wim_resource_size(lte)); + int fd = *(int*)arg; + ssize_t ret = full_write(fd, buf, len); + if (ret < len) { + ERROR_WITH_ERRNO("Error writing to file descriptor"); + return WIMLIB_ERR_WRITE; + } else { + return 0; + } } /* diff --git a/src/util.c b/src/util.c index 01ba8f36..78272dfc 100644 --- a/src/util.c +++ b/src/util.c @@ -360,31 +360,6 @@ char *utf8_to_utf16(const char *utf8_str, size_t utf8_len, return orig_utf16_str; } -/* Write @n bytes from @buf to the file descriptor @fd, retrying on interupt and - * on short writes. - * - * Returns short count and set errno on failure. */ -ssize_t full_write(int fd, const void *buf, size_t n) -{ - const char *p = buf; - ssize_t ret; - ssize_t total = 0; - - while (total != n) { - ret = write(fd, p, n); - if (ret < 0) { - if (errno == EINTR) - continue; - else - break; - } - total += ret; - p += ret; - } - return total; -} - - static bool seeded = false; static void seed_random() diff --git a/src/util.h b/src/util.h index 28935938..083ddb2e 100644 --- a/src/util.h +++ b/src/util.h @@ -181,8 +181,6 @@ extern void print_string(const void *string, size_t len); extern int get_num_path_components(const char *path); -extern ssize_t full_write(int fd, const void *buf, size_t n); - static inline void print_byte_field(const u8 field[], size_t len) { while (len--) diff --git a/src/wimlib_internal.h b/src/wimlib_internal.h index 458cacef..9d25e1e9 100644 --- a/src/wimlib_internal.h +++ b/src/wimlib_internal.h @@ -396,6 +396,12 @@ extern int new_joined_lookup_table(WIMStruct *w, unsigned num_additional_swms, struct lookup_table **table_ret); +/* metadata_resource.c */ + +extern int read_metadata_resource(WIMStruct *w, + struct image_metadata *image_metadata); +extern int write_metadata_resource(WIMStruct *w); + /* ntfs-apply.c */ struct apply_args { @@ -447,20 +453,32 @@ extern int write_wim_resource(struct lookup_table_entry *lte, struct resource_entry *out_res_entry, int flags); -extern int extract_wim_resource_to_fd(const struct lookup_table_entry *lte, - int fd, u64 size); +typedef int (*extract_chunk_func_t)(const u8 *, size_t, u64, void *); -extern int extract_full_wim_resource_to_fd(const struct lookup_table_entry *lte, - int fd); +extern int extract_wim_chunk_to_fd(const u8 *buf, size_t len, + u64 offset, void *arg); -extern int read_metadata_resource(WIMStruct *w, - struct image_metadata *image_metadata); +extern int extract_wim_resource(const struct lookup_table_entry *lte, + u64 size, extract_chunk_func_t extract_chunk, + void *extract_chunk_arg); +/* + * Extracts the first @size bytes of the WIM resource specified by @lte to the + * open file descriptor @fd. + * + * Returns 0 on success; nonzero on failure. + */ +static inline int +extract_wim_resource_to_fd(const struct lookup_table_entry *lte, + int fd, u64 size) +{ + return extract_wim_resource(lte, size, + extract_wim_chunk_to_fd, &fd); +} extern int write_dentry_resources(struct dentry *dentry, void *wim_p); extern int copy_resource(struct lookup_table_entry *lte, void *w); -extern int write_metadata_resource(WIMStruct *w); /* security.c */ -- 2.43.0