/*
* resource.c
*
- * Read uncompressed and compressed metadata and file resources.
+ * Read uncompressed and compressed metadata and file resources from a WIM file.
*/
/*
- * Copyright (C) 2012 Eric Biggers
+ * Copyright (C) 2012, 2013 Eric Biggers
*
* This file is part of wimlib, a library for working with WIM files.
*
#include "xpress.h"
#include "sha1.h"
+#ifdef __WIN32__
+# include "win32.h"
+#endif
+
#include <errno.h>
#include <stdarg.h>
#include <stdlib.h>
#include <unistd.h>
#ifdef WITH_NTFS_3G
-#include <time.h>
-#include <ntfs-3g/attrib.h>
-#include <ntfs-3g/inode.h>
-#include <ntfs-3g/dir.h>
+# include <time.h>
+# include <ntfs-3g/attrib.h>
+# include <ntfs-3g/inode.h>
+# include <ntfs-3g/dir.h>
#endif
/*
*
* Returns zero on success, nonzero on failure.
*/
-static int read_compressed_resource(FILE *fp, u64 resource_compressed_size,
- u64 resource_uncompressed_size,
- u64 resource_offset, int resource_ctype,
- u64 len, u64 offset, u8 contents_ret[])
+static int
+read_compressed_resource(FILE *fp, u64 resource_compressed_size,
+ u64 resource_uncompressed_size,
+ u64 resource_offset, int resource_ctype,
+ u64 len, u64 offset, void *contents_ret)
{
DEBUG2("comp size = %"PRIu64", uncomp size = %"PRIu64", "
/* Pointer to current position in the output buffer for uncompressed
* data. */
- u8 *out_p = (u8*)contents_ret;
+ u8 *out_p = contents_ret;
/* Buffer for compressed data. While most compressed chunks will have a
* size much less than WIM_CHUNK_SIZE, WIM_CHUNK_SIZE - 1 is the maximum
bool is_partial_chunk = (partial_chunk_size !=
uncompressed_chunk_size);
- DEBUG2("start_offset = %u, end_offset = %u", start_offset,
- end_offset);
- DEBUG2("partial_chunk_size = %u", partial_chunk_size);
+ DEBUG2("start_offset = %"PRIu64", end_offset = %"PRIu64"",
+ start_offset, end_offset);
+ DEBUG2("partial_chunk_size = %"PRIu64"", partial_chunk_size);
/* This is undocumented, but chunks can be uncompressed. This
* appears to always be the case when the compressed chunk size
/*
* Reads uncompressed data from an open file stream.
*/
-int read_uncompressed_resource(FILE *fp, u64 offset, u64 len,
- u8 contents_ret[])
+int
+read_uncompressed_resource(FILE *fp, u64 offset, u64 len, void *contents_ret)
{
if (fseeko(fp, offset, SEEK_SET) != 0) {
ERROR("Failed to seek to byte %"PRIu64" of input file "
/* 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. */
-const u8 *get_resource_entry(const u8 *p, struct resource_entry *entry)
+const u8 *
+get_resource_entry(const u8 *p, struct resource_entry *entry)
{
u64 size;
u8 flags;
/* Copies the struct resource_entry @entry to the memory pointed to by @p in the
* on-disk format. A pointer to the byte after the memory written at @p is
* returned. */
-u8 *put_resource_entry(u8 *p, const struct resource_entry *entry)
+u8 *
+put_resource_entry(u8 *p, const struct resource_entry *entry)
{
p = put_u56(p, entry->size);
p = put_u8(p, entry->flags);
}
#ifdef WITH_FUSE
-static FILE *wim_get_fp(WIMStruct *w)
+static FILE *
+wim_get_fp(WIMStruct *w)
{
pthread_mutex_lock(&w->fp_tab_mutex);
FILE *fp;
return fp;
}
-static int wim_release_fp(WIMStruct *w, FILE *fp)
+static int
+wim_release_fp(WIMStruct *w, FILE *fp)
{
int ret = 0;
FILE **fp_tab;
pthread_mutex_unlock(&w->fp_tab_mutex);
return ret;
}
-#endif
+#endif /* !WITH_FUSE */
/*
* Reads some data from the resource corresponding to a WIM lookup table entry.
*
* Returns zero on success, nonzero on failure.
*/
-int read_wim_resource(const struct lookup_table_entry *lte, u8 buf[],
- size_t size, u64 offset, int flags)
+int
+read_wim_resource(const struct wim_lookup_table_entry *lte, void *buf,
+ size_t size, u64 offset, int flags)
{
int ctype;
int ret = 0;
case RESOURCE_IN_FILE_ON_DISK:
/* The resource is in some file on the external filesystem and
* needs to be read uncompressed */
- wimlib_assert(lte->file_on_disk);
- wimlib_assert(<e->file_on_disk == <e->staging_file_name);
+ wimlib_assert(lte->file_on_disk != NULL);
+ BUILD_BUG_ON(<e->file_on_disk != <e->staging_file_name);
/* Use existing file pointer if available; otherwise open one
* temporarily */
if (lte->file_on_disk_fp) {
if (fp != lte->file_on_disk_fp)
fclose(fp);
break;
+#ifdef __WIN32__
+ case RESOURCE_WIN32:
+ wimlib_assert(lte->file_on_disk_fp != NULL);
+ ret = win32_read_file(lte->file_on_disk, lte->file_on_disk_fp,
+ offset, size, buf);
+ break;
+#endif
case RESOURCE_IN_ATTACHED_BUFFER:
/* The resource is directly attached uncompressed in an
* in-memory buffer. */
if (ntfs_attr_pread(lte->attr, offset, size, buf) != size) {
ERROR_WITH_ERRNO("Error reading NTFS attribute "
"at `%s'",
- lte->ntfs_loc->path_utf8);
+ lte->ntfs_loc->path);
ret = WIMLIB_ERR_NTFS_3G;
}
break;
*
* Returns 0 on success; nonzero on failure.
*/
-int read_full_wim_resource(const struct lookup_table_entry *lte, u8 buf[],
- int flags)
+int
+read_full_wim_resource(const struct wim_lookup_table_entry *lte,
+ void *buf, int flags)
{
return read_wim_resource(lte, buf, wim_resource_size(lte), 0, flags);
}
-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 a WIM resource to somewhere. In the
+ * process, the SHA1 message digest of the resource is checked if the full
+ * resource is being extracted.
+ *
+ * @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, sizeof(buf));
ret = read_wim_resource(lte, buf, to_read, offset, 0);
if (ret != 0)
return ret;
- sha1_update(&ctx, buf, to_read);
+ 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");
bytes_remaining -= to_read;
offset += to_read;
}
- 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;
+ 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, stderr);
+ #endif
+ return WIMLIB_ERR_INVALID_RESOURCE_HASH;
+ }
}
return 0;
}
-/* Write @n bytes from @buf to the file descriptor @fd, retrying on interupt and
- * on short writes.
+/* Write @n bytes from @buf to the file descriptor @fd, retrying on internupt
+ * and on short writes.
*
* Returns short count and set errno on failure. */
-static ssize_t full_write(int fd, const void *buf, size_t n)
+static ssize_t
+full_write(int fd, const void *buf, size_t n)
{
- const char *p = buf;
+ const void *p = buf;
ssize_t ret;
ssize_t total = 0;
return total;
}
-int extract_wim_chunk_to_fd(const u8 *buf, size_t len,
- u64 offset, void *arg)
+int
+extract_wim_chunk_to_fd(const void *buf, size_t len, u64 offset, void *arg)
{
int fd = *(int*)arg;
ssize_t ret = full_write(fd, buf, len);
*
* 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;