]> wimlib.net Git - wimlib/blobdiff - src/dentry.c
dentry.c: Fix broken tree traversal functions
[wimlib] / src / dentry.c
index 7cd93ed1ab9e42a21aa0dfcaf6ae31d6e5e441c7..cf6abec5913c0869c9dffea27a30f4f05d65bdcd 100644 (file)
@@ -230,13 +230,13 @@ for_dentry_tree_in_rbtree(struct rb_node *node,
        int ret;
        if (node) {
                ret = for_dentry_tree_in_rbtree(node->rb_left, visitor, arg);
-               if (ret != 0)
+               if (ret)
                        return ret;
                ret = for_dentry_in_tree(rbnode_dentry(node), visitor, arg);
-               if (ret != 0)
+               if (ret)
                        return ret;
                ret = for_dentry_tree_in_rbtree(node->rb_right, visitor, arg);
-               if (ret != 0)
+               if (ret)
                        return ret;
        }
        return 0;
@@ -250,13 +250,16 @@ int
 for_dentry_in_tree(struct wim_dentry *root,
                   int (*visitor)(struct wim_dentry*, void*), void *arg)
 {
-       int ret = visitor(root, arg);
-       if (ret == 0) {
-               ret = for_dentry_tree_in_rbtree(root->d_inode->i_children.rb_node,
-                                               visitor,
-                                               arg);
-       }
-       return ret;
+       int ret;
+
+       if (!root)
+               return 0;
+       ret = (*visitor)(root, arg);
+       if (ret)
+               return ret;
+       return for_dentry_tree_in_rbtree(root->d_inode->i_children.rb_node,
+                                        visitor,
+                                        arg);
 }
 
 /* Like for_dentry_in_tree(), but the visitor function is always called on a
@@ -266,11 +269,14 @@ for_dentry_in_tree_depth(struct wim_dentry *root,
                         int (*visitor)(struct wim_dentry*, void*), void *arg)
 {
        int ret;
+
+       if (!root)
+               return 0;
        ret = for_dentry_tree_in_rbtree_depth(root->d_inode->i_children.rb_node,
                                              visitor, arg);
-       if (ret == 0)
-               ret = visitor(root, arg);
-       return ret;
+       if (ret)
+               return ret;
+       return (*visitor)(root, arg);
 }
 
 /* Calculate the full path of @dentry.  The full path of its parent must have
@@ -493,6 +499,10 @@ get_dentry_utf16le(WIMStruct *w, const utf16lechar *path,
        const utf16lechar *p, *pp;
 
        cur_dentry = parent_dentry = wim_root_dentry(w);
+       if (!cur_dentry) {
+               errno = ENOENT;
+               return NULL;
+       }
        p = path;
        while (1) {
                while (*p == cpu_to_le16('/'))
@@ -711,6 +721,7 @@ new_timeless_inode()
                inode->i_nlink = 1;
                inode->i_next_stream_id = 1;
                inode->i_not_rpfixed = 1;
+               INIT_LIST_HEAD(&inode->i_list);
        #ifdef WITH_FUSE
                if (pthread_mutex_init(&inode->i_mutex, NULL) != 0) {
                        ERROR_WITH_ERRNO("Error initializing mutex");
@@ -798,6 +809,25 @@ new_dentry_with_inode(const tchar *name, struct wim_dentry **dentry_ret)
        return __new_dentry_with_inode(name, dentry_ret, false);
 }
 
+int
+new_filler_directory(const tchar *name, struct wim_dentry **dentry_ret)
+{
+       int ret;
+       struct wim_dentry *dentry;
+
+       DEBUG("Creating filler directory \"%"TS"\"", name);
+       ret = new_dentry_with_inode(name, &dentry);
+       if (ret)
+               goto out;
+       /* Leave the inode number as 0; this is allowed for non
+        * hard-linked files. */
+       dentry->d_inode->i_resolved = 1;
+       dentry->d_inode->i_attributes = FILE_ATTRIBUTE_DIRECTORY;
+       *dentry_ret = dentry;
+       ret = 0;
+out:
+       return ret;
+}
 
 static int
 init_ads_entry(struct wim_ads_entry *ads_entry, const void *name,
@@ -843,9 +873,10 @@ free_inode(struct wim_inode *inode)
                wimlib_assert(inode->i_num_opened_fds == 0);
                FREE(inode->i_fds);
                pthread_mutex_destroy(&inode->i_mutex);
-               if (inode->i_hlist.pprev)
-                       hlist_del(&inode->i_hlist);
        #endif
+               /* HACK: This may instead delete the inode from i_list, but the
+                * hlist_del() behaves the same as list_del(). */
+               hlist_del(&inode->i_hlist);
                FREE(inode->i_extracted_file);
                FREE(inode);
        }
@@ -917,8 +948,7 @@ do_free_dentry(struct wim_dentry *dentry, void *__lookup_table)
 void
 free_dentry_tree(struct wim_dentry *root, struct wim_lookup_table *lookup_table)
 {
-       if (root)
-               for_dentry_in_tree_depth(root, do_free_dentry, lookup_table);
+       for_dentry_in_tree_depth(root, do_free_dentry, lookup_table);
 }
 
 /*
@@ -1211,7 +1241,7 @@ inode_get_unix_data(const struct wim_inode *inode,
        if (size != sizeof(struct wimlib_unix_data))
                return BAD_UNIX_DATA;
 
-       ret = read_full_resource_into_buf(lte, unix_data, true);
+       ret = read_full_resource_into_buf(lte, unix_data);
        if (ret)
                return ret;
 
@@ -1268,13 +1298,13 @@ replace_forbidden_characters(utf16lechar *name)
        #ifdef __WIN32__
                if (wcschr(L"<>:\"/\\|?*", (wchar_t)*p))
        #else
-               if (*p == '/')
+               if (*p == cpu_to_le16('/'))
        #endif
                {
                #ifdef __WIN32__
                        *p = cpu_to_le16(0xfffd);
                #else
-                       *p = '?';
+                       *p = cpu_to_le16('?');
                #endif
                        if (name) {
                                WARNING("File, directory, or stream name \"%"WS"\"\n"