]> wimlib.net Git - wimlib/blob - src/dentry.c
0a898ff73943e3327b3f3b604c96630080fe9cad
[wimlib] / src / dentry.c
1 /*
2  * dentry.c
3  *
4  * In the WIM file format, the dentries are stored in the "metadata resource"
5  * section right after the security data.  Each image in the WIM file has its
6  * own metadata resource with its own security data and dentry tree.  Dentries
7  * in different images may share file resources by referring to the same lookup
8  * table entries.
9  */
10
11 /*
12  * Copyright (C) 2012, 2013 Eric Biggers
13  *
14  * This file is part of wimlib, a library for working with WIM files.
15  *
16  * wimlib is free software; you can redistribute it and/or modify it under the
17  * terms of the GNU General Public License as published by the Free Software
18  * Foundation; either version 3 of the License, or (at your option) any later
19  * version.
20  *
21  * wimlib is distributed in the hope that it will be useful, but WITHOUT ANY
22  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
23  * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
24  *
25  * You should have received a copy of the GNU General Public License along with
26  * wimlib; if not, see http://www.gnu.org/licenses/.
27  */
28
29 #ifdef HAVE_CONFIG_H
30 #  include "config.h"
31 #endif
32
33 #include "wimlib.h"
34 #include "wimlib/case.h"
35 #include "wimlib/dentry.h"
36 #include "wimlib/encoding.h"
37 #include "wimlib/endianness.h"
38 #include "wimlib/error.h"
39 #include "wimlib/lookup_table.h"
40 #include "wimlib/metadata.h"
41 #include "wimlib/paths.h"
42 #include "wimlib/resource.h"
43 #include "wimlib/security.h"
44 #include "wimlib/sha1.h"
45 #include "wimlib/timestamp.h"
46
47 #include <errno.h>
48
49 /* On-disk format of a WIM dentry (directory entry), located in the metadata
50  * resource for a WIM image.  */
51 struct wim_dentry_on_disk {
52
53         /* Length of this directory entry in bytes, not including any alternate
54          * data stream entries.  Should be a multiple of 8 so that the following
55          * dentry or alternate data stream entry is aligned on an 8-byte
56          * boundary.  (If not, wimlib will round it up.)  It must be at least as
57          * long as the fixed-length fields of the dentry (WIM_DENTRY_DISK_SIZE),
58          * plus the lengths of the file name and/or short name if present.
59          *
60          * It is also possible for this field to be 0.  This situation, which is
61          * undocumented, indicates the end of a list of sibling nodes in a
62          * directory.  It also means the real length is 8, because the dentry
63          * included only the length field, but that takes up 8 bytes.  */
64         le64 length;
65
66         /* Attributes of the file or directory.  This is a bitwise OR of the
67          * FILE_ATTRIBUTE_* constants and should correspond to the value
68          * retrieved by GetFileAttributes() on Windows. */
69         le32 attributes;
70
71         /* A value that specifies the security descriptor for this file or
72          * directory.  If -1, the file or directory has no security descriptor.
73          * Otherwise, it is a 0-based index into the WIM image's table of
74          * security descriptors (see: `struct wim_security_data') */
75         sle32 security_id;
76
77         /* Offset, in bytes, from the start of the uncompressed metadata
78          * resource of this directory's child directory entries, or 0 if this
79          * directory entry does not correspond to a directory or otherwise does
80          * not have any children. */
81         le64 subdir_offset;
82
83         /* Reserved fields */
84         le64 unused_1;
85         le64 unused_2;
86
87
88         /* Creation time, last access time, and last write time, in
89          * 100-nanosecond intervals since 12:00 a.m UTC January 1, 1601.  They
90          * should correspond to the times gotten by calling GetFileTime() on
91          * Windows. */
92         le64 creation_time;
93         le64 last_access_time;
94         le64 last_write_time;
95
96         /* Vaguely, the SHA-1 message digest ("hash") of the file's contents.
97          * More specifically, this is for the "unnamed data stream" rather than
98          * any "alternate data streams".  This hash value is used to look up the
99          * corresponding entry in the WIM's stream lookup table to actually find
100          * the file contents within the WIM.
101          *
102          * If the file has no unnamed data stream (e.g. is a directory), then
103          * this field will be all zeroes.  If the unnamed data stream is empty
104          * (i.e. an "empty file"), then this field is also expected to be all
105          * zeroes.  (It will be if wimlib created the WIM image, at least;
106          * otherwise it can't be ruled out that the SHA-1 message digest of 0
107          * bytes of data is given explicitly.)
108          *
109          * If the file has reparse data, then this field will instead specify
110          * the SHA-1 message digest of the reparse data.  If it is somehow
111          * possible for a file to have both an unnamed data stream and reparse
112          * data, then this is not handled by wimlib.
113          *
114          * As a further special case, if this field is all zeroes but there is
115          * an alternate data stream entry with no name and a nonzero SHA-1
116          * message digest field, then that hash must be used instead of this
117          * one.  In fact, when named data streams are present, some versions of
118          * Windows PE contain a bug where they only look in the alternate data
119          * stream entries for the unnamed data stream, not here.
120          */
121         u8 unnamed_stream_hash[SHA1_HASH_SIZE];
122
123         /* The format of the following data is not yet completely known and they
124          * do not correspond to Microsoft's documentation.
125          *
126          * If this directory entry is for a reparse point (has
127          * FILE_ATTRIBUTE_REPARSE_POINT set in the attributes field), then the
128          * version of the following fields containing the reparse tag is valid.
129          * Furthermore, the field notated as not_rpfixed, as far as I can tell,
130          * is supposed to be set to 1 if reparse point fixups (a.k.a. fixing the
131          * targets of absolute symbolic links) were *not* done, and otherwise 0.
132          *
133          * If this directory entry is not for a reparse point, then the version
134          * of the following fields containing the hard_link_group_id is valid.
135          * All MS says about this field is that "If this file is part of a hard
136          * link set, all the directory entries in the set will share the same
137          * value in this field.".  However, more specifically I have observed
138          * the following:
139          *    - If the file is part of a hard link set of size 1, then the
140          *    hard_link_group_id should be set to either 0, which is treated
141          *    specially as indicating "not hardlinked", or any unique value.
142          *    - The specific nonzero values used to identity hard link sets do
143          *    not matter, as long as they are unique.
144          *    - However, due to bugs in Microsoft's software, it is actually NOT
145          *    guaranteed that directory entries that share the same hard link
146          *    group ID are actually hard linked to each either.  We have to
147          *    handle this by using special code to use distinguishing features
148          *    (which is possible because some information about the underlying
149          *    inode is repeated in each dentry) to split up these fake hard link
150          *    groups into what they actually are supposed to be.
151          */
152         union {
153                 struct {
154                         le32 rp_unknown_1;
155                         le32 reparse_tag;
156                         le16 rp_unknown_2;
157                         le16 not_rpfixed;
158                 } _packed_attribute reparse;
159                 struct {
160                         le32 rp_unknown_1;
161                         le64 hard_link_group_id;
162                 } _packed_attribute nonreparse;
163         };
164
165         /* Number of alternate data stream entries that directly follow this
166          * dentry on-disk. */
167         le16 num_alternate_data_streams;
168
169         /* Length of this file's UTF-16LE encoded short name (8.3 DOS-compatible
170          * name), if present, in bytes, excluding the null terminator.  If this
171          * file has no short name, then this field should be 0.  */
172         le16 short_name_nbytes;
173
174         /* Length of this file's UTF-16LE encoded "long" name, excluding the
175          * null terminator.  If this file has no short name, then this field
176          * should be 0.  It's expected that only the root dentry has this field
177          * set to 0.  */
178         le16 file_name_nbytes;
179
180         /* Followed by variable length file name, in UTF16-LE, if
181          * file_name_nbytes != 0.  Includes null terminator. */
182         /*utf16lechar file_name[];*/
183
184         /* Followed by variable length short name, in UTF16-LE, if
185          * short_name_nbytes != 0.  Includes null terminator. */
186         /*utf16lechar short_name[];*/
187 } _packed_attribute;
188
189 /* Calculates the unaligned length, in bytes, of an on-disk WIM dentry that has
190  * a file name and short name that take the specified numbers of bytes.  This
191  * excludes any alternate data stream entries that may follow the dentry. */
192 static u64
193 dentry_correct_length_unaligned(u16 file_name_nbytes, u16 short_name_nbytes)
194 {
195         u64 length = sizeof(struct wim_dentry_on_disk);
196         if (file_name_nbytes)
197                 length += file_name_nbytes + 2;
198         if (short_name_nbytes)
199                 length += short_name_nbytes + 2;
200         return length;
201 }
202
203 /* Calculates the unaligned length, in bytes, of an on-disk WIM dentry, based on
204  * the file name length and short name length.  Note that dentry->length is
205  * ignored; also, this excludes any alternate data stream entries that may
206  * follow the dentry. */
207 static u64
208 dentry_correct_length_aligned(const struct wim_dentry *dentry)
209 {
210         u64 len;
211
212         len = dentry_correct_length_unaligned(dentry->file_name_nbytes,
213                                               dentry->short_name_nbytes);
214         return (len + 7) & ~7;
215 }
216
217 /* Sets the name of a WIM dentry from a multibyte string.
218  * Only use this on dentries not inserted into the tree.  Use rename_wim_path()
219  * to do a real rename.  */
220 int
221 dentry_set_name(struct wim_dentry *dentry, const tchar *new_name)
222 {
223         int ret;
224         ret = get_utf16le_string(new_name, &dentry->file_name,
225                                  &dentry->file_name_nbytes);
226         if (ret == 0) {
227                 /* Clear the short name and recalculate the dentry length */
228                 if (dentry_has_short_name(dentry)) {
229                         FREE(dentry->short_name);
230                         dentry->short_name = NULL;
231                         dentry->short_name_nbytes = 0;
232                 }
233         }
234         return ret;
235 }
236
237 /* Returns the total length of a WIM alternate data stream entry on-disk,
238  * including the stream name, the null terminator, AND the padding after the
239  * entry to align the next ADS entry or dentry on an 8-byte boundary. */
240 static u64
241 ads_entry_total_length(const struct wim_ads_entry *entry)
242 {
243         u64 len = sizeof(struct wim_ads_entry_on_disk);
244         if (entry->stream_name_nbytes)
245                 len += entry->stream_name_nbytes + 2;
246         return (len + 7) & ~7;
247 }
248
249 /*
250  * Determine whether to include a "dummy" stream when writing a WIM dentry:
251  *
252  * Some versions of Microsoft's WIM software (the boot driver(s) in WinPE 3.0,
253  * for example) contain a bug where they assume the first alternate data stream
254  * (ADS) entry of a dentry with a nonzero ADS count specifies the unnamed
255  * stream, even if it has a name and the unnamed stream is already specified in
256  * the hash field of the dentry itself.
257  *
258  * wimlib has to work around this behavior by carefully emulating the behavior
259  * of (most versions of) ImageX/WIMGAPI, which move the unnamed stream reference
260  * into the alternate stream entries whenever there are named data streams, even
261  * though there is already a field in the dentry itself for the unnamed stream
262  * reference, which then goes to waste.
263  */
264 static inline bool
265 inode_needs_dummy_stream(const struct wim_inode *inode)
266 {
267         return (inode->i_num_ads > 0 &&
268                 inode->i_num_ads < 0xffff && /* overflow check */
269                 inode->i_canonical_streams); /* assume the dentry is okay if it
270                                                 already had an unnamed ADS entry
271                                                 when it was read in  */
272 }
273
274 /* Calculate the total number of bytes that will be consumed when a WIM dentry
275  * is written.  This includes base dentry and name fields as well as all
276  * alternate data stream entries and alignment bytes.  */
277 u64
278 dentry_out_total_length(const struct wim_dentry *dentry)
279 {
280         u64 length = dentry_correct_length_aligned(dentry);
281         const struct wim_inode *inode = dentry->d_inode;
282
283         if (inode_needs_dummy_stream(inode))
284                 length += ads_entry_total_length(&(struct wim_ads_entry){});
285
286         for (u16 i = 0; i < inode->i_num_ads; i++)
287                 length += ads_entry_total_length(&inode->i_ads_entries[i]);
288
289         return length;
290 }
291
292 /* Calculate the aligned, total length of a dentry, including all alternate data
293  * stream entries.  Uses dentry->length.  */
294 static u64
295 dentry_in_total_length(const struct wim_dentry *dentry)
296 {
297         u64 length = dentry->length;
298         const struct wim_inode *inode = dentry->d_inode;
299         for (u16 i = 0; i < inode->i_num_ads; i++)
300                 length += ads_entry_total_length(&inode->i_ads_entries[i]);
301         return (length + 7) & ~7;
302 }
303
304 int
305 for_dentry_in_rbtree(struct rb_node *root,
306                      int (*visitor)(struct wim_dentry *, void *),
307                      void *arg)
308 {
309         int ret;
310         struct rb_node *node = root;
311         LIST_HEAD(stack);
312         while (1) {
313                 if (node) {
314                         list_add(&rbnode_dentry(node)->tmp_list, &stack);
315                         node = node->rb_left;
316                 } else {
317                         struct list_head *next;
318                         struct wim_dentry *dentry;
319
320                         next = stack.next;
321                         if (next == &stack)
322                                 return 0;
323                         dentry = container_of(next, struct wim_dentry, tmp_list);
324                         list_del(next);
325                         ret = visitor(dentry, arg);
326                         if (ret != 0)
327                                 return ret;
328                         node = dentry->rb_node.rb_right;
329                 }
330         }
331 }
332
333 static int
334 for_dentry_tree_in_rbtree_depth(struct rb_node *node,
335                                 int (*visitor)(struct wim_dentry*, void*),
336                                 void *arg)
337 {
338         int ret;
339         if (node) {
340                 ret = for_dentry_tree_in_rbtree_depth(node->rb_left,
341                                                       visitor, arg);
342                 if (ret != 0)
343                         return ret;
344                 ret = for_dentry_tree_in_rbtree_depth(node->rb_right,
345                                                       visitor, arg);
346                 if (ret != 0)
347                         return ret;
348                 ret = for_dentry_in_tree_depth(rbnode_dentry(node), visitor, arg);
349                 if (ret != 0)
350                         return ret;
351         }
352         return 0;
353 }
354
355 static int
356 for_dentry_tree_in_rbtree(struct rb_node *node,
357                           int (*visitor)(struct wim_dentry*, void*),
358                           void *arg)
359 {
360         int ret;
361         if (node) {
362                 ret = for_dentry_tree_in_rbtree(node->rb_left, visitor, arg);
363                 if (ret)
364                         return ret;
365                 ret = for_dentry_in_tree(rbnode_dentry(node), visitor, arg);
366                 if (ret)
367                         return ret;
368                 ret = for_dentry_tree_in_rbtree(node->rb_right, visitor, arg);
369                 if (ret)
370                         return ret;
371         }
372         return 0;
373 }
374
375 /*
376  * Iterate over all children of @dentry, calling the function @visitor, passing
377  * it a child dentry and the extra argument @arg.
378  *
379  * Note: this function iterates over ALL child dentries, even those with the
380  * same case-insensitive name.
381  *
382  * Note: this function clobbers the tmp_list field of the child dentries.  */
383 int
384 for_dentry_child(const struct wim_dentry *dentry,
385                  int (*visitor)(struct wim_dentry *, void *),
386                  void *arg)
387 {
388         return for_dentry_in_rbtree(dentry->d_inode->i_children.rb_node,
389                                     visitor,
390                                     arg);
391 }
392
393 /* Calls a function on all directory entries in a WIM dentry tree.  Logically,
394  * this is a pre-order traversal (the function is called on a parent dentry
395  * before its children), but sibling dentries will be visited in order as well.
396  * */
397 int
398 for_dentry_in_tree(struct wim_dentry *root,
399                    int (*visitor)(struct wim_dentry*, void*), void *arg)
400 {
401         int ret;
402
403         if (root == NULL)
404                 return 0;
405         ret = (*visitor)(root, arg);
406         if (ret)
407                 return ret;
408         return for_dentry_tree_in_rbtree(root->d_inode->i_children.rb_node,
409                                          visitor,
410                                          arg);
411 }
412
413 /* Like for_dentry_in_tree(), but the visitor function is always called on a
414  * dentry's children before on itself. */
415 int
416 for_dentry_in_tree_depth(struct wim_dentry *root,
417                          int (*visitor)(struct wim_dentry*, void*), void *arg)
418 {
419         int ret;
420
421         if (root == NULL)
422                 return 0;
423         ret = for_dentry_tree_in_rbtree_depth(root->d_inode->i_children.rb_node,
424                                               visitor, arg);
425         if (ret)
426                 return ret;
427         return (*visitor)(root, arg);
428 }
429
430 /* Calculate the full path of @dentry.  The full path of its parent must have
431  * already been calculated, or it must be the root dentry. */
432 int
433 calculate_dentry_full_path(struct wim_dentry *dentry)
434 {
435         tchar *full_path;
436         u32 full_path_nbytes;
437         int ret;
438
439         if (dentry->_full_path)
440                 return 0;
441
442         if (dentry_is_root(dentry)) {
443                 static const tchar _root_path[] = {WIM_PATH_SEPARATOR, T('\0')};
444                 full_path = TSTRDUP(_root_path);
445                 if (full_path == NULL)
446                         return WIMLIB_ERR_NOMEM;
447                 full_path_nbytes = 1 * sizeof(tchar);
448         } else {
449                 struct wim_dentry *parent;
450                 tchar *parent_full_path;
451                 u32 parent_full_path_nbytes;
452                 size_t filename_nbytes;
453
454                 parent = dentry->parent;
455                 if (dentry_is_root(parent)) {
456                         parent_full_path = T("");
457                         parent_full_path_nbytes = 0;
458                 } else {
459                         if (parent->_full_path == NULL) {
460                                 ret = calculate_dentry_full_path(parent);
461                                 if (ret)
462                                         return ret;
463                         }
464                         parent_full_path = parent->_full_path;
465                         parent_full_path_nbytes = parent->full_path_nbytes;
466                 }
467
468                 /* Append this dentry's name as a tchar string to the full path
469                  * of the parent followed by the path separator */
470         #if TCHAR_IS_UTF16LE
471                 filename_nbytes = dentry->file_name_nbytes;
472         #else
473                 {
474                         int ret = utf16le_to_tstr_nbytes(dentry->file_name,
475                                                          dentry->file_name_nbytes,
476                                                          &filename_nbytes);
477                         if (ret)
478                                 return ret;
479                 }
480         #endif
481
482                 full_path_nbytes = parent_full_path_nbytes + sizeof(tchar) +
483                                    filename_nbytes;
484                 full_path = MALLOC(full_path_nbytes + sizeof(tchar));
485                 if (full_path == NULL)
486                         return WIMLIB_ERR_NOMEM;
487                 memcpy(full_path, parent_full_path, parent_full_path_nbytes);
488                 full_path[parent_full_path_nbytes / sizeof(tchar)] = WIM_PATH_SEPARATOR;
489         #if TCHAR_IS_UTF16LE
490                 memcpy(&full_path[parent_full_path_nbytes / sizeof(tchar) + 1],
491                        dentry->file_name,
492                        filename_nbytes + sizeof(tchar));
493         #else
494                 utf16le_to_tstr_buf(dentry->file_name,
495                                     dentry->file_name_nbytes,
496                                     &full_path[parent_full_path_nbytes /
497                                                sizeof(tchar) + 1]);
498         #endif
499         }
500         dentry->_full_path = full_path;
501         dentry->full_path_nbytes= full_path_nbytes;
502         return 0;
503 }
504
505 static int
506 do_calculate_dentry_full_path(struct wim_dentry *dentry, void *_ignore)
507 {
508         return calculate_dentry_full_path(dentry);
509 }
510
511 int
512 calculate_dentry_tree_full_paths(struct wim_dentry *root)
513 {
514         return for_dentry_in_tree(root, do_calculate_dentry_full_path, NULL);
515 }
516
517 tchar *
518 dentry_full_path(struct wim_dentry *dentry)
519 {
520         calculate_dentry_full_path(dentry);
521         return dentry->_full_path;
522 }
523
524 static int
525 increment_subdir_offset(struct wim_dentry *dentry, void *subdir_offset_p)
526 {
527         *(u64*)subdir_offset_p += dentry_out_total_length(dentry);
528         return 0;
529 }
530
531 static int
532 call_calculate_subdir_offsets(struct wim_dentry *dentry, void *subdir_offset_p)
533 {
534         calculate_subdir_offsets(dentry, subdir_offset_p);
535         return 0;
536 }
537
538 /*
539  * Recursively calculates the subdir offsets for a directory tree.
540  *
541  * @dentry:  The root of the directory tree.
542  * @subdir_offset_p:  The current subdirectory offset; i.e., the subdirectory
543  *                    offset for @dentry.
544  */
545 void
546 calculate_subdir_offsets(struct wim_dentry *dentry, u64 *subdir_offset_p)
547 {
548         struct rb_node *node;
549
550         dentry->subdir_offset = *subdir_offset_p;
551         node = dentry->d_inode->i_children.rb_node;
552         if (node) {
553                 /* Advance the subdir offset by the amount of space the children
554                  * of this dentry take up. */
555                 for_dentry_in_rbtree(node, increment_subdir_offset, subdir_offset_p);
556
557                 /* End-of-directory dentry on disk. */
558                 *subdir_offset_p += 8;
559
560                 /* Recursively call calculate_subdir_offsets() on all the
561                  * children. */
562                 for_dentry_in_rbtree(node, call_calculate_subdir_offsets, subdir_offset_p);
563         } else {
564                 /* On disk, childless directories have a valid subdir_offset
565                  * that points to an 8-byte end-of-directory dentry.  Regular
566                  * files or reparse points have a subdir_offset of 0. */
567                 if (dentry_is_directory(dentry))
568                         *subdir_offset_p += 8;
569                 else
570                         dentry->subdir_offset = 0;
571         }
572 }
573
574 static int
575 dentry_compare_names_case_insensitive(const struct wim_dentry *d1,
576                                       const struct wim_dentry *d2)
577 {
578         return cmp_utf16le_strings(d1->file_name,
579                                    d1->file_name_nbytes / 2,
580                                    d2->file_name,
581                                    d2->file_name_nbytes / 2,
582                                    true);
583 }
584
585 static int
586 dentry_compare_names_case_sensitive(const struct wim_dentry *d1,
587                                     const struct wim_dentry *d2)
588 {
589         return cmp_utf16le_strings(d1->file_name,
590                                    d1->file_name_nbytes / 2,
591                                    d2->file_name,
592                                    d2->file_name_nbytes / 2,
593                                    false);
594 }
595
596 /* Default case sensitivity behavior for searches with
597  * WIMLIB_CASE_PLATFORM_DEFAULT specified.  This can be modified by
598  * wimlib_global_init().  */
599 bool default_ignore_case =
600 #ifdef __WIN32__
601         true
602 #else
603         false
604 #endif
605 ;
606
607 /* Given a UTF-16LE filename and a directory, look up the dentry for the file.
608  * Return it if found, otherwise NULL.  This is case-sensitive on UNIX and
609  * case-insensitive on Windows. */
610 struct wim_dentry *
611 get_dentry_child_with_utf16le_name(const struct wim_dentry *dentry,
612                                    const utf16lechar *name,
613                                    size_t name_nbytes,
614                                    CASE_SENSITIVITY_TYPE case_ctype)
615 {
616         struct rb_node *node;
617
618         bool ignore_case = will_ignore_case(case_ctype);
619
620         if (ignore_case)
621                 node = dentry->d_inode->i_children_case_insensitive.rb_node;
622         else
623                 node = dentry->d_inode->i_children.rb_node;
624
625         struct wim_dentry *child;
626         while (node) {
627                 if (ignore_case)
628                         child = rb_entry(node, struct wim_dentry, rb_node_case_insensitive);
629                 else
630                         child = rb_entry(node, struct wim_dentry, rb_node);
631
632                 int result = cmp_utf16le_strings(name,
633                                                  name_nbytes / 2,
634                                                  child->file_name,
635                                                  child->file_name_nbytes / 2,
636                                                  ignore_case);
637                 if (result < 0) {
638                         node = node->rb_left;
639                 } else if (result > 0) {
640                         node = node->rb_right;
641                 } else if (!ignore_case ||
642                         list_empty(&child->case_insensitive_conflict_list)) {
643                         return child;
644                 } else {
645                         /* Multiple dentries have the same case-insensitive
646                          * name, and a case-insensitive lookup is being
647                          * performed.  Choose the dentry with the same
648                          * case-sensitive name, if one exists; otherwise print a
649                          * warning and choose one arbitrarily.  */
650                         struct wim_dentry *alt = child;
651                         size_t num_alts = 0;
652
653                         do {
654                                 num_alts++;
655                                 if (0 == cmp_utf16le_strings(name,
656                                                              name_nbytes / 2,
657                                                              alt->file_name,
658                                                              alt->file_name_nbytes / 2,
659                                                              false))
660                                         return alt;
661                                 alt = list_entry(alt->case_insensitive_conflict_list.next,
662                                                  struct wim_dentry,
663                                                  case_insensitive_conflict_list);
664                         } while (alt != child);
665
666                         WARNING("Result of case-insensitive lookup is ambiguous\n"
667                                 "          (returning \"%"TS"\" of %zu "
668                                 "possible files, including \"%"TS"\")",
669                                 dentry_full_path(child),
670                                 num_alts,
671                                 dentry_full_path(list_entry(child->case_insensitive_conflict_list.next,
672                                                             struct wim_dentry,
673                                                             case_insensitive_conflict_list)));
674                         return child;
675                 }
676         }
677         return NULL;
678 }
679
680 /* Returns the child of @dentry that has the file name @name.  Returns NULL if
681  * no child has the name. */
682 struct wim_dentry *
683 get_dentry_child_with_name(const struct wim_dentry *dentry, const tchar *name,
684                            CASE_SENSITIVITY_TYPE case_type)
685 {
686 #if TCHAR_IS_UTF16LE
687         return get_dentry_child_with_utf16le_name(dentry, name,
688                                                   tstrlen(name) * sizeof(tchar),
689                                                   case_type);
690 #else
691         utf16lechar *utf16le_name;
692         size_t utf16le_name_nbytes;
693         int ret;
694         struct wim_dentry *child;
695
696         ret = tstr_to_utf16le(name, tstrlen(name) * sizeof(tchar),
697                               &utf16le_name, &utf16le_name_nbytes);
698         if (ret) {
699                 child = NULL;
700         } else {
701                 child = get_dentry_child_with_utf16le_name(dentry,
702                                                            utf16le_name,
703                                                            utf16le_name_nbytes,
704                                                            case_type);
705                 FREE(utf16le_name);
706         }
707         return child;
708 #endif
709 }
710
711 static struct wim_dentry *
712 get_dentry_utf16le(WIMStruct *wim, const utf16lechar *path,
713                    CASE_SENSITIVITY_TYPE case_type)
714 {
715         struct wim_dentry *cur_dentry;
716         const utf16lechar *name_start, *name_end;
717
718         /* Start with the root directory of the image.  Note: this will be NULL
719          * if an image has been added directly with wimlib_add_empty_image() but
720          * no files have been added yet; in that case we fail with ENOENT.  */
721         cur_dentry = wim_root_dentry(wim);
722
723         name_start = path;
724         for (;;) {
725                 if (cur_dentry == NULL) {
726                         errno = ENOENT;
727                         return NULL;
728                 }
729
730                 if (*name_start && !dentry_is_directory(cur_dentry)) {
731                         errno = ENOTDIR;
732                         return NULL;
733                 }
734
735                 while (*name_start == cpu_to_le16(WIM_PATH_SEPARATOR))
736                         name_start++;
737
738                 if (!*name_start)
739                         return cur_dentry;
740
741                 name_end = name_start;
742                 do {
743                         ++name_end;
744                 } while (*name_end != cpu_to_le16(WIM_PATH_SEPARATOR) && *name_end);
745
746                 cur_dentry = get_dentry_child_with_utf16le_name(cur_dentry,
747                                                                 name_start,
748                                                                 (u8*)name_end - (u8*)name_start,
749                                                                 case_type);
750                 name_start = name_end;
751         }
752 }
753
754 /*
755  * WIM path lookup: translate a path in the currently selected WIM image to the
756  * corresponding dentry, if it exists.
757  *
758  * @wim
759  *      The WIMStruct for the WIM.  The search takes place in the currently
760  *      selected image.
761  *
762  * @path
763  *      The path to look up, given relative to the root of the WIM image.
764  *      Characters with value WIM_PATH_SEPARATOR are taken to be path
765  *      separators.  Leading path separators are ignored, whereas one or more
766  *      trailing path separators cause the path to only match a directory.
767  *
768  * @case_type
769  *      The case-sensitivity behavior of this function, as one of the following
770  *      constants:
771  *
772  *    - WIMLIB_CASE_SENSITIVE:  Perform the search case sensitively.  This means
773  *      that names must match exactly.
774  *
775  *    - WIMLIB_CASE_INSENSITIVE:  Perform the search case insensitively.  This
776  *      means that names are considered to match if they are equal when
777  *      transformed to upper case.  If a path component matches multiple names
778  *      case-insensitively, the name that matches the path component
779  *      case-sensitively is chosen, if existent; otherwise one
780  *      case-insensitively matching name is chosen arbitrarily.
781  *
782  *    - WIMLIB_CASE_PLATFORM_DEFAULT:  Perform either case-sensitive or
783  *      case-insensitive search, depending on the value of the global variable
784  *      default_ignore_case.
785  *
786  *    In any case, no Unicode normalization is done before comparing strings.
787  *
788  * Returns a pointer to the dentry that is the result of the lookup, or NULL if
789  * no such dentry exists.  If NULL is returned, errno is set to one of the
790  * following values:
791  *
792  *      ENOTDIR if one of the path components used as a directory existed but
793  *      was not, in fact, a directory.
794  *
795  *      ENOENT otherwise.
796  *
797  * Additional notes:
798  *
799  *    - This function does not consider a reparse point to be a directory, even
800  *      if it has FILE_ATTRIBUTE_DIRECTORY set.
801  *
802  *    - This function does not dereference symbolic links or junction points
803  *      when performing the search.
804  *
805  *    - Since this function ignores leading slashes, the empty path is valid and
806  *      names the root directory of the WIM image.
807  *
808  *    - An image added with wimlib_add_empty_image() does not have a root
809  *      directory yet, and this function will fail with ENOENT for any path on
810  *      such an image.
811  */
812 struct wim_dentry *
813 get_dentry(WIMStruct *wim, const tchar *path, CASE_SENSITIVITY_TYPE case_type)
814 {
815 #if TCHAR_IS_UTF16LE
816         return get_dentry_utf16le(wim, path, case_type);
817 #else
818         utf16lechar *path_utf16le;
819         size_t path_utf16le_nbytes;
820         int ret;
821         struct wim_dentry *dentry;
822
823         ret = tstr_to_utf16le(path, tstrlen(path) * sizeof(tchar),
824                               &path_utf16le, &path_utf16le_nbytes);
825         if (ret)
826                 return NULL;
827         dentry = get_dentry_utf16le(wim, path_utf16le, case_type);
828         FREE(path_utf16le);
829         return dentry;
830 #endif
831 }
832
833 /* Takes in a path of length @len in @buf, and transforms it into a string for
834  * the path of its parent directory. */
835 static void
836 to_parent_name(tchar *buf, size_t len)
837 {
838         ssize_t i = (ssize_t)len - 1;
839         while (i >= 0 && buf[i] == WIM_PATH_SEPARATOR)
840                 i--;
841         while (i >= 0 && buf[i] != WIM_PATH_SEPARATOR)
842                 i--;
843         while (i >= 0 && buf[i] == WIM_PATH_SEPARATOR)
844                 i--;
845         buf[i + 1] = T('\0');
846 }
847
848 /* Similar to get_dentry(), but returns the dentry named by @path with the last
849  * component stripped off.
850  *
851  * Note: The returned dentry is NOT guaranteed to be a directory.  */
852 struct wim_dentry *
853 get_parent_dentry(WIMStruct *wim, const tchar *path,
854                   CASE_SENSITIVITY_TYPE case_type)
855 {
856         size_t path_len = tstrlen(path);
857         tchar buf[path_len + 1];
858
859         tmemcpy(buf, path, path_len + 1);
860         to_parent_name(buf, path_len);
861         return get_dentry(wim, buf, case_type);
862 }
863
864 #ifdef WITH_FUSE
865 /* Finds the dentry, lookup table entry, and stream index for a WIM file stream,
866  * given a path name.
867  *
868  * Currently, lookups of this type are only needed if FUSE is enabled.  */
869 int
870 wim_pathname_to_stream(WIMStruct *wim,
871                        const tchar *path,
872                        int lookup_flags,
873                        struct wim_dentry **dentry_ret,
874                        struct wim_lookup_table_entry **lte_ret,
875                        u16 *stream_idx_ret)
876 {
877         struct wim_dentry *dentry;
878         struct wim_lookup_table_entry *lte;
879         u16 stream_idx;
880         const tchar *stream_name = NULL;
881         struct wim_inode *inode;
882         tchar *p = NULL;
883
884         if (lookup_flags & LOOKUP_FLAG_ADS_OK) {
885                 stream_name = path_stream_name(path);
886                 if (stream_name) {
887                         p = (tchar*)stream_name - 1;
888                         *p = T('\0');
889                 }
890         }
891
892         dentry = get_dentry(wim, path, WIMLIB_CASE_SENSITIVE);
893         if (p)
894                 *p = T(':');
895         if (!dentry)
896                 return -errno;
897
898         inode = dentry->d_inode;
899
900         if (!inode->i_resolved)
901                 if (inode_resolve_streams(inode, wim->lookup_table, false))
902                         return -EIO;
903
904         if (!(lookup_flags & LOOKUP_FLAG_DIRECTORY_OK)
905               && inode_is_directory(inode))
906                 return -EISDIR;
907
908         if (stream_name) {
909                 struct wim_ads_entry *ads_entry;
910                 u16 ads_idx;
911                 ads_entry = inode_get_ads_entry(inode, stream_name,
912                                                 &ads_idx);
913                 if (ads_entry) {
914                         stream_idx = ads_idx + 1;
915                         lte = ads_entry->lte;
916                         goto out;
917                 } else {
918                         return -ENOENT;
919                 }
920         } else {
921                 lte = inode_unnamed_stream_resolved(inode, &stream_idx);
922         }
923 out:
924         if (dentry_ret)
925                 *dentry_ret = dentry;
926         if (lte_ret)
927                 *lte_ret = lte;
928         if (stream_idx_ret)
929                 *stream_idx_ret = stream_idx;
930         return 0;
931 }
932 #endif /* WITH_FUSE  */
933
934 /* Prints the full path of a dentry. */
935 int
936 print_dentry_full_path(struct wim_dentry *dentry, void *_ignore)
937 {
938         int ret = calculate_dentry_full_path(dentry);
939         if (ret)
940                 return ret;
941         tprintf(T("%"TS"\n"), dentry->_full_path);
942         return 0;
943 }
944
945 /* We want to be able to show the names of the file attribute flags that are
946  * set. */
947 struct file_attr_flag {
948         u32 flag;
949         const tchar *name;
950 };
951 struct file_attr_flag file_attr_flags[] = {
952         {FILE_ATTRIBUTE_READONLY,           T("READONLY")},
953         {FILE_ATTRIBUTE_HIDDEN,             T("HIDDEN")},
954         {FILE_ATTRIBUTE_SYSTEM,             T("SYSTEM")},
955         {FILE_ATTRIBUTE_DIRECTORY,          T("DIRECTORY")},
956         {FILE_ATTRIBUTE_ARCHIVE,            T("ARCHIVE")},
957         {FILE_ATTRIBUTE_DEVICE,             T("DEVICE")},
958         {FILE_ATTRIBUTE_NORMAL,             T("NORMAL")},
959         {FILE_ATTRIBUTE_TEMPORARY,          T("TEMPORARY")},
960         {FILE_ATTRIBUTE_SPARSE_FILE,        T("SPARSE_FILE")},
961         {FILE_ATTRIBUTE_REPARSE_POINT,      T("REPARSE_POINT")},
962         {FILE_ATTRIBUTE_COMPRESSED,         T("COMPRESSED")},
963         {FILE_ATTRIBUTE_OFFLINE,            T("OFFLINE")},
964         {FILE_ATTRIBUTE_NOT_CONTENT_INDEXED,T("NOT_CONTENT_INDEXED")},
965         {FILE_ATTRIBUTE_ENCRYPTED,          T("ENCRYPTED")},
966         {FILE_ATTRIBUTE_VIRTUAL,            T("VIRTUAL")},
967 };
968
969 /* Prints a directory entry.  @lookup_table is a pointer to the lookup table, if
970  * available.  If the dentry is unresolved and the lookup table is NULL, the
971  * lookup table entries will not be printed.  Otherwise, they will be. */
972 int
973 print_dentry(struct wim_dentry *dentry, void *lookup_table)
974 {
975         const u8 *hash;
976         struct wim_lookup_table_entry *lte;
977         const struct wim_inode *inode = dentry->d_inode;
978         tchar buf[50];
979
980         tprintf(T("[DENTRY]\n"));
981         tprintf(T("Length            = %"PRIu64"\n"), dentry->length);
982         tprintf(T("Attributes        = 0x%x\n"), inode->i_attributes);
983         for (size_t i = 0; i < ARRAY_LEN(file_attr_flags); i++)
984                 if (file_attr_flags[i].flag & inode->i_attributes)
985                         tprintf(T("    FILE_ATTRIBUTE_%"TS" is set\n"),
986                                 file_attr_flags[i].name);
987         tprintf(T("Security ID       = %d\n"), inode->i_security_id);
988         tprintf(T("Subdir offset     = %"PRIu64"\n"), dentry->subdir_offset);
989
990         wim_timestamp_to_str(inode->i_creation_time, buf, sizeof(buf));
991         tprintf(T("Creation Time     = %"TS"\n"), buf);
992
993         wim_timestamp_to_str(inode->i_last_access_time, buf, sizeof(buf));
994         tprintf(T("Last Access Time  = %"TS"\n"), buf);
995
996         wim_timestamp_to_str(inode->i_last_write_time, buf, sizeof(buf));
997         tprintf(T("Last Write Time   = %"TS"\n"), buf);
998
999         if (inode->i_attributes & FILE_ATTRIBUTE_REPARSE_POINT) {
1000                 tprintf(T("Reparse Tag       = 0x%"PRIx32"\n"), inode->i_reparse_tag);
1001                 tprintf(T("Reparse Point Flags = 0x%"PRIx16"\n"),
1002                         inode->i_not_rpfixed);
1003                 tprintf(T("Reparse Point Unknown 2 = 0x%"PRIx32"\n"),
1004                         inode->i_rp_unknown_2);
1005         }
1006         tprintf(T("Reparse Point Unknown 1 = 0x%"PRIx32"\n"),
1007                 inode->i_rp_unknown_1);
1008         tprintf(T("Hard Link Group   = 0x%"PRIx64"\n"), inode->i_ino);
1009         tprintf(T("Hard Link Group Size = %"PRIu32"\n"), inode->i_nlink);
1010         tprintf(T("Number of Alternate Data Streams = %hu\n"), inode->i_num_ads);
1011         if (dentry_has_long_name(dentry))
1012                 wimlib_printf(T("Filename = \"%"WS"\"\n"), dentry->file_name);
1013         if (dentry_has_short_name(dentry))
1014                 wimlib_printf(T("Short Name \"%"WS"\"\n"), dentry->short_name);
1015         if (dentry->_full_path)
1016                 tprintf(T("Full Path = \"%"TS"\"\n"), dentry->_full_path);
1017
1018         lte = inode_stream_lte(dentry->d_inode, 0, lookup_table);
1019         if (lte) {
1020                 print_lookup_table_entry(lte, stdout);
1021         } else {
1022                 hash = inode_stream_hash(inode, 0);
1023                 if (hash) {
1024                         tprintf(T("Hash              = 0x"));
1025                         print_hash(hash, stdout);
1026                         tputchar(T('\n'));
1027                         tputchar(T('\n'));
1028                 }
1029         }
1030         for (u16 i = 0; i < inode->i_num_ads; i++) {
1031                 tprintf(T("[Alternate Stream Entry %u]\n"), i);
1032                 wimlib_printf(T("Name = \"%"WS"\"\n"),
1033                               inode->i_ads_entries[i].stream_name);
1034                 tprintf(T("Name Length (UTF16 bytes) = %hu\n"),
1035                        inode->i_ads_entries[i].stream_name_nbytes);
1036                 hash = inode_stream_hash(inode, i + 1);
1037                 if (hash) {
1038                         tprintf(T("Hash              = 0x"));
1039                         print_hash(hash, stdout);
1040                         tputchar(T('\n'));
1041                 }
1042                 print_lookup_table_entry(inode_stream_lte(inode, i + 1, lookup_table),
1043                                          stdout);
1044         }
1045         return 0;
1046 }
1047
1048 /* Initializations done on every `struct wim_dentry'. */
1049 static void
1050 dentry_common_init(struct wim_dentry *dentry)
1051 {
1052         memset(dentry, 0, sizeof(struct wim_dentry));
1053 }
1054
1055 /* Creates an unlinked directory entry. */
1056 int
1057 new_dentry(const tchar *name, struct wim_dentry **dentry_ret)
1058 {
1059         struct wim_dentry *dentry;
1060         int ret;
1061
1062         dentry = MALLOC(sizeof(struct wim_dentry));
1063         if (dentry == NULL)
1064                 return WIMLIB_ERR_NOMEM;
1065
1066         dentry_common_init(dentry);
1067         if (*name) {
1068                 ret = dentry_set_name(dentry, name);
1069                 if (ret) {
1070                         FREE(dentry);
1071                         ERROR("Failed to set name on new dentry with name \"%"TS"\"",
1072                               name);
1073                         return ret;
1074                 }
1075         }
1076         dentry->parent = dentry;
1077         *dentry_ret = dentry;
1078         return 0;
1079 }
1080
1081 static int
1082 _new_dentry_with_inode(const tchar *name, struct wim_dentry **dentry_ret,
1083                         bool timeless)
1084 {
1085         struct wim_dentry *dentry;
1086         int ret;
1087
1088         ret = new_dentry(name, &dentry);
1089         if (ret)
1090                 return ret;
1091
1092         if (timeless)
1093                 dentry->d_inode = new_timeless_inode();
1094         else
1095                 dentry->d_inode = new_inode();
1096         if (dentry->d_inode == NULL) {
1097                 free_dentry(dentry);
1098                 return WIMLIB_ERR_NOMEM;
1099         }
1100
1101         inode_add_dentry(dentry, dentry->d_inode);
1102         *dentry_ret = dentry;
1103         return 0;
1104 }
1105
1106 int
1107 new_dentry_with_timeless_inode(const tchar *name, struct wim_dentry **dentry_ret)
1108 {
1109         return _new_dentry_with_inode(name, dentry_ret, true);
1110 }
1111
1112 int
1113 new_dentry_with_inode(const tchar *name, struct wim_dentry **dentry_ret)
1114 {
1115         return _new_dentry_with_inode(name, dentry_ret, false);
1116 }
1117
1118 int
1119 new_filler_directory(const tchar *name, struct wim_dentry **dentry_ret)
1120 {
1121         int ret;
1122         struct wim_dentry *dentry;
1123
1124         DEBUG("Creating filler directory \"%"TS"\"", name);
1125         ret = new_dentry_with_inode(name, &dentry);
1126         if (ret)
1127                 return ret;
1128         /* Leave the inode number as 0; this is allowed for non
1129          * hard-linked files. */
1130         dentry->d_inode->i_resolved = 1;
1131         dentry->d_inode->i_attributes = FILE_ATTRIBUTE_DIRECTORY;
1132         *dentry_ret = dentry;
1133         return 0;
1134 }
1135
1136 static int
1137 dentry_clear_inode_visited(struct wim_dentry *dentry, void *_ignore)
1138 {
1139         dentry->d_inode->i_visited = 0;
1140         return 0;
1141 }
1142
1143 void
1144 dentry_tree_clear_inode_visited(struct wim_dentry *root)
1145 {
1146         for_dentry_in_tree(root, dentry_clear_inode_visited, NULL);
1147 }
1148
1149 /* Frees a WIM dentry.
1150  *
1151  * The corresponding inode (if any) is freed only if its link count is
1152  * decremented to 0.  */
1153 void
1154 free_dentry(struct wim_dentry *dentry)
1155 {
1156         if (dentry) {
1157                 FREE(dentry->file_name);
1158                 FREE(dentry->short_name);
1159                 FREE(dentry->_full_path);
1160                 if (dentry->d_inode)
1161                         put_inode(dentry->d_inode);
1162                 FREE(dentry);
1163         }
1164 }
1165
1166 /* This function is passed as an argument to for_dentry_in_tree_depth() in order
1167  * to free a directory tree. */
1168 static int
1169 do_free_dentry(struct wim_dentry *dentry, void *_lookup_table)
1170 {
1171         struct wim_lookup_table *lookup_table = _lookup_table;
1172
1173         if (lookup_table) {
1174                 struct wim_inode *inode = dentry->d_inode;
1175                 for (unsigned i = 0; i <= inode->i_num_ads; i++) {
1176                         struct wim_lookup_table_entry *lte;
1177
1178                         lte = inode_stream_lte(inode, i, lookup_table);
1179                         if (lte)
1180                                 lte_decrement_refcnt(lte, lookup_table);
1181                 }
1182         }
1183         free_dentry(dentry);
1184         return 0;
1185 }
1186
1187 /*
1188  * Unlinks and frees a dentry tree.
1189  *
1190  * @root:
1191  *      The root of the tree.
1192  *
1193  * @lookup_table:
1194  *      The lookup table for dentries.  If non-NULL, the reference counts in the
1195  *      lookup table for the lookup table entries corresponding to the dentries
1196  *      will be decremented.
1197  */
1198 void
1199 free_dentry_tree(struct wim_dentry *root, struct wim_lookup_table *lookup_table)
1200 {
1201         for_dentry_in_tree_depth(root, do_free_dentry, lookup_table);
1202 }
1203
1204 /* Insert a dentry into the case insensitive index for a directory.
1205  *
1206  * This is a red-black tree, but when multiple dentries share the same
1207  * case-insensitive name, only one is inserted into the tree itself; the rest
1208  * are connected in a list.
1209  */
1210 static struct wim_dentry *
1211 dentry_add_child_case_insensitive(struct wim_dentry *parent,
1212                                   struct wim_dentry *child)
1213 {
1214         struct rb_root *root;
1215         struct rb_node **new;
1216         struct rb_node *rb_parent;
1217
1218         root = &parent->d_inode->i_children_case_insensitive;
1219         new = &root->rb_node;
1220         rb_parent = NULL;
1221         while (*new) {
1222                 struct wim_dentry *this = container_of(*new, struct wim_dentry,
1223                                                        rb_node_case_insensitive);
1224                 int result = dentry_compare_names_case_insensitive(child, this);
1225
1226                 rb_parent = *new;
1227
1228                 if (result < 0)
1229                         new = &((*new)->rb_left);
1230                 else if (result > 0)
1231                         new = &((*new)->rb_right);
1232                 else
1233                         return this;
1234         }
1235         rb_link_node(&child->rb_node_case_insensitive, rb_parent, new);
1236         rb_insert_color(&child->rb_node_case_insensitive, root);
1237         return NULL;
1238 }
1239
1240 /*
1241  * Links a dentry into the directory tree.
1242  *
1243  * @parent: The dentry that will be the parent of @child.
1244  * @child: The dentry to link.
1245  *
1246  * Returns NULL if successful.  If @parent already contains a dentry with the
1247  * same case-sensitive name as @child, the pointer to this duplicate dentry is
1248  * returned.
1249  */
1250 struct wim_dentry *
1251 dentry_add_child(struct wim_dentry * restrict parent,
1252                  struct wim_dentry * restrict child)
1253 {
1254         struct rb_root *root;
1255         struct rb_node **new;
1256         struct rb_node *rb_parent;
1257
1258         wimlib_assert(dentry_is_directory(parent));
1259         wimlib_assert(parent != child);
1260
1261         /* Case sensitive child dentry index */
1262         root = &parent->d_inode->i_children;
1263         new = &root->rb_node;
1264         rb_parent = NULL;
1265         while (*new) {
1266                 struct wim_dentry *this = rbnode_dentry(*new);
1267                 int result = dentry_compare_names_case_sensitive(child, this);
1268
1269                 rb_parent = *new;
1270
1271                 if (result < 0)
1272                         new = &((*new)->rb_left);
1273                 else if (result > 0)
1274                         new = &((*new)->rb_right);
1275                 else
1276                         return this;
1277         }
1278         child->parent = parent;
1279         rb_link_node(&child->rb_node, rb_parent, new);
1280         rb_insert_color(&child->rb_node, root);
1281
1282         /* Case insensitive child dentry index */
1283         {
1284                 struct wim_dentry *existing;
1285                 existing = dentry_add_child_case_insensitive(parent, child);
1286                 if (existing) {
1287                         list_add(&child->case_insensitive_conflict_list,
1288                                  &existing->case_insensitive_conflict_list);
1289                         child->rb_node_case_insensitive.__rb_parent_color = 0;
1290                 } else {
1291                         INIT_LIST_HEAD(&child->case_insensitive_conflict_list);
1292                 }
1293         }
1294         return NULL;
1295 }
1296
1297 /* Unlink a WIM dentry from the directory entry tree. */
1298 void
1299 unlink_dentry(struct wim_dentry *dentry)
1300 {
1301         struct wim_dentry *parent = dentry->parent;
1302
1303         if (parent == dentry)
1304                 return;
1305         rb_erase(&dentry->rb_node, &parent->d_inode->i_children);
1306
1307         if (dentry->rb_node_case_insensitive.__rb_parent_color) {
1308                 /* This dentry was in the case-insensitive red-black tree. */
1309                 rb_erase(&dentry->rb_node_case_insensitive,
1310                          &parent->d_inode->i_children_case_insensitive);
1311                 if (!list_empty(&dentry->case_insensitive_conflict_list)) {
1312                         /* Make a different case-insensitively-the-same dentry
1313                          * be the "representative" in the red-black tree. */
1314                         struct list_head *next;
1315                         struct wim_dentry *other;
1316                         struct wim_dentry *existing;
1317
1318                         next = dentry->case_insensitive_conflict_list.next;
1319                         other = list_entry(next, struct wim_dentry, case_insensitive_conflict_list);
1320                         existing = dentry_add_child_case_insensitive(parent, other);
1321                         wimlib_assert(existing == NULL);
1322                 }
1323         }
1324         list_del(&dentry->case_insensitive_conflict_list);
1325 }
1326
1327 static int
1328 free_dentry_full_path(struct wim_dentry *dentry, void *_ignore)
1329 {
1330         FREE(dentry->_full_path);
1331         dentry->_full_path = NULL;
1332         return 0;
1333 }
1334
1335 /* Rename a file or directory in the WIM.  */
1336 int
1337 rename_wim_path(WIMStruct *wim, const tchar *from, const tchar *to,
1338                 CASE_SENSITIVITY_TYPE case_type)
1339 {
1340         struct wim_dentry *src;
1341         struct wim_dentry *dst;
1342         struct wim_dentry *parent_of_dst;
1343         int ret;
1344
1345         /* This rename() implementation currently only supports actual files
1346          * (not alternate data streams) */
1347
1348         src = get_dentry(wim, from, case_type);
1349         if (!src)
1350                 return -errno;
1351
1352         dst = get_dentry(wim, to, case_type);
1353
1354         if (dst) {
1355                 /* Destination file exists */
1356
1357                 if (src == dst) /* Same file */
1358                         return 0;
1359
1360                 if (!dentry_is_directory(src)) {
1361                         /* Cannot rename non-directory to directory. */
1362                         if (dentry_is_directory(dst))
1363                                 return -EISDIR;
1364                 } else {
1365                         /* Cannot rename directory to a non-directory or a non-empty
1366                          * directory */
1367                         if (!dentry_is_directory(dst))
1368                                 return -ENOTDIR;
1369                         if (dentry_has_children(dst))
1370                                 return -ENOTEMPTY;
1371                 }
1372                 parent_of_dst = dst->parent;
1373         } else {
1374                 /* Destination does not exist */
1375                 parent_of_dst = get_parent_dentry(wim, to, case_type);
1376                 if (!parent_of_dst)
1377                         return -errno;
1378
1379                 if (!dentry_is_directory(parent_of_dst))
1380                         return -ENOTDIR;
1381         }
1382
1383         ret = dentry_set_name(src, path_basename(to));
1384         if (ret)
1385                 return -ENOMEM;
1386         if (dst) {
1387                 unlink_dentry(dst);
1388                 free_dentry_tree(dst, wim->lookup_table);
1389         }
1390         unlink_dentry(src);
1391         dentry_add_child(parent_of_dst, src);
1392         if (src->_full_path)
1393                 for_dentry_in_tree(src, free_dentry_full_path, NULL);
1394         return 0;
1395 }
1396
1397 /* Reads a WIM directory entry, including all alternate data stream entries that
1398  * follow it, from the WIM image's metadata resource.  */
1399 static int
1400 read_dentry(const u8 * restrict buf, size_t buf_len,
1401             u64 offset, struct wim_dentry **dentry_ret)
1402 {
1403         u64 length;
1404         const u8 *p;
1405         const struct wim_dentry_on_disk *disk_dentry;
1406         struct wim_dentry *dentry;
1407         struct wim_inode *inode;
1408         u16 short_name_nbytes;
1409         u16 file_name_nbytes;
1410         u64 calculated_size;
1411         int ret;
1412
1413         BUILD_BUG_ON(sizeof(struct wim_dentry_on_disk) != WIM_DENTRY_DISK_SIZE);
1414
1415         /* Before reading the whole dentry, we need to read just the length.
1416          * This is because a dentry of length 8 (that is, just the length field)
1417          * terminates the list of sibling directory entries. */
1418
1419         /* Check for buffer overrun.  */
1420         if (unlikely(offset + sizeof(u64) > buf_len ||
1421                      offset + sizeof(u64) < offset))
1422         {
1423                 ERROR("Directory entry starting at %"PRIu64" ends past the "
1424                       "end of the metadata resource (size %zu)",
1425                       offset, buf_len);
1426                 return WIMLIB_ERR_INVALID_METADATA_RESOURCE;
1427         }
1428
1429         /* Get pointer to the dentry data.  */
1430         p = &buf[offset];
1431         disk_dentry = (const struct wim_dentry_on_disk*)p;
1432
1433         if (unlikely((uintptr_t)p & 7))
1434                 WARNING("WIM dentry is not 8-byte aligned");
1435
1436         /* Get dentry length.  */
1437         length = le64_to_cpu(disk_dentry->length);
1438
1439         /* Check for end-of-directory.  */
1440         if (length <= 8) {
1441                 *dentry_ret = NULL;
1442                 return 0;
1443         }
1444
1445         /* Validate dentry length.  */
1446         if (unlikely(length < sizeof(struct wim_dentry_on_disk))) {
1447                 ERROR("Directory entry has invalid length of %"PRIu64" bytes",
1448                       length);
1449                 return WIMLIB_ERR_INVALID_METADATA_RESOURCE;
1450         }
1451
1452         /* Check for buffer overrun.  */
1453         if (unlikely(offset + length > buf_len ||
1454                      offset + length < offset))
1455         {
1456                 ERROR("Directory entry at offset %"PRIu64" and with size "
1457                       "%"PRIu64" ends past the end of the metadata resource "
1458                       "(size %zu)", offset, length, buf_len);
1459                 return WIMLIB_ERR_INVALID_METADATA_RESOURCE;
1460         }
1461
1462         /* Allocate new dentry structure, along with a preliminary inode.  */
1463         ret = new_dentry_with_timeless_inode(T(""), &dentry);
1464         if (ret)
1465                 return ret;
1466
1467         dentry->length = length;
1468         inode = dentry->d_inode;
1469
1470         /* Read more fields: some into the dentry, and some into the inode.  */
1471         inode->i_attributes = le32_to_cpu(disk_dentry->attributes);
1472         inode->i_security_id = le32_to_cpu(disk_dentry->security_id);
1473         dentry->subdir_offset = le64_to_cpu(disk_dentry->subdir_offset);
1474         dentry->d_unused_1 = le64_to_cpu(disk_dentry->unused_1);
1475         dentry->d_unused_2 = le64_to_cpu(disk_dentry->unused_2);
1476         inode->i_creation_time = le64_to_cpu(disk_dentry->creation_time);
1477         inode->i_last_access_time = le64_to_cpu(disk_dentry->last_access_time);
1478         inode->i_last_write_time = le64_to_cpu(disk_dentry->last_write_time);
1479         copy_hash(inode->i_hash, disk_dentry->unnamed_stream_hash);
1480
1481         /* I don't know what's going on here.  It seems like M$ screwed up the
1482          * reparse points, then put the fields in the same place and didn't
1483          * document it.  So we have some fields we read for reparse points, and
1484          * some fields in the same place for non-reparse-points.  */
1485         if (inode->i_attributes & FILE_ATTRIBUTE_REPARSE_POINT) {
1486                 inode->i_rp_unknown_1 = le32_to_cpu(disk_dentry->reparse.rp_unknown_1);
1487                 inode->i_reparse_tag = le32_to_cpu(disk_dentry->reparse.reparse_tag);
1488                 inode->i_rp_unknown_2 = le16_to_cpu(disk_dentry->reparse.rp_unknown_2);
1489                 inode->i_not_rpfixed = le16_to_cpu(disk_dentry->reparse.not_rpfixed);
1490                 /* Leave inode->i_ino at 0.  Note that this means the WIM file
1491                  * cannot archive hard-linked reparse points.  Such a thing
1492                  * doesn't really make sense anyway, although I believe it's
1493                  * theoretically possible to have them on NTFS.  */
1494         } else {
1495                 inode->i_rp_unknown_1 = le32_to_cpu(disk_dentry->nonreparse.rp_unknown_1);
1496                 inode->i_ino = le64_to_cpu(disk_dentry->nonreparse.hard_link_group_id);
1497         }
1498         inode->i_num_ads = le16_to_cpu(disk_dentry->num_alternate_data_streams);
1499
1500         /* Now onto reading the names.  There are two of them: the (long) file
1501          * name, and the short name.  */
1502
1503         short_name_nbytes = le16_to_cpu(disk_dentry->short_name_nbytes);
1504         file_name_nbytes = le16_to_cpu(disk_dentry->file_name_nbytes);
1505
1506         if (unlikely((short_name_nbytes & 1) | (file_name_nbytes & 1))) {
1507                 ERROR("Dentry name is not valid UTF-16 (odd number of bytes)!");
1508                 ret = WIMLIB_ERR_INVALID_METADATA_RESOURCE;
1509                 goto err_free_dentry;
1510         }
1511
1512         /* We now know the length of the file name and short name.  Make sure
1513          * the length of the dentry is large enough to actually hold them.
1514          *
1515          * The calculated length here is unaligned to allow for the possibility
1516          * that the dentry->length names an unaligned length, although this
1517          * would be unexpected.  */
1518         calculated_size = dentry_correct_length_unaligned(file_name_nbytes,
1519                                                           short_name_nbytes);
1520
1521         if (unlikely(dentry->length < calculated_size)) {
1522                 ERROR("Unexpected end of directory entry! (Expected "
1523                       "at least %"PRIu64" bytes, got %"PRIu64" bytes.)",
1524                       calculated_size, dentry->length);
1525                 ret = WIMLIB_ERR_INVALID_METADATA_RESOURCE;
1526                 goto err_free_dentry;
1527         }
1528
1529         /* Advance p to point past the base dentry, to the first name.  */
1530         p += sizeof(struct wim_dentry_on_disk);
1531
1532         /* Read the filename if present.  Note: if the filename is empty, there
1533          * is no null terminator following it.  */
1534         if (file_name_nbytes) {
1535                 dentry->file_name = MALLOC(file_name_nbytes + 2);
1536                 if (dentry->file_name == NULL) {
1537                         ret = WIMLIB_ERR_NOMEM;
1538                         goto err_free_dentry;
1539                 }
1540                 dentry->file_name_nbytes = file_name_nbytes;
1541                 memcpy(dentry->file_name, p, file_name_nbytes);
1542                 p += file_name_nbytes + 2;
1543                 dentry->file_name[file_name_nbytes / 2] = cpu_to_le16(0);
1544         }
1545
1546         /* Read the short filename if present.  Note: if there is no short
1547          * filename, there is no null terminator following it. */
1548         if (short_name_nbytes) {
1549                 dentry->short_name = MALLOC(short_name_nbytes + 2);
1550                 if (dentry->short_name == NULL) {
1551                         ret = WIMLIB_ERR_NOMEM;
1552                         goto err_free_dentry;
1553                 }
1554                 dentry->short_name_nbytes = short_name_nbytes;
1555                 memcpy(dentry->short_name, p, short_name_nbytes);
1556                 p += short_name_nbytes + 2;
1557                 dentry->short_name[short_name_nbytes / 2] = cpu_to_le16(0);
1558         }
1559
1560         /* Align the dentry length.  */
1561         dentry->length = (dentry->length + 7) & ~7;
1562
1563         /* Read the alternate data streams, if present.  inode->i_num_ads tells
1564          * us how many they are, and they will directly follow the dentry in the
1565          * metadata resource buffer.
1566          *
1567          * Note that each alternate data stream entry begins on an 8-byte
1568          * aligned boundary, and the alternate data stream entries seem to NOT
1569          * be included in the dentry->length field for some reason.  */
1570         if (unlikely(inode->i_num_ads != 0)) {
1571                 ret = WIMLIB_ERR_INVALID_METADATA_RESOURCE;
1572                 if (offset + dentry->length > buf_len ||
1573                     (ret = read_ads_entries(&buf[offset + dentry->length],
1574                                             inode,
1575                                             buf_len - offset - dentry->length)))
1576                 {
1577                         ERROR("Failed to read alternate data stream "
1578                               "entries of WIM dentry \"%"WS"\"",
1579                               dentry->file_name);
1580                         goto err_free_dentry;
1581                 }
1582         }
1583
1584         *dentry_ret = dentry;
1585         return 0;
1586
1587 err_free_dentry:
1588         free_dentry(dentry);
1589         return ret;
1590 }
1591
1592 static const tchar *
1593 dentry_get_file_type_string(const struct wim_dentry *dentry)
1594 {
1595         const struct wim_inode *inode = dentry->d_inode;
1596         if (inode_is_directory(inode))
1597                 return T("directory");
1598         else if (inode_is_symlink(inode))
1599                 return T("symbolic link");
1600         else
1601                 return T("file");
1602 }
1603
1604 static bool
1605 dentry_is_dot_or_dotdot(const struct wim_dentry *dentry)
1606 {
1607         if (dentry->file_name_nbytes <= 4) {
1608                 if (dentry->file_name_nbytes == 4) {
1609                         if (dentry->file_name[0] == cpu_to_le16('.') &&
1610                             dentry->file_name[1] == cpu_to_le16('.'))
1611                                 return true;
1612                 } else if (dentry->file_name_nbytes == 2) {
1613                         if (dentry->file_name[0] == cpu_to_le16('.'))
1614                                 return true;
1615                 }
1616         }
1617         return false;
1618 }
1619
1620 static int
1621 read_dentry_tree_recursive(const u8 * restrict buf, size_t buf_len,
1622                            struct wim_dentry * restrict dir)
1623 {
1624         u64 cur_offset = dir->subdir_offset;
1625
1626         /* Check for cyclic directory structure, which would cause infinite
1627          * recursion if not handled.  */
1628         for (struct wim_dentry *d = dir->parent;
1629              !dentry_is_root(d); d = d->parent)
1630         {
1631                 if (unlikely(d->subdir_offset == cur_offset)) {
1632                         ERROR("Cyclic directory structure detected: children "
1633                               "of \"%"TS"\" coincide with children of \"%"TS"\"",
1634                               dentry_full_path(dir), dentry_full_path(d));
1635                         return WIMLIB_ERR_INVALID_METADATA_RESOURCE;
1636                 }
1637         }
1638
1639         for (;;) {
1640                 struct wim_dentry *child;
1641                 struct wim_dentry *duplicate;
1642                 int ret;
1643
1644                 /* Read next child of @dir.  */
1645                 ret = read_dentry(buf, buf_len, cur_offset, &child);
1646                 if (ret)
1647                         return ret;
1648
1649                 /* Check for end of directory.  */
1650                 if (child == NULL)
1651                         return 0;
1652
1653                 /* Advance to the offset of the next child.  Note: We need to
1654                  * advance by the TOTAL length of the dentry, not by the length
1655                  * child->length, which although it does take into account the
1656                  * padding, it DOES NOT take into account alternate stream
1657                  * entries.  */
1658                 cur_offset += dentry_in_total_length(child);
1659
1660                 /* All dentries except the root should be named.  */
1661                 if (unlikely(!dentry_has_long_name(child))) {
1662                         WARNING("Ignoring unnamed dentry in "
1663                                 "directory \"%"TS"\"", dentry_full_path(dir));
1664                         free_dentry(child);
1665                         continue;
1666                 }
1667
1668                 /* Don't allow files named "." or "..".  */
1669                 if (unlikely(dentry_is_dot_or_dotdot(child))) {
1670                         WARNING("Ignoring file named \".\" or \"..\"; "
1671                                 "potentially malicious archive!!!");
1672                         free_dentry(child);
1673                         continue;
1674                 }
1675
1676                 /* Link the child into the directory.  */
1677                 duplicate = dentry_add_child(dir, child);
1678                 if (unlikely(duplicate)) {
1679                         /* We already found a dentry with this same
1680                          * case-sensitive long name.  Only keep the first one.
1681                          */
1682                         const tchar *child_type, *duplicate_type;
1683                         child_type = dentry_get_file_type_string(child);
1684                         duplicate_type = dentry_get_file_type_string(duplicate);
1685                         WARNING("Ignoring duplicate %"TS" \"%"TS"\" "
1686                                 "(the WIM image already contains a %"TS" "
1687                                 "at that path with the exact same name)",
1688                                 child_type, dentry_full_path(duplicate),
1689                                 duplicate_type);
1690                         free_dentry(child);
1691                         continue;
1692                 }
1693
1694                 /* If this child is a directory that itself has children, call
1695                  * this procedure recursively.  */
1696                 if (child->subdir_offset != 0) {
1697                         if (likely(dentry_is_directory(child))) {
1698                                 ret = read_dentry_tree_recursive(buf,
1699                                                                  buf_len,
1700                                                                  child);
1701                                 if (ret)
1702                                         return ret;
1703                         } else {
1704                                 WARNING("Ignoring children of "
1705                                         "non-directory file \"%"TS"\"",
1706                                         dentry_full_path(child));
1707                         }
1708                 }
1709         }
1710 }
1711
1712 /*
1713  * Read a tree of dentries (directory entries) from a WIM metadata resource.
1714  *
1715  * @buf:
1716  *      Buffer containing an uncompressed WIM metadata resource.
1717  *
1718  * @buf_len:
1719  *      Length of the uncompressed metadata resource, in bytes.
1720  *
1721  * @root_offset
1722  *      Offset in the metadata resource of the root of the dentry tree.
1723  *
1724  * @root_ret:
1725  *      On success, either NULL or a pointer to the root dentry is written to
1726  *      this location.  The former case only occurs in the unexpected case that
1727  *      the tree began with an end-of-directory entry.
1728  *
1729  * Return values:
1730  *      WIMLIB_ERR_SUCCESS (0)
1731  *      WIMLIB_ERR_INVALID_METADATA_RESOURCE
1732  *      WIMLIB_ERR_NOMEM
1733  */
1734 int
1735 read_dentry_tree(const u8 *buf, size_t buf_len,
1736                  u64 root_offset, struct wim_dentry **root_ret)
1737 {
1738         int ret;
1739         struct wim_dentry *root;
1740
1741         DEBUG("Reading dentry tree (root_offset=%"PRIu64")", root_offset);
1742
1743         ret = read_dentry(buf, buf_len, root_offset, &root);
1744         if (ret)
1745                 return ret;
1746
1747         if (likely(root != NULL)) {
1748                 if (unlikely(dentry_has_long_name(root) ||
1749                              dentry_has_short_name(root)))
1750                 {
1751                         WARNING("The root directory has a nonempty name; "
1752                                 "removing it.");
1753                         FREE(root->file_name);
1754                         FREE(root->short_name);
1755                         root->file_name = NULL;
1756                         root->short_name = NULL;
1757                         root->file_name_nbytes = 0;
1758                         root->short_name_nbytes = 0;
1759                 }
1760
1761                 if (unlikely(!dentry_is_directory(root))) {
1762                         ERROR("The root of the WIM image is not a directory!");
1763                         ret = WIMLIB_ERR_INVALID_METADATA_RESOURCE;
1764                         goto err_free_dentry_tree;
1765                 }
1766
1767                 if (likely(root->subdir_offset != 0)) {
1768                         ret = read_dentry_tree_recursive(buf, buf_len, root);
1769                         if (ret)
1770                                 goto err_free_dentry_tree;
1771                 }
1772         } else {
1773                 WARNING("The metadata resource has no directory entries; "
1774                         "treating as an empty image.");
1775         }
1776         *root_ret = root;
1777         return 0;
1778
1779 err_free_dentry_tree:
1780         free_dentry_tree(root, NULL);
1781         return ret;
1782 }
1783
1784 /*
1785  * Writes a WIM alternate data stream (ADS) entry to an output buffer.
1786  *
1787  * @ads_entry:  The ADS entry structure.
1788  * @hash:       The hash field to use (instead of the one in the ADS entry).
1789  * @p:          The memory location to write the data to.
1790  *
1791  * Returns a pointer to the byte after the last byte written.
1792  */
1793 static u8 *
1794 write_ads_entry(const struct wim_ads_entry *ads_entry,
1795                 const u8 *hash, u8 * restrict p)
1796 {
1797         struct wim_ads_entry_on_disk *disk_ads_entry =
1798                         (struct wim_ads_entry_on_disk*)p;
1799         u8 *orig_p = p;
1800
1801         disk_ads_entry->reserved = cpu_to_le64(ads_entry->reserved);
1802         copy_hash(disk_ads_entry->hash, hash);
1803         disk_ads_entry->stream_name_nbytes = cpu_to_le16(ads_entry->stream_name_nbytes);
1804         p += sizeof(struct wim_ads_entry_on_disk);
1805         if (ads_entry->stream_name_nbytes) {
1806                 p = mempcpy(p, ads_entry->stream_name,
1807                             ads_entry->stream_name_nbytes + 2);
1808         }
1809         /* Align to 8-byte boundary */
1810         while ((uintptr_t)p & 7)
1811                 *p++ = 0;
1812         disk_ads_entry->length = cpu_to_le64(p - orig_p);
1813         return p;
1814 }
1815
1816 /*
1817  * Writes a WIM dentry to an output buffer.
1818  *
1819  * @dentry:  The dentry structure.
1820  * @p:       The memory location to write the data to.
1821  *
1822  * Returns the pointer to the byte after the last byte we wrote as part of the
1823  * dentry, including any alternate data stream entries.
1824  */
1825 static u8 *
1826 write_dentry(const struct wim_dentry * restrict dentry, u8 * restrict p)
1827 {
1828         const struct wim_inode *inode;
1829         struct wim_dentry_on_disk *disk_dentry;
1830         const u8 *orig_p;
1831         const u8 *hash;
1832         bool use_dummy_stream;
1833         u16 num_ads;
1834
1835         wimlib_assert(((uintptr_t)p & 7) == 0); /* 8 byte aligned */
1836         orig_p = p;
1837
1838         inode = dentry->d_inode;
1839         use_dummy_stream = inode_needs_dummy_stream(inode);
1840         disk_dentry = (struct wim_dentry_on_disk*)p;
1841
1842         disk_dentry->attributes = cpu_to_le32(inode->i_attributes);
1843         disk_dentry->security_id = cpu_to_le32(inode->i_security_id);
1844         disk_dentry->subdir_offset = cpu_to_le64(dentry->subdir_offset);
1845         disk_dentry->unused_1 = cpu_to_le64(dentry->d_unused_1);
1846         disk_dentry->unused_2 = cpu_to_le64(dentry->d_unused_2);
1847         disk_dentry->creation_time = cpu_to_le64(inode->i_creation_time);
1848         disk_dentry->last_access_time = cpu_to_le64(inode->i_last_access_time);
1849         disk_dentry->last_write_time = cpu_to_le64(inode->i_last_write_time);
1850         if (use_dummy_stream)
1851                 hash = zero_hash;
1852         else
1853                 hash = inode_stream_hash(inode, 0);
1854         copy_hash(disk_dentry->unnamed_stream_hash, hash);
1855         if (inode->i_attributes & FILE_ATTRIBUTE_REPARSE_POINT) {
1856                 disk_dentry->reparse.rp_unknown_1 = cpu_to_le32(inode->i_rp_unknown_1);
1857                 disk_dentry->reparse.reparse_tag = cpu_to_le32(inode->i_reparse_tag);
1858                 disk_dentry->reparse.rp_unknown_2 = cpu_to_le16(inode->i_rp_unknown_2);
1859                 disk_dentry->reparse.not_rpfixed = cpu_to_le16(inode->i_not_rpfixed);
1860         } else {
1861                 disk_dentry->nonreparse.rp_unknown_1 = cpu_to_le32(inode->i_rp_unknown_1);
1862                 disk_dentry->nonreparse.hard_link_group_id =
1863                         cpu_to_le64((inode->i_nlink == 1) ? 0 : inode->i_ino);
1864         }
1865         num_ads = inode->i_num_ads;
1866         if (use_dummy_stream)
1867                 num_ads++;
1868         disk_dentry->num_alternate_data_streams = cpu_to_le16(num_ads);
1869         disk_dentry->short_name_nbytes = cpu_to_le16(dentry->short_name_nbytes);
1870         disk_dentry->file_name_nbytes = cpu_to_le16(dentry->file_name_nbytes);
1871         p += sizeof(struct wim_dentry_on_disk);
1872
1873         wimlib_assert(dentry_is_root(dentry) != dentry_has_long_name(dentry));
1874
1875         if (dentry_has_long_name(dentry))
1876                 p = mempcpy(p, dentry->file_name, dentry->file_name_nbytes + 2);
1877
1878         if (dentry_has_short_name(dentry))
1879                 p = mempcpy(p, dentry->short_name, dentry->short_name_nbytes + 2);
1880
1881         /* Align to 8-byte boundary */
1882         while ((uintptr_t)p & 7)
1883                 *p++ = 0;
1884
1885         /* We calculate the correct length of the dentry ourselves because the
1886          * dentry->length field may been set to an unexpected value from when we
1887          * read the dentry in (for example, there may have been unknown data
1888          * appended to the end of the dentry...).  Furthermore, the dentry may
1889          * have been renamed, thus changing its needed length. */
1890         disk_dentry->length = cpu_to_le64(p - orig_p);
1891
1892         if (use_dummy_stream) {
1893                 hash = inode_unnamed_stream_hash(inode);
1894                 p = write_ads_entry(&(struct wim_ads_entry){}, hash, p);
1895         }
1896
1897         /* Write the alternate data streams entries, if any. */
1898         for (u16 i = 0; i < inode->i_num_ads; i++) {
1899                 hash = inode_stream_hash(inode, i + 1);
1900                 p = write_ads_entry(&inode->i_ads_entries[i], hash, p);
1901         }
1902
1903         return p;
1904 }
1905
1906 static int
1907 write_dentry_cb(struct wim_dentry *dentry, void *_p)
1908 {
1909         u8 **p = _p;
1910         *p = write_dentry(dentry, *p);
1911         return 0;
1912 }
1913
1914 static u8 *
1915 write_dentry_tree_recursive(const struct wim_dentry *parent, u8 *p);
1916
1917 static int
1918 write_dentry_tree_recursive_cb(struct wim_dentry *dentry, void *_p)
1919 {
1920         u8 **p = _p;
1921         *p = write_dentry_tree_recursive(dentry, *p);
1922         return 0;
1923 }
1924
1925 /* Recursive function that writes a dentry tree rooted at @parent, not including
1926  * @parent itself, which has already been written. */
1927 static u8 *
1928 write_dentry_tree_recursive(const struct wim_dentry *parent, u8 *p)
1929 {
1930         /* Nothing to do if this dentry has no children. */
1931         if (parent->subdir_offset == 0)
1932                 return p;
1933
1934         /* Write child dentries and end-of-directory entry.
1935          *
1936          * Note: we need to write all of this dentry's children before
1937          * recursively writing the directory trees rooted at each of the child
1938          * dentries, since the on-disk dentries for a dentry's children are
1939          * always located at consecutive positions in the metadata resource! */
1940         for_dentry_child(parent, write_dentry_cb, &p);
1941
1942         /* write end of directory entry */
1943         *(le64*)p = cpu_to_le64(0);
1944         p += 8;
1945
1946         /* Recurse on children. */
1947         for_dentry_child(parent, write_dentry_tree_recursive_cb, &p);
1948         return p;
1949 }
1950
1951 /* Writes a directory tree to the metadata resource.
1952  *
1953  * @root:       Root of the dentry tree.
1954  * @p:          Pointer to a buffer with enough space for the dentry tree.
1955  *
1956  * Returns pointer to the byte after the last byte we wrote.
1957  */
1958 u8 *
1959 write_dentry_tree(const struct wim_dentry * restrict root, u8 * restrict p)
1960 {
1961         DEBUG("Writing dentry tree.");
1962         wimlib_assert(dentry_is_root(root));
1963
1964         /* If we're the root dentry, we have no parent that already
1965          * wrote us, so we need to write ourselves. */
1966         p = write_dentry(root, p);
1967
1968         /* Write end of directory entry after the root dentry just to be safe;
1969          * however the root dentry obviously cannot have any siblings. */
1970         *(le64*)p = cpu_to_le64(0);
1971         p += 8;
1972
1973         /* Recursively write the rest of the dentry tree. */
1974         return write_dentry_tree_recursive(root, p);
1975 }