]> wimlib.net Git - wimlib/blobdiff - src/dentry.c
write_dentry(): Remove unhelpful comment
[wimlib] / src / dentry.c
index ff4df8be41dce328d7eac452b049c943feee7979..3e462a6e38f472e623ab4ea887e257f05c257177 100644 (file)
@@ -214,6 +214,17 @@ dentry_correct_length_aligned(const struct wim_dentry *dentry)
        return (len + 7) & ~7;
 }
 
+static int
+dentry_clear_short_name(struct wim_dentry *dentry)
+{
+       if (dentry_has_short_name(dentry)) {
+               FREE(dentry->short_name);
+               dentry->short_name = NULL;
+               dentry->short_name_nbytes = 0;
+       }
+       return 0;
+}
+
 /* Sets the name of a WIM dentry from a multibyte string.
  * Only use this on dentries not inserted into the tree.  Use rename_wim_path()
  * to do a real rename.  */
@@ -221,17 +232,42 @@ int
 dentry_set_name(struct wim_dentry *dentry, const tchar *new_name)
 {
        int ret;
+
        ret = get_utf16le_string(new_name, &dentry->file_name,
                                 &dentry->file_name_nbytes);
-       if (ret == 0) {
-               /* Clear the short name and recalculate the dentry length */
-               if (dentry_has_short_name(dentry)) {
-                       FREE(dentry->short_name);
-                       dentry->short_name = NULL;
-                       dentry->short_name_nbytes = 0;
-               }
+       if (ret)
+               return ret;
+
+       return dentry_clear_short_name(dentry);
+}
+
+/* Sets the name of a WIM dentry from a UTF-16LE string.
+ * Only use this on dentries not inserted into the tree.  Use rename_wim_path()
+ * to do a real rename.  */
+int
+dentry_set_name_utf16le(struct wim_dentry *dentry, const utf16lechar *new_name)
+{
+       utf16lechar *name = NULL;
+       size_t name_nbytes = 0;
+
+       if (new_name && *new_name) {
+               const utf16lechar *tmp;
+
+               tmp = new_name;
+               do {
+                       name_nbytes += sizeof(utf16lechar);
+               } while (*++tmp);
+
+               name = memdup(new_name, name_nbytes + sizeof(utf16lechar));
+               if (!name)
+                       return WIMLIB_ERR_NOMEM;
        }
-       return ret;
+
+       FREE(dentry->file_name);
+       dentry->file_name = name;
+       dentry->file_name_nbytes = name_nbytes;
+
+       return dentry_clear_short_name(dentry);
 }
 
 /* Returns the total length of a WIM alternate data stream entry on-disk,
@@ -360,8 +396,7 @@ for_dentry_in_tree_depth(struct wim_dentry *root,
        return do_for_dentry_in_tree_depth(root, visitor, arg);
 }
 
-/* Calculate the full path of @dentry.  The full path of its parent must have
- * already been calculated, or it must be the root dentry. */
+/* Calculate the full path of @dentry.  */
 int
 calculate_dentry_full_path(struct wim_dentry *dentry)
 {
@@ -435,18 +470,6 @@ 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)
 {
@@ -867,14 +890,12 @@ wim_pathname_to_stream(WIMStruct *wim,
                if (ads_entry) {
                        stream_idx = ads_idx + 1;
                        lte = ads_entry->lte;
-                       goto out;
                } else {
                        return -ENOENT;
                }
        } else {
                lte = inode_unnamed_stream_resolved(inode, &stream_idx);
        }
-out:
        if (dentry_ret)
                *dentry_ret = dentry;
        if (lte_ret)
@@ -885,13 +906,6 @@ out:
 }
 #endif /* WITH_FUSE  */
 
-/* Initializations done on every `struct wim_dentry'. */
-static void
-dentry_common_init(struct wim_dentry *dentry)
-{
-       memset(dentry, 0, sizeof(struct wim_dentry));
-}
-
 /* Creates an unlinked directory entry. */
 int
 new_dentry(const tchar *name, struct wim_dentry **dentry_ret)
@@ -899,11 +913,10 @@ new_dentry(const tchar *name, struct wim_dentry **dentry_ret)
        struct wim_dentry *dentry;
        int ret;
 
-       dentry = MALLOC(sizeof(struct wim_dentry));
-       if (dentry == NULL)
+       dentry = CALLOC(1, sizeof(struct wim_dentry));
+       if (!dentry)
                return WIMLIB_ERR_NOMEM;
 
-       dentry_common_init(dentry);
        if (*name) {
                ret = dentry_set_name(dentry, name);
                if (ret) {
@@ -956,13 +969,12 @@ new_dentry_with_inode(const tchar *name, struct wim_dentry **dentry_ret)
 }
 
 int
-new_filler_directory(const tchar *name, struct wim_dentry **dentry_ret)
+new_filler_directory(struct wim_dentry **dentry_ret)
 {
        int ret;
        struct wim_dentry *dentry;
 
-       DEBUG("Creating filler directory \"%"TS"\"", name);
-       ret = new_dentry_with_inode(name, &dentry);
+       ret = new_dentry_with_inode(T(""), &dentry);
        if (ret)
                return ret;
        /* Leave the inode number as 0; this is allowed for non
@@ -986,10 +998,13 @@ dentry_tree_clear_inode_visited(struct wim_dentry *root)
        for_dentry_in_tree(root, dentry_clear_inode_visited, NULL);
 }
 
-/* Frees a WIM dentry.
+/*
+ * Free a WIM dentry.
  *
- * The corresponding inode (if any) is freed only if its link count is
- * decremented to 0.  */
+ * In addition to freeing the dentry itself, this decrements the link count of
+ * the corresponding inode (if any).  If the inode's link count reaches 0, the
+ * inode is freed as well.
+ */
 void
 free_dentry(struct wim_dentry *dentry)
 {
@@ -1003,29 +1018,23 @@ free_dentry(struct wim_dentry *dentry)
        }
 }
 
-/* This function is passed as an argument to for_dentry_in_tree_depth() in order
- * to free a directory tree. */
 static int
-do_free_dentry(struct wim_dentry *dentry, void *_lookup_table)
+do_free_dentry(struct wim_dentry *dentry, void *_ignore)
 {
-       struct wim_lookup_table *lookup_table = _lookup_table;
-
-       if (lookup_table) {
-               struct wim_inode *inode = dentry->d_inode;
-               for (unsigned i = 0; i <= inode->i_num_ads; i++) {
-                       struct wim_lookup_table_entry *lte;
+       free_dentry(dentry);
+       return 0;
+}
 
-                       lte = inode_stream_lte(inode, i, lookup_table);
-                       if (lte)
-                               lte_decrement_refcnt(lte, lookup_table);
-               }
-       }
+static int
+do_free_dentry_and_unref_streams(struct wim_dentry *dentry, void *lookup_table)
+{
+       inode_unref_streams(dentry->d_inode, lookup_table);
        free_dentry(dentry);
        return 0;
 }
 
 /*
- * Unlinks and frees a dentry tree.
+ * Recursively frees all directory entries in the specified tree.
  *
  * @root:
  *     The root of the tree.
@@ -1034,11 +1043,22 @@ do_free_dentry(struct wim_dentry *dentry, void *_lookup_table)
  *     The lookup table for dentries.  If non-NULL, the reference counts in the
  *     lookup table for the lookup table entries corresponding to the dentries
  *     will be decremented.
+ *
+ * This also puts references to the corresponding inodes.
+ *
+ * This does *not* unlink @root from its parent directory (if it has one).
  */
 void
 free_dentry_tree(struct wim_dentry *root, struct wim_lookup_table *lookup_table)
 {
-       for_dentry_in_tree_depth(root, do_free_dentry, lookup_table);
+       int (*f)(struct wim_dentry *, void *);
+
+       if (lookup_table)
+               f = do_free_dentry_and_unref_streams;
+       else
+               f = do_free_dentry;
+
+       for_dentry_in_tree_depth(root, f, lookup_table);
 }
 
 /* Insert the @child dentry into the case sensitive index of the @dir directory.
@@ -1165,76 +1185,6 @@ unlink_dentry(struct wim_dentry *dentry)
        list_del(&dentry->d_ci_conflict_list);
 }
 
-static int
-free_dentry_full_path(struct wim_dentry *dentry, void *_ignore)
-{
-       FREE(dentry->_full_path);
-       dentry->_full_path = NULL;
-       return 0;
-}
-
-/* Rename a file or directory in the WIM.  */
-int
-rename_wim_path(WIMStruct *wim, const tchar *from, const tchar *to,
-               CASE_SENSITIVITY_TYPE case_type)
-{
-       struct wim_dentry *src;
-       struct wim_dentry *dst;
-       struct wim_dentry *parent_of_dst;
-       int ret;
-
-       /* This rename() implementation currently only supports actual files
-        * (not alternate data streams) */
-
-       src = get_dentry(wim, from, case_type);
-       if (!src)
-               return -errno;
-
-       dst = get_dentry(wim, to, case_type);
-
-       if (dst) {
-               /* Destination file exists */
-
-               if (src == dst) /* Same file */
-                       return 0;
-
-               if (!dentry_is_directory(src)) {
-                       /* Cannot rename non-directory to directory. */
-                       if (dentry_is_directory(dst))
-                               return -EISDIR;
-               } else {
-                       /* Cannot rename directory to a non-directory or a non-empty
-                        * directory */
-                       if (!dentry_is_directory(dst))
-                               return -ENOTDIR;
-                       if (dentry_has_children(dst))
-                               return -ENOTEMPTY;
-               }
-               parent_of_dst = dst->parent;
-       } else {
-               /* Destination does not exist */
-               parent_of_dst = get_parent_dentry(wim, to, case_type);
-               if (!parent_of_dst)
-                       return -errno;
-
-               if (!dentry_is_directory(parent_of_dst))
-                       return -ENOTDIR;
-       }
-
-       ret = dentry_set_name(src, path_basename(to));
-       if (ret)
-               return -ENOMEM;
-       if (dst) {
-               unlink_dentry(dst);
-               free_dentry_tree(dst, wim->lookup_table);
-       }
-       unlink_dentry(src);
-       dentry_add_child(parent_of_dst, src);
-       if (src->_full_path)
-               for_dentry_in_tree(src, free_dentry_full_path, NULL);
-       return 0;
-}
-
 /* Reads a WIM directory entry, including all alternate data stream entries that
  * follow it, from the WIM image's metadata resource.  */
 static int
@@ -1271,9 +1221,6 @@ read_dentry(const u8 * restrict buf, size_t buf_len,
        p = &buf[offset];
        disk_dentry = (const struct wim_dentry_on_disk*)p;
 
-       if (unlikely((uintptr_t)p & 7))
-               WARNING("WIM dentry is not 8-byte aligned");
-
        /* Get dentry length.  */
        length = le64_to_cpu(disk_dentry->length);
 
@@ -1428,18 +1375,6 @@ err_free_dentry:
        return ret;
 }
 
-static const tchar *
-dentry_get_file_type_string(const struct wim_dentry *dentry)
-{
-       const struct wim_inode *inode = dentry->d_inode;
-       if (inode_is_directory(inode))
-               return T("directory");
-       else if (inode_is_symlink(inode))
-               return T("symbolic link");
-       else
-               return T("file");
-}
-
 static bool
 dentry_is_dot_or_dotdot(const struct wim_dentry *dentry)
 {
@@ -1518,14 +1453,10 @@ read_dentry_tree_recursive(const u8 * restrict buf, size_t buf_len,
                        /* We already found a dentry with this same
                         * case-sensitive long name.  Only keep the first one.
                         */
-                       const tchar *child_type, *duplicate_type;
-                       child_type = dentry_get_file_type_string(child);
-                       duplicate_type = dentry_get_file_type_string(duplicate);
-                       WARNING("Ignoring duplicate %"TS" \"%"TS"\" "
-                               "(the WIM image already contains a %"TS" "
+                       WARNING("Ignoring duplicate file \"%"TS"\" "
+                               "(the WIM image already contains a file "
                                "at that path with the exact same name)",
-                               child_type, dentry_full_path(duplicate),
-                               duplicate_type);
+                               dentry_full_path(duplicate));
                        free_dentry(child);
                        continue;
                }
@@ -1721,11 +1652,6 @@ write_dentry(const struct wim_dentry * restrict dentry, u8 * restrict p)
        while ((uintptr_t)p & 7)
                *p++ = 0;
 
-       /* We calculate the correct length of the dentry ourselves because the
-        * dentry->length field may been set to an unexpected value from when we
-        * read the dentry in (for example, there may have been unknown data
-        * appended to the end of the dentry...).  Furthermore, the dentry may
-        * have been renamed, thus changing its needed length. */
        disk_dentry->length = cpu_to_le64(p - orig_p);
 
        if (use_dummy_stream) {