]> wimlib.net Git - wimlib/blobdiff - src/dentry.c
Initial update functionality (library only)
[wimlib] / src / dentry.c
index fac2be7abcaa6f72a7493ce5dd16c51dafd7219d..48b310411f2d1ed447bcd6eb19298f4ab90e01fc 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,11 +250,15 @@ 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);
+       int ret = 0;
+
+       if (root) {
+               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;
 }
@@ -265,11 +269,13 @@ int
 for_dentry_in_tree_depth(struct wim_dentry *root,
                         int (*visitor)(struct wim_dentry*, void*), void *arg)
 {
-       int ret;
-       ret = for_dentry_tree_in_rbtree_depth(root->d_inode->i_children.rb_node,
-                                             visitor, arg);
-       if (ret == 0)
-               ret = visitor(root, arg);
+       int ret = 0;
+       if (root) {
+               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;
 }
 
@@ -711,6 +717,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");
@@ -843,9 +850,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 +925,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);
 }
 
 /*
@@ -1129,16 +1136,12 @@ inode_set_unnamed_stream(struct wim_inode *inode, const void *data, size_t len,
        void *buf;
 
        sha1_buffer(data, len, hash);
-
        existing_lte = __lookup_resource(lookup_table, hash);
-
        if (existing_lte) {
                wimlib_assert(wim_resource_size(existing_lte) == len);
                lte = existing_lte;
                lte->refcnt++;
        } else {
-               void *buf;
-
                lte = new_lookup_table_entry();
                if (!lte)
                        return WIMLIB_ERR_NOMEM;
@@ -1215,7 +1218,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;
 
@@ -1258,6 +1261,11 @@ inode_set_unix_data(struct wim_inode *inode, uid_t uid, gid_t gid, mode_t mode,
 }
 #endif /* !__WIN32__ */
 
+/* Replace weird characters in filenames and alternate data stream names.
+ *
+ * In particular we do not want the path separator to appear in any names, as
+ * that would make it possible for a "malicious" WIM to extract itself to any
+ * location it wanted to. */
 static void
 replace_forbidden_characters(utf16lechar *name)
 {
@@ -1267,17 +1275,21 @@ 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 = cpu_to_le16('?');
+               #endif
                        if (name) {
                                WARNING("File, directory, or stream name \"%"WS"\"\n"
                                        "          contains forbidden characters; "
-                                       "replacing them with Unicode codepoint U+001A",
+                                       "substituting replacement characters.",
                                        name);
                                name = NULL;
                        }
-                       *p = 0x1a;
                }
        }
 }
@@ -1359,7 +1371,7 @@ read_ads_entries(const u8 *p, struct wim_inode *inode, u64 remaining_size)
                }
 
                p = get_u64(p, &length);
-               p += 8; /* Skip the reserved field */
+               p = get_u64(p, &cur_entry->unused);
                p = get_bytes(p, SHA1_HASH_SIZE, cur_entry->hash);
                p = get_u16(p, &cur_entry->stream_name_nbytes);
 
@@ -1516,10 +1528,8 @@ read_dentry(const u8 metadata_resource[], u64 metadata_resource_len,
        p = get_u32(p, (u32*)&inode->i_security_id);
        p = get_u64(p, &dentry->subdir_offset);
 
-       /* 2 unused fields */
-       p += 2 * sizeof(u64);
-       /*p = get_u64(p, &dentry->unused1);*/
-       /*p = get_u64(p, &dentry->unused2);*/
+       p = get_u64(p, &inode->i_unused_1);
+       p = get_u64(p, &inode->i_unused_2);
 
        p = get_u64(p, &inode->i_creation_time);
        p = get_u64(p, &inode->i_last_access_time);
@@ -1797,21 +1807,21 @@ write_dentry(const struct wim_dentry *dentry, u8 *p)
        p = put_u32(p, inode->i_attributes);
        p = put_u32(p, inode->i_security_id);
        p = put_u64(p, dentry->subdir_offset);
-       p = put_u64(p, 0); /* unused1 */
-       p = put_u64(p, 0); /* unused2 */
+       p = put_u64(p, inode->i_unused_1);
+       p = put_u64(p, inode->i_unused_2);
        p = put_u64(p, inode->i_creation_time);
        p = put_u64(p, inode->i_last_access_time);
        p = put_u64(p, inode->i_last_write_time);
        hash = inode_stream_hash(inode, 0);
        p = put_bytes(p, SHA1_HASH_SIZE, hash);
        if (inode->i_attributes & FILE_ATTRIBUTE_REPARSE_POINT) {
-               p = put_u32(p, 0);
+               p = put_u32(p, inode->i_rp_unknown_1);
                p = put_u32(p, inode->i_reparse_tag);
-               p = put_u16(p, 0);
+               p = put_u16(p, inode->i_rp_unknown_2);
                p = put_u16(p, inode->i_not_rpfixed);
        } else {
                u64 link_group_id;
-               p = put_u32(p, 0);
+               p = put_u32(p, inode->i_rp_unknown_1);
                if (inode->i_nlink == 1)
                        link_group_id = 0;
                else
@@ -1839,7 +1849,7 @@ write_dentry(const struct wim_dentry *dentry, u8 *p)
         * alternate data stream entries. */
        for (u16 i = 0; i < inode->i_num_ads; i++) {
                p = put_u64(p, ads_entry_total_length(&inode->i_ads_entries[i]));
-               p = put_u64(p, 0); /* Unused */
+               p = put_u64(p, inode->i_ads_entries[i].unused);
                hash = inode_stream_hash(inode, i + 1);
                p = put_bytes(p, SHA1_HASH_SIZE, hash);
                p = put_u16(p, inode->i_ads_entries[i].stream_name_nbytes);