WIMLIB_ERR_WRITE,
WIMLIB_ERR_XML,
WIMLIB_ERR_WIM_IS_READONLY,
+ WIMLIB_ERR_RESOURCE_NOT_FOUND,
};
* @retval ::WIMLIB_ERR_READ
* A unexpected end-of-file or read error occurred when trying to read data
* from the WIM file associated with @a wim.
+ * @retval ::WIMLIB_ERR_RESOURCE_NOT_FOUND
+ * One of the dentries in the image referenced a stream not present in the
+ * WIM's lookup table (or in any of the lookup tables of the split WIM
+ * parts).
* @retval ::WIMLIB_ERR_SPLIT_INVALID
* The WIM is a split WIM, but the parts specified do not form a complete
* split WIM because they do not include all the parts of the original WIM,
* @retval ::WIMLIB_ERR_READ
* An unexpected end-of-file or read error occurred when trying to read
* data from the WIM file associated with @a wim.
+ * @retval ::WIMLIB_ERR_RESOURCE_NOT_FOUND
+ * One of the dentries in the image referenced a stream not present in the
+ * WIM's lookup table (or in any of the lookup tables of the split WIM
+ * parts).
* @retval ::WIMLIB_ERR_SPLIT_INVALID
* The WIM is a split WIM, but the parts specified do not form a complete
* split WIM because they do not include all the parts of the original WIM,
extern int
lte_free_extracted_file(struct wim_lookup_table_entry *lte, void *ignore);
-extern void
+extern int
inode_resolve_ltes(struct wim_inode *inode, struct wim_lookup_table *table);
extern void
struct wim_inode *inode = dentry->d_inode;
struct wim_lookup_table *lookup_table = _lookup_table;
struct wim_lookup_table_entry *lte;
+ int ret;
- inode_resolve_ltes(inode, lookup_table);
+ ret = inode_resolve_ltes(inode, lookup_table);
+ if (ret)
+ return ret;
for (unsigned i = 0; i <= inode->i_num_ads; i++) {
lte = inode_stream_lte_resolved(inode, i);
if (lte)
return 0;
}
-static void
+static int
find_streams_for_extraction(struct wim_dentry *root,
struct list_head *stream_list,
struct wim_lookup_table *lookup_table,
int extract_flags)
{
struct find_streams_ctx ctx;
+ int ret;
INIT_LIST_HEAD(&ctx.stream_list);
ctx.extract_flags = extract_flags;
- for_dentry_in_tree(root, dentry_resolve_and_zero_lte_refcnt, lookup_table);
+ ret = for_dentry_in_tree(root, dentry_resolve_and_zero_lte_refcnt, lookup_table);
+ if (ret)
+ return ret;
for_dentry_in_tree(root, dentry_find_streams_to_extract, &ctx);
list_transfer(&ctx.stream_list, stream_list);
+ return 0;
}
struct apply_operations {
goto out_dentry_reset_needs_extraction;
/* Build a list of the streams that need to be extracted */
- find_streams_for_extraction(root,
- &stream_list,
- wim->lookup_table, extract_flags);
+ ret = find_streams_for_extraction(root,
+ &stream_list,
+ wim->lookup_table, extract_flags);
+ if (ret)
+ goto out_dentry_reset_needs_extraction;
/* Calculate the number of bytes of data that will be extracted */
calculate_bytes_to_extract(&stream_list, extract_flags,
* This function always succeeds; unresolved lookup table entries are given a
* NULL pointer.
*/
-void
+int
inode_resolve_ltes(struct wim_inode *inode, struct wim_lookup_table *table)
{
+ int ret;
+ const u8 *hash;
if (!inode->i_resolved) {
- struct wim_lookup_table_entry *lte;
+ struct wim_lookup_table_entry *lte, *ads_lte;
+
/* Resolve the default file stream */
- lte = __lookup_resource(table, inode->i_hash);
- inode->i_lte = lte;
- inode->i_resolved = 1;
+ lte = NULL;
+ hash = inode->i_hash;
+ if (!is_zero_hash(hash)) {
+ lte = __lookup_resource(table, hash);
+ if (unlikely(!lte))
+ goto resource_not_found;
+ }
/* Resolve the alternate data streams */
+ struct wim_lookup_table_entry *ads_ltes[inode->i_num_ads];
for (u16 i = 0; i < inode->i_num_ads; i++) {
- struct wim_ads_entry *cur_entry = &inode->i_ads_entries[i];
- lte = __lookup_resource(table, cur_entry->hash);
- cur_entry->lte = lte;
+ struct wim_ads_entry *cur_entry;
+
+ ads_lte = NULL;
+ cur_entry = &inode->i_ads_entries[i];
+ hash = cur_entry->hash;
+ if (!is_zero_hash(hash)) {
+ ads_lte = __lookup_resource(table, hash);
+ if (unlikely(!ads_lte))
+ goto resource_not_found;
+ }
+ ads_ltes[i] = ads_lte;
}
+ inode->i_lte = lte;
+ for (u16 i = 0; i < inode->i_num_ads; i++)
+ inode->i_ads_entries[i].lte = ads_ltes[i];
+ inode->i_resolved = 1;
+ }
+ return 0;
+resource_not_found:
+ if (wimlib_print_errors) {
+ ERROR("\"%"TS"\": resource not found", inode_first_full_path(inode));
+ tfprintf(stderr, T(" SHA-1 message digest of missing resource:\n "));
+ print_hash(hash, stderr);
+ tputc(T('\n'), stderr);
}
+ return WIMLIB_ERR_RESOURCE_NOT_FOUND;
}
void
DEBUG("Resolving lookup table entries and assigning inode numbers");
ctx.next_ino = 1;
image_for_each_inode(inode, imd) {
- inode_resolve_ltes(inode, wim->lookup_table);
+ ret = inode_resolve_ltes(inode, wim->lookup_table);
+ if (ret)
+ goto out_delete_staging_dir;
inode->i_ino = ctx.next_ino++;
}
DEBUG("(next_ino = %"PRIu64")", ctx.next_ino);
/* Try to delete the staging directory if a deletion wasn't yet
* attempted due to an earlier error */
+out_delete_staging_dir:
if (ctx.staging_dir_name)
delete_staging_dir(&ctx);
out_free_dir_copy:
= T("Could not rename a file"),
[WIMLIB_ERR_REPARSE_POINT_FIXUP_FAILED]
= T("Unable to complete reparse point fixup"),
+ [WIMLIB_ERR_RESOURCE_NOT_FOUND]
+ = T("A file resource needed to complete the operation was missing from the WIM"),
[WIMLIB_ERR_RESOURCE_ORDER]
= T("The components of the WIM were arranged in an unexpected order"),
[WIMLIB_ERR_SPECIAL_FILE]