From a933b4cc3f0bb93093287e353df8bebb2b714a42 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 1 Sep 2013 11:12:59 -0500 Subject: [PATCH] wimlib_iterate_dir_tree(): Define behavior when resources missing --- include/wimlib.h | 33 +++++++++++++++++++++++---------- include/wimlib/lookup_table.h | 5 ++++- src/dentry.c | 23 +++++++++++++++++++---- src/lookup_table.c | 18 +++++++++++++++++- 4 files changed, 63 insertions(+), 16 deletions(-) diff --git a/include/wimlib.h b/include/wimlib.h index faeb1a3e..6f0e45fe 100644 --- a/include/wimlib.h +++ b/include/wimlib.h @@ -1,7 +1,6 @@ -/* - * wimlib.h - * - * External header for wimlib. +/** + * @file wimlib.h + * @brief External header for wimlib. * * This file contains extensive comments for generating documentation with * Doxygen. The built HTML documentation can be viewed at @@ -870,7 +869,14 @@ struct wimlib_resource_entry { uint32_t is_free : 1; uint32_t is_spanned : 1; - uint32_t reserved_flags : 28; + + /** 1 if this resource was not found in the lookup table of the + * ::WIMStruct. This normally implies a missing call to + * wimlib_reference_resource_files() or wimlib_reference_resources(). + */ + uint32_t is_missing : 1; + + uint32_t reserved_flags : 27; uint64_t reserved[4]; }; @@ -1008,6 +1014,12 @@ typedef int (*wimlib_iterate_lookup_table_callback_t)(const struct wimlib_resour * itself; only its children (in the case of a non-empty directory) */ #define WIMLIB_ITERATE_DIR_TREE_FLAG_CHILDREN 0x00000002 +/** Return ::WIMLIB_ERR_RESOURCE_NOT_FOUND if any resources needed to fill in + * the ::wimlib_resource_entry's for the iteration cannot be found in the lookup + * table of the ::WIMStruct. The default behavior without this flag is to fill + * in the SHA1 message digest of the ::wimlib_resource_entry and set the @ref + * wimlib_resource_entry::is_missing "is_missing" flag. */ +#define WIMLIB_ITERATE_DIR_TREE_FLAG_RESOURCES_NEEDED 0x00000004 /** @@ -2342,9 +2354,11 @@ wimlib_image_name_in_use(const WIMStruct *wim, const wimlib_tchar *name); * The WIM containing the image(s) over which to iterate, specified as a * pointer to the ::WIMStruct for a standalone WIM file, a delta WIM file, * or part 1 of a split WIM. In the case of a WIM file that is not - * standalone, this ::WIMStruct must have had any needed external resources - * previously referenced using wimlib_reference_resources() or - * wimlib_reference_resource_files(). + * standalone, this ::WIMStruct should have had any needed external + * resources previously referenced using wimlib_reference_resources() or + * wimlib_reference_resource_files(). If not, see + * ::WIMLIB_ITERATE_DIR_TREE_FLAG_RESOURCES_NEEDED for information about + * the behavior when resources are missing. * * @param image * The 1-based number of the image in @p wim that contains the files or @@ -2355,8 +2369,7 @@ wimlib_image_name_in_use(const WIMStruct *wim, const wimlib_tchar *name); * Path in the WIM image at which to do the iteration. * * @param flags - * Bitwise OR of ::WIMLIB_ITERATE_DIR_TREE_FLAG_RECURSIVE and/or - * ::WIMLIB_ITERATE_DIR_TREE_FLAG_CHILDREN. + * Bitwise OR of flags prefixed with WIMLIB_ITERATE_DIR_TREE_FLAG. * * @param cb * A callback function that will receive each directory entry. diff --git a/include/wimlib/lookup_table.h b/include/wimlib/lookup_table.h index 93616348..48ee9fc5 100644 --- a/include/wimlib/lookup_table.h +++ b/include/wimlib/lookup_table.h @@ -419,7 +419,7 @@ inode_resolve_ltes(struct wim_inode *inode, struct wim_lookup_table *table, bool force); extern int -resource_not_found_error(struct wim_inode *inode, const u8 *hash); +resource_not_found_error(const struct wim_inode *inode, const u8 *hash); extern void inode_unresolve_ltes(struct wim_inode *inode); @@ -514,6 +514,9 @@ inode_unnamed_lte_unresolved(const struct wim_inode *inode, extern struct wim_lookup_table_entry * inode_unnamed_lte(const struct wim_inode *inode, const 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); diff --git a/src/dentry.c b/src/dentry.c index 7762e702..af27c687 100644 --- a/src/dentry.c +++ b/src/dentry.c @@ -2308,12 +2308,14 @@ write_dentry_tree(const struct wim_dentry * restrict root, u8 * restrict p) static int init_wimlib_dentry(struct wimlib_dir_entry *wdentry, struct wim_dentry *dentry, - const WIMStruct *wim) + const WIMStruct *wim, + int flags) { int ret; size_t dummy; const struct wim_inode *inode = dentry->d_inode; struct wim_lookup_table_entry *lte; + const u8 *hash; #if TCHAR_IS_UTF16LE wdentry->filename = dentry->file_name; @@ -2358,17 +2360,30 @@ init_wimlib_dentry(struct wimlib_dir_entry *wdentry, wdentry->last_access_time = wim_timestamp_to_timespec(inode->i_last_access_time); lte = inode_unnamed_lte(inode, wim->lookup_table); - if (lte) + if (lte) { lte_to_wimlib_resource_entry(lte, &wdentry->streams[0].resource); + } else if (!is_zero_hash(hash = inode_unnamed_stream_hash(inode))) { + if (flags & WIMLIB_ITERATE_DIR_TREE_FLAG_RESOURCES_NEEDED) + return resource_not_found_error(inode, hash); + copy_hash(wdentry->streams[0].resource.sha1_hash, hash); + wdentry->streams[0].resource.is_missing = 1; + } for (unsigned i = 0; i < inode->i_num_ads; i++) { - if (inode->i_ads_entries[i].stream_name == NULL) + if (!ads_entry_is_named_stream(&inode->i_ads_entries[i])) continue; lte = inode_stream_lte(inode, i + 1, wim->lookup_table); wdentry->num_named_streams++; if (lte) { lte_to_wimlib_resource_entry(lte, &wdentry->streams[ wdentry->num_named_streams].resource); + } else if (!is_zero_hash(hash = inode_stream_hash(inode, i + 1))) { + if (flags & WIMLIB_ITERATE_DIR_TREE_FLAG_RESOURCES_NEEDED) + return resource_not_found_error(inode, hash); + copy_hash(wdentry->streams[ + wdentry->num_named_streams].resource.sha1_hash, hash); + wdentry->streams[ + wdentry->num_named_streams].resource.is_missing = 1; } #if TCHAR_IS_UTF16LE wdentry->streams[wdentry->num_named_streams].stream_name = @@ -2437,7 +2452,7 @@ do_iterate_dir_tree(WIMStruct *wim, if (!wdentry) goto out; - ret = init_wimlib_dentry(wdentry, dentry, wim); + ret = init_wimlib_dentry(wdentry, dentry, wim, flags); if (ret) goto out_free_wimlib_dentry; diff --git a/src/lookup_table.c b/src/lookup_table.c index f7fb7c3a..125887db 100644 --- a/src/lookup_table.c +++ b/src/lookup_table.c @@ -1035,7 +1035,7 @@ out: #endif int -resource_not_found_error(struct wim_inode *inode, const u8 *hash) +resource_not_found_error(const struct wim_inode *inode, const u8 *hash) { if (wimlib_print_errors) { ERROR("\"%"TS"\": resource not found", inode_first_full_path(inode)); @@ -1214,6 +1214,22 @@ inode_unnamed_lte(const struct wim_inode *inode, return inode_unnamed_lte_unresolved(inode, table); } +const u8 * +inode_unnamed_stream_hash(const struct wim_inode *inode) +{ + const u8 *hash; + + for (unsigned i = 0; i <= inode->i_num_ads; i++) { + if (inode_stream_name_nbytes(inode, i) == 0) { + hash = inode_stream_hash(inode, i); + if (!is_zero_hash(hash)) + return hash; + } + } + return NULL; +} + + static int lte_add_stream_size(struct wim_lookup_table_entry *lte, void *total_bytes_p) { -- 2.43.0