X-Git-Url: https://wimlib.net/git/?a=blobdiff_plain;f=src%2Fdentry.c;h=0e0bfd5df73832c17a39cabd13f9a50d440cf985;hb=bde1c17816c7ed97c236158e2f1359bb34af08bf;hp=ff4df8be41dce328d7eac452b049c943feee7979;hpb=60358c75e65f428a2da957cace0bc7a980e17fa2;p=wimlib diff --git a/src/dentry.c b/src/dentry.c index ff4df8be..0e0bfd5d 100644 --- a/src/dentry.c +++ b/src/dentry.c @@ -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) { @@ -1010,22 +1025,14 @@ do_free_dentry(struct wim_dentry *dentry, void *_lookup_table) { 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; - - lte = inode_stream_lte(inode, i, lookup_table); - if (lte) - lte_decrement_refcnt(lte, lookup_table); - } - } + if (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,6 +1041,10 @@ 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) @@ -1165,76 +1176,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