*/
/*
- * Copyright (C) 2012, 2013 Eric Biggers
+ * Copyright (C) 2012, 2013, 2014 Eric Biggers
*
* This file is part of wimlib, a library for working with WIM files.
*
void
free_lookup_table(struct wim_lookup_table *table)
{
- DEBUG("Freeing lookup table.");
- if (table == NULL)
- return;
-
- if (table->array) {
- for_lookup_table_entry(table,
- do_free_lookup_table_entry,
- NULL);
+ if (table) {
+ for_lookup_table_entry(table, do_free_lookup_table_entry, NULL);
FREE(table->array);
+ FREE(table);
}
- FREE(table);
}
struct wim_lookup_table_entry *
if (new == NULL)
return NULL;
- new->extracted_file = NULL;
switch (new->resource_location) {
case RESOURCE_IN_WIM:
list_add(&new->rspec_node, &new->rspec->stream_list);
case RESOURCE_IN_FILE_ON_DISK:
#ifdef __WIN32__
+ case RESOURCE_IN_WINNT_FILE_ON_DISK:
case RESOURCE_WIN32_ENCRYPTED:
#endif
#ifdef WITH_FUSE
break;
case RESOURCE_IN_FILE_ON_DISK:
#ifdef __WIN32__
+ case RESOURCE_IN_WINNT_FILE_ON_DISK:
case RESOURCE_WIN32_ENCRYPTED:
#endif
#ifdef WITH_FUSE
* that there still may be open file descriptors to it.)
* */
if (lte->resource_location == RESOURCE_IN_STAGING_FILE)
- unlink(lte->staging_file_name);
+ unlinkat(lte->staging_dir_fd,
+ lte->staging_file_name, 0);
#endif
} else {
if (!should_retain_lte(lte))
/* Different (possibly split) WIMs? */
if (wim1 != wim2) {
- v = memcmp(wim1->hdr.guid, wim2->hdr.guid, WIM_GID_LEN);
+ v = memcmp(wim1->hdr.guid, wim2->hdr.guid, WIM_GUID_LEN);
if (v)
return v;
}
case RESOURCE_IN_STAGING_FILE:
#endif
#ifdef __WIN32__
+ case RESOURCE_IN_WINNT_FILE_ON_DISK:
case RESOURCE_WIN32_ENCRYPTED:
#endif
/* Compare files by path: just a heuristic that will place files
/* cur_entry is now a stream bound to a resource. */
+ /* Ignore entries with all zeroes in the hash field. */
+ if (is_zero_hash(cur_entry->hash))
+ goto free_cur_entry_and_continue;
+
/* Verify that the part number matches that of the underlying
* WIM file. */
if (part_number != wim->hdr.part_number) {
goto free_cur_entry_and_continue;
}
- /* Ignore entries with all zeroes in the hash field. */
- if (is_zero_hash(cur_entry->hash))
- goto free_cur_entry_and_continue;
-
if (reshdr.flags & WIM_RESHDR_FLAG_METADATA) {
/* Lookup table entry for a metadata resource. */
copy_hash(disk_entry->hash, hash);
}
+/* Note: the list of stream entries must be sorted so that all entries for the
+ * same packed resource are consecutive. In addition, entries with
+ * WIM_RESHDR_FLAG_METADATA set must be in the same order as the indices of the
+ * underlying images. */
int
write_wim_lookup_table_from_stream_list(struct list_head *stream_list,
struct filedes *out_fd,
struct wim_lookup_table_entry_disk *table_buf_ptr;
int ret;
u64 prev_res_offset_in_wim = ~0ULL;
+ u64 prev_uncompressed_size;
+ u64 logical_offset;
table_size = 0;
list_for_each_entry(lte, stream_list, lookup_table_list) {
table_buf_ptr = table_buf;
prev_res_offset_in_wim = ~0ULL;
+ prev_uncompressed_size = 0;
+ logical_offset = 0;
list_for_each_entry(lte, stream_list, lookup_table_list) {
+ if (lte->out_reshdr.flags & WIM_RESHDR_FLAG_PACKED_STREAMS) {
+ struct wim_reshdr tmp_reshdr;
- put_wim_lookup_table_entry(table_buf_ptr++,
- <e->out_reshdr,
- part_number,
- lte->out_refcnt,
- lte->hash);
- if (lte->out_reshdr.flags & WIM_RESHDR_FLAG_PACKED_STREAMS &&
- lte->out_res_offset_in_wim != prev_res_offset_in_wim)
- {
- /* Put the main resource entry for the pack. */
+ /* Eww. When WIMGAPI sees multiple resource packs, it
+ * expects the offsets to be adjusted as if there were
+ * really only one pack. */
- struct wim_reshdr reshdr;
+ if (lte->out_res_offset_in_wim != prev_res_offset_in_wim) {
+ /* Put the resource entry for pack */
+ tmp_reshdr.offset_in_wim = lte->out_res_offset_in_wim;
+ tmp_reshdr.size_in_wim = lte->out_res_size_in_wim;
+ tmp_reshdr.uncompressed_size = WIM_PACK_MAGIC_NUMBER;
+ tmp_reshdr.flags = WIM_RESHDR_FLAG_PACKED_STREAMS;
- reshdr.offset_in_wim = lte->out_res_offset_in_wim;
- reshdr.size_in_wim = lte->out_res_size_in_wim;
- reshdr.uncompressed_size = WIM_PACK_MAGIC_NUMBER;
- reshdr.flags = WIM_RESHDR_FLAG_PACKED_STREAMS;
+ put_wim_lookup_table_entry(table_buf_ptr++,
+ &tmp_reshdr,
+ part_number,
+ 1, zero_hash);
- DEBUG("Putting main entry for pack: "
- "size_in_wim=%"PRIu64", "
- "offset_in_wim=%"PRIu64", "
- "uncompressed_size=%"PRIu64,
- reshdr.size_in_wim,
- reshdr.offset_in_wim,
- reshdr.uncompressed_size);
+ logical_offset += prev_uncompressed_size;
+ prev_res_offset_in_wim = lte->out_res_offset_in_wim;
+ prev_uncompressed_size = lte->out_res_uncompressed_size;
+ }
+ tmp_reshdr = lte->out_reshdr;
+ tmp_reshdr.offset_in_wim += logical_offset;
put_wim_lookup_table_entry(table_buf_ptr++,
- &reshdr,
+ &tmp_reshdr,
part_number,
- 1, zero_hash);
- prev_res_offset_in_wim = lte->out_res_offset_in_wim;
+ lte->out_refcnt,
+ lte->hash);
+ } else {
+ put_wim_lookup_table_entry(table_buf_ptr++,
+ <e->out_reshdr,
+ part_number,
+ lte->out_refcnt,
+ lte->hash);
}
}
return 0;
}
-int
-lte_free_extracted_file(struct wim_lookup_table_entry *lte, void *_ignore)
-{
- if (lte->extracted_file != NULL) {
- FREE(lte->extracted_file);
- lte->extracted_file = NULL;
- }
- return 0;
-}
-
/* Allocate a stream entry for the contents of the buffer, or re-use an existing
* entry in @lookup_table for the same stream. */
struct wim_lookup_table_entry *
.cb = cb,
.user_ctx = user_ctx,
};
- if (wim->hdr.part_number == 1) {
+ if (wim_has_metadata(wim)) {
int ret;
for (int i = 0; i < wim->hdr.image_count; i++) {
ret = do_iterate_lte(wim->image_metadata[i]->metadata_lte,