X-Git-Url: https://wimlib.net/git/?p=wimlib;a=blobdiff_plain;f=src%2Fresource.c;h=3c0804b0d3a98c4f9f5e83b8afe21f8c90cf769b;hp=66360130229ea6931f906ed09ca5f9197c782635;hb=1530b6dab02a9e1e5faf81529ab502aee68d8cd2;hpb=c6e063fcb2b1ffa76df62ab902a38bf5f604d2e2 diff --git a/src/resource.c b/src/resource.c index 66360130..3c0804b0 100644 --- a/src/resource.c +++ b/src/resource.c @@ -1,7 +1,7 @@ /* * resource.c * - * Read uncompressed and compressed metadata and file resources. + * Read uncompressed and compressed metadata and file resources from a WIM file. */ /* @@ -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. */ @@ -483,7 +476,7 @@ out: * * Returns zero on success, nonzero on failure. */ -int read_wim_resource(const struct lookup_table_entry *lte, u8 buf[], +int read_wim_resource(const struct wim_lookup_table_entry *lte, u8 buf[], size_t size, u64 offset, int flags) { int ctype; @@ -603,62 +596,96 @@ int read_wim_resource(const struct lookup_table_entry *lte, u8 buf[], * * Returns 0 on success; nonzero on failure. */ -int read_full_wim_resource(const struct lookup_table_entry *lte, u8 buf[], +int read_full_wim_resource(const struct wim_lookup_table_entry *lte, u8 buf[], int flags) { 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. +/* Extracts the first @size bytes of a WIM resource to somewhere. In the + * process, the SHA1 message digest of the resource is checked if the full + * resource is being extracted. * - * Returns 0 on success; nonzero on failure. - */ -int extract_wim_resource_to_fd(const struct lookup_table_entry *lte, int fd, - u64 size) + * @extract_chunk is a function that is called to extract each chunk of the + * resource. */ +int extract_wim_resource(const struct wim_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)]; u64 offset = 0; int ret = 0; u8 hash[SHA1_HASH_SIZE]; - + bool check_hash = (size == wim_resource_size(lte)); SHA_CTX ctx; - sha1_init(&ctx); + + if (check_hash) + 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) { + return ret; + if (check_hash) + sha1_update(&ctx, buf, 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:"); - print_lookup_table_entry(lte); - return WIMLIB_ERR_INVALID_RESOURCE_HASH; + if (check_hash) { + sha1_final(hash, &ctx); + if (!hashes_equal(hash, lte->hash)) { + #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 internupt + * 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; + } } /* @@ -668,8 +695,10 @@ int extract_full_wim_resource_to_fd(const struct lookup_table_entry *lte, int fd * * The output_resource_entry, out_refcnt, and part_number fields of @lte are * updated. + * + * (This function is confusing and should be refactored somehow.) */ -int copy_resource(struct lookup_table_entry *lte, void *wim) +int copy_resource(struct wim_lookup_table_entry *lte, void *wim) { WIMStruct *w = wim; int ret;