/** Compressed resources in the WIM use XPRESS compression. */
WIMLIB_COMPRESSION_TYPE_XPRESS = 2,
+
+ /** TODO */
+ WIMLIB_COMPRESSION_TYPE_LZMS = 3,
};
/** @} */
/* Version of the WIM file. There is an older version (used for prerelease
* versions of Windows Vista), but wimlib doesn't support it. The differences
* between the versions are undocumented. */
-#define WIM_VERSION 0x10d00
+#define WIM_VERSION_DEFAULT 0x10d00
/* Version number used for a different WIM format, which as of Windows 8 can be
* created by passing 0x20000000 in dwFlagsAndAttributes to WIMGAPI's
* WIMCreateFile() and specifying either NONE, XPRESS, or LZMS compression.
- * This format is, however, currently undocumented by Microsoft and is seemingly
- * incompatible with their own ImageX and Dism programs. wimlib does not yet
- * support this format. */
-#define WIM_MYSTERY_VERSION 0xe00
+ * This format is currently undocumented by Microsoft and is seemingly
+ * incompatible with their own ImageX and Dism programs; however, it seems to be
+ * used for Windows 8 updates. The format appears to feature a new flag (0x10)
+ * in resource entries, which I've named WIM_RESHDR_FLAG_CONCAT. */
+#define WIM_VERSION_STREAM_CONCAT 0xe00
/* WIM magic characters, translated to a single 64-bit little endian number. */
#define WIM_MAGIC \
* (currently the only supported value). */
u32 hdr_size;
- /* Version of the WIM file; WIM_VERSION expected (currently the only
- * supported value). */
+ /* Version of the WIM file
+ * TODO */
u32 wim_version;
/* Flags for the WIM file (WIM_HDR_FLAG_*) */
u32 image_count;
/* Location and size of the WIM's lookup table. */
- struct resource_entry_disk lookup_table_res_entry;
+ struct wim_reshdr_disk lookup_table_reshdr;
/* Location and size of the WIM's XML data. */
- struct resource_entry_disk xml_data_res_entry;
+ struct wim_reshdr_disk xml_data_reshdr;
/* Location and size of metadata resource for the bootable image of the
* WIM, or all zeroes if no image is bootable. */
- struct resource_entry_disk boot_metadata_res_entry;
+ struct wim_reshdr_disk boot_metadata_reshdr;
/* 1-based index of the bootable image of the WIM, or 0 if no image is
* bootable. */
/* Location and size of the WIM's integrity table, or all zeroes if the
* WIM has no integrity table.
*
- * Note the integrity_table_res_entry here is 4-byte aligned even though
+ * Note the integrity_table_reshdr here is 4-byte aligned even though
* it would ordinarily be 8-byte aligned--- hence, the _packed_attribute
* on the `struct wim_header_disk' is essential. */
- struct resource_entry_disk integrity_table_res_entry;
+ struct wim_reshdr_disk integrity_table_reshdr;
/* Unused bytes. */
u8 unused[60];
/* Magic characters: either WIM_MAGIC or PWM_MAGIC. */
le64 magic;
+ /* Version of the WIM file */
+ u32 wim_version;
+
/* Bitwise OR of one or more of the WIM_HDR_FLAG_* defined below. */
u32 flags;
u32 image_count;
/* Location, size, and flags of the lookup table of the WIM. */
- struct resource_entry lookup_table_res_entry;
+ struct wim_reshdr lookup_table_reshdr;
/* Location, size, and flags for the XML data of the WIM. */
- struct resource_entry xml_res_entry;
+ struct wim_reshdr xml_data_reshdr;
/* Location, size, and flags for the boot metadata. This means the
* metadata resource for the image specified by boot_idx below. Should
* be zeroed out if boot_idx is 0. */
- struct resource_entry boot_metadata_res_entry;
+ struct wim_reshdr boot_metadata_reshdr;
/* The index of the bootable image in the WIM file. If 0, there are no
* bootable images available. */
/* The location of the optional integrity table used to verify the
* integrity WIM. Zeroed out if there is no integrity table.*/
- struct resource_entry integrity;
+ struct wim_reshdr integrity_table_reshdr;
};
/* Flags for the `flags' field of the struct wim_header: */
/* List of lookup table entries in this hash bucket */
struct hlist_node hash_list;
- /* Location and size of the stream in the WIM, whether it is compressed
- * or not, and whether it's a metadata resource or not. This is an
- * on-disk field. */
- struct resource_entry resource_entry;
+ /* Uncompressed size of the stream. */
+ u64 size : 56;
- /* Specifies which part of the split WIM the resource is located in.
- * This is on on-disk field.
- *
- * In stand-alone WIMs, this must be 1.
- *
- * In split WIMs, every split WIM part has its own lookup table, and in
- * read_lookup_table() it's currently expected that the part number of
- * each lookup table entry in a split WIM part's lookup table is the
- * same as the part number of that split WIM part. So this makes this
- * field redundant since we store a pointer to the corresponding
- * WIMStruct in the lookup table entry anyway.
- */
- u16 part_number;
+ /* Stream flags (WIM_RESHDR_FLAG_*). */
+ u64 flags : 8;
/* One of the `enum resource_location' values documented above. */
u16 resource_location : 5;
u16 no_progress : 1;
- /* If resource_location == RESOURCE_IN_WIM, this will be a cached value
- * that specifies the compression type of this stream as one of
- * WIMLIB_COMPRESSION_TYPE_*. Otherwise this will be 0, which is the
- * same as WIMLIB_COMPRESSION_TYPE_NONE. */
- u16 compression_type : 2;
-
- /* If resource_location == RESOURCE_IN_WIM, this flag will be set if the
- * WIM is pipable and therefore the stream is in a slightly different
- * format. See comment above write_pipable_wim(). */
- u16 is_pipable : 1;
-
/* Set to 1 when a metadata entry has its checksum changed; in such
* cases the hash is no longer valid to verify the data if the metadata
* resource is read again. */
/* Pointers to somewhere where the stream is actually located. See the
* comments for the @resource_location field above. */
union {
- WIMStruct *wim;
+ struct wim_resource_spec *rspec;
tchar *file_on_disk;
void *attached_buffer;
#ifdef WITH_FUSE
struct list_head being_compressed_list;
};
- /* When a WIM file is written, @output_resource_entry is filled
- * in with the resource entry for the output WIM. This will not
- * necessarily be the same as the @resource_entry since:
- * - The stream may have a different offset in the new WIM
- * - The stream may have a different compressed size in the new
- * WIM if the compression type changed
- */
- struct resource_entry output_resource_entry;
-
+ /* When a WIM file is written, @output_reshdr is filled in with
+ * the resource header for the output WIM. */
+ struct wim_reshdr out_reshdr;
/* Used temporarily during extraction */
union {
/* Links streams that are still unhashed after being been added
* to a WIM. */
struct list_head unhashed_list;
+
+ struct list_head wim_resource_list;
};
-static inline u64
-wim_resource_size(const struct wim_lookup_table_entry *lte)
+static inline int
+lte_ctype(const struct wim_lookup_table_entry *lte)
{
- return lte->resource_entry.original_size;
+ if (lte->resource_location == RESOURCE_IN_WIM)
+ return lte->rspec->ctype;
+ else
+ return WIMLIB_COMPRESSION_TYPE_NONE;
}
static inline u32
-wim_resource_chunk_size(const struct wim_lookup_table_entry * lte)
+lte_cchunk_size(const struct wim_lookup_table_entry * lte)
{
if (lte->resource_location == RESOURCE_IN_WIM &&
- lte->compression_type != WIMLIB_COMPRESSION_TYPE_NONE)
- return lte->wim->chunk_size;
+ lte->rspec->ctype != WIMLIB_COMPRESSION_TYPE_NONE)
+ return lte->rspec->cchunk_size;
else
return 32768;
}
-
-static inline u64
-wim_resource_chunks(const struct wim_lookup_table_entry *lte)
-{
- return DIV_ROUND_UP(wim_resource_size(lte), wim_resource_chunk_size(lte));
-}
-
-static inline int
-wim_resource_compression_type(const struct wim_lookup_table_entry *lte)
-{
- return lte->compression_type;
-}
-
static inline bool
lte_filename_valid(const struct wim_lookup_table_entry *lte)
{
extern int
write_wim_lookup_table(WIMStruct *wim, int image, int write_flags,
- struct resource_entry *out_res_entry,
+ struct wim_reshdr *out_reshdr,
struct list_head *stream_list_override);
extern void
_malloc_attribute;
extern void
-print_lookup_table_entry(const struct wim_lookup_table_entry *entry,
- FILE *out);
+print_lookup_table_entry(const struct wim_lookup_table_entry *lte, FILE *out);
extern void
free_lookup_table_entry(struct wim_lookup_table_entry *lte);
#endif
extern int
-lte_zero_out_refcnt(struct wim_lookup_table_entry *entry, void *ignore);
+lte_zero_out_refcnt(struct wim_lookup_table_entry *lte, void *ignore);
extern int
-lte_zero_real_refcnt(struct wim_lookup_table_entry *entry, void *ignore);
+lte_zero_real_refcnt(struct wim_lookup_table_entry *lte, void *ignore);
extern int
lte_free_extracted_file(struct wim_lookup_table_entry *lte, void *ignore);
-extern void
-lte_init_wim(struct wim_lookup_table_entry *lte, WIMStruct *wim);
+static inline void
+lte_bind_wim_resource_spec(struct wim_lookup_table_entry *lte,
+ struct wim_resource_spec *rspec)
+{
+ lte->resource_location = RESOURCE_IN_WIM;
+ lte->rspec = rspec;
+ list_add(<e->wim_resource_list, &rspec->lte_list);
+ lte->flags = rspec->flags;
+ lte->size = rspec->uncompressed_size;
+}
+
+static inline void
+lte_unbind_wim_resource_spec(struct wim_lookup_table_entry *lte)
+{
+ list_del(<e->wim_resource_list);
+ lte->rspec = NULL;
+ lte->resource_location = RESOURCE_NONEXISTENT;
+}
extern int
inode_resolve_ltes(struct wim_inode *inode, struct wim_lookup_table *table,
extern const u8 *
inode_unnamed_stream_hash(const struct wim_inode *inode);
-extern u64
-lookup_table_total_stream_size(struct wim_lookup_table *table);
-
-
static inline void
lookup_table_insert_unhashed(struct wim_lookup_table *table,
struct wim_lookup_table_entry *lte,
#include "wimlib/endianness.h"
#include "wimlib/callback.h"
#include "wimlib/file_io.h"
+#include "wimlib/list.h"
#include "wimlib/sha1.h"
struct wim_lookup_table_entry;
struct wim_image_metadata;
-/* Description of the location, size, and compression status of a WIM resource
- * (stream). This is the in-memory version of `struct resource_entry_disk'. */
-struct resource_entry {
- /* Size, in bytes, of the resource as it appears in the WIM file. If
- * the resource is uncompressed, this will be the same as
- * @original_size. If the resource is compressed, this will be the
- * compressed size of the resource, including all compressed chunks as
- * well as the chunk table.
- *
- * Note: if the WIM is "pipable", this value does not include the stream
- * header. */
- u64 size : 56;
-
- /* Bitwise OR of one or more of the WIM_RESHDR_FLAG_* flags. */
- u64 flags : 8;
+/* Specification of a resource in a WIM file.
+ *
+ * If a `struct wim_lookup_table_entry' lte has
+ * (lte->resource_location == RESOURCE_IN_WIM), then lte->wim_res_spec points to
+ * an instance of this structure.
+ *
+ * Normally, there is a one-to-one correspondence between WIM lookup table
+ * entries ("streams") and WIM resources. However, the flag
+ * WIM_RESHDR_FLAG_CONCAT can be used to specify that two streams be combined
+ * into the same resource and compressed together. Caveats about this flag are
+ * noted in the comment above the definition of WIM_VERSION_STREAM_CONCAT. */
+struct wim_resource_spec {
+ /* The WIM file containing this resource. */
+ WIMStruct *wim;
+
+ /* Offset, in bytes, from the start of WIM file at which this resource
+ * starts. */
+ u64 offset_in_wim;
+
+ /* The size of this resource in the WIM file. For compressed resources
+ * this is the compressed size. */
+ u64 size_in_wim;
+
+ /* Number of bytes of uncompressed data this resource uncompresses to.
+ */
+ u64 uncompressed_size;
+
+ /* List of streams this resource contains. */
+ struct list_head lte_list;
+
+ /* Resource flags. */
+ u32 flags : 8;
+
+ /* This flag will be set if the WIM is pipable and therefore the
+ * resource will be in a slightly different format if it is compressed
+ * (wimlib extension). */
+ u32 is_pipable : 1;
+
+ /* Compression type of this resource as one of WIMLIB_COMPRESSION_TYPE_*
+ * constants. */
+ u32 ctype : 3;
+
+ /* Compression chunk size. */
+ u32 cchunk_size;
+};
- /* Offset, in bytes, of the resource from the start of the WIM file. */
- u64 offset;
- /* Uncompressed size, in bytes, of the resource (stream). */
- u64 original_size;
-};
+/* On-disk version of a WIM resource header: This structure specifies the
+ * location, size, and flags (e.g. compressed or not compressed) for a resource
+ * in the WIM file. */
+struct wim_reshdr_disk {
+ /* Size of the resource as it appears in the WIM file (possibly
+ * compressed). */
+ u8 size_in_wim[7];
-/* On-disk version of `struct resource_entry'. See `struct resource_entry' for
- * description of fields. */
-struct resource_entry_disk {
- u8 size[7];
+ /* WIM_RESHDR_FLAG_* flags. */
u8 flags;
- le64 offset;
- le64 original_size;
+
+ /* Offset of the resource from the start of the WIM file. */
+ le64 offset_in_wim;
+
+ /* Uncompressed size of the resource. */
+ le64 uncompressed_size;
} _packed_attribute;
+/* In-memory version of wim_reshdr_disk. */
+struct wim_reshdr {
+ u64 size_in_wim : 56;
+ u64 flags : 8;
+ u64 offset_in_wim;
+ u64 uncompressed_size;
+};
+
/* Flags for the `flags' field of the struct resource_entry structure. */
/* I haven't seen this flag used in any of the WIMs I have examined. I assume
* Either way, wimlib doesn't actually use this flag for anything. */
#define WIM_RESHDR_FLAG_SPANNED 0x08
-/* Functions that operate directly on `struct resource_entry's. */
-
-static inline int
-resource_is_compressed(const struct resource_entry *entry)
-{
- return (entry->flags & WIM_RESHDR_FLAG_COMPRESSED);
-}
+/* TODO */
+#define WIM_RESHDR_FLAG_CONCAT 0x10
static inline void
-copy_resource_entry(struct resource_entry *dst,
- const struct resource_entry *src)
+copy_reshdr(struct wim_reshdr *dest, const struct wim_reshdr *src)
{
- memcpy(dst, src, sizeof(struct resource_entry));
+ memcpy(dest, src, sizeof(struct wim_reshdr));
}
static inline void
-zero_resource_entry(struct resource_entry *entry)
+zero_reshdr(struct wim_reshdr *reshdr)
{
- memset(entry, 0, sizeof(struct resource_entry));
+ memset(reshdr, 0, sizeof(struct wim_reshdr));
}
+
+extern void
+wim_res_hdr_to_spec(const struct wim_reshdr *reshdr, WIMStruct *wim,
+ struct wim_resource_spec *rspec);
+
extern void
-get_resource_entry(const struct resource_entry_disk *disk_entry,
- struct resource_entry *entry);
+wim_res_spec_to_hdr(const struct wim_resource_spec *rspec,
+ struct wim_reshdr *reshdr);
extern void
-put_resource_entry(const struct resource_entry *entry,
- struct resource_entry_disk *disk_entry);
+get_wim_reshdr(const struct wim_reshdr_disk *disk_reshdr,
+ struct wim_reshdr *reshdr);
+
+void
+put_wim_reshdr(const struct wim_reshdr *reshdr,
+ struct wim_reshdr_disk *disk_reshdr);
/* wimlib internal flags used when reading or writing resources. */
#define WIMLIB_WRITE_RESOURCE_FLAG_RECOMPRESS 0x00000001
void **buf_ret);
extern int
-res_entry_to_data(const struct resource_entry *res_entry,
- WIMStruct *wim, void **buf_ret);
+wim_reshdr_to_data(const struct wim_reshdr *reshdr,
+ WIMStruct *wim, void **buf_ret);
extern int
read_resource_prefix(const struct wim_lookup_table_entry *lte,
u64 size, consume_data_callback_t cb,
u32 in_chunk_size, void *ctx_or_buf, int flags);
-/* Functions to write a resource. */
-
-extern int
-write_wim_resource_from_buffer(const void *buf, size_t buf_size,
- int reshdr_flags, struct filedes *out_fd,
- int out_ctype,
- u32 out_chunk_size,
- struct resource_entry *out_res_entry,
- u8 *hash_ret, int write_resource_flags,
- struct wimlib_lzx_context **comp_ctx);
-
/* Functions to extract a resource. */
extern int
static inline bool wim_has_integrity_table(const WIMStruct *wim)
{
- return (wim->hdr.integrity.offset != 0);
+ return (wim->hdr.integrity_table_reshdr.offset_in_wim != 0);
}
static inline bool wim_has_metadata(const WIMStruct *wim)
init_wim_header(struct wim_header *hdr, int ctype, u32 chunk_size);
extern int
-read_wim_header(const tchar *filename, struct filedes *in_fd,
- struct wim_header *hdr);
+read_wim_header(WIMStruct *wim, struct wim_header *hdr);
extern int
write_wim_header(const struct wim_header *hdr, struct filedes *out_fd);
struct list_head *stream_list_override,
const u8 *guid);
+int
+write_wim_resource_from_buffer(const void *buf, size_t buf_size,
+ int reshdr_flags, struct filedes *out_fd,
+ int out_ctype,
+ u32 out_chunk_size,
+ struct wim_reshdr *out_reshdr,
+ u8 *hash_ret, int write_resource_flags,
+ struct wimlib_lzx_context **comp_ctx);
+
#endif /* _WIMLIB_WRITE_H */
#include "wimlib/file_io.h"
struct wim_info;
-struct resource_entry;
+struct wim_reshdr;
extern u64
wim_info_get_total_bytes(const struct wim_info *info);
extern int
write_wim_xml_data(WIMStruct *wim, int image,
- u64 total_bytes, struct resource_entry *out_res_entry,
+ u64 total_bytes, struct wim_reshdr *out_reshdr,
int write_resource_flags);
extern void
int ret;
metadata_lte = new_lookup_table_entry();
- if (!metadata_lte)
+ if (metadata_lte == NULL)
return WIMLIB_ERR_NOMEM;
- metadata_lte->resource_entry.flags = WIM_RESHDR_FLAG_METADATA;
+ metadata_lte->flags = WIM_RESHDR_FLAG_METADATA;
metadata_lte->unhashed = 1;
new_imd = new_image_metadata();
- if (!new_imd) {
+ if (new_imd == NULL) {
free_lookup_table_entry(metadata_lte);
return WIMLIB_ERR_NOMEM;
}
}
sd = new_wim_security_data();
- if (!sd) {
+ if (sd == NULL) {
ret = WIMLIB_ERR_NOMEM;
goto out;
}
/* Translate the "capture sources" into generic update commands. */
add_cmds = capture_sources_to_add_cmds(sources, num_sources,
add_flags, config);
- if (!add_cmds) {
+ if (add_cmds == NULL) {
ret = WIMLIB_ERR_NOMEM;
goto out_delete_image;
}
#if TCHAR_IS_UTF16LE
name_utf16le_nbytes = tstrlen(name) * sizeof(utf16lechar);
name_utf16le = MALLOC(name_utf16le_nbytes + sizeof(utf16lechar));
- if (!name_utf16le)
+ if (name_utf16le == NULL)
return WIMLIB_ERR_NOMEM;
memcpy(name_utf16le, name, name_utf16le_nbytes + sizeof(utf16lechar));
ret = 0;
{
int ret;
- if (!root)
+ if (root == NULL)
return 0;
ret = (*visitor)(root, arg);
if (ret)
{
int ret;
- if (!root)
+ if (root == NULL)
return 0;
ret = for_dentry_tree_in_rbtree_depth(root->d_inode->i_children.rb_node,
visitor, arg);
if (dentry_is_root(dentry)) {
static const tchar _root_path[] = {WIM_PATH_SEPARATOR, T('\0')};
full_path = TSTRDUP(_root_path);
- if (!full_path)
+ if (full_path == NULL)
return WIMLIB_ERR_NOMEM;
full_path_nbytes = 1 * sizeof(tchar);
} else {
parent_full_path = T("");
parent_full_path_nbytes = 0;
} else {
- if (!parent->_full_path) {
+ if (parent->_full_path == NULL) {
ret = calculate_dentry_full_path(parent);
if (ret)
return ret;
full_path_nbytes = parent_full_path_nbytes + sizeof(tchar) +
filename_nbytes;
full_path = MALLOC(full_path_nbytes + sizeof(tchar));
- if (!full_path)
+ if (full_path == NULL)
return WIMLIB_ERR_NOMEM;
memcpy(full_path, parent_full_path, parent_full_path_nbytes);
full_path[parent_full_path_nbytes / sizeof(tchar)] = WIM_PATH_SEPARATOR;
const utf16lechar *p, *pp;
cur_dentry = parent_dentry = wim_root_dentry(wim);
- if (!cur_dentry) {
+ if (cur_dentry == NULL) {
errno = ENOENT;
return NULL;
}
int ret;
dentry = MALLOC(sizeof(struct wim_dentry));
- if (!dentry)
+ if (dentry == NULL)
return WIMLIB_ERR_NOMEM;
dentry_common_init(dentry);
dentry->d_inode = new_timeless_inode();
else
dentry->d_inode = new_inode();
- if (!dentry->d_inode) {
+ if (dentry->d_inode == NULL) {
free_dentry(dentry);
return WIMLIB_ERR_NOMEM;
}
if (is_utf16le) {
utf16lechar *p = MALLOC(name_nbytes + sizeof(utf16lechar));
- if (!p)
+ if (p == NULL)
return WIMLIB_ERR_NOMEM;
memcpy(p, name, name_nbytes);
p[name_nbytes / 2] = cpu_to_le16(0);
num_ads = inode->i_num_ads + 1;
ads_entries = REALLOC(inode->i_ads_entries,
num_ads * sizeof(inode->i_ads_entries[0]));
- if (!ads_entries) {
+ if (ads_entries == NULL) {
ERROR("Failed to allocate memory for new alternate data stream");
return NULL;
}
sha1_buffer(buffer, size, hash);
existing_lte = lookup_resource(lookup_table, hash);
if (existing_lte) {
- wimlib_assert(wim_resource_size(existing_lte) == size);
+ wimlib_assert(existing_lte->size == size);
lte = existing_lte;
lte->refcnt++;
} else {
void *buffer_copy;
lte = new_lookup_table_entry();
- if (!lte)
+ if (lte == NULL)
return NULL;
buffer_copy = memdup(buffer, size);
- if (!buffer_copy) {
+ if (buffer_copy == NULL) {
free_lookup_table_entry(lte);
return NULL;
}
- lte->resource_location = RESOURCE_IN_ATTACHED_BUFFER;
- lte->attached_buffer = buffer_copy;
- lte->resource_entry.original_size = size;
+ lte->resource_location = RESOURCE_IN_ATTACHED_BUFFER;
+ lte->attached_buffer = buffer_copy;
+ lte->size = size;
copy_hash(lte->hash, hash);
lookup_table_insert(lookup_table, lte);
}
wimlib_assert(inode->i_resolved);
new_ads_entry = inode_add_ads(inode, name);
- if (!new_ads_entry)
+ if (new_ads_entry == NULL)
return WIMLIB_ERR_NOMEM;
new_ads_entry->lte = add_stream_from_data_buffer(value, size,
lookup_table);
- if (!new_ads_entry->lte) {
+ if (new_ads_entry->lte == NULL) {
inode_remove_ads(inode, new_ads_entry - inode->i_ads_entries,
lookup_table);
return WIMLIB_ERR_NOMEM;
struct wim_lookup_table *lookup_table)
{
inode->i_lte = add_stream_from_data_buffer(data, len, lookup_table);
- if (!inode->i_lte)
+ if (inode->i_lte == NULL)
return WIMLIB_ERR_NOMEM;
inode->i_resolved = 1;
return 0;
ads_entry = inode_get_ads_entry((struct wim_inode*)inode,
WIMLIB_UNIX_DATA_TAG, NULL);
- if (!ads_entry)
+ if (ads_entry == NULL)
return NO_UNIX_DATA;
if (stream_idx_ret)
*stream_idx_ret = ads_entry - inode->i_ads_entries;
lte = ads_entry->lte;
- if (!lte)
+ if (lte == NULL)
return NO_UNIX_DATA;
- size = wim_resource_size(lte);
+ size = lte->size;
if (size != sizeof(struct wimlib_unix_data))
return BAD_UNIX_DATA;
* data stream entries. */
num_ads = inode->i_num_ads;
ads_entries = CALLOC(num_ads, sizeof(inode->i_ads_entries[0]));
- if (!ads_entries)
+ if (ads_entries == NULL)
goto out_of_memory;
/* Read the entries into our newly allocated buffer. */
goto out_invalid;
cur_entry->stream_name = MALLOC(cur_entry->stream_name_nbytes + 2);
- if (!cur_entry->stream_name)
+ if (cur_entry->stream_name == NULL)
goto out_of_memory;
memcpy(cur_entry->stream_name,
/* Allocate a `struct wim_inode' for this `struct wim_dentry'. */
inode = new_timeless_inode();
- if (!inode)
+ if (inode == NULL)
return WIMLIB_ERR_NOMEM;
/* Read more fields; some into the dentry, and some into the inode. */
* is no null terminator following it. */
if (file_name_nbytes) {
file_name = MALLOC(file_name_nbytes + 2);
- if (!file_name) {
+ if (file_name == NULL) {
ERROR("Failed to allocate %d bytes for dentry file name",
file_name_nbytes + 2);
ret = WIMLIB_ERR_NOMEM;
* filename, there is no null terminator following it. */
if (short_name_nbytes) {
short_name = MALLOC(short_name_nbytes + 2);
- if (!short_name) {
+ if (short_name == NULL) {
ERROR("Failed to allocate %d bytes for dentry short name",
short_name_nbytes + 2);
ret = WIMLIB_ERR_NOMEM;
/* Not end of directory. Allocate this child permanently and
* link it to the parent and previous child. */
child = memdup(&cur_child, sizeof(struct wim_dentry));
- if (!child) {
+ if (child == NULL) {
ERROR("Failed to allocate new dentry!");
ret = WIMLIB_ERR_NOMEM;
break;
wdentry = CALLOC(1, sizeof(struct wimlib_dir_entry) +
(1 + dentry->d_inode->i_num_ads) *
sizeof(struct wimlib_stream_entry));
- if (!wdentry)
+ if (wdentry == NULL)
goto out;
ret = init_wimlib_dentry(wdentry, dentry, wim, flags);
struct wim_dentry *dentry;
dentry = get_dentry(wim, ctx->path);
- if (!dentry)
+ if (dentry == NULL)
return WIMLIB_ERR_PATH_DOES_NOT_EXIST;
return do_iterate_dir_tree(wim, dentry, ctx->flags, ctx->cb, ctx->user_ctx);
}
/* Compare stream sizes. */
if (lte && template_lte) {
- if (wim_resource_size(lte) != wim_resource_size(template_lte))
+ if (lte->size != template_lte->size)
return false;
/* If hash happens to be available, compare with template. */
!hashes_equal(lte->hash, template_lte->hash))
return false;
- } else if (lte && wim_resource_size(lte)) {
+ } else if (lte && lte->size) {
return false;
- } else if (template_lte && wim_resource_size(template_lte)) {
+ } else if (template_lte && template_lte->size) {
return false;
}
}
/* Only take action if both entries exist, the entry for @inode
* has no checksum calculated, but the entry for @template_inode
* does. */
- if (!lte || !template_lte ||
+ if (lte == NULL || template_lte == NULL ||
!lte->unhashed || template_lte->unhashed)
continue;
return ret;
template_dentry = get_dentry(template_wim, dentry->_full_path);
- if (!template_dentry) {
+ if (template_dentry == NULL) {
DEBUG("\"%"TS"\": newly added file", dentry->_full_path);
return 0;
}
(!is_linked_extraction(ctx) || (lte->out_refcnt == 0 &&
lte->extracted_file == NULL)))
{
- ctx->progress.extract.total_bytes += wim_resource_size(lte);
+ ctx->progress.extract.total_bytes += lte->size;
ctx->progress.extract.num_streams++;
}
wimlib_progress_func_t progress_func = ctx->progress_func;
union wimlib_progress_info *progress = &ctx->progress;
- progress->extract.completed_bytes += wim_resource_size(lte);
+ progress->extract.completed_bytes += lte->size;
if (progress_func &&
progress->extract.completed_bytes >= ctx->next_progress)
{
goto out_free_lte_tmp;
}
filedes_init(&fd, raw_fd);
- ret = extract_wim_resource_to_fd(lte, &fd,
- wim_resource_size(lte));
+ ret = extract_wim_resource_to_fd(lte, &fd, lte->size);
if (filedes_close(&fd) && !ret)
ret = WIMLIB_ERR_WRITE;
if (ret)
/* Read the header from a stream in a pipable WIM. */
static int
read_pwm_stream_header(WIMStruct *pwm, struct wim_lookup_table_entry *lte,
+ struct wim_resource_spec *rspec,
int flags, struct wim_header_disk *hdr_ret)
{
union {
struct pwm_stream_hdr stream_hdr;
struct wim_header_disk pwm_hdr;
} buf;
+ struct wim_reshdr reshdr;
int ret;
ret = full_read(&pwm->in_fd, &buf.stream_hdr, sizeof(buf.stream_hdr));
return WIMLIB_ERR_INVALID_PIPABLE_WIM;
}
- lte->resource_entry.original_size = le64_to_cpu(buf.stream_hdr.uncompressed_size);
copy_hash(lte->hash, buf.stream_hdr.hash);
- lte->resource_entry.flags = le32_to_cpu(buf.stream_hdr.flags);
- lte->resource_entry.offset = pwm->in_fd.offset;
- lte->resource_location = RESOURCE_IN_WIM;
- lte->wim = pwm;
- if (lte->resource_entry.flags & WIM_RESHDR_FLAG_COMPRESSED) {
- lte->compression_type = pwm->compression_type;
- lte->resource_entry.size = 0;
- } else {
- lte->compression_type = WIMLIB_COMPRESSION_TYPE_NONE;
- lte->resource_entry.size = lte->resource_entry.original_size;
- }
- lte->is_pipable = 1;
+
+ reshdr.size_in_wim = 0;
+ reshdr.flags = le32_to_cpu(buf.stream_hdr.flags);
+ reshdr.offset_in_wim = pwm->in_fd.offset;
+ reshdr.uncompressed_size = le64_to_cpu(buf.stream_hdr.uncompressed_size);
+ wim_res_hdr_to_spec(&reshdr, pwm, rspec);
+ lte_bind_wim_resource_spec(lte, rspec);
return 0;
read_error:
skip_pwm_stream(struct wim_lookup_table_entry *lte)
{
return read_partial_wim_resource(lte,
- wim_resource_size(lte),
+ lte->size,
skip_pwm_chunk_cb,
- wim_resource_chunk_size(lte),
+ lte_cchunk_size(lte),
NULL,
WIMLIB_READ_RESOURCE_FLAG_RAW_CHUNKS,
0);
extract_streams_from_pipe(struct apply_ctx *ctx)
{
struct wim_lookup_table_entry *found_lte;
+ struct wim_resource_spec *rspec;
struct wim_lookup_table_entry *needed_lte;
struct wim_lookup_table *lookup_table;
struct wim_header_disk pwm_hdr;
ret = WIMLIB_ERR_NOMEM;
found_lte = new_lookup_table_entry();
- if (!found_lte)
+ if (found_lte == NULL)
goto out;
+ rspec = MALLOC(sizeof(struct wim_resource_spec));
+ if (rspec == NULL)
+ goto out_free_found_lte;
+
lookup_table = ctx->wim->lookup_table;
pwm_flags = PWM_ALLOW_WIM_HDR;
if ((ctx->extract_flags & WIMLIB_EXTRACT_FLAG_RESUME))
ctx->progress_func(WIMLIB_PROGRESS_MSG_EXTRACT_SPWM_PART_BEGIN,
&ctx->progress);
while (ctx->num_streams_remaining) {
- ret = read_pwm_stream_header(ctx->wim, found_lte, pwm_flags,
- &pwm_hdr);
+ if (found_lte->resource_location != RESOURCE_NONEXISTENT)
+ lte_unbind_wim_resource_spec(found_lte);
+ ret = read_pwm_stream_header(ctx->wim, found_lte, rspec,
+ pwm_flags, &pwm_hdr);
if (ret) {
if (ret == WIMLIB_ERR_UNEXPECTED_END_OF_FILE &&
(ctx->extract_flags & WIMLIB_EXTRACT_FLAG_RESUME))
}
if ((found_lte->resource_location != RESOURCE_NONEXISTENT)
- && !(found_lte->resource_entry.flags & WIM_RESHDR_FLAG_METADATA)
+ && !(found_lte->flags & WIM_RESHDR_FLAG_METADATA)
&& (needed_lte = lookup_resource(lookup_table, found_lte->hash))
&& (needed_lte->out_refcnt))
{
- copy_resource_entry(&needed_lte->resource_entry,
- &found_lte->resource_entry);
- needed_lte->resource_location = found_lte->resource_location;
- needed_lte->wim = found_lte->wim;
- needed_lte->compression_type = found_lte->compression_type;
- needed_lte->is_pipable = found_lte->is_pipable;
-
+ lte_unbind_wim_resource_spec(found_lte);
+ lte_bind_wim_resource_spec(needed_lte, rspec);
ret = extract_stream_instances(needed_lte, ctx, false);
+ lte_unbind_wim_resource_spec(needed_lte);
+
if (ret)
goto out_free_found_lte;
ctx->num_streams_remaining--;
}
ret = 0;
out_free_found_lte:
+ if (found_lte->resource_location != RESOURCE_IN_WIM)
+ FREE(rspec);
free_lookup_table_entry(found_lte);
out:
return ret;
if (lte) {
struct filedes _stdout;
filedes_init(&_stdout, STDOUT_FILENO);
- ret = extract_wim_resource_to_fd(lte, &_stdout,
- wim_resource_size(lte));
+ ret = extract_wim_resource_to_fd(lte, &_stdout, lte->size);
}
}
return ret;
{
int ret;
tchar *target_copy = canonicalize_fs_path(target);
- if (!target_copy)
+ if (target_copy == NULL)
return WIMLIB_ERR_NOMEM;
struct wimlib_extract_command cmd = {
.wim_source_path = T(""),
* WIMs.) */
{
struct wim_lookup_table_entry xml_lte;
- ret = read_pwm_stream_header(pwm, &xml_lte, 0, NULL);
+ struct wim_resource_spec xml_rspec;
+ ret = read_pwm_stream_header(pwm, &xml_lte, &xml_rspec, 0, NULL);
if (ret)
goto out_wimlib_free;
- if (!(xml_lte.resource_entry.flags & WIM_RESHDR_FLAG_METADATA))
+ if (!(xml_lte.flags & WIM_RESHDR_FLAG_METADATA))
{
ERROR("Expected XML data, but found non-metadata "
"stream.");
goto out_wimlib_free;
}
- copy_resource_entry(&pwm->hdr.xml_res_entry,
- &xml_lte.resource_entry);
+ wim_res_spec_to_hdr(&xml_rspec, &pwm->hdr.xml_data_reshdr);
ret = read_wim_xml_data(pwm);
if (ret)
goto out_wimlib_free;
+
if (wim_info_get_num_images(pwm->wim_info) != pwm->hdr.image_count) {
ERROR("Image count in XML data is not the same as in WIM header.");
ret = WIMLIB_ERR_XML;
for (i = 1; i <= pwm->hdr.image_count; i++) {
struct wim_lookup_table_entry *metadata_lte;
struct wim_image_metadata *imd;
+ struct wim_resource_spec *metadata_rspec;
metadata_lte = new_lookup_table_entry();
- if (!metadata_lte) {
+ if (metadata_lte == NULL) {
ret = WIMLIB_ERR_NOMEM;
goto out_wimlib_free;
}
+ metadata_rspec = MALLOC(sizeof(struct wim_resource_spec));
+ if (metadata_rspec == NULL) {
+ ret = WIMLIB_ERR_NOMEM;
+ free_lookup_table_entry(metadata_lte);
+ goto out_wimlib_free;
+ }
- ret = read_pwm_stream_header(pwm, metadata_lte, 0, NULL);
+ ret = read_pwm_stream_header(pwm, metadata_lte, metadata_rspec, 0, NULL);
imd = pwm->image_metadata[i - 1];
imd->metadata_lte = metadata_lte;
- if (ret)
+ if (ret) {
+ FREE(metadata_rspec);
goto out_wimlib_free;
+ }
- if (!(metadata_lte->resource_entry.flags &
- WIM_RESHDR_FLAG_METADATA))
- {
+ if (!(metadata_lte->flags & WIM_RESHDR_FLAG_METADATA)) {
ERROR("Expected metadata resource, but found "
"non-metadata stream.");
ret = WIMLIB_ERR_INVALID_PIPABLE_WIM;
/*
* Reads the header from a WIM file.
*
- * @filename
- * Name of the WIM file (for error/debug messages only), or NULL if reading
- * directly from file descriptor.
- * @in_fd
- * File descriptor, positioned at offset 0, to read the header from.
+ * @wim
+ * WIM to read the header from; @wim->in_fd must be positioned at the
+ * offset at which to read the header.
+ *
* @hdr
* Structure to read the header into.
*
* Return values:
* WIMLIB_ERR_SUCCESS (0)
* WIMLIB_ERR_IMAGE_COUNT
- * WIMLIB_ERR_INVALID_CHUNK_SIZE
* WIMLIB_ERR_INVALID_PART_NUMBER
* WIMLIB_ERR_NOT_A_WIM_FILE
* WIMLIB_ERR_READ
* WIMLIB_ERR_UNKNOWN_VERSION
*/
int
-read_wim_header(const tchar *filename, struct filedes *in_fd,
- struct wim_header *hdr)
+read_wim_header(WIMStruct *wim, struct wim_header *hdr)
{
struct wim_header_disk disk_hdr _aligned_attribute(8);
+ struct filedes *in_fd = &wim->in_fd;
+ const tchar *filename = wim->filename;
int ret;
tchar *pipe_str;
return WIMLIB_ERR_INVALID_HEADER;
}
- if (le32_to_cpu(disk_hdr.wim_version) != WIM_VERSION) {
- ERROR("\"%"TS"\": The WIM header says the WIM version is %u, "
- "but wimlib only knows about version %u",
- filename, le32_to_cpu(disk_hdr.wim_version), WIM_VERSION);
- if (le32_to_cpu(disk_hdr.wim_flags) & WIM_HDR_FLAG_COMPRESS_LZMS) {
- ERROR("\"%"TS"\": This WIM uses LZMS compression, "
- "which is not supported by wimlib.", filename);
- }
+ hdr->wim_version = le32_to_cpu(disk_hdr.wim_version);
+ if (hdr->wim_version != WIM_VERSION_DEFAULT &&
+ hdr->wim_version != WIM_VERSION_STREAM_CONCAT)
+ {
+ ERROR("\"%"TS"\": Unknown WIM version: %u", hdr->wim_version);
return WIMLIB_ERR_UNKNOWN_VERSION;
}
return WIMLIB_ERR_IMAGE_COUNT;
}
- get_resource_entry(&disk_hdr.lookup_table_res_entry, &hdr->lookup_table_res_entry);
- get_resource_entry(&disk_hdr.xml_data_res_entry, &hdr->xml_res_entry);
- get_resource_entry(&disk_hdr.boot_metadata_res_entry, &hdr->boot_metadata_res_entry);
+ get_wim_reshdr(&disk_hdr.lookup_table_reshdr, &hdr->lookup_table_reshdr);
+ get_wim_reshdr(&disk_hdr.xml_data_reshdr, &hdr->xml_data_reshdr);
+ get_wim_reshdr(&disk_hdr.boot_metadata_reshdr, &hdr->boot_metadata_reshdr);
hdr->boot_idx = le32_to_cpu(disk_hdr.boot_idx);
- get_resource_entry(&disk_hdr.integrity_table_res_entry, &hdr->integrity);
+ get_wim_reshdr(&disk_hdr.integrity_table_reshdr, &hdr->integrity_table_reshdr);
return 0;
read_error:
disk_hdr.magic = hdr->magic;
disk_hdr.hdr_size = cpu_to_le32(sizeof(struct wim_header_disk));
- disk_hdr.wim_version = cpu_to_le32(WIM_VERSION);
+ disk_hdr.wim_version = cpu_to_le32(hdr->wim_version);
disk_hdr.wim_flags = cpu_to_le32(hdr->flags);
if (hdr->flags & WIM_HDR_FLAG_COMPRESSION)
disk_hdr.chunk_size = cpu_to_le32(hdr->chunk_size);
disk_hdr.part_number = cpu_to_le16(hdr->part_number);
disk_hdr.total_parts = cpu_to_le16(hdr->total_parts);
disk_hdr.image_count = cpu_to_le32(hdr->image_count);
- put_resource_entry(&hdr->lookup_table_res_entry, &disk_hdr.lookup_table_res_entry);
- put_resource_entry(&hdr->xml_res_entry, &disk_hdr.xml_data_res_entry);
- put_resource_entry(&hdr->boot_metadata_res_entry, &disk_hdr.boot_metadata_res_entry);
+ put_wim_reshdr(&hdr->lookup_table_reshdr, &disk_hdr.lookup_table_reshdr);
+ put_wim_reshdr(&hdr->xml_data_reshdr, &disk_hdr.xml_data_reshdr);
+ put_wim_reshdr(&hdr->boot_metadata_reshdr, &disk_hdr.boot_metadata_reshdr);
disk_hdr.boot_idx = cpu_to_le32(hdr->boot_idx);
- put_resource_entry(&hdr->integrity, &disk_hdr.integrity_table_res_entry);
+ put_wim_reshdr(&hdr->integrity_table_reshdr, &disk_hdr.integrity_table_reshdr);
memset(disk_hdr.unused, 0, sizeof(disk_hdr.unused));
if (offset == out_fd->offset)
{
memset(hdr, 0, sizeof(struct wim_header));
hdr->magic = WIM_MAGIC;
+ hdr->wim_version = WIM_VERSION_DEFAULT;
if (set_wim_hdr_cflags(ctype, hdr)) {
ERROR("Invalid compression type specified (%d)", ctype);
return WIMLIB_ERR_INVALID_COMPRESSION_TYPE;
tprintf(T("Magic Characters = MSWIM\\000\\000\\000\n"));
tprintf(T("Header Size = %u\n"), WIM_HEADER_DISK_SIZE);
- tprintf(T("Version = 0x%x\n"), WIM_VERSION);
+ tprintf(T("Version = 0x%x\n"), hdr->wim_version);
tprintf(T("Flags = 0x%x\n"), hdr->flags);
for (size_t i = 0; i < ARRAY_LEN(hdr_flags); i++)
if (hdr_flags[i].flag & hdr->flags)
tprintf(T(" WIM_HDR_FLAG_%s is set\n"), hdr_flags[i].name);
- tprintf(T("Chunk Size = %u\n"), wim->hdr.chunk_size);
+ tprintf(T("Chunk Size = %u\n"), hdr->chunk_size);
tfputs (T("GUID = "), stdout);
print_byte_field(hdr->guid, WIM_GID_LEN, stdout);
tputchar(T('\n'));
- tprintf(T("Part Number = %hu\n"), wim->hdr.part_number);
- tprintf(T("Total Parts = %hu\n"), wim->hdr.total_parts);
+ tprintf(T("Part Number = %hu\n"), hdr->part_number);
+ tprintf(T("Total Parts = %hu\n"), hdr->total_parts);
tprintf(T("Image Count = %u\n"), hdr->image_count);
tprintf(T("Lookup Table Size = %"PRIu64"\n"),
- (u64)hdr->lookup_table_res_entry.size);
+ (u64)hdr->lookup_table_reshdr.size_in_wim);
tprintf(T("Lookup Table Flags = 0x%hhx\n"),
- (u8)hdr->lookup_table_res_entry.flags);
+ (u8)hdr->lookup_table_reshdr.flags);
tprintf(T("Lookup Table Offset = %"PRIu64"\n"),
- hdr->lookup_table_res_entry.offset);
+ hdr->lookup_table_reshdr.offset_in_wim);
tprintf(T("Lookup Table Original_size = %"PRIu64"\n"),
- hdr->lookup_table_res_entry.original_size);
+ hdr->lookup_table_reshdr.uncompressed_size);
tprintf(T("XML Data Size = %"PRIu64"\n"),
- (u64)hdr->xml_res_entry.size);
+ (u64)hdr->xml_data_reshdr.size_in_wim);
tprintf(T("XML Data Flags = 0x%hhx\n"),
- (u8)hdr->xml_res_entry.flags);
+ (u8)hdr->xml_data_reshdr.flags);
tprintf(T("XML Data Offset = %"PRIu64"\n"),
- hdr->xml_res_entry.offset);
+ hdr->xml_data_reshdr.offset_in_wim);
tprintf(T("XML Data Original Size = %"PRIu64"\n"),
- hdr->xml_res_entry.original_size);
+ hdr->xml_data_reshdr.uncompressed_size);
tprintf(T("Boot Metadata Size = %"PRIu64"\n"),
- (u64)hdr->boot_metadata_res_entry.size);
+ (u64)hdr->boot_metadata_reshdr.size_in_wim);
tprintf(T("Boot Metadata Flags = 0x%hhx\n"),
- (u8)hdr->boot_metadata_res_entry.flags);
+ (u8)hdr->boot_metadata_reshdr.flags);
tprintf(T("Boot Metadata Offset = %"PRIu64"\n"),
- hdr->boot_metadata_res_entry.offset);
+ hdr->boot_metadata_reshdr.offset_in_wim);
tprintf(T("Boot Metadata Original Size = %"PRIu64"\n"),
- hdr->boot_metadata_res_entry.original_size);
+ hdr->boot_metadata_reshdr.uncompressed_size);
tprintf(T("Boot Index = %u\n"), hdr->boot_idx);
tprintf(T("Integrity Size = %"PRIu64"\n"),
- (u64)hdr->integrity.size);
+ (u64)hdr->integrity_table_reshdr.size_in_wim);
tprintf(T("Integrity Flags = 0x%hhx\n"),
- (u8)hdr->integrity.flags);
+ (u8)hdr->integrity_table_reshdr.flags);
tprintf(T("Integrity Offset = %"PRIu64"\n"),
- hdr->integrity.offset);
+ hdr->integrity_table_reshdr.offset_in_wim);
tprintf(T("Integrity Original_size = %"PRIu64"\n"),
- hdr->integrity.original_size);
+ hdr->integrity_table_reshdr.uncompressed_size);
}
#include "wimlib/resource.h"
#include "wimlib/sha1.h"
#include "wimlib/wim.h"
+#include "wimlib/write.h"
/* Size, in bytes, of each SHA1-summed chunk, when wimlib writes integrity
* information. */
* read_integrity_table: - Reads the integrity table from a WIM file.
*
* @wim:
- * WIMStruct for the WIM file; @wim->hdr.integrity specifies the location
- * of the integrity table. The integrity table must exist (i.e.
- * res_entry->offset must not be 0). @wim->in_fd is expected to be a
+ * WIMStruct for the WIM file; @wim->hdr.integrity_table_reshdr specifies
+ * the location of the integrity table. @wim->in_fd is expected to be a
* seekable file descriptor to the WIM file opened for reading.
*
* @num_checked_bytes:
struct integrity_table *table;
int ret;
- if (wim->hdr.integrity.size < 8)
+ if (wim->hdr.integrity_table_reshdr.uncompressed_size < 8)
goto invalid;
- DEBUG("Reading integrity table (offset %"PRIu64", "
- "original_size %"PRIu64")",
- wim->hdr.integrity.offset, wim->hdr.integrity.original_size);
+ DEBUG("Reading integrity table.");
- ret = res_entry_to_data(&wim->hdr.integrity, wim, &buf);
+ ret = wim_reshdr_to_data(&wim->hdr.integrity_table_reshdr, wim, &buf);
if (ret)
return ret;
table = buf;
"table->chunk_size = %u",
table->size, table->num_entries, table->chunk_size);
- if (table->size != wim->hdr.integrity.original_size ||
+ if (table->size != wim->hdr.integrity_table_reshdr.uncompressed_size ||
table->size != (u64)table->num_entries * SHA1_HASH_SIZE + 12 ||
table->chunk_size == 0 ||
table->num_entries != DIV_ROUND_UP(num_checked_bytes, table->chunk_size))
* chunks of the file).
*
* This function can optionally re-use entries from an older integrity table.
- * To do this, make @integrity_res_entry point to the resource entry for the
- * older table (note: this is an input-output parameter), and set
+ * To do this, ensure that @wim->hdr.integrity_table_reshdr is the resource
+ * header for the older table (note: this is an input-output parameter), and set
* @old_lookup_table_end to the offset of the byte directly following the last
* byte checked by the old table. If the old integrity table is invalid or
* cannot be read, a warning is printed and the integrity information is
&wim->out_fd,
WIMLIB_COMPRESSION_TYPE_NONE,
0,
- &wim->hdr.integrity,
+ &wim->hdr.integrity_table_reshdr,
NULL,
0,
&wim->lzx_context);
return WIM_INTEGRITY_NONEXISTENT;
}
- end_lookup_table_offset = wim->hdr.lookup_table_res_entry.offset +
- wim->hdr.lookup_table_res_entry.size;
+ end_lookup_table_offset = wim->hdr.lookup_table_reshdr.offset_in_wim +
+ wim->hdr.lookup_table_reshdr.size_in_wim;
if (end_lookup_table_offset < WIM_HEADER_DISK_SIZE) {
ERROR("WIM lookup table ends before WIM header ends!");
struct wim_lookup_table_entry *lte;
lte = CALLOC(1, sizeof(struct wim_lookup_table_entry));
- if (lte) {
- lte->part_number = 1;
- lte->refcnt = 1;
- BUILD_BUG_ON(RESOURCE_NONEXISTENT != 0);
- BUILD_BUG_ON(WIMLIB_COMPRESSION_TYPE_NONE != 0);
- } else {
+ if (lte == NULL) {
ERROR("Out of memory (tried to allocate %zu bytes for "
"lookup table entry)",
sizeof(struct wim_lookup_table_entry));
+ return NULL;
}
+ lte->refcnt = 1;
+ BUILD_BUG_ON(RESOURCE_NONEXISTENT != 0);
+ BUILD_BUG_ON(WIMLIB_COMPRESSION_TYPE_NONE != 0);
return lte;
}
new->extracted_file = NULL;
switch (new->resource_location) {
+ case RESOURCE_IN_WIM:
+ list_add(&new->wim_resource_list, &new->rspec->lte_list);
+ break;
+
case RESOURCE_IN_FILE_ON_DISK:
#ifdef __WIN32__
case RESOURCE_WIN32_ENCRYPTED:
goto out_free;
break;
case RESOURCE_IN_ATTACHED_BUFFER:
- new->attached_buffer = memdup(old->attached_buffer,
- wim_resource_size(old));
+ new->attached_buffer = memdup(old->attached_buffer, old->size);
if (!new->attached_buffer)
goto out_free;
break;
{
if (lte) {
switch (lte->resource_location) {
+ case RESOURCE_IN_WIM:
+ list_del(<e->wim_resource_list);
+ if (list_empty(<e->rspec->lte_list))
+ FREE(lte->rspec);
+ break;
case RESOURCE_IN_FILE_ON_DISK:
#ifdef __WIN32__
case RESOURCE_WIN32_ENCRYPTED:
{
const struct wim_lookup_table_entry *lte1, *lte2;
int v;
+ WIMStruct *wim1, *wim2;
lte1 = *(const struct wim_lookup_table_entry**)p1;
lte2 = *(const struct wim_lookup_table_entry**)p2;
switch (lte1->resource_location) {
case RESOURCE_IN_WIM:
+ wim1 = lte1->rspec->wim;
+ wim2 = lte2->rspec->wim;
/* Different (possibly split) WIMs? */
- if (lte1->wim != lte2->wim) {
- v = memcmp(lte1->wim->hdr.guid, lte2->wim->hdr.guid,
- WIM_GID_LEN);
+ if (wim1 != wim2) {
+ v = memcmp(wim1->hdr.guid, wim2->hdr.guid, WIM_GID_LEN);
if (v)
return v;
}
/* Different part numbers in the same WIM? */
- v = (int)lte1->wim->hdr.part_number - (int)lte2->wim->hdr.part_number;
+ v = (int)wim1->hdr.part_number - (int)wim2->hdr.part_number;
if (v)
return v;
/* Compare by offset. */
- if (lte1->resource_entry.offset < lte2->resource_entry.offset)
+ if (lte1->rspec->offset_in_wim < lte2->rspec->offset_in_wim)
return -1;
- else if (lte1->resource_entry.offset > lte2->resource_entry.offset)
+ if (lte1->rspec->offset_in_wim > lte2->rspec->offset_in_wim)
return 1;
return 0;
case RESOURCE_IN_FILE_ON_DISK:
/* On-disk format of a WIM lookup table entry (stream entry). */
struct wim_lookup_table_entry_disk {
- /* Location, offset, compression status, and metadata status of the
- * stream. */
- struct resource_entry_disk resource_entry;
+ /* Size, offset, and flags of the stream. */
+ struct wim_reshdr_disk reshdr;
/* Which part of the split WIM this stream is in; indexed from 1. */
le16 part_number;
#define WIM_LOOKUP_TABLE_ENTRY_DISK_SIZE 50
-void
-lte_init_wim(struct wim_lookup_table_entry *lte, WIMStruct *wim)
-{
- lte->resource_location = RESOURCE_IN_WIM;
- lte->wim = wim;
- if (lte->resource_entry.flags & WIM_RESHDR_FLAG_COMPRESSED)
- lte->compression_type = wim->compression_type;
- else
- lte->compression_type = WIMLIB_COMPRESSION_TYPE_NONE;
-
- if (wim_is_pipable(wim))
- lte->is_pipable = 1;
-}
-
/*
* Reads the lookup table from a WIM file.
*
struct wim_lookup_table *table;
struct wim_lookup_table_entry *cur_entry, *duplicate_entry;
void *buf;
+ bool in_concat_run;
BUILD_BUG_ON(sizeof(struct wim_lookup_table_entry_disk) !=
WIM_LOOKUP_TABLE_ENTRY_DISK_SIZE);
- DEBUG("Reading lookup table: offset %"PRIu64", size %"PRIu64"",
- wim->hdr.lookup_table_res_entry.offset,
- wim->hdr.lookup_table_res_entry.size);
+ DEBUG("Reading lookup table.");
/* Calculate number of entries in the lookup table. */
- num_entries = wim->hdr.lookup_table_res_entry.size /
+ num_entries = wim->hdr.lookup_table_reshdr.uncompressed_size /
sizeof(struct wim_lookup_table_entry_disk);
-
/* Read the lookup table into a buffer. */
- ret = res_entry_to_data(&wim->hdr.lookup_table_res_entry, wim, &buf);
+ ret = wim_reshdr_to_data(&wim->hdr.lookup_table_reshdr, wim, &buf);
if (ret)
goto out;
/* Allocate and initalize `struct wim_lookup_table_entry's from the
* on-disk lookup table. */
wim->current_image = 0;
+ in_concat_run = false;
for (i = 0; i < num_entries; i++) {
const struct wim_lookup_table_entry_disk *disk_entry =
&((const struct wim_lookup_table_entry_disk*)buf)[i];
+ u16 part_number;
+ struct wim_reshdr reshdr;
+ struct wim_resource_spec *cur_rspec;
cur_entry = new_lookup_table_entry();
- if (!cur_entry) {
+ if (cur_entry == NULL) {
ERROR("Not enough memory to read lookup table.");
ret = WIMLIB_ERR_NOMEM;
goto out_free_lookup_table;
}
- cur_entry->wim = wim;
- cur_entry->resource_location = RESOURCE_IN_WIM;
- get_resource_entry(&disk_entry->resource_entry, &cur_entry->resource_entry);
- cur_entry->part_number = le16_to_cpu(disk_entry->part_number);
+ part_number = le16_to_cpu(disk_entry->part_number);
cur_entry->refcnt = le32_to_cpu(disk_entry->refcnt);
copy_hash(cur_entry->hash, disk_entry->hash);
- lte_init_wim(cur_entry, wim);
- if (cur_entry->part_number != wim->hdr.part_number) {
+ if (part_number != wim->hdr.part_number) {
WARNING("A lookup table entry in part %hu of the WIM "
"points to part %hu (ignoring it)",
- wim->hdr.part_number, cur_entry->part_number);
+ wim->hdr.part_number, part_number);
free_lookup_table_entry(cur_entry);
continue;
}
-
if (is_zero_hash(cur_entry->hash)) {
WARNING("The WIM lookup table contains an entry with a "
"SHA1 message digest of all 0's (ignoring it)");
continue;
}
- if (!(cur_entry->resource_entry.flags & WIM_RESHDR_FLAG_COMPRESSED)
- && (cur_entry->resource_entry.size !=
- cur_entry->resource_entry.original_size))
- {
- if (wimlib_print_errors) {
- WARNING("Found uncompressed resource with "
- "original size (%"PRIu64") not the same "
- "as compressed size (%"PRIu64")",
- cur_entry->resource_entry.original_size,
- cur_entry->resource_entry.size);
- if (cur_entry->resource_entry.original_size) {
- WARNING("Overriding compressed size with original size.");
- cur_entry->resource_entry.size =
- cur_entry->resource_entry.original_size;
- } else {
- WARNING("Overriding original size with compressed size");
- cur_entry->resource_entry.original_size =
- cur_entry->resource_entry.size;
- }
- }
+ cur_rspec = MALLOC(sizeof(struct wim_resource_spec));
+ if (cur_rspec == NULL) {
+ ERROR("Not enough memory to read lookup table.");
+ ret = WIMLIB_ERR_NOMEM;
+ goto out_free_cur_entry;
}
- if (cur_entry->resource_entry.flags & WIM_RESHDR_FLAG_METADATA) {
+ get_wim_reshdr(&disk_entry->reshdr, &reshdr);
+ wim_res_hdr_to_spec(&reshdr, wim, cur_rspec);
+ lte_bind_wim_resource_spec(cur_entry, cur_rspec);
+
+ if (cur_entry->flags & WIM_RESHDR_FLAG_METADATA) {
/* Lookup table entry for a metadata resource */
if (cur_entry->refcnt != 1) {
/* Metadata entries with no references must be
DEBUG("Found metadata resource for image %u at "
"offset %"PRIu64".",
wim->current_image + 1,
- cur_entry->resource_entry.offset);
+ cur_entry->rspec->offset_in_wim);
wim->image_metadata[
wim->current_image++]->metadata_lte = cur_entry;
} else {
wim->lookup_table = table;
ret = 0;
goto out_free_buf;
+
out_free_cur_entry:
FREE(cur_entry);
out_free_lookup_table:
static void
write_wim_lookup_table_entry(const struct wim_lookup_table_entry *lte,
- struct wim_lookup_table_entry_disk *disk_entry)
+ struct wim_lookup_table_entry_disk *disk_entry,
+ u16 part_number)
{
- put_resource_entry(<e->output_resource_entry, &disk_entry->resource_entry);
- disk_entry->part_number = cpu_to_le16(lte->part_number);
+ put_wim_reshdr(<e->out_reshdr, &disk_entry->reshdr);
+ disk_entry->part_number = cpu_to_le16(part_number);
disk_entry->refcnt = cpu_to_le32(lte->out_refcnt);
copy_hash(disk_entry->hash, lte->hash);
}
static int
write_wim_lookup_table_from_stream_list(struct list_head *stream_list,
struct filedes *out_fd,
- struct resource_entry *out_res_entry,
+ u16 part_number,
+ struct wim_reshdr *out_reshdr,
int write_resource_flags,
struct wimlib_lzx_context **comp_ctx)
{
}
table_buf_ptr = table_buf;
list_for_each_entry(lte, stream_list, lookup_table_list)
- write_wim_lookup_table_entry(lte, table_buf_ptr++);
+ write_wim_lookup_table_entry(lte, table_buf_ptr++, part_number);
/* Write the lookup table uncompressed. Although wimlib can handle a
* compressed lookup table, MS software cannot. */
out_fd,
WIMLIB_COMPRESSION_TYPE_NONE,
0,
- out_res_entry,
+ out_reshdr,
NULL,
write_resource_flags,
comp_ctx);
* needs to be copied from the resource information read originally.
*/
if (lte->out_refcnt != 0 && !(lte->filtered & FILTERED_EXTERNAL_WIM)) {
- if (lte->filtered & FILTERED_SAME_WIM) {
- copy_resource_entry(<e->output_resource_entry,
- <e->resource_entry);
- }
+ if (lte->filtered & FILTERED_SAME_WIM)
+ wim_res_spec_to_hdr(lte->rspec, <e->out_reshdr);
list_add_tail(<e->lookup_table_list, (struct list_head*)_list);
}
return 0;
int
write_wim_lookup_table(WIMStruct *wim, int image, int write_flags,
- struct resource_entry *out_res_entry,
+ struct wim_reshdr *out_reshdr,
struct list_head *stream_list_override)
{
int write_resource_flags;
metadata_lte = wim->image_metadata[i - 1]->metadata_lte;
metadata_lte->out_refcnt = 1;
- metadata_lte->part_number = wim->hdr.part_number;
- metadata_lte->output_resource_entry.flags |= WIM_RESHDR_FLAG_METADATA;
-
+ metadata_lte->out_reshdr.flags |= WIM_RESHDR_FLAG_METADATA;
list_add(&metadata_lte->lookup_table_list, stream_list);
}
}
write_resource_flags |= WIMLIB_WRITE_RESOURCE_FLAG_PIPABLE;
return write_wim_lookup_table_from_stream_list(stream_list,
&wim->out_fd,
- out_res_entry,
+ wim->hdr.part_number,
+ out_reshdr,
write_resource_flags,
&wim->lzx_context);
}
void
print_lookup_table_entry(const struct wim_lookup_table_entry *lte, FILE *out)
{
- if (!lte) {
+ if (lte == NULL) {
tputc(T('\n'), out);
return;
}
- tfprintf(out, T("Offset = %"PRIu64" bytes\n"),
- lte->resource_entry.offset);
- tfprintf(out, T("Size = %"PRIu64" bytes\n"),
- (u64)lte->resource_entry.size);
+ tfprintf(out, T("Reference Count = %u\n"), lte->refcnt);
+ tfprintf(out, T("Uncompressed Size = %"PRIu64" bytes\n"), lte->size);
- tfprintf(out, T("Original size = %"PRIu64" bytes\n"),
- lte->resource_entry.original_size);
+ if (lte->resource_location == RESOURCE_IN_WIM) {
+ tfprintf(out, T("Offset in WIM = %"PRIu64" bytes\n"),
+ lte->rspec->offset_in_wim);
- tfprintf(out, T("Part Number = %hu\n"), lte->part_number);
- tfprintf(out, T("Reference Count = %u\n"), lte->refcnt);
+ tfprintf(out, T("Size in WIM = %"PRIu64" bytes\n"),
+ lte->rspec->size_in_wim);
+ }
if (lte->unhashed) {
tfprintf(out, T("(Unhashed: inode %p, stream_id = %u)\n"),
}
tfprintf(out, T("Flags = "));
- u8 flags = lte->resource_entry.flags;
+ u8 flags = lte->flags;
if (flags & WIM_RESHDR_FLAG_COMPRESSED)
tfputs(T("WIM_RESHDR_FLAG_COMPRESSED, "), out);
if (flags & WIM_RESHDR_FLAG_FREE)
tfputs(T("WIM_RESHDR_FLAG_METADATA, "), out);
if (flags & WIM_RESHDR_FLAG_SPANNED)
tfputs(T("WIM_RESHDR_FLAG_SPANNED, "), out);
+ if (flags & WIM_RESHDR_FLAG_CONCAT)
+ tfputs(T("WIM_RESHDR_FLAG_CONCAT, "), out);
tputc(T('\n'), out);
switch (lte->resource_location) {
case RESOURCE_IN_WIM:
- if (lte->wim->filename) {
+ if (lte->rspec->wim->filename) {
tfprintf(out, T("WIM file = `%"TS"'\n"),
- lte->wim->filename);
+ lte->rspec->wim->filename);
}
break;
#ifdef __WIN32__
lte_to_wimlib_resource_entry(const struct wim_lookup_table_entry *lte,
struct wimlib_resource_entry *wentry)
{
- wentry->uncompressed_size = lte->resource_entry.original_size;
- wentry->compressed_size = lte->resource_entry.size;
- wentry->offset = lte->resource_entry.offset;
+ wentry->uncompressed_size = lte->size;
+
+ if (lte->resource_location == RESOURCE_IN_WIM) {
+ wentry->compressed_size = lte->rspec->size_in_wim;
+ wentry->offset = lte->rspec->offset_in_wim;
+ wentry->part_number = lte->rspec->wim->hdr.part_number;
+ } else {
+ wentry->compressed_size = 0;
+ wentry->offset = 0;
+ wentry->part_number = 0;
+ }
copy_hash(wentry->sha1_hash, lte->hash);
- wentry->part_number = lte->part_number;
wentry->reference_count = lte->refcnt;
- wentry->is_compressed = (lte->resource_entry.flags & WIM_RESHDR_FLAG_COMPRESSED) != 0;
- wentry->is_metadata = (lte->resource_entry.flags & WIM_RESHDR_FLAG_METADATA) != 0;
- wentry->is_free = (lte->resource_entry.flags & WIM_RESHDR_FLAG_FREE) != 0;
- wentry->is_spanned = (lte->resource_entry.flags & WIM_RESHDR_FLAG_SPANNED) != 0;
+ wentry->is_compressed = (lte->flags & WIM_RESHDR_FLAG_COMPRESSED) != 0;
+ wentry->is_metadata = (lte->flags & WIM_RESHDR_FLAG_METADATA) != 0;
+ wentry->is_free = (lte->flags & WIM_RESHDR_FLAG_FREE) != 0;
+ wentry->is_spanned = (lte->flags & WIM_RESHDR_FLAG_SPANNED) != 0;
}
struct iterate_lte_context {
return zero_hash;
}
-
-static int
-lte_add_stream_size(struct wim_lookup_table_entry *lte, void *total_bytes_p)
-{
- *(u64*)total_bytes_p += lte->resource_entry.size;
- return 0;
-}
-
-u64
-lookup_table_total_stream_size(struct wim_lookup_table *table)
-{
- u64 total_size = 0;
- for_lookup_table_entry(table, lte_add_stream_size, &total_size);
- return total_size;
-}
-
struct wim_lookup_table_entry **
retrieve_lte_pointer(struct wim_lookup_table_entry *lte)
{
#include "wimlib/metadata.h"
#include "wimlib/resource.h"
#include "wimlib/security.h"
+#include "wimlib/write.h"
/*
* Reads a metadata resource for an image in the WIM file. The metadata
struct wim_inode *inode;
metadata_lte = imd->metadata_lte;
- metadata_len = wim_resource_size(metadata_lte);
+ metadata_len = metadata_lte->size;
DEBUG("Reading metadata resource: original_size = %"PRIu64", "
"size = %"PRIu64", offset = %"PRIu64"",
- metadata_lte->resource_entry.original_size,
- metadata_lte->resource_entry.size,
- metadata_lte->resource_entry.offset);
+ metadata_lte->rspec->uncompressed_size,
+ metadata_lte->rspec->size_in_wim,
+ metadata_lte->rspec->offset_in_wim);
/* There is no way the metadata resource could possibly be less than (8
* + WIM_DENTRY_DISK_SIZE) bytes, where the 8 is for security data (with
&wim->out_fd,
wim->out_compression_type,
wim->out_chunk_size,
- &imd->metadata_lte->output_resource_entry,
+ &imd->metadata_lte->out_reshdr,
imd->metadata_lte->hash,
write_resource_flags,
&wim->lzx_context);
stbuf->st_ino = (ino_t)inode->i_ino;
stbuf->st_nlink = inode->i_nlink;
if (lte)
- stbuf->st_size = wim_resource_size(lte);
+ stbuf->st_size = lte->size;
else
stbuf->st_size = 0;
#ifdef HAVE_STAT_NANOSECOND_PRECISION
if (old_lte) {
struct filedes wimlib_fd;
filedes_init(&wimlib_fd, fd);
- extract_size = min(wim_resource_size(old_lte), size);
+ extract_size = min(old_lte->size, size);
ret = extract_wim_resource_to_fd(old_lte, &wimlib_fd,
extract_size);
} else {
}
}
- new_lte->refcnt = inode->i_nlink;
- new_lte->resource_location = RESOURCE_IN_STAGING_FILE;
- new_lte->staging_file_name = staging_file_name;
- new_lte->resource_entry.original_size = size;
+ new_lte->refcnt = inode->i_nlink;
+ new_lte->resource_location = RESOURCE_IN_STAGING_FILE;
+ new_lte->staging_file_name = staging_file_name;
+ new_lte->size = size;
lookup_table_insert_unhashed(ctx->wim->lookup_table, new_lte,
inode, stream_id);
DEBUG("Freeing entries for zero-length streams");
image_for_each_unhashed_stream_safe(lte, tmp, imd) {
wimlib_assert(lte->unhashed);
- if (wim_resource_size(lte) == 0) {
+ if (lte->size == 0) {
struct wim_lookup_table_entry **back_ptr;
back_ptr = retrieve_lte_pointer(lte);
*back_ptr = NULL;
if (ret)
return -errno;
touch_inode(fd->f_inode);
- fd->f_lte->resource_entry.original_size = size;
+ fd->f_lte->size = size;
return 0;
}
int ret;
struct wim_inode *inode;
struct wim_ads_entry *ads_entry;
- size_t res_size;
+ u64 stream_size;
struct wim_lookup_table_entry *lte;
struct wimfs_context *ctx = wimfs_get_context();
return -ENOATTR;
lte = ads_entry->lte;
- res_size = wim_resource_size(lte);
+ stream_size = lte->size;
if (size == 0)
- return res_size;
+ return stream_size;
- if (res_size > size)
+ if (stream_size > size)
return -ERANGE;
ret = read_full_resource_into_buf(lte, value);
else
return -EIO;
}
- return res_size;
+ return stream_size;
}
#endif
if (flags_writable(fi->flags) &&
(!lte || lte->resource_location != RESOURCE_IN_STAGING_FILE)) {
- u64 size = (lte) ? wim_resource_size(lte) : 0;
+ u64 size = (lte) ? lte->size : 0;
ret = extract_resource_to_staging_dir(inode, stream_id,
<e, size, ctx);
if (ret)
{
struct wimfs_fd *fd = (struct wimfs_fd*)(uintptr_t)fi->fh;
ssize_t ret;
- u64 res_size;
+ u64 stream_size;
if (!fd)
return -EBADF;
return 0;
if (fd->f_lte)
- res_size = wim_resource_size(fd->f_lte);
+ stream_size = fd->f_lte->size;
else
- res_size = 0;
+ stream_size = 0;
- if (offset > res_size)
+ if (offset > stream_size)
return -EOVERFLOW;
- size = min(size, res_size - offset);
+ size = min(size, stream_size - offset);
if (size == 0)
return 0;
if (ret)
ret = -errno;
else
- lte->resource_entry.original_size = size;
+ lte->size = size;
} else {
/* File in WIM. Extract it to the staging directory, but only
* the first @size bytes of it. */
return -errno;
/* Update file size */
- if (offset + size > fd->f_lte->resource_entry.original_size) {
+ if (offset + size > fd->f_lte->size) {
DEBUG("Update file size %"PRIu64 " => %"PRIu64"",
- fd->f_lte->resource_entry.original_size,
- offset + size);
- fd->f_lte->resource_entry.original_size = offset + size;
+ fd->f_lte->size, offset + size);
+ fd->f_lte->size = offset + size;
}
/* Update timestamps */
* to skip even more useless work (for example it fills resized
* attributes with 0's, then we just override it.) */
ret = WIMLIB_ERR_WRITE;
- if (ntfs_attr_truncate_solid(na, wim_resource_size(lte)))
+ if (ntfs_attr_truncate_solid(na, lte->size))
goto out_attr_close;
/* Extract stream data to the NTFS attribute. */
extract_ctx.na = na;
extract_ctx.offset = 0;
- ret = extract_wim_resource(lte, wim_resource_size(lte),
+ ret = extract_wim_resource(lte, lte->size,
ntfs_3g_extract_wim_chunk, &extract_ctx);
/* Clean up and return. */
out_attr_close:
goto out_free_lte;
}
lte->ntfs_loc->is_reparse_point = true;
- lte->resource_entry.original_size = data_size - 8;
+ lte->size = data_size - 8;
ret = read_reparse_tag(ni, lte->ntfs_loc,
&inode->i_reparse_tag);
if (ret)
goto out_free_lte;
} else {
lte->ntfs_loc->is_reparse_point = false;
- lte->resource_entry.original_size = data_size;
+ lte->size = data_size;
}
}
if (name_length == 0) {
if (lte) {
ERROR("Found two un-named data streams for \"%s\" "
"(sizes = %"PRIu64", %"PRIu64")",
- path, wim_resource_size(inode->i_lte),
- wim_resource_size(lte));
+ path, inode->i_lte->size,
+ lte->size);
ret = WIMLIB_ERR_NTFS_3G;
goto out_free_lte;
}
lte = lte_override;
}
- if (wim_resource_size(lte) > REPARSE_POINT_MAX_SIZE - 8) {
+ if (lte->size > REPARSE_POINT_MAX_SIZE - 8) {
ERROR("Reparse data is too long!");
return WIMLIB_ERR_INVALID_REPARSE_DATA;
}
- rpdatalen = wim_resource_size(lte);
+ rpdatalen = lte->size;
/* Read the data from the WIM file */
ret = read_full_resource_into_buf(lte, rpbuf + 8);
/* Read data from a compressed WIM resource. Assumes parameters were already
* verified by read_partial_wim_resource(). */
static int
-read_compressed_wim_resource(const struct wim_lookup_table_entry * const lte,
+read_compressed_wim_resource(const struct wim_resource_spec * const rspec,
const u64 size, const consume_data_callback_t cb,
const u32 cb_chunk_size, void * const ctx_or_buf,
const int flags, const u64 offset)
int ret;
int errno_save;
- const u32 orig_chunk_size = wim_resource_chunk_size(lte);
+ const u32 orig_chunk_size = rspec->cchunk_size;
const u32 orig_chunk_order = bsr32(orig_chunk_size);
wimlib_assert(is_power_of_2(orig_chunk_size));
bool compressed_buf_malloced = false;
/* Get the file descriptor for the WIM. */
- struct filedes * const in_fd = <e->wim->in_fd;
+ struct filedes * const in_fd = &rspec->wim->in_fd;
/* Determine if we're reading a pipable resource from a pipe or not. */
const bool is_pipe_read = !filedes_is_seekable(in_fd);
/* Calculate the number of chunks the resource is divided into. */
- const u64 num_chunks = wim_resource_chunks(lte);
+ const u64 num_chunks = (rspec->uncompressed_size + orig_chunk_size - 1) >> orig_chunk_order;
/* Calculate the 0-based index of the chunk at which the read starts.
*/
/* Set the size of each chunk table entry based on the resource's
* uncompressed size. */
- const u64 chunk_entry_size = (wim_resource_size(lte) > (1ULL << 32)) ? 8 : 4;
+ const u64 chunk_entry_size = (rspec->uncompressed_size > (1ULL << 32)) ? 8 : 4;
/* Calculate the size, in bytes, of the full chunk table. */
const u64 chunk_table_size = num_chunk_entries * chunk_entry_size;
/* Current offset to read from. */
- u64 cur_read_offset = lte->resource_entry.offset;
+ u64 cur_read_offset = rspec->offset_in_wim;
if (!is_pipe_read) {
/* Read the chunk table into memory. */
* file is in the special "pipable" format, then the chunk table
* is at the end of the resource, not the beginning. */
const u64 file_offset_of_needed_chunk_entries =
- lte->resource_entry.offset
+ rspec->offset_in_wim
+ (start_table_idx * chunk_entry_size)
- + (lte->is_pipable ? (lte->resource_entry.size - chunk_table_size) : 0);
+ + (rspec->is_pipable ? (rspec->size_in_wim - chunk_table_size) : 0);
/* Read the needed chunk table entries into the end of the
* chunk_offsets buffer. */
/* Set offset to beginning of first chunk to read. */
cur_read_offset += chunk_offsets[0];
- if (lte->is_pipable)
+ if (rspec->is_pipable)
cur_read_offset += start_chunk * sizeof(struct pwm_chunk_hdr);
else
cur_read_offset += chunk_table_size;
* chunks for which only part of the data is needed. */
if (start_offset_in_chunk != 0 ||
(end_offset_in_chunk != orig_chunk_size - 1 &&
- offset + size != wim_resource_size(lte)))
+ offset + size != rspec->uncompressed_size))
{
if (orig_chunk_size <= STACK_MAX) {
tmp_buf = alloca(orig_chunk_size);
/* Calculate uncompressed size of next chunk. */
u32 chunk_usize;
- if ((i == num_chunks - 1) && (wim_resource_size(lte) & (orig_chunk_size - 1)))
- chunk_usize = (wim_resource_size(lte) & (orig_chunk_size - 1));
+ if ((i == num_chunks - 1) && (rspec->uncompressed_size & (orig_chunk_size - 1)))
+ chunk_usize = (rspec->uncompressed_size & (orig_chunk_size - 1));
else
chunk_usize = orig_chunk_size;
chunk_csize = le32_to_cpu(chunk_hdr.compressed_size);
} else {
if (i == num_chunks - 1) {
- chunk_csize = lte->resource_entry.size -
+ chunk_csize = rspec->size_in_wim -
chunk_table_size -
chunk_offsets[i - start_chunk];
- if (lte->is_pipable)
+ if (rspec->is_pipable)
chunk_csize -= num_chunks * sizeof(struct pwm_chunk_hdr);
} else {
chunk_csize = chunk_offsets[i + 1 - start_chunk] -
ret = WIMLIB_ERR_DECOMPRESSION;
goto out_free_memory;
}
- if (lte->is_pipable)
+ if (rspec->is_pipable)
cur_read_offset += sizeof(struct pwm_chunk_hdr);
if (i >= start_chunk) {
chunk_csize,
target,
chunk_usize,
- wim_resource_compression_type(lte),
+ rspec->ctype,
orig_chunk_size);
if (ret) {
ERROR("Failed to decompress data!");
}
if (is_pipe_read
- && size == lte->resource_entry.original_size
+ && size == rspec->uncompressed_size
&& chunk_table_size)
{
u8 dummy;
u32 cb_chunk_size,
void *ctx_or_buf, int flags, u64 offset)
{
+ const struct wim_resource_spec *rspec;
struct filedes *in_fd;
/* Verify parameters. */
wimlib_assert(lte->resource_location == RESOURCE_IN_WIM);
- in_fd = <e->wim->in_fd;
+ rspec = lte->rspec;
+ in_fd = &rspec->wim->in_fd;
if (cb)
wimlib_assert(is_power_of_2(cb_chunk_size));
if (flags & WIMLIB_READ_RESOURCE_FLAG_RAW_CHUNKS) {
/* Raw chunks mode is subject to the restrictions noted. */
wimlib_assert(!(flags & WIMLIB_READ_RESOURCE_FLAG_RAW_FULL));
- wimlib_assert(cb_chunk_size == wim_resource_chunk_size(lte));
- wimlib_assert(size == lte->resource_entry.original_size);
+ wimlib_assert(cb_chunk_size == rspec->cchunk_size);
+ wimlib_assert(size == rspec->uncompressed_size);
wimlib_assert(offset == 0);
} else if (flags & WIMLIB_READ_RESOURCE_FLAG_RAW_FULL) {
/* Raw full mode: read must not overrun end of store size. */
wimlib_assert(offset + size >= size &&
- offset + size <= lte->resource_entry.size);
+ offset + size <= rspec->size_in_wim);
} else {
/* Normal mode: read must not overrun end of original size. */
wimlib_assert(offset + size >= size &&
- offset + size <= lte->resource_entry.original_size);
+ offset + size <= rspec->uncompressed_size);
}
DEBUG("Reading WIM resource: %"PRIu64" @ +%"PRIu64" "
"from %"PRIu64"(%"PRIu64") @ +%"PRIu64" "
"(readflags 0x%08x, resflags 0x%02x%s)",
size, offset,
- lte->resource_entry.size,
- lte->resource_entry.original_size,
- lte->resource_entry.offset,
- flags, lte->resource_entry.flags,
- (lte->is_pipable ? ", pipable" : ""));
+ rspec->size_in_wim,
+ rspec->uncompressed_size,
+ rspec->offset_in_wim,
+ flags, lte->flags,
+ (rspec->is_pipable ? ", pipable" : ""));
if ((flags & WIMLIB_READ_RESOURCE_FLAG_RAW_FULL) ||
- !resource_is_compressed(<e->resource_entry)) {
+ rspec->ctype == WIMLIB_COMPRESSION_TYPE_NONE)
+ {
return read_raw_file_data(in_fd,
size,
cb,
cb_chunk_size,
ctx_or_buf,
- offset + lte->resource_entry.offset);
+ offset + rspec->offset_in_wim);
} else {
- return read_compressed_wim_resource(lte, size, cb,
+ return read_compressed_wim_resource(rspec, size, cb,
cb_chunk_size,
ctx_or_buf, flags, offset);
}
int raw_fd;
struct filedes fd;
- wimlib_assert(size <= wim_resource_size(lte));
+ wimlib_assert(size <= lte->size);
DEBUG("Reading %"PRIu64" bytes from \"%"TS"\"", size, lte->file_on_disk);
raw_fd = open(lte->file_on_disk, O_BINARY | O_RDONLY);
u32 cb_chunk_size,
void *ctx_or_buf, int _ignored_flags)
{
- wimlib_assert(size <= wim_resource_size(lte));
+ wimlib_assert(size <= lte->size);
if (cb) {
/* Feed the data into the callback function in
read_full_resource_into_buf(const struct wim_lookup_table_entry *lte,
void *buf)
{
- return read_resource_prefix(lte, wim_resource_size(lte),
- NULL, 0, buf, 0);
+ return read_resource_prefix(lte, lte->size, NULL, 0, buf, 0);
}
/* Read the full uncompressed data of the specified resource. A buffer
int ret;
void *buf;
- if ((size_t)lte->resource_entry.original_size !=
- lte->resource_entry.original_size)
- {
+ if ((size_t)lte->size != lte->size) {
ERROR("Can't read %"PRIu64" byte resource into "
- "memory", lte->resource_entry.original_size);
+ "memory", lte->size);
return WIMLIB_ERR_NOMEM;
}
- buf = MALLOC(lte->resource_entry.original_size);
+ buf = MALLOC(lte->size);
if (buf == NULL)
return WIMLIB_ERR_NOMEM;
/* Retrieve the full uncompressed data of the specified WIM resource, provided
* as a raw `struct resource_entry'. */
-int
-res_entry_to_data(const struct resource_entry *res_entry,
- WIMStruct *wim, void **buf_ret)
+static int
+wim_resource_spec_to_data(struct wim_resource_spec *rspec, void **buf_ret)
{
int ret;
struct wim_lookup_table_entry *lte;
if (lte == NULL)
return WIMLIB_ERR_NOMEM;
- copy_resource_entry(<e->resource_entry, res_entry);
lte->unhashed = 1;
- lte->part_number = wim->hdr.part_number;
- lte_init_wim(lte, wim);
+ lte_bind_wim_resource_spec(lte, rspec);
ret = read_full_resource_into_alloc_buf(lte, buf_ret);
+
+ lte_unbind_wim_resource_spec(lte);
free_lookup_table_entry(lte);
return ret;
}
+int
+wim_reshdr_to_data(const struct wim_reshdr *reshdr, WIMStruct *wim, void **buf_ret)
+{
+ DEBUG("offset_in_wim=%"PRIu64", size_in_wim=%"PRIu64", "
+ "uncompressed_size=%"PRIu64,
+ reshdr->offset_in_wim, reshdr->size_in_wim, reshdr->uncompressed_size);
+
+ struct wim_resource_spec rspec;
+ wim_res_hdr_to_spec(reshdr, wim, &rspec);
+ return wim_resource_spec_to_data(&rspec, buf_ret);
+}
+
struct extract_ctx {
SHA_CTX sha_ctx;
consume_data_callback_t extract_chunk;
void *extract_chunk_arg)
{
int ret;
- if (size == wim_resource_size(lte)) {
+ if (size == lte->size) {
/* Do SHA1 */
struct extract_ctx ctx;
ctx.extract_chunk = extract_chunk;
sha1_init(&ctx.sha_ctx);
ret = read_resource_prefix(lte, size,
extract_chunk_sha1_wrapper,
- wim_resource_chunk_size(lte),
+ lte_cchunk_size(lte),
&ctx, 0);
if (ret == 0) {
u8 hash[SHA1_HASH_SIZE];
} else {
/* Don't do SHA1 */
ret = read_resource_prefix(lte, size, extract_chunk,
- wim_resource_chunk_size(lte),
+ lte_cchunk_size(lte),
extract_chunk_arg, 0);
}
return ret;
SHA_CTX sha_ctx;
sha1_init(&sha_ctx);
- ret = read_resource_prefix(lte, wim_resource_size(lte),
- sha1_chunk, wim_resource_chunk_size(lte),
+ ret = read_resource_prefix(lte, lte->size,
+ sha1_chunk, lte_cchunk_size(lte),
&sha_ctx, 0);
if (ret == 0)
sha1_final(lte->hash, &sha_ctx);
return ret;
}
-/* Translates a WIM resource entry from the on-disk format into an in-memory
+/* Convert a WIM resource header to a stand-alone resource specification. */
+void
+wim_res_hdr_to_spec(const struct wim_reshdr *reshdr, WIMStruct *wim,
+ struct wim_resource_spec *spec)
+{
+ spec->wim = wim;
+ spec->offset_in_wim = reshdr->offset_in_wim;
+ spec->size_in_wim = reshdr->size_in_wim;
+ spec->uncompressed_size = reshdr->uncompressed_size;
+ INIT_LIST_HEAD(&spec->lte_list);
+ spec->flags = reshdr->flags;
+ spec->is_pipable = wim_is_pipable(wim);
+ if (spec->flags & WIM_RESHDR_FLAG_COMPRESSED) {
+ spec->ctype = wim->compression_type;
+ spec->cchunk_size = wim->chunk_size;
+ } else {
+ spec->ctype = WIMLIB_COMPRESSION_TYPE_NONE;
+ spec->cchunk_size = 0;
+ }
+}
+
+/* Convert a stand-alone resource specification to a WIM resource header. */
+void
+wim_res_spec_to_hdr(const struct wim_resource_spec *rspec,
+ struct wim_reshdr *reshdr)
+{
+ reshdr->offset_in_wim = rspec->offset_in_wim;
+ reshdr->size_in_wim = rspec->size_in_wim;
+ reshdr->flags = rspec->flags;
+ reshdr->uncompressed_size = rspec->uncompressed_size;
+}
+
+/* Translates a WIM resource header from the on-disk format into an in-memory
* format. */
void
-get_resource_entry(const struct resource_entry_disk *disk_entry,
- struct resource_entry *entry)
+get_wim_reshdr(const struct wim_reshdr_disk *disk_reshdr,
+ struct wim_reshdr *reshdr)
{
- /* Note: disk_entry may not be 8 byte aligned--- in that case, the
+ /* Note: disk_reshdr may not be 8 byte aligned--- in that case, the
* offset and original_size members will be unaligned. (This is okay
- * since `struct resource_entry_disk' is declared as packed.) */
-
- /* Read the size and flags into a bitfield portably... */
- entry->size = (((u64)disk_entry->size[0] << 0) |
- ((u64)disk_entry->size[1] << 8) |
- ((u64)disk_entry->size[2] << 16) |
- ((u64)disk_entry->size[3] << 24) |
- ((u64)disk_entry->size[4] << 32) |
- ((u64)disk_entry->size[5] << 40) |
- ((u64)disk_entry->size[6] << 48));
- entry->flags = disk_entry->flags;
- entry->offset = le64_to_cpu(disk_entry->offset);
- entry->original_size = le64_to_cpu(disk_entry->original_size);
-
- /* 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... */
- if (entry->offset & 0xc000000000000000ULL) {
- WARNING("Truncating offset in resource entry");
- entry->offset &= 0x3fffffffffffffffULL;
+ * since `struct resource_reshdr_disk' is declared as packed.) */
+
+ reshdr->offset_in_wim = le64_to_cpu(disk_reshdr->offset_in_wim);
+ reshdr->size_in_wim = (((u64)disk_reshdr->size_in_wim[0] << 0) |
+ ((u64)disk_reshdr->size_in_wim[1] << 8) |
+ ((u64)disk_reshdr->size_in_wim[2] << 16) |
+ ((u64)disk_reshdr->size_in_wim[3] << 24) |
+ ((u64)disk_reshdr->size_in_wim[4] << 32) |
+ ((u64)disk_reshdr->size_in_wim[5] << 40) |
+ ((u64)disk_reshdr->size_in_wim[6] << 48));
+ reshdr->uncompressed_size = le64_to_cpu(disk_reshdr->uncompressed_size);
+ reshdr->flags = disk_reshdr->flags;
+
+ /* Truncate numbers to 62 bits to avoid possible overflows. */
+ if (reshdr->offset_in_wim & 0xc000000000000000ULL) {
+ WARNING("Truncating offset in resource reshdr");
+ reshdr->offset_in_wim &= 0x3fffffffffffffffULL;
}
- if (entry->original_size & 0xc000000000000000ULL) {
- WARNING("Truncating original_size in resource entry");
- entry->original_size &= 0x3fffffffffffffffULL;
+ if (reshdr->uncompressed_size & 0xc000000000000000ULL) {
+ WARNING("Truncating original_size in resource reshdr");
+ reshdr->uncompressed_size &= 0x3fffffffffffffffULL;
}
}
-/* Translates a WIM resource entry from an in-memory format into the on-disk
- * format. */
+/* Translates a WIM resource header from an in-memory format into the on-disk
+ * format. */
void
-put_resource_entry(const struct resource_entry *entry,
- struct resource_entry_disk *disk_entry)
+put_wim_reshdr(const struct wim_reshdr *reshdr,
+ struct wim_reshdr_disk *disk_reshdr)
{
- /* Note: disk_entry may not be 8 byte aligned--- in that case, the
+ /* Note: disk_reshdr may not be 8 byte aligned--- in that case, the
* offset and original_size members will be unaligned. (This is okay
- * since `struct resource_entry_disk' is declared as packed.) */
- u64 size = entry->size;
-
- disk_entry->size[0] = size >> 0;
- disk_entry->size[1] = size >> 8;
- disk_entry->size[2] = size >> 16;
- disk_entry->size[3] = size >> 24;
- disk_entry->size[4] = size >> 32;
- disk_entry->size[5] = size >> 40;
- disk_entry->size[6] = size >> 48;
- disk_entry->flags = entry->flags;
- disk_entry->offset = cpu_to_le64(entry->offset);
- disk_entry->original_size = cpu_to_le64(entry->original_size);
+ * since `struct resource_reshdr_disk' is declared as packed.) */
+ disk_reshdr->size_in_wim[0] = reshdr->size_in_wim >> 0;
+ disk_reshdr->size_in_wim[1] = reshdr->size_in_wim >> 8;
+ disk_reshdr->size_in_wim[2] = reshdr->size_in_wim >> 16;
+ disk_reshdr->size_in_wim[3] = reshdr->size_in_wim >> 24;
+ disk_reshdr->size_in_wim[4] = reshdr->size_in_wim >> 32;
+ disk_reshdr->size_in_wim[5] = reshdr->size_in_wim >> 40;
+ disk_reshdr->size_in_wim[6] = reshdr->size_in_wim >> 48;
+ disk_reshdr->flags = reshdr->flags;
+ disk_reshdr->offset_in_wim = cpu_to_le64(reshdr->offset_in_wim);
+ disk_reshdr->uncompressed_size = cpu_to_le64(reshdr->uncompressed_size);
}
struct swm_info *swm_info = _swm_info;
u64 stream_size;
- stream_size = lte->resource_entry.size;
+ /* TODO */
+ stream_size = lte->rspec->size_in_wim;
/* - Start first part if no parts have been started so far;
* - Start next part if adding this stream exceeds maximum part size,
if (swm_info->num_parts == 0 ||
((swm_info->parts[swm_info->num_parts - 1].size +
stream_size >= swm_info->max_part_size)
- && !((lte->resource_entry.flags & WIM_RESHDR_FLAG_METADATA) ||
+ && !((lte->flags & WIM_RESHDR_FLAG_METADATA) ||
swm_info->parts[swm_info->num_parts - 1].size == 0)))
{
if (swm_info->num_parts == swm_info->num_alloc_parts) {
swm_info->parts[swm_info->num_parts - 1].size = 0;
}
swm_info->parts[swm_info->num_parts - 1].size += stream_size;
- if (!(lte->resource_entry.flags & WIM_RESHDR_FLAG_METADATA)) {
+ if (!(lte->flags & WIM_RESHDR_FLAG_METADATA)) {
list_add_tail(<e->write_streams_list,
&swm_info->parts[swm_info->num_parts - 1].stream_list);
}
if (raw_fd < 0)
return WIMLIB_ERR_OPEN;
filedes_init(&fd, raw_fd);
- ret = extract_wim_resource_to_fd(lte, &fd, wim_resource_size(lte));
+ ret = extract_wim_resource_to_fd(lte, &fd, lte->size);
if (filedes_close(&fd) && !ret)
ret = WIMLIB_ERR_WRITE;
return ret;
}
lte->file_on_disk = file_on_disk;
lte->resource_location = RESOURCE_IN_FILE_ON_DISK;
- lte->resource_entry.original_size = size;
+ lte->size = size;
lookup_table_insert_unhashed(lookup_table, lte, inode, 0);
inode->i_lte = lte;
}
* 2^15 = 32768 is the default value used for compatibility, but
* wimlib can actually use up to 2^26. */
return order >= 15 && order <= 26;
+
+ case WIMLIB_COMPRESSION_TYPE_LZMS:
+ /* TODO */
+ return 131072;
}
return false;
}
memcpy(info->guid, wim->hdr.guid, WIMLIB_GUID_LEN);
info->image_count = wim->hdr.image_count;
info->boot_index = wim->hdr.boot_idx;
- info->wim_version = WIM_VERSION;
+ info->wim_version = wim->hdr.wim_version;
info->chunk_size = wim->hdr.chunk_size;
info->part_number = wim->hdr.part_number;
info->total_parts = wim->hdr.total_parts;
wim->in_fd.is_pipe = 1;
} else {
wimfile = wim_filename_or_fd;
- DEBUG("Reading the WIM file `%"TS"'", wimfile);
ret = do_open_wim(wimfile, &wim->in_fd);
if (ret)
return ret;
}
}
- ret = read_wim_header(wim->filename, &wim->in_fd, &wim->hdr);
+ ret = read_wim_header(wim, &wim->hdr);
if (ret)
return ret;
/* Check and cache the compression type */
if (wim->hdr.flags & WIM_HDR_FLAG_COMPRESSION) {
if (wim->hdr.flags & WIM_HDR_FLAG_COMPRESS_LZX) {
- if (wim->hdr.flags & WIM_HDR_FLAG_COMPRESS_XPRESS) {
- ERROR("Multiple compression flags are set in \"%"TS"\"",
- wimfile);
- return WIMLIB_ERR_INVALID_COMPRESSION_TYPE;
- }
wim->compression_type = WIMLIB_COMPRESSION_TYPE_LZX;
} else if (wim->hdr.flags & WIM_HDR_FLAG_COMPRESS_XPRESS) {
wim->compression_type = WIMLIB_COMPRESSION_TYPE_XPRESS;
+ #if 0
+ /* TODO */
+ } else if (wim->hdr.flags & WIM_HDR_FLAG_COMPRESS_LZMS) {
+ wim->compression_type = WIMLIB_COMPRESSION_TYPE_LZMS;
+ #endif
} else {
ERROR("The compression flag is set on \"%"TS"\", but "
- "neither the XPRESS nor LZX flag is set",
+ "a flag for a recognized format is not",
wimfile);
return WIMLIB_ERR_INVALID_COMPRESSION_TYPE;
}
WIMStruct *wim;
int ret;
+ if (open_flags & WIMLIB_OPEN_FLAG_FROM_PIPE)
+ DEBUG("Opening pipable WIM from file descriptor %d.", *(const int*)wim_filename_or_fd);
+ else
+ DEBUG("Opening WIM file \"%"TS"\"", (const tchar*)wim_filename_or_fd);
+
wimlib_global_init(WIMLIB_INIT_FLAG_ASSUME_UTF8);
if (wim_ret == NULL)
return ret;
}
+ DEBUG("Successfully opened WIM and created WIMStruct.");
*wim_ret = wim;
return 0;
}
ret = 0;
if (!lte)
goto out_close_handle;
- ret = extract_wim_resource(lte, wim_resource_size(lte),
- win32_extract_wim_chunk, h);
+ ret = extract_wim_resource(lte, lte->size, win32_extract_wim_chunk, h);
out_close_handle:
if (!CloseHandle(h))
goto error;
unsigned long len = *len_p;
const struct wim_lookup_table_entry *lte = import_ctx->lte;
- len = min(len, wim_resource_size(lte) - import_ctx->offset);
+ len = min(len, lte->size - import_ctx->offset);
if (read_partial_wim_resource_into_buf(lte, len, import_ctx->offset, data))
return ERROR_READ_FAULT;
can_raw_copy(const struct wim_lookup_table_entry *lte,
int write_resource_flags, int out_ctype, u32 out_chunk_size)
{
- return (out_ctype == wim_resource_compression_type(lte)
- && out_chunk_size == wim_resource_chunk_size(lte)
+ return (out_ctype == lte_ctype(lte)
+ && out_chunk_size == lte_cchunk_size(lte)
&& out_ctype != WIMLIB_COMPRESSION_TYPE_NONE);
}
struct chunk_table *chunk_tab;
int ret;
- size = wim_resource_size(lte);
+ size = lte->size;
num_chunks = DIV_ROUND_UP(size, out_chunk_size);
bytes_per_chunk_entry = (size > (1ULL << 32)) ? 8 : 4;
alloc_size = sizeof(struct chunk_table) + num_chunks * sizeof(u64);
int ret;
stream_hdr.magic = PWM_STREAM_MAGIC;
- stream_hdr.uncompressed_size = cpu_to_le64(lte->resource_entry.original_size);
+ stream_hdr.uncompressed_size = cpu_to_le64(lte->size);
if (additional_reshdr_flags & PWM_RESHDR_FLAG_UNHASHED) {
zero_out_hash(stream_hdr.hash);
} else {
copy_hash(stream_hdr.hash, lte->hash);
}
- reshdr_flags = lte->resource_entry.flags & ~WIM_RESHDR_FLAG_COMPRESSED;
+ reshdr_flags = lte->flags & ~WIM_RESHDR_FLAG_COMPRESSED;
reshdr_flags |= additional_reshdr_flags;
stream_hdr.flags = cpu_to_le32(reshdr_flags);
ret = full_write(out_fd, &stream_hdr, sizeof(stream_hdr));
* @out_chunk_size:
* Compressed chunk size to use.
*
- * @out_res_entry:
+ * @out_reshdr:
* On success, this is filled in with the offset, flags, compressed size,
* and uncompressed size of the resource in the output WIM.
*
write_wim_resource(struct wim_lookup_table_entry *lte,
struct filedes *out_fd, int out_ctype,
u32 out_chunk_size,
- struct resource_entry *out_res_entry,
+ struct wim_reshdr *out_reshdr,
int resource_flags,
struct wimlib_lzx_context **comp_ctx)
{
* needs to be requested so that the written resource can be
* appropriately formatted. However, in neither case is any
* actual decompression needed. */
- if (lte->is_pipable == !!(resource_flags &
- WIMLIB_WRITE_RESOURCE_FLAG_PIPABLE))
+ if (lte->rspec->is_pipable == !!(resource_flags &
+ WIMLIB_WRITE_RESOURCE_FLAG_PIPABLE))
{
resource_flags |= WIMLIB_READ_RESOURCE_FLAG_RAW_FULL;
- read_size = lte->resource_entry.size;
+ read_size = lte->rspec->size_in_wim;
} else {
resource_flags |= WIMLIB_READ_RESOURCE_FLAG_RAW_CHUNKS;
- read_size = lte->resource_entry.original_size;
+ read_size = lte->size;
}
write_ctx.doing_sha = false;
} else {
write_ctx.doing_sha = true;
sha1_init(&write_ctx.sha_ctx);
- read_size = lte->resource_entry.original_size;
+ read_size = lte->size;
}
/* Set the output compression mode and initialize chunk table if needed.
write_ctx.resource_flags = resource_flags;
try_write_again:
if (write_ctx.out_ctype == WIMLIB_COMPRESSION_TYPE_NONE)
- in_chunk_size = wim_resource_chunk_size(lte);
+ in_chunk_size = lte_cchunk_size(lte);
else
in_chunk_size = out_chunk_size;
ret = read_resource_prefix(lte, read_size,
goto out_free_chunk_tab;
}
- /* Fill in out_res_entry with information about the newly written
+ /* Fill in out_reshdr with information about the newly written
* resource. */
- out_res_entry->size = out_fd->offset - res_start_offset;
- out_res_entry->flags = lte->resource_entry.flags;
+ out_reshdr->size_in_wim = out_fd->offset - res_start_offset;
+ out_reshdr->flags = lte->flags;
if (out_ctype == WIMLIB_COMPRESSION_TYPE_NONE)
- out_res_entry->flags &= ~WIM_RESHDR_FLAG_COMPRESSED;
+ out_reshdr->flags &= ~WIM_RESHDR_FLAG_COMPRESSED;
else
- out_res_entry->flags |= WIM_RESHDR_FLAG_COMPRESSED;
- out_res_entry->offset = res_start_offset;
- out_res_entry->original_size = wim_resource_size(lte);
+ out_reshdr->flags |= WIM_RESHDR_FLAG_COMPRESSED;
+ out_reshdr->offset_in_wim = res_start_offset;
+ out_reshdr->uncompressed_size = lte->size;
/* Check for resources compressed to greater than their original size
* and write them uncompressed instead. (But never do this if writing
* to a pipe, and don't bother if we did a raw copy.) */
- if (out_res_entry->size > out_res_entry->original_size &&
+ if (out_reshdr->size_in_wim > out_reshdr->uncompressed_size &&
!(resource_flags & (WIMLIB_WRITE_RESOURCE_FLAG_PIPABLE |
WIMLIB_READ_RESOURCE_FLAG_RAW)))
{
DEBUG("Compressed %"PRIu64" => %"PRIu64" bytes; "
"writing uncompressed instead",
- out_res_entry->original_size, out_res_entry->size);
+ out_reshdr->uncompressed_size, out_reshdr->size_in_wim);
ret = seek_and_truncate(out_fd, res_start_offset);
if (ret)
goto out_free_chunk_tab;
if (resource_flags & WIMLIB_READ_RESOURCE_FLAG_RAW) {
DEBUG("Copied raw compressed data "
"(%"PRIu64" => %"PRIu64" bytes @ +%"PRIu64", flags=0x%02x)",
- out_res_entry->original_size, out_res_entry->size,
- out_res_entry->offset, out_res_entry->flags);
+ out_reshdr->uncompressed_size, out_reshdr->size_in_wim,
+ out_reshdr->offset_in_wim, out_reshdr->flags);
} else if (out_ctype != WIMLIB_COMPRESSION_TYPE_NONE) {
DEBUG("Wrote compressed resource "
"(%"PRIu64" => %"PRIu64" bytes @ +%"PRIu64", flags=0x%02x)",
- out_res_entry->original_size, out_res_entry->size,
- out_res_entry->offset, out_res_entry->flags);
+ out_reshdr->uncompressed_size, out_reshdr->size_in_wim,
+ out_reshdr->offset_in_wim, out_reshdr->flags);
} else {
DEBUG("Wrote uncompressed resource "
"(%"PRIu64" bytes @ +%"PRIu64", flags=0x%02x)",
- out_res_entry->original_size,
- out_res_entry->offset, out_res_entry->flags);
+ out_reshdr->uncompressed_size,
+ out_reshdr->offset_in_wim, out_reshdr->flags);
}
ret = 0;
out_free_chunk_tab:
int reshdr_flags, struct filedes *out_fd,
int out_ctype,
u32 out_chunk_size,
- struct resource_entry *out_res_entry,
+ struct wim_reshdr *out_reshdr,
u8 *hash_ret, int write_resource_flags,
struct wimlib_lzx_context **comp_ctx)
{
if (lte == NULL)
return WIMLIB_ERR_NOMEM;
- lte->resource_location = RESOURCE_IN_ATTACHED_BUFFER;
- lte->attached_buffer = (void*)buf;
- lte->resource_entry.original_size = buf_size;
- lte->resource_entry.flags = reshdr_flags;
+ lte->resource_location = RESOURCE_IN_ATTACHED_BUFFER;
+ lte->attached_buffer = (void*)buf;
+ lte->size = buf_size;
+ lte->flags = reshdr_flags;
if (write_resource_flags & WIMLIB_WRITE_RESOURCE_FLAG_PIPABLE) {
sha1_buffer(buf, buf_size, lte->hash);
}
ret = write_wim_resource(lte, out_fd, out_ctype, out_chunk_size,
- out_res_entry, write_resource_flags, comp_ctx);
+ out_reshdr, write_resource_flags, comp_ctx);
if (ret)
goto out_free_lte;
if (hash_ret)
bool new_wim_part;
if (stream_discarded) {
- progress->write_streams.total_bytes -= wim_resource_size(lte);
+ progress->write_streams.total_bytes -= lte->size;
if (progress_data->next_progress != ~(uint64_t)0 &&
progress_data->next_progress > progress->write_streams.total_bytes)
{
progress_data->next_progress = progress->write_streams.total_bytes;
}
} else {
- progress->write_streams.completed_bytes += wim_resource_size(lte);
+ progress->write_streams.completed_bytes += lte->size;
}
new_wim_part = false;
if (lte->resource_location == RESOURCE_IN_WIM &&
- lte->wim != progress_data->prev_wim_part)
+ lte->rspec->wim != progress_data->prev_wim_part)
{
if (progress_data->prev_wim_part) {
new_wim_part = true;
progress->write_streams.completed_parts++;
}
- progress_data->prev_wim_part = lte->wim;
+ progress_data->prev_wim_part = lte->rspec->wim;
}
progress->write_streams.completed_streams++;
if (progress_data->progress_func
return write_wim_resource(lte, ctx->out_fd,
ctx->out_ctype,
ctx->out_chunk_size,
- <e->output_resource_entry,
+ <e->out_reshdr,
ctx->write_resource_flags,
ctx->comp_ctx);
}
lte->filtered) {
DEBUG("Discarding duplicate stream of "
"length %"PRIu64,
- wim_resource_size(lte));
+ lte->size);
lte->no_progress = 0;
stream_discarded = true;
goto skip_to_progress;
* equal to their original size and write them
* uncompressed instead. (But never do this if writing
* to a pipe.) */
- if (res_csize >= wim_resource_size(cur_lte) &&
+ if (res_csize >= cur_lte->size &&
!(ctx->write_resource_flags & WIMLIB_WRITE_RESOURCE_FLAG_PIPABLE))
{
DEBUG("Compressed %"PRIu64" => %"PRIu64" bytes; "
"writing uncompressed instead",
- wim_resource_size(cur_lte), res_csize);
+ cur_lte->size, res_csize);
ret = seek_and_truncate(ctx->out_fd, ctx->res_start_offset);
if (ret)
return ret;
ctx->out_fd,
WIMLIB_COMPRESSION_TYPE_NONE,
0,
- &cur_lte->output_resource_entry,
+ &cur_lte->out_reshdr,
ctx->write_resource_flags,
ctx->comp_ctx);
if (ret)
return ret;
} else {
- cur_lte->output_resource_entry.size =
+ cur_lte->out_reshdr.size_in_wim =
res_csize;
- cur_lte->output_resource_entry.original_size =
- cur_lte->resource_entry.original_size;
+ cur_lte->out_reshdr.uncompressed_size =
+ cur_lte->size;
- cur_lte->output_resource_entry.offset =
+ cur_lte->out_reshdr.offset_in_wim =
ctx->res_start_offset;
- cur_lte->output_resource_entry.flags =
- cur_lte->resource_entry.flags |
+ cur_lte->out_reshdr.flags =
+ cur_lte->flags |
WIM_RESHDR_FLAG_COMPRESSED;
DEBUG("Wrote compressed resource "
"(%"PRIu64" => %"PRIu64" bytes @ +%"PRIu64", flags=0x%02x)",
- cur_lte->output_resource_entry.original_size,
- cur_lte->output_resource_entry.size,
- cur_lte->output_resource_entry.offset,
- cur_lte->output_resource_entry.flags);
+ cur_lte->out_reshdr.uncompressed_size,
+ cur_lte->out_reshdr.size_in_wim,
+ cur_lte->out_reshdr.offset_in_wim,
+ cur_lte->out_reshdr.flags);
}
do_write_streams_progress(ctx->progress_data,
* when @lte is already hashed. */
sha1_init(&ctx->next_sha_ctx);
ctx->next_chunk = 0;
- ctx->next_num_chunks = DIV_ROUND_UP(wim_resource_size(lte),
- ctx->out_chunk_size);
+ ctx->next_num_chunks = DIV_ROUND_UP(lte->size, ctx->out_chunk_size);
ctx->next_lte = lte;
INIT_LIST_HEAD(<e->msg_list);
list_add_tail(<e->being_compressed_list, &ctx->outstanding_streams);
- ret = read_resource_prefix(lte, wim_resource_size(lte),
+ ret = read_resource_prefix(lte, lte->size,
main_writer_thread_cb,
ctx->out_chunk_size, ctx, 0);
if (ret)
struct main_writer_thread_ctx *ctx = _ctx;
int ret;
- if (wim_resource_size(lte) < 1000 ||
+ if (lte->size < 1000 ||
!must_compress_stream(lte, ctx->write_resource_flags,
ctx->out_ctype, ctx->out_chunk_size))
{
prev_wim_part = NULL;
list_for_each_entry(lte, stream_list, write_streams_list) {
num_streams++;
- total_bytes += wim_resource_size(lte);
+ total_bytes += lte->size;
if (must_compress_stream(lte, write_resource_flags,
out_ctype, out_chunk_size))
- total_compression_bytes += wim_resource_size(lte);
+ total_compression_bytes += lte->size;
if (lte->resource_location == RESOURCE_IN_WIM) {
- if (prev_wim_part != lte->wim) {
- prev_wim_part = lte->wim;
+ if (prev_wim_part != lte->rspec->wim) {
+ prev_wim_part = lte->rspec->wim;
total_parts++;
}
}
struct wim_lookup_table_entry *same_size_lte;
struct hlist_node *tmp;
- pos = hash_u64(wim_resource_size(lte)) % tab->capacity;
+ pos = hash_u64(lte->size) % tab->capacity;
lte->unique_size = 1;
hlist_for_each_entry(same_size_lte, tmp, &tab->array[pos], hash_list_2) {
- if (wim_resource_size(same_size_lte) == wim_resource_size(lte)) {
+ if (same_size_lte->size == lte->size) {
lte->unique_size = 0;
same_size_lte->unique_size = 0;
break;
struct find_streams_ctx *ctx)
{
int ret;
- struct wim_lookup_table_entry *lte;
if (streams_ok && (image == WIMLIB_ALL_IMAGES ||
(image == 1 && wim->hdr.image_count == 1)))
return ret;
}
- list_for_each_entry(lte, &ctx->stream_list, write_streams_list)
- lte->part_number = wim->hdr.part_number;
return 0;
}
/* Calculate and set lte->filtered. */
if (lte->resource_location == RESOURCE_IN_WIM) {
- if (lte->wim == ctx->wim &&
+ if (lte->rspec->wim == ctx->wim &&
(ctx->write_flags & WIMLIB_WRITE_FLAG_OVERWRITE))
filtered |= FILTERED_SAME_WIM;
- if (lte->wim != ctx->wim &&
+ if (lte->rspec->wim != ctx->wim &&
(ctx->write_flags & WIMLIB_WRITE_FLAG_SKIP_EXTERNAL_WIMS))
filtered |= FILTERED_EXTERNAL_WIM;
}
* use stream list already explicitly provided. Use existing
* reference counts. */
stream_list = stream_list_override;
- list_for_each_entry(lte, stream_list, write_streams_list) {
+ list_for_each_entry(lte, stream_list, write_streams_list)
lte->out_refcnt = (lte->refcnt ? lte->refcnt : 1);
- lte->part_number = wim->hdr.part_number;
- }
}
return write_stream_list(stream_list,
} else if (write_flags & WIMLIB_WRITE_FLAG_OVERWRITE) {
DEBUG("Image %u was not modified; re-using existing "
"metadata resource.", i);
- copy_resource_entry(&imd->metadata_lte->output_resource_entry,
- &imd->metadata_lte->resource_entry);
+ wim_res_spec_to_hdr(imd->metadata_lte->rspec,
+ &imd->metadata_lte->out_reshdr);
ret = 0;
} else {
DEBUG("Image %u was not modified; copying existing "
&wim->out_fd,
wim->out_compression_type,
wim->out_chunk_size,
- &imd->metadata_lte->output_resource_entry,
+ &imd->metadata_lte->out_reshdr,
write_resource_flags,
&wim->lzx_context);
}
* it should be a copy of the resource entry for the image that is
* marked as bootable. This is not well documented... */
if (wim->hdr.boot_idx == 0) {
- zero_resource_entry(&wim->hdr.boot_metadata_res_entry);
+ zero_reshdr(&wim->hdr.boot_metadata_reshdr);
} else {
- copy_resource_entry(&wim->hdr.boot_metadata_res_entry,
+ copy_reshdr(&wim->hdr.boot_metadata_reshdr,
&wim->image_metadata[wim->hdr.boot_idx- 1
- ]->metadata_lte->output_resource_entry);
+ ]->metadata_lte->out_reshdr);
}
/* Write lookup table. (Save old position first.) */
- old_lookup_table_end = wim->hdr.lookup_table_res_entry.offset +
- wim->hdr.lookup_table_res_entry.size;
+ old_lookup_table_end = wim->hdr.lookup_table_reshdr.offset_in_wim +
+ wim->hdr.lookup_table_reshdr.size_in_wim;
if (!(write_flags & WIMLIB_WRITE_FLAG_NO_LOOKUP_TABLE)) {
ret = write_wim_lookup_table(wim, image, write_flags,
- &wim->hdr.lookup_table_res_entry,
+ &wim->hdr.lookup_table_reshdr,
stream_list_override);
if (ret)
return ret;
if (write_flags & WIMLIB_WRITE_FLAG_USE_EXISTING_TOTALBYTES)
xml_totalbytes = WIM_TOTALBYTES_USE_EXISTING;
ret = write_wim_xml_data(wim, image, xml_totalbytes,
- &wim->hdr.xml_res_entry,
+ &wim->hdr.xml_data_reshdr,
write_resource_flags);
if (ret)
return ret;
if (write_flags & WIMLIB_WRITE_FLAG_CHECKPOINT_AFTER_XML) {
struct wim_header checkpoint_hdr;
memcpy(&checkpoint_hdr, &wim->hdr, sizeof(struct wim_header));
- zero_resource_entry(&checkpoint_hdr.integrity);
+ zero_reshdr(&checkpoint_hdr.integrity_table_reshdr);
checkpoint_hdr.flags |= WIM_HDR_FLAG_WRITE_IN_PROGRESS;
ret = write_wim_header_at_offset(&checkpoint_hdr,
&wim->out_fd, 0);
if (!(write_flags & WIMLIB_WRITE_FLAG_REUSE_INTEGRITY_TABLE))
old_lookup_table_end = 0;
- new_lookup_table_end = wim->hdr.lookup_table_res_entry.offset +
- wim->hdr.lookup_table_res_entry.size;
+ new_lookup_table_end = wim->hdr.lookup_table_reshdr.offset_in_wim +
+ wim->hdr.lookup_table_reshdr.size_in_wim;
ret = write_integrity_table(wim,
new_lookup_table_end,
return ret;
} else {
/* No integrity table. */
- zero_resource_entry(&wim->hdr.integrity);
+ zero_reshdr(&wim->hdr.integrity_table_reshdr);
}
/* Now that all information in the WIM header has been determined, the
struct list_head *stream_list_override)
{
int ret;
- struct resource_entry xml_res_entry;
+ struct wim_reshdr xml_reshdr;
WARNING("Creating a pipable WIM, which will "
"be incompatible\n"
/* Write extra copy of the XML data. */
ret = write_wim_xml_data(wim, image, WIM_TOTALBYTES_OMIT,
- &xml_res_entry,
+ &xml_reshdr,
WIMLIB_WRITE_RESOURCE_FLAG_PIPABLE);
if (ret)
return ret;
randomize_byte_array(wim->hdr.guid, WIMLIB_GUID_LEN);
/* Clear references to resources that have not been written yet. */
- zero_resource_entry(&wim->hdr.lookup_table_res_entry);
- zero_resource_entry(&wim->hdr.xml_res_entry);
- zero_resource_entry(&wim->hdr.boot_metadata_res_entry);
- zero_resource_entry(&wim->hdr.integrity);
+ zero_reshdr(&wim->hdr.lookup_table_reshdr);
+ zero_reshdr(&wim->hdr.xml_data_reshdr);
+ zero_reshdr(&wim->hdr.boot_metadata_reshdr);
+ zero_reshdr(&wim->hdr.integrity_table_reshdr);
/* Set image count and boot index correctly for single image writes. */
if (image != WIMLIB_ALL_IMAGES) {
const WIMStruct *wim = _wim;
off_t end_offset = *(const off_t*)wim->private;
- if (lte->resource_location == RESOURCE_IN_WIM && lte->wim == wim &&
- lte->resource_entry.offset + lte->resource_entry.size > end_offset)
+ if (lte->resource_location == RESOURCE_IN_WIM && lte->rspec->wim == wim &&
+ lte->rspec->offset_in_wim + lte->rspec->size_in_wim > end_offset)
return WIMLIB_ERR_RESOURCE_ORDER;
return 0;
}
* data, and that there are no stream resources, metadata resources, or
* lookup tables after the XML data. Otherwise, these data would be
* overwritten. */
- old_xml_begin = wim->hdr.xml_res_entry.offset;
- old_xml_end = old_xml_begin + wim->hdr.xml_res_entry.size;
- old_lookup_table_end = wim->hdr.lookup_table_res_entry.offset +
- wim->hdr.lookup_table_res_entry.size;
- if (wim->hdr.integrity.offset != 0 && wim->hdr.integrity.offset < old_xml_end) {
+ old_xml_begin = wim->hdr.xml_data_reshdr.offset_in_wim;
+ old_xml_end = old_xml_begin + wim->hdr.xml_data_reshdr.size_in_wim;
+ old_lookup_table_end = wim->hdr.lookup_table_reshdr.offset_in_wim +
+ wim->hdr.lookup_table_reshdr.size_in_wim;
+ if (wim->hdr.integrity_table_reshdr.offset_in_wim != 0 &&
+ wim->hdr.integrity_table_reshdr.offset_in_wim < old_xml_end) {
WARNING("Didn't expect the integrity table to be before the XML data");
return WIMLIB_ERR_RESOURCE_ORDER;
}
old_wim_end = old_lookup_table_end;
write_flags |= WIMLIB_WRITE_FLAG_NO_LOOKUP_TABLE |
WIMLIB_WRITE_FLAG_CHECKPOINT_AFTER_XML;
- } else if (wim->hdr.integrity.offset) {
+ } else if (wim->hdr.integrity_table_reshdr.offset_in_wim != 0) {
/* Old WIM has an integrity table; begin writing new streams
* after it. */
- old_wim_end = wim->hdr.integrity.offset + wim->hdr.integrity.size;
+ old_wim_end = wim->hdr.integrity_table_reshdr.offset_in_wim +
+ wim->hdr.integrity_table_reshdr.size_in_wim;
} else {
/* No existing integrity table; begin writing new streams after
* the old XML data. */
#include "wimlib/resource.h"
#include "wimlib/timestamp.h"
#include "wimlib/xml.h"
+#include "wimlib/write.h"
#include <libxml/encoding.h>
#include <libxml/parser.h>
*/
lte = inode_unnamed_lte(inode, info->lookup_table);
if (lte) {
- info->total_bytes += wim_resource_size(lte);
+ info->total_bytes += lte->size;
if (!dentry_is_first_in_inode(dentry))
- info->hard_link_bytes += wim_resource_size(lte);
+ info->hard_link_bytes += lte->size;
}
if (inode->i_nlink >= 2 && dentry_is_first_in_inode(dentry)) {
lte = inode_stream_lte(inode, i + 1, info->lookup_table);
if (lte) {
info->hard_link_bytes += inode->i_nlink *
- wim_resource_size(lte);
+ lte->size;
}
}
}
read_wim_xml_data(WIMStruct *wim)
{
void *buf;
+ size_t bufsize;
u8 *xml_data;
xmlDoc *doc;
xmlNode *root;
int ret;
- const struct resource_entry *res_entry;
-
- res_entry = &wim->hdr.xml_res_entry;
-
- DEBUG("Reading XML data: %"PRIu64" bytes at offset %"PRIu64"",
- (u64)res_entry->size, res_entry->offset);
- ret = res_entry_to_data(res_entry, wim, &buf);
+ ret = wimlib_get_xml_data(wim, &buf, &bufsize);
if (ret)
goto out;
xml_data = buf;
- doc = xmlReadMemory((const char *)xml_data, res_entry->original_size,
+ doc = xmlReadMemory((const char *)xml_data, bufsize,
NULL, "UTF-16LE", 0);
if (!doc) {
ERROR("Failed to parse XML data");
/* Writes the XML data to a WIM file. */
int
write_wim_xml_data(WIMStruct *wim, int image, u64 total_bytes,
- struct resource_entry *out_res_entry,
+ struct wim_reshdr *out_reshdr,
int write_resource_flags)
{
int ret;
&wim->out_fd,
WIMLIB_COMPRESSION_TYPE_NONE,
0,
- out_res_entry,
+ out_reshdr,
NULL,
write_resource_flags,
&wim->lzx_context);
WIMLIBAPI int
wimlib_get_xml_data(WIMStruct *wim, void **buf_ret, size_t *bufsize_ret)
{
- if (wim->filename == NULL)
+ const struct wim_reshdr *xml_reshdr;
+
+ if (wim->filename == NULL && filedes_is_seekable(&wim->in_fd))
return WIMLIB_ERR_INVALID_PARAM;
if (buf_ret == NULL || bufsize_ret == NULL)
return WIMLIB_ERR_INVALID_PARAM;
- *bufsize_ret = wim->hdr.xml_res_entry.original_size;
- return res_entry_to_data(&wim->hdr.xml_res_entry, wim, buf_ret);
+ xml_reshdr = &wim->hdr.xml_data_reshdr;
+
+ DEBUG("Reading XML data.");
+ *bufsize_ret = xml_reshdr->uncompressed_size;
+ return wim_reshdr_to_data(xml_reshdr, wim, buf_ret);
}
WIMLIBAPI int