4 * Iterate through files in a WIM image.
5 * This is the stable API; internal code can just use for_dentry_in_tree().
9 * Copyright (C) 2013 Eric Biggers
11 * This file is part of wimlib, a library for working with WIM files.
13 * wimlib is free software; you can redistribute it and/or modify it under the
14 * terms of the GNU General Public License as published by the Free
15 * Software Foundation; either version 3 of the License, or (at your option)
18 * wimlib is distributed in the hope that it will be useful, but WITHOUT ANY
19 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
20 * A PARTICULAR PURPOSE. See the GNU General Public License for more
23 * You should have received a copy of the GNU General Public License
24 * along with wimlib; if not, see http://www.gnu.org/licenses/.
32 #include "wimlib/dentry.h"
33 #include "wimlib/encoding.h"
34 #include "wimlib/lookup_table.h"
35 #include "wimlib/metadata.h"
36 #include "wimlib/paths.h"
37 #include "wimlib/security.h"
38 #include "wimlib/timestamp.h"
39 #include "wimlib/util.h"
40 #include "wimlib/wim.h"
43 init_wimlib_dentry(struct wimlib_dir_entry *wdentry,
44 struct wim_dentry *dentry,
50 const struct wim_inode *inode = dentry->d_inode;
51 struct wim_lookup_table_entry *lte;
55 wdentry->filename = dentry->file_name;
56 wdentry->dos_name = dentry->short_name;
58 if (dentry_has_long_name(dentry)) {
59 ret = utf16le_to_tstr(dentry->file_name,
60 dentry->file_name_nbytes,
61 (tchar**)&wdentry->filename,
66 if (dentry_has_short_name(dentry)) {
67 ret = utf16le_to_tstr(dentry->short_name,
68 dentry->short_name_nbytes,
69 (tchar**)&wdentry->dos_name,
75 ret = calculate_dentry_full_path(dentry);
78 wdentry->full_path = dentry->_full_path;
80 for (struct wim_dentry *d = dentry; !dentry_is_root(d); d = d->parent)
83 if (inode->i_security_id >= 0) {
84 const struct wim_security_data *sd = wim_const_security_data(wim);
85 wdentry->security_descriptor = sd->descriptors[inode->i_security_id];
86 wdentry->security_descriptor_size = sd->sizes[inode->i_security_id];
88 wdentry->reparse_tag = inode->i_reparse_tag;
89 wdentry->num_links = inode->i_nlink;
90 wdentry->attributes = inode->i_attributes;
91 wdentry->hard_link_group_id = inode->i_ino;
92 wdentry->creation_time = wim_timestamp_to_timespec(inode->i_creation_time);
93 wdentry->last_write_time = wim_timestamp_to_timespec(inode->i_last_write_time);
94 wdentry->last_access_time = wim_timestamp_to_timespec(inode->i_last_access_time);
96 lte = inode_unnamed_lte(inode, wim->lookup_table);
98 lte_to_wimlib_resource_entry(lte, &wdentry->streams[0].resource);
99 } else if (!is_zero_hash(hash = inode_unnamed_stream_hash(inode))) {
100 if (flags & WIMLIB_ITERATE_DIR_TREE_FLAG_RESOURCES_NEEDED)
101 return stream_not_found_error(inode, hash);
102 copy_hash(wdentry->streams[0].resource.sha1_hash, hash);
103 wdentry->streams[0].resource.is_missing = 1;
106 for (unsigned i = 0; i < inode->i_num_ads; i++) {
107 if (!ads_entry_is_named_stream(&inode->i_ads_entries[i]))
109 lte = inode_stream_lte(inode, i + 1, wim->lookup_table);
110 wdentry->num_named_streams++;
112 lte_to_wimlib_resource_entry(lte, &wdentry->streams[
113 wdentry->num_named_streams].resource);
114 } else if (!is_zero_hash(hash = inode_stream_hash(inode, i + 1))) {
115 if (flags & WIMLIB_ITERATE_DIR_TREE_FLAG_RESOURCES_NEEDED)
116 return stream_not_found_error(inode, hash);
117 copy_hash(wdentry->streams[
118 wdentry->num_named_streams].resource.sha1_hash, hash);
120 wdentry->num_named_streams].resource.is_missing = 1;
123 wdentry->streams[wdentry->num_named_streams].stream_name =
124 inode->i_ads_entries[i].stream_name;
128 ret = utf16le_to_tstr(inode->i_ads_entries[i].stream_name,
129 inode->i_ads_entries[i].stream_name_nbytes,
130 (tchar**)&wdentry->streams[
131 wdentry->num_named_streams].stream_name,
141 free_wimlib_dentry(struct wimlib_dir_entry *wdentry)
143 #if !TCHAR_IS_UTF16LE
144 FREE((tchar*)wdentry->filename);
145 FREE((tchar*)wdentry->dos_name);
146 for (unsigned i = 1; i <= wdentry->num_named_streams; i++)
147 FREE((tchar*)wdentry->streams[i].stream_name);
153 do_iterate_dir_tree(WIMStruct *wim,
154 struct wim_dentry *dentry, int flags,
155 wimlib_iterate_dir_tree_callback_t cb,
158 struct wimlib_dir_entry *wdentry;
159 int ret = WIMLIB_ERR_NOMEM;
162 wdentry = CALLOC(1, sizeof(struct wimlib_dir_entry) +
163 (1 + dentry->d_inode->i_num_ads) *
164 sizeof(struct wimlib_stream_entry));
168 ret = init_wimlib_dentry(wdentry, dentry, wim, flags);
170 goto out_free_wimlib_dentry;
172 if (!(flags & WIMLIB_ITERATE_DIR_TREE_FLAG_CHILDREN)) {
173 ret = (*cb)(wdentry, user_ctx);
175 goto out_free_wimlib_dentry;
178 if (flags & (WIMLIB_ITERATE_DIR_TREE_FLAG_RECURSIVE |
179 WIMLIB_ITERATE_DIR_TREE_FLAG_CHILDREN))
181 struct wim_dentry *child;
184 for_dentry_child(child, dentry) {
185 ret = do_iterate_dir_tree(wim, child,
186 flags & ~WIMLIB_ITERATE_DIR_TREE_FLAG_CHILDREN,
192 out_free_wimlib_dentry:
193 free_wimlib_dentry(wdentry);
198 struct image_iterate_dir_tree_ctx {
201 wimlib_iterate_dir_tree_callback_t cb;
207 image_do_iterate_dir_tree(WIMStruct *wim)
209 struct image_iterate_dir_tree_ctx *ctx = wim->private;
210 struct wim_dentry *dentry;
212 dentry = get_dentry(wim, ctx->path, WIMLIB_CASE_PLATFORM_DEFAULT);
214 return WIMLIB_ERR_PATH_DOES_NOT_EXIST;
215 return do_iterate_dir_tree(wim, dentry, ctx->flags, ctx->cb, ctx->user_ctx);
218 /* API function documented in wimlib.h */
220 wimlib_iterate_dir_tree(WIMStruct *wim, int image, const tchar *_path,
222 wimlib_iterate_dir_tree_callback_t cb, void *user_ctx)
227 if (flags & ~(WIMLIB_ITERATE_DIR_TREE_FLAG_RECURSIVE |
228 WIMLIB_ITERATE_DIR_TREE_FLAG_CHILDREN |
229 WIMLIB_ITERATE_DIR_TREE_FLAG_RESOURCES_NEEDED))
230 return WIMLIB_ERR_INVALID_PARAM;
232 path = canonicalize_wim_path(_path);
234 return WIMLIB_ERR_NOMEM;
235 struct image_iterate_dir_tree_ctx ctx = {
239 .user_ctx = user_ctx,
242 ret = for_image(wim, image, image_do_iterate_dir_tree);