wimlib_iterate_dir_tree(): Define behavior when resources missing
authorEric Biggers <ebiggers3@gmail.com>
Sun, 1 Sep 2013 16:12:59 +0000 (11:12 -0500)
committerEric Biggers <ebiggers3@gmail.com>
Sun, 1 Sep 2013 16:12:59 +0000 (11:12 -0500)
include/wimlib.h
include/wimlib/lookup_table.h
src/dentry.c
src/lookup_table.c

index faeb1a3..6f0e45f 100644 (file)
@@ -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.
index 9361634..48ee9fc 100644 (file)
@@ -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);
 
index 7762e70..af27c68 100644 (file)
@@ -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;
 
index f7fb7c3..125887d 100644 (file)
@@ -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)
 {