]> wimlib.net Git - wimlib/blobdiff - src/dentry.c
do_overlay(): Do overlays recursively
[wimlib] / src / dentry.c
index e9826b55d1e4f1ae9911e1b5dcdf0d793a1e0489..8f591c3d9f57c18f63d89ae90c72504a895c0608 100644 (file)
@@ -275,7 +275,7 @@ for_dentry_in_tree_depth(struct wim_dentry *root,
 
 /* Calculate the full path of @dentry.  The full path of its parent must have
  * already been calculated, or it must be the root dentry. */
-int
+static int
 calculate_dentry_full_path(struct wim_dentry *dentry)
 {
        tchar *full_path;
@@ -347,6 +347,18 @@ calculate_dentry_full_path(struct wim_dentry *dentry)
        return 0;
 }
 
+static int
+do_calculate_dentry_full_path(struct wim_dentry *dentry, void *_ignore)
+{
+       return calculate_dentry_full_path(dentry);
+}
+
+int
+calculate_dentry_tree_full_paths(struct wim_dentry *root)
+{
+       return for_dentry_in_tree(root, do_calculate_dentry_full_path, NULL);
+}
+
 tchar *
 dentry_full_path(struct wim_dentry *dentry)
 {
@@ -577,9 +589,6 @@ print_dentry_full_path(struct wim_dentry *dentry, void *_ignore)
        if (ret)
                return ret;
        tprintf(T("%"TS"\n"), dentry->_full_path);
-       FREE(dentry->_full_path);
-       dentry->_full_path = NULL;
-       dentry->full_path_nbytes = 0;
        return 0;
 }
 
@@ -637,7 +646,15 @@ print_dentry(struct wim_dentry *dentry, void *lookup_table)
        wim_timestamp_to_str(inode->i_last_write_time, buf, sizeof(buf));
        tprintf(T("Last Write Time   = %"TS"\n"), buf);
 
-       tprintf(T("Reparse Tag       = 0x%"PRIx32"\n"), inode->i_reparse_tag);
+       if (inode->i_attributes & FILE_ATTRIBUTE_REPARSE_POINT) {
+               tprintf(T("Reparse Tag       = 0x%"PRIx32"\n"), inode->i_reparse_tag);
+               tprintf(T("Reparse Point Flags = 0x%"PRIx16"\n"),
+                       inode->i_not_rpfixed);
+               tprintf(T("Reparse Point Unknown 2 = 0x%"PRIx32"\n"),
+                       inode->i_rp_unknown_2);
+       }
+       tprintf(T("Reparse Point Unknown 1 = 0x%"PRIx32"\n"),
+               inode->i_rp_unknown_1);
        tprintf(T("Hard Link Group   = 0x%"PRIx64"\n"), inode->i_ino);
        tprintf(T("Hard Link Group Size = %"PRIu32"\n"), inode->i_nlink);
        tprintf(T("Number of Alternate Data Streams = %hu\n"), inode->i_num_ads);
@@ -693,6 +710,7 @@ new_timeless_inode()
                inode->i_security_id = -1;
                inode->i_nlink = 1;
                inode->i_next_stream_id = 1;
+               inode->i_not_rpfixed = 1;
        #ifdef WITH_FUSE
                if (pthread_mutex_init(&inode->i_mutex, NULL) != 0) {
                        ERROR_WITH_ERRNO("Error initializing mutex");
@@ -909,7 +927,7 @@ free_dentry_tree(struct wim_dentry *root, struct wim_lookup_table *lookup_table)
  * @parent: The dentry that will be the parent of @dentry.
  * @dentry: The dentry to link.
  */
-bool
+struct wim_dentry *
 dentry_add_child(struct wim_dentry * restrict parent,
                 struct wim_dentry * restrict child)
 {
@@ -930,12 +948,12 @@ dentry_add_child(struct wim_dentry * restrict parent,
                else if (result > 0)
                        new = &((*new)->rb_right);
                else
-                       return false;
+                       return this;
        }
        child->parent = parent;
        rb_link_node(&child->rb_node, rb_parent, new);
        rb_insert_color(&child->rb_node, root);
-       return true;
+       return NULL;
 }
 
 /* Unlink a WIM dentry from the directory entry tree. */
@@ -1199,6 +1217,30 @@ inode_set_unix_data(struct wim_inode *inode, uid_t uid, gid_t gid, mode_t mode,
 }
 #endif /* !__WIN32__ */
 
+static void
+replace_forbidden_characters(utf16lechar *name)
+{
+       utf16lechar *p;
+
+       for (p = name; *p; p++) {
+       #ifdef __WIN32__
+               if (wcschr(L"<>:\"/\\|?*", (wchar_t)*p))
+       #else
+               if (*p == '/')
+       #endif
+               {
+                       if (name) {
+                               WARNING("File, directory, or stream name \"%"WS"\"\n"
+                                       "          contains forbidden characters; "
+                                       "replacing them with Unicode codepoint U+001A",
+                                       name);
+                               name = NULL;
+                       }
+                       *p = 0x1a;
+               }
+       }
+}
+
 /*
  * Reads the alternate data stream entries of a WIM dentry.
  *
@@ -1326,6 +1368,7 @@ read_ads_entries(const u8 *p, struct wim_inode *inode, u64 remaining_size)
                        get_bytes(p, cur_entry->stream_name_nbytes,
                                  cur_entry->stream_name);
                        cur_entry->stream_name[cur_entry->stream_name_nbytes / 2] = 0;
+                       replace_forbidden_characters(cur_entry->stream_name);
                }
                /* It's expected that the size of every ADS entry is a multiple
                 * of 8.  However, to be safe, I'm allowing the possibility of
@@ -1447,12 +1490,12 @@ read_dentry(const u8 metadata_resource[], u64 metadata_resource_len,
         * reparse points, then put the fields in the same place and didn't
         * document it.  */
        if (inode->i_attributes & FILE_ATTRIBUTE_REPARSE_POINT) {
-               p += 4;
+               p = get_u32(p, &inode->i_rp_unknown_1);
                p = get_u32(p, &inode->i_reparse_tag);
-               p += 4;
+               p = get_u16(p, &inode->i_rp_unknown_2);
+               p = get_u16(p, &inode->i_not_rpfixed);
        } else {
-               p += 4;
-               /* i_reparse_tag is irrelevant; just leave it at 0. */
+               p = get_u32(p, &inode->i_rp_unknown_1);
                p = get_u64(p, &inode->i_ino);
        }
 
@@ -1499,6 +1542,7 @@ read_dentry(const u8 metadata_resource[], u64 metadata_resource_len,
                        WARNING("File name in WIM dentry \"%"WS"\" is not "
                                "null-terminated!", file_name);
                }
+               replace_forbidden_characters(file_name);
        }
 
        /* Align the calculated size */
@@ -1549,6 +1593,7 @@ read_dentry(const u8 metadata_resource[], u64 metadata_resource_len,
                        WARNING("Short name in WIM dentry \"%"WS"\" is not "
                                "null-terminated!", file_name);
                }
+               replace_forbidden_characters(short_name);
        }
 
        /*
@@ -1719,9 +1764,10 @@ write_dentry(const struct wim_dentry *dentry, u8 *p)
        hash = inode_stream_hash(inode, 0);
        p = put_bytes(p, SHA1_HASH_SIZE, hash);
        if (inode->i_attributes & FILE_ATTRIBUTE_REPARSE_POINT) {
-               p = put_zeroes(p, 4);
+               p = put_u32(p, 0);
                p = put_u32(p, inode->i_reparse_tag);
-               p = put_zeroes(p, 4);
+               p = put_u16(p, 0);
+               p = put_u16(p, inode->i_not_rpfixed);
        } else {
                u64 link_group_id;
                p = put_u32(p, 0);