return NULL;
}
+/* Calculate the SHA1 message digest of a stream and move it from the list of
+ * unhashed streams to the stream lookup table, possibly joining it with an
+ * existing lookup table entry for an identical stream.
+ *
+ * @lte: An unhashed lookup table entry.
+ * @lookup_table: Lookup table for the WIM.
+ * @lte_ret: On success, write a pointer to the resulting lookup table
+ * entry to this location. This will be the same as @lte
+ * if it was inserted into the lookup table, or different if
+ * a duplicate stream was found.
+ *
+ * Returns 0 on success; nonzero if there is an error reading the stream.
+ */
int
hash_unhashed_stream(struct wim_lookup_table_entry *lte,
struct wim_lookup_table *lookup_table,
/* No duplicate stream, so we need to insert
* this stream into the lookup table and treat
* it as a hashed stream. */
- list_del(<e->unhashed_list);
lookup_table_insert(lookup_table, lte);
- lte->out_refcnt = lte->refcnt;
lte->unhashed = 0;
}
if (lte_ret)
return (entry->flags & WIM_RESHDR_FLAG_COMPRESSED);
}
+/* Iterate over each inode in a WIM image that has not yet been hashed */
#define image_for_each_inode(inode, imd) \
list_for_each_entry(inode, &imd->inode_list, i_list)
+/* Iterate over each stream in a WIM image that has not yet been hashed */
#define image_for_each_unhashed_stream(lte, imd) \
list_for_each_entry(lte, &imd->unhashed_streams, unhashed_list)
+/* Iterate over each stream in a WIM image that has not yet been hashed (safe
+ * against stream removal) */
#define image_for_each_unhashed_stream_safe(lte, tmp, imd) \
list_for_each_entry_safe(lte, tmp, &imd->unhashed_streams, unhashed_list)
#if 1
# define copy_resource_entry(dst, src) memcpy(dst, src, sizeof(struct resource_entry))
+# define zero_resource_entry(entry) memset(entry, 0, sizeof(struct resource_entry))
#else
static inline void
copy_resource_entry(struct resource_entry *dst,
const struct resource_entry *src)
{
- memcpy(dst, src, sizeof(struct resource_entry));
BUILD_BUG_ON(sizeof(struct resource_entry) != 24);
((u64*)dst)[0] = ((u64*)src)[0];
((u64*)dst)[1] = ((u64*)src)[1];
((u64*)dst)[2] = ((u64*)src)[2];
}
+
+static inline void
+zero_resource_entry(struct resource_entry *entry)
+{
+ BUILD_BUG_ON(sizeof(struct resource_entry) != 24);
+ ((u64*)entry)[0] = 0;
+ ((u64*)entry)[1] = 0;
+ ((u64*)entry)[2] = 0;
+}
#endif
/* add_image.c */
#define WIMLIB_WRITE_FLAG_NO_LOOKUP_TABLE 0x80000000
#define WIMLIB_WRITE_FLAG_REUSE_INTEGRITY_TABLE 0x40000000
#define WIMLIB_WRITE_FLAG_CHECKPOINT_AFTER_XML 0x20000000
-//#define WIMLIB_WRITE_FLAG_OVERWRITE_INPLACE 0x10000000
-#define WIMLIB_WRITE_MASK_PUBLIC 0x0fffffff
+#define WIMLIB_WRITE_MASK_PUBLIC 0x1fffffff
/* We are capturing a tree to be placed in the root of the WIM image */
#define WIMLIB_ADD_IMAGE_FLAG_ROOT 0x80000000
struct wim_lookup_table *lookup_table,
FILE *out_fp,
int out_ctype,
+ int write_resource_flags,
wimlib_progress_func_t progress_func,
- union wimlib_progress_info *progress,
- int write_resource_flags)
+ union wimlib_progress_info *progress)
{
- int ret;
+ int ret = 0;
struct wim_lookup_table_entry *lte;
/* For each stream in @stream_list ... */
lookup_table,
&tmp);
if (ret)
- return ret;
+ break;
if (tmp != lte) {
lte = tmp;
/* We found a duplicate stream. */
<e->output_resource_entry,
write_resource_flags);
if (ret)
- return ret;
+ break;
if (lte->unhashed) {
list_del(<e->unhashed_list);
lookup_table_insert(lookup_table, lte);
progress_func,
wim_resource_size(lte));
}
- return 0;
+ return ret;
}
static int
return do_write_stream_list(stream_list,
lookup_table,
out_fp,
- out_ctype, progress_func,
- progress, write_resource_flags);
+ out_ctype,
+ write_resource_flags,
+ progress_func,
+ progress);
}
#ifdef ENABLE_MULTITHREADED_COMPRESSION
if (list_empty(stream_list))
return 0;
+ /* Calculate the total size of the streams to be written. Note: this
+ * will be the uncompressed size, as we may not know the compressed size
+ * yet, and also this will assume that every unhashed stream will be
+ * written (which will not necessarily be the case). */
list_for_each_entry(lte, stream_list, write_streams_list) {
num_streams++;
total_bytes += wim_resource_size(lte);
lte_set_output_res_entry(wim->image_metadata[i]->metadata_lte,
wim);
for_lookup_table_entry(wim->lookup_table, lte_set_output_res_entry, wim);
- INIT_LIST_HEAD(stream_list);
- list_splice(&args.stream_list, stream_list);
+ list_transfer(&args.stream_list, stream_list);
out_destroy_stream_size_table:
destroy_stream_size_table(&args.stream_size_tab);
return ret;
static int
image_find_streams_to_write(WIMStruct *w)
{
- struct wim_image_metadata *imd;
struct find_streams_ctx *ctx;
+ struct wim_image_metadata *imd;
struct wim_inode *inode;
struct wim_lookup_table_entry *lte;
wim->private = &ctx;
ret = for_image(wim, image, image_find_streams_to_write);
destroy_stream_size_table(&ctx.stream_size_tab);
- if (ret == 0) {
- INIT_LIST_HEAD(stream_list);
- list_splice(&ctx.stream_list, stream_list);
- }
+ if (ret == 0)
+ list_transfer(&ctx.stream_list, stream_list);
return ret;
}
* it should be a copy of the resource entry for the image that is
* marked as bootable. This is not well documented... */
if (hdr.boot_idx == 0) {
- memset(&hdr.boot_metadata_res_entry, 0,
- sizeof(struct resource_entry));
+ zero_resource_entry(&hdr.boot_metadata_res_entry);
} else {
- memcpy(&hdr.boot_metadata_res_entry,
- &w->image_metadata[
- hdr.boot_idx - 1]->metadata_lte->output_resource_entry,
- sizeof(struct resource_entry));
+ copy_resource_entry(&hdr.boot_metadata_res_entry,
+ &w->image_metadata[ hdr.boot_idx- 1
+ ]->metadata_lte->output_resource_entry);
}
if (!(write_flags & WIMLIB_WRITE_FLAG_NO_LOOKUP_TABLE)) {
if (write_flags & WIMLIB_WRITE_FLAG_CHECKPOINT_AFTER_XML) {
struct wim_header checkpoint_hdr;
memcpy(&checkpoint_hdr, &hdr, sizeof(struct wim_header));
- memset(&checkpoint_hdr.integrity, 0, sizeof(struct resource_entry));
+ zero_resource_entry(&checkpoint_hdr.integrity);
if (fseeko(out, 0, SEEK_SET)) {
ERROR_WITH_ERRNO("Failed to seek to beginning "
"of WIM being written");
if (ret)
goto out_close_wim;
} else {
- memset(&hdr.integrity, 0, sizeof(struct resource_entry));
+ zero_resource_entry(&hdr.integrity);
}
if (fseeko(out, 0, SEEK_SET) != 0) {
ret = wimlib_write(w, tmpfile, WIMLIB_ALL_IMAGES,
write_flags | WIMLIB_WRITE_FLAG_FSYNC,
num_threads, progress_func);
- if (ret != 0) {
+ if (ret) {
ERROR("Failed to write the WIM file `%"TS"'", tmpfile);
- goto err;
+ goto out_unlink;
}
DEBUG("Renaming `%"TS"' to `%"TS"'", tmpfile, w->filename);
ERROR_WITH_ERRNO("Failed to rename `%"TS"' to `%"TS"'",
tmpfile, w->filename);
ret = WIMLIB_ERR_RENAME;
- goto err;
+ goto out_unlink;
}
if (progress_func) {
FREE(w->filename);
w->filename = NULL;
}
- return ret;
-err:
+ goto out;
+out_unlink:
/* Remove temporary file. */
if (tunlink(tmpfile) != 0)
WARNING_WITH_ERRNO("Failed to remove `%"TS"'", tmpfile);
+out:
return ret;
}