]> wimlib.net Git - wimlib/blob - src/dentry.c
struct wim_dentry: Remove 'length' field
[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, 2014 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         /* Creation time, last access time, and last write time, in
88          * 100-nanosecond intervals since 12:00 a.m UTC January 1, 1601.  They
89          * should correspond to the times gotten by calling GetFileTime() on
90          * Windows. */
91         le64 creation_time;
92         le64 last_access_time;
93         le64 last_write_time;
94
95         /* Vaguely, the SHA-1 message digest ("hash") of the file's contents.
96          * More specifically, this is for the "unnamed data stream" rather than
97          * any "alternate data streams".  This hash value is used to look up the
98          * corresponding entry in the WIM's stream lookup table to actually find
99          * the file contents within the WIM.
100          *
101          * If the file has no unnamed data stream (e.g. is a directory), then
102          * this field will be all zeroes.  If the unnamed data stream is empty
103          * (i.e. an "empty file"), then this field is also expected to be all
104          * zeroes.  (It will be if wimlib created the WIM image, at least;
105          * otherwise it can't be ruled out that the SHA-1 message digest of 0
106          * bytes of data is given explicitly.)
107          *
108          * If the file has reparse data, then this field will instead specify
109          * the SHA-1 message digest of the reparse data.  If it is somehow
110          * possible for a file to have both an unnamed data stream and reparse
111          * data, then this is not handled by wimlib.
112          *
113          * As a further special case, if this field is all zeroes but there is
114          * an alternate data stream entry with no name and a nonzero SHA-1
115          * message digest field, then that hash must be used instead of this
116          * one.  In fact, when named data streams are present, some versions of
117          * Windows PE contain a bug where they only look in the alternate data
118          * stream entries for the unnamed data stream, not here.
119          */
120         u8 unnamed_stream_hash[SHA1_HASH_SIZE];
121
122         /* The format of the following data is not yet completely known and they
123          * do not correspond to Microsoft's documentation.
124          *
125          * If this directory entry is for a reparse point (has
126          * FILE_ATTRIBUTE_REPARSE_POINT set in the attributes field), then the
127          * version of the following fields containing the reparse tag is valid.
128          * Furthermore, the field notated as not_rpfixed, as far as I can tell,
129          * is supposed to be set to 1 if reparse point fixups (a.k.a. fixing the
130          * targets of absolute symbolic links) were *not* done, and otherwise 0.
131          *
132          * If this directory entry is not for a reparse point, then the version
133          * of the following fields containing the hard_link_group_id is valid.
134          * All MS says about this field is that "If this file is part of a hard
135          * link set, all the directory entries in the set will share the same
136          * value in this field.".  However, more specifically I have observed
137          * the following:
138          *    - If the file is part of a hard link set of size 1, then the
139          *    hard_link_group_id should be set to either 0, which is treated
140          *    specially as indicating "not hardlinked", or any unique value.
141          *    - The specific nonzero values used to identity hard link sets do
142          *    not matter, as long as they are unique.
143          *    - However, due to bugs in Microsoft's software, it is actually NOT
144          *    guaranteed that directory entries that share the same hard link
145          *    group ID are actually hard linked to each either.  We have to
146          *    handle this by using special code to use distinguishing features
147          *    (which is possible because some information about the underlying
148          *    inode is repeated in each dentry) to split up these fake hard link
149          *    groups into what they actually are supposed to be.
150          */
151         union {
152                 struct {
153                         le32 rp_unknown_1;
154                         le32 reparse_tag;
155                         le16 rp_unknown_2;
156                         le16 not_rpfixed;
157                 } _packed_attribute reparse;
158                 struct {
159                         le32 rp_unknown_1;
160                         le64 hard_link_group_id;
161                 } _packed_attribute nonreparse;
162         };
163
164         /* Number of alternate data stream entries that directly follow this
165          * dentry on-disk. */
166         le16 num_alternate_data_streams;
167
168         /* Length of this file's UTF-16LE encoded short name (8.3 DOS-compatible
169          * name), if present, in bytes, excluding the null terminator.  If this
170          * file has no short name, then this field should be 0.  */
171         le16 short_name_nbytes;
172
173         /* Length of this file's UTF-16LE encoded "long" name, excluding the
174          * null terminator.  If this file has no short name, then this field
175          * should be 0.  It's expected that only the root dentry has this field
176          * set to 0.  */
177         le16 file_name_nbytes;
178
179         /* Followed by variable length file name, in UTF16-LE, if
180          * file_name_nbytes != 0.  Includes null terminator. */
181         /*utf16lechar file_name[];*/
182
183         /* Followed by variable length short name, in UTF16-LE, if
184          * short_name_nbytes != 0.  Includes null terminator. */
185         /*utf16lechar short_name[];*/
186
187         /* And optionally followed by a variable-length series of tagged items;
188          * see tagged_items.c.  */
189 } _packed_attribute;
190
191 /* Calculates the unaligned length, in bytes, of an on-disk WIM dentry that has
192  * a file name and short name that take the specified numbers of bytes.  This
193  * excludes tagged items as well as any alternate data stream entries that may
194  * follow the dentry.  */
195 static u64
196 dentry_min_len_with_names(u16 file_name_nbytes, u16 short_name_nbytes)
197 {
198         u64 length = sizeof(struct wim_dentry_on_disk);
199         if (file_name_nbytes)
200                 length += file_name_nbytes + 2;
201         if (short_name_nbytes)
202                 length += short_name_nbytes + 2;
203         return length;
204 }
205
206 static void
207 do_dentry_set_name(struct wim_dentry *dentry, utf16lechar *file_name,
208                    size_t file_name_nbytes)
209 {
210         FREE(dentry->file_name);
211         dentry->file_name = file_name;
212         dentry->file_name_nbytes = file_name_nbytes;
213
214         if (dentry_has_short_name(dentry)) {
215                 FREE(dentry->short_name);
216                 dentry->short_name = NULL;
217                 dentry->short_name_nbytes = 0;
218         }
219 }
220
221 /* Sets the name of a WIM dentry from a UTF-16LE string.
222  * Only use this on dentries not inserted into the tree.  Use rename_wim_path()
223  * to do a real rename.  */
224 int
225 dentry_set_name_utf16le(struct wim_dentry *dentry, const utf16lechar *name,
226                         size_t name_nbytes)
227 {
228         utf16lechar *dup = NULL;
229
230         if (name_nbytes) {
231                 dup = utf16le_dupz(name, name_nbytes);
232                 if (!dup)
233                         return WIMLIB_ERR_NOMEM;
234         }
235         do_dentry_set_name(dentry, dup, name_nbytes);
236         return 0;
237 }
238
239
240 /* Sets the name of a WIM dentry from a multibyte string.
241  * Only use this on dentries not inserted into the tree.  Use rename_wim_path()
242  * to do a real rename.  */
243 int
244 dentry_set_name(struct wim_dentry *dentry, const tchar *name)
245 {
246         utf16lechar *name_utf16le = NULL;
247         size_t name_utf16le_nbytes = 0;
248         int ret;
249
250         if (name && *name) {
251                 ret = tstr_to_utf16le(name, tstrlen(name) * sizeof(tchar),
252                                       &name_utf16le, &name_utf16le_nbytes);
253                 if (ret)
254                         return ret;
255         }
256
257         do_dentry_set_name(dentry, name_utf16le, name_utf16le_nbytes);
258         return 0;
259 }
260
261 /* Returns the total length of a WIM alternate data stream entry on-disk,
262  * including the stream name, the null terminator, AND the padding after the
263  * entry to align the next ADS entry or dentry on an 8-byte boundary. */
264 static u64
265 ads_entry_total_length(const struct wim_ads_entry *entry)
266 {
267         u64 len = sizeof(struct wim_ads_entry_on_disk);
268         if (entry->stream_name_nbytes)
269                 len += entry->stream_name_nbytes + 2;
270         return (len + 7) & ~7;
271 }
272
273 /*
274  * Determine whether to include a "dummy" stream when writing a WIM dentry:
275  *
276  * Some versions of Microsoft's WIM software (the boot driver(s) in WinPE 3.0,
277  * for example) contain a bug where they assume the first alternate data stream
278  * (ADS) entry of a dentry with a nonzero ADS count specifies the unnamed
279  * stream, even if it has a name and the unnamed stream is already specified in
280  * the hash field of the dentry itself.
281  *
282  * wimlib has to work around this behavior by carefully emulating the behavior
283  * of (most versions of) ImageX/WIMGAPI, which move the unnamed stream reference
284  * into the alternate stream entries whenever there are named data streams, even
285  * though there is already a field in the dentry itself for the unnamed stream
286  * reference, which then goes to waste.
287  */
288 static inline bool
289 inode_needs_dummy_stream(const struct wim_inode *inode)
290 {
291         return (inode->i_num_ads > 0 &&
292                 inode->i_num_ads < 0xffff && /* overflow check */
293                 inode->i_canonical_streams); /* assume the dentry is okay if it
294                                                 already had an unnamed ADS entry
295                                                 when it was read in  */
296 }
297
298 /* Calculate the total number of bytes that will be consumed when a WIM dentry
299  * is written.  This includes the base dentry the name fields, any tagged items,
300  * any alternate data stream entries.  Also includes all alignment bytes between
301  * these parts.  */
302 u64
303 dentry_out_total_length(const struct wim_dentry *dentry)
304 {
305         const struct wim_inode *inode = dentry->d_inode;
306         u64 len;
307
308         len = dentry_min_len_with_names(dentry->file_name_nbytes,
309                                         dentry->short_name_nbytes);
310         len = (len + 7) & ~7;
311
312         if (inode->i_extra_size) {
313                 len += inode->i_extra_size;
314                 len = (len + 7) & ~7;
315         }
316
317         if (unlikely(inode->i_num_ads)) {
318                 if (inode_needs_dummy_stream(inode))
319                         len += ads_entry_total_length(&(struct wim_ads_entry){});
320
321                 for (u16 i = 0; i < inode->i_num_ads; i++)
322                         len += ads_entry_total_length(&inode->i_ads_entries[i]);
323         }
324
325         return len;
326 }
327
328 static int
329 do_for_dentry_in_tree(struct wim_dentry *dentry,
330                       int (*visitor)(struct wim_dentry *, void *), void *arg)
331 {
332         int ret;
333         struct wim_dentry *child;
334
335         ret = (*visitor)(dentry, arg);
336         if (unlikely(ret))
337                 return ret;
338
339         for_dentry_child(child, dentry) {
340                 ret = do_for_dentry_in_tree(child, visitor, arg);
341                 if (unlikely(ret))
342                         return ret;
343         }
344         return 0;
345 }
346
347
348 static int
349 do_for_dentry_in_tree_depth(struct wim_dentry *dentry,
350                             int (*visitor)(struct wim_dentry *, void *), void *arg)
351 {
352         int ret;
353         struct wim_dentry *child;
354
355         for_dentry_child_postorder(child, dentry) {
356                 ret = do_for_dentry_in_tree_depth(child, visitor, arg);
357                 if (unlikely(ret))
358                         return ret;
359         }
360         return unlikely((*visitor)(dentry, arg));
361 }
362
363 /* Calls a function on all directory entries in a WIM dentry tree.  Logically,
364  * this is a pre-order traversal (the function is called on a parent dentry
365  * before its children), but sibling dentries will be visited in order as well.
366  * */
367 int
368 for_dentry_in_tree(struct wim_dentry *root,
369                    int (*visitor)(struct wim_dentry *, void *), void *arg)
370 {
371         if (unlikely(!root))
372                 return 0;
373         return do_for_dentry_in_tree(root, visitor, arg);
374 }
375
376 /* Like for_dentry_in_tree(), but the visitor function is always called on a
377  * dentry's children before on itself. */
378 int
379 for_dentry_in_tree_depth(struct wim_dentry *root,
380                          int (*visitor)(struct wim_dentry *, void *), void *arg)
381 {
382         if (unlikely(!root))
383                 return 0;
384         return do_for_dentry_in_tree_depth(root, visitor, arg);
385 }
386
387 /* Calculate the full path of @dentry.  */
388 int
389 calculate_dentry_full_path(struct wim_dentry *dentry)
390 {
391         size_t ulen;
392         size_t dummy;
393         const struct wim_dentry *d;
394
395         if (dentry->_full_path)
396                 return 0;
397
398         ulen = 0;
399         d = dentry;
400         do {
401                 ulen += d->file_name_nbytes / sizeof(utf16lechar);
402                 ulen++;
403                 d = d->d_parent;  /* assumes d == d->d_parent for root  */
404         } while (!dentry_is_root(d));
405
406         utf16lechar ubuf[ulen];
407         utf16lechar *p = &ubuf[ulen];
408
409         d = dentry;
410         do {
411                 p -= d->file_name_nbytes / sizeof(utf16lechar);
412                 memcpy(p, d->file_name, d->file_name_nbytes);
413                 *--p = cpu_to_le16(WIM_PATH_SEPARATOR);
414                 d = d->d_parent;  /* assumes d == d->d_parent for root  */
415         } while (!dentry_is_root(d));
416
417         wimlib_assert(p == ubuf);
418
419         return utf16le_to_tstr(ubuf, ulen * sizeof(utf16lechar),
420                                &dentry->_full_path, &dummy);
421 }
422
423 tchar *
424 dentry_full_path(struct wim_dentry *dentry)
425 {
426         calculate_dentry_full_path(dentry);
427         return dentry->_full_path;
428 }
429
430 static int
431 dentry_calculate_subdir_offset(struct wim_dentry *dentry, void *_subdir_offset_p)
432 {
433
434         if (dentry_is_directory(dentry)) {
435                 u64 *subdir_offset_p = _subdir_offset_p;
436                 struct wim_dentry *child;
437
438                 /* Set offset of directory's child dentries  */
439                 dentry->subdir_offset = *subdir_offset_p;
440
441                 /* Account for child dentries  */
442                 for_dentry_child(child, dentry)
443                         *subdir_offset_p += dentry_out_total_length(child);
444
445                 /* Account for end-of-directory entry  */
446                 *subdir_offset_p += 8;
447         } else {
448                 /* Not a directory; set subdir_offset to 0  */
449                 dentry->subdir_offset = 0;
450         }
451         return 0;
452 }
453
454 /*
455  * Calculates the subdir offsets for a directory tree.
456  */
457 void
458 calculate_subdir_offsets(struct wim_dentry *root, u64 *subdir_offset_p)
459 {
460         for_dentry_in_tree(root, dentry_calculate_subdir_offset, subdir_offset_p);
461 }
462
463 /* Compare the UTF-16LE long filenames of two dentries case insensitively.  */
464 static int
465 dentry_compare_names_case_insensitive(const struct wim_dentry *d1,
466                                       const struct wim_dentry *d2)
467 {
468         return cmp_utf16le_strings(d1->file_name,
469                                    d1->file_name_nbytes / 2,
470                                    d2->file_name,
471                                    d2->file_name_nbytes / 2,
472                                    true);
473 }
474
475 /* Compare the UTF-16LE long filenames of two dentries case sensitively.  */
476 static int
477 dentry_compare_names_case_sensitive(const struct wim_dentry *d1,
478                                     const struct wim_dentry *d2)
479 {
480         return cmp_utf16le_strings(d1->file_name,
481                                    d1->file_name_nbytes / 2,
482                                    d2->file_name,
483                                    d2->file_name_nbytes / 2,
484                                    false);
485 }
486
487 static int
488 _avl_dentry_compare_names_ci(const struct avl_tree_node *n1,
489                              const struct avl_tree_node *n2)
490 {
491         const struct wim_dentry *d1, *d2;
492
493         d1 = avl_tree_entry(n1, struct wim_dentry, d_index_node_ci);
494         d2 = avl_tree_entry(n2, struct wim_dentry, d_index_node_ci);
495         return dentry_compare_names_case_insensitive(d1, d2);
496 }
497
498 static int
499 _avl_dentry_compare_names(const struct avl_tree_node *n1,
500                           const struct avl_tree_node *n2)
501 {
502         const struct wim_dentry *d1, *d2;
503
504         d1 = avl_tree_entry(n1, struct wim_dentry, d_index_node);
505         d2 = avl_tree_entry(n2, struct wim_dentry, d_index_node);
506         return dentry_compare_names_case_sensitive(d1, d2);
507 }
508
509 /* Default case sensitivity behavior for searches with
510  * WIMLIB_CASE_PLATFORM_DEFAULT specified.  This can be modified by
511  * wimlib_global_init().  */
512 bool default_ignore_case =
513 #ifdef __WIN32__
514         true
515 #else
516         false
517 #endif
518 ;
519
520 /* Case-sensitive dentry lookup.  Only @file_name and @file_name_nbytes of
521  * @dummy must be valid.  */
522 static struct wim_dentry *
523 dir_lookup(const struct wim_inode *dir, const struct wim_dentry *dummy)
524 {
525         struct avl_tree_node *node;
526
527         node = avl_tree_lookup_node(dir->i_children,
528                                     &dummy->d_index_node,
529                                     _avl_dentry_compare_names);
530         if (!node)
531                 return NULL;
532         return avl_tree_entry(node, struct wim_dentry, d_index_node);
533 }
534
535 /* Case-insensitive dentry lookup.  Only @file_name and @file_name_nbytes of
536  * @dummy must be valid.  */
537 static struct wim_dentry *
538 dir_lookup_ci(const struct wim_inode *dir, const struct wim_dentry *dummy)
539 {
540         struct avl_tree_node *node;
541
542         node = avl_tree_lookup_node(dir->i_children_ci,
543                                     &dummy->d_index_node_ci,
544                                     _avl_dentry_compare_names_ci);
545         if (!node)
546                 return NULL;
547         return avl_tree_entry(node, struct wim_dentry, d_index_node_ci);
548 }
549
550 /* Given a UTF-16LE filename and a directory, look up the dentry for the file.
551  * Return it if found, otherwise NULL.  This has configurable case sensitivity,
552  * and @name need not be null-terminated.  */
553 struct wim_dentry *
554 get_dentry_child_with_utf16le_name(const struct wim_dentry *dentry,
555                                    const utf16lechar *name,
556                                    size_t name_nbytes,
557                                    CASE_SENSITIVITY_TYPE case_ctype)
558 {
559         const struct wim_inode *dir = dentry->d_inode;
560         bool ignore_case = will_ignore_case(case_ctype);
561         struct wim_dentry dummy;
562         struct wim_dentry *child;
563
564         dummy.file_name = (utf16lechar*)name;
565         dummy.file_name_nbytes = name_nbytes;
566
567         if (!ignore_case)
568                 /* Case-sensitive lookup.  */
569                 return dir_lookup(dir, &dummy);
570
571         /* Case-insensitive lookup.  */
572
573         child = dir_lookup_ci(dir, &dummy);
574         if (!child)
575                 return NULL;
576
577         if (likely(list_empty(&child->d_ci_conflict_list)))
578                 /* Only one dentry has this case-insensitive name; return it */
579                 return child;
580
581         /* Multiple dentries have the same case-insensitive name.  Choose the
582          * dentry with the same case-sensitive name, if one exists; otherwise
583          * print a warning and choose one of the possible dentries arbitrarily.
584          */
585         struct wim_dentry *alt = child;
586         size_t num_alts = 0;
587
588         do {
589                 num_alts++;
590                 if (!dentry_compare_names_case_sensitive(&dummy, alt))
591                         return alt;
592                 alt = list_entry(alt->d_ci_conflict_list.next,
593                                  struct wim_dentry, d_ci_conflict_list);
594         } while (alt != child);
595
596         WARNING("Result of case-insensitive lookup is ambiguous\n"
597                 "          (returning \"%"TS"\" of %zu "
598                 "possible files, including \"%"TS"\")",
599                 dentry_full_path(child),
600                 num_alts,
601                 dentry_full_path(list_entry(child->d_ci_conflict_list.next,
602                                             struct wim_dentry,
603                                             d_ci_conflict_list)));
604         return child;
605 }
606
607 /* Returns the child of @dentry that has the file name @name.  Returns NULL if
608  * no child has the name. */
609 struct wim_dentry *
610 get_dentry_child_with_name(const struct wim_dentry *dentry, const tchar *name,
611                            CASE_SENSITIVITY_TYPE case_type)
612 {
613         int ret;
614         const utf16lechar *name_utf16le;
615         size_t name_utf16le_nbytes;
616         struct wim_dentry *child;
617
618         ret = tstr_get_utf16le_and_len(name, &name_utf16le,
619                                        &name_utf16le_nbytes);
620         if (ret)
621                 return NULL;
622
623         child = get_dentry_child_with_utf16le_name(dentry,
624                                                    name_utf16le,
625                                                    name_utf16le_nbytes,
626                                                    case_type);
627         tstr_put_utf16le(name_utf16le);
628         return child;
629 }
630
631 static struct wim_dentry *
632 get_dentry_utf16le(WIMStruct *wim, const utf16lechar *path,
633                    CASE_SENSITIVITY_TYPE case_type)
634 {
635         struct wim_dentry *cur_dentry;
636         const utf16lechar *name_start, *name_end;
637
638         /* Start with the root directory of the image.  Note: this will be NULL
639          * if an image has been added directly with wimlib_add_empty_image() but
640          * no files have been added yet; in that case we fail with ENOENT.  */
641         cur_dentry = wim_get_current_root_dentry(wim);
642
643         name_start = path;
644         for (;;) {
645                 if (cur_dentry == NULL) {
646                         errno = ENOENT;
647                         return NULL;
648                 }
649
650                 if (*name_start && !dentry_is_directory(cur_dentry)) {
651                         errno = ENOTDIR;
652                         return NULL;
653                 }
654
655                 while (*name_start == cpu_to_le16(WIM_PATH_SEPARATOR))
656                         name_start++;
657
658                 if (!*name_start)
659                         return cur_dentry;
660
661                 name_end = name_start;
662                 do {
663                         ++name_end;
664                 } while (*name_end != cpu_to_le16(WIM_PATH_SEPARATOR) && *name_end);
665
666                 cur_dentry = get_dentry_child_with_utf16le_name(cur_dentry,
667                                                                 name_start,
668                                                                 (u8*)name_end - (u8*)name_start,
669                                                                 case_type);
670                 name_start = name_end;
671         }
672 }
673
674 /*
675  * WIM path lookup: translate a path in the currently selected WIM image to the
676  * corresponding dentry, if it exists.
677  *
678  * @wim
679  *      The WIMStruct for the WIM.  The search takes place in the currently
680  *      selected image.
681  *
682  * @path
683  *      The path to look up, given relative to the root of the WIM image.
684  *      Characters with value WIM_PATH_SEPARATOR are taken to be path
685  *      separators.  Leading path separators are ignored, whereas one or more
686  *      trailing path separators cause the path to only match a directory.
687  *
688  * @case_type
689  *      The case-sensitivity behavior of this function, as one of the following
690  *      constants:
691  *
692  *    - WIMLIB_CASE_SENSITIVE:  Perform the search case sensitively.  This means
693  *      that names must match exactly.
694  *
695  *    - WIMLIB_CASE_INSENSITIVE:  Perform the search case insensitively.  This
696  *      means that names are considered to match if they are equal when
697  *      transformed to upper case.  If a path component matches multiple names
698  *      case-insensitively, the name that matches the path component
699  *      case-sensitively is chosen, if existent; otherwise one
700  *      case-insensitively matching name is chosen arbitrarily.
701  *
702  *    - WIMLIB_CASE_PLATFORM_DEFAULT:  Perform either case-sensitive or
703  *      case-insensitive search, depending on the value of the global variable
704  *      default_ignore_case.
705  *
706  *    In any case, no Unicode normalization is done before comparing strings.
707  *
708  * Returns a pointer to the dentry that is the result of the lookup, or NULL if
709  * no such dentry exists.  If NULL is returned, errno is set to one of the
710  * following values:
711  *
712  *      ENOTDIR if one of the path components used as a directory existed but
713  *      was not, in fact, a directory.
714  *
715  *      ENOENT otherwise.
716  *
717  * Additional notes:
718  *
719  *    - This function does not consider a reparse point to be a directory, even
720  *      if it has FILE_ATTRIBUTE_DIRECTORY set.
721  *
722  *    - This function does not dereference symbolic links or junction points
723  *      when performing the search.
724  *
725  *    - Since this function ignores leading slashes, the empty path is valid and
726  *      names the root directory of the WIM image.
727  *
728  *    - An image added with wimlib_add_empty_image() does not have a root
729  *      directory yet, and this function will fail with ENOENT for any path on
730  *      such an image.
731  */
732 struct wim_dentry *
733 get_dentry(WIMStruct *wim, const tchar *path, CASE_SENSITIVITY_TYPE case_type)
734 {
735         int ret;
736         const utf16lechar *path_utf16le;
737         struct wim_dentry *dentry;
738
739         ret = tstr_get_utf16le(path, &path_utf16le);
740         if (ret)
741                 return NULL;
742         dentry = get_dentry_utf16le(wim, path_utf16le, case_type);
743         tstr_put_utf16le(path_utf16le);
744         return dentry;
745 }
746
747 /* Takes in a path of length @len in @buf, and transforms it into a string for
748  * the path of its parent directory. */
749 static void
750 to_parent_name(tchar *buf, size_t len)
751 {
752         ssize_t i = (ssize_t)len - 1;
753         while (i >= 0 && buf[i] == WIM_PATH_SEPARATOR)
754                 i--;
755         while (i >= 0 && buf[i] != WIM_PATH_SEPARATOR)
756                 i--;
757         while (i >= 0 && buf[i] == WIM_PATH_SEPARATOR)
758                 i--;
759         buf[i + 1] = T('\0');
760 }
761
762 /* Similar to get_dentry(), but returns the dentry named by @path with the last
763  * component stripped off.
764  *
765  * Note: The returned dentry is NOT guaranteed to be a directory.  */
766 struct wim_dentry *
767 get_parent_dentry(WIMStruct *wim, const tchar *path,
768                   CASE_SENSITIVITY_TYPE case_type)
769 {
770         size_t path_len = tstrlen(path);
771         tchar buf[path_len + 1];
772
773         tmemcpy(buf, path, path_len + 1);
774         to_parent_name(buf, path_len);
775         return get_dentry(wim, buf, case_type);
776 }
777
778 #ifdef WITH_FUSE
779 /* Finds the dentry, lookup table entry, and stream index for a WIM file stream,
780  * given a path name.
781  *
782  * Currently, lookups of this type are only needed if FUSE is enabled.  */
783 int
784 wim_pathname_to_stream(WIMStruct *wim,
785                        const tchar *path,
786                        int lookup_flags,
787                        struct wim_dentry **dentry_ret,
788                        struct wim_lookup_table_entry **lte_ret,
789                        u16 *stream_idx_ret)
790 {
791         struct wim_dentry *dentry;
792         struct wim_lookup_table_entry *lte;
793         u16 stream_idx;
794         const tchar *stream_name = NULL;
795         struct wim_inode *inode;
796         tchar *p = NULL;
797
798         if (lookup_flags & LOOKUP_FLAG_ADS_OK) {
799                 stream_name = path_stream_name(path);
800                 if (stream_name) {
801                         p = (tchar*)stream_name - 1;
802                         *p = T('\0');
803                 }
804         }
805
806         dentry = get_dentry(wim, path, WIMLIB_CASE_SENSITIVE);
807         if (p)
808                 *p = T(':');
809         if (!dentry)
810                 return -errno;
811
812         inode = dentry->d_inode;
813
814         if (!inode->i_resolved)
815                 if (inode_resolve_streams(inode, wim->lookup_table, false))
816                         return -EIO;
817
818         if (!(lookup_flags & LOOKUP_FLAG_DIRECTORY_OK)
819               && inode_is_directory(inode))
820                 return -EISDIR;
821
822         if (stream_name) {
823                 struct wim_ads_entry *ads_entry;
824
825                 ads_entry = inode_get_ads_entry(inode, stream_name);
826                 if (!ads_entry)
827                         return -errno;
828
829                 stream_idx = ads_entry - inode->i_ads_entries + 1;
830                 lte = ads_entry->lte;
831         } else {
832                 lte = inode_unnamed_stream_resolved(inode, &stream_idx);
833         }
834         if (dentry_ret)
835                 *dentry_ret = dentry;
836         if (lte_ret)
837                 *lte_ret = lte;
838         if (stream_idx_ret)
839                 *stream_idx_ret = stream_idx;
840         return 0;
841 }
842 #endif /* WITH_FUSE  */
843
844 /* Creates an unlinked directory entry. */
845 int
846 new_dentry(const tchar *name, struct wim_dentry **dentry_ret)
847 {
848         struct wim_dentry *dentry;
849         int ret;
850
851         dentry = CALLOC(1, sizeof(struct wim_dentry));
852         if (!dentry)
853                 return WIMLIB_ERR_NOMEM;
854
855         if (*name) {
856                 ret = dentry_set_name(dentry, name);
857                 if (ret) {
858                         FREE(dentry);
859                         ERROR("Failed to set name on new dentry with name \"%"TS"\"",
860                               name);
861                         return ret;
862                 }
863         }
864         dentry->d_parent = dentry;
865         *dentry_ret = dentry;
866         return 0;
867 }
868
869 static int
870 _new_dentry_with_inode(const tchar *name, struct wim_dentry **dentry_ret,
871                         bool timeless)
872 {
873         struct wim_dentry *dentry;
874         int ret;
875
876         ret = new_dentry(name, &dentry);
877         if (ret)
878                 return ret;
879
880         if (timeless)
881                 dentry->d_inode = new_timeless_inode();
882         else
883                 dentry->d_inode = new_inode();
884         if (dentry->d_inode == NULL) {
885                 free_dentry(dentry);
886                 return WIMLIB_ERR_NOMEM;
887         }
888
889         inode_add_dentry(dentry, dentry->d_inode);
890         *dentry_ret = dentry;
891         return 0;
892 }
893
894 int
895 new_dentry_with_timeless_inode(const tchar *name, struct wim_dentry **dentry_ret)
896 {
897         return _new_dentry_with_inode(name, dentry_ret, true);
898 }
899
900 int
901 new_dentry_with_inode(const tchar *name, struct wim_dentry **dentry_ret)
902 {
903         return _new_dentry_with_inode(name, dentry_ret, false);
904 }
905
906 int
907 new_filler_directory(struct wim_dentry **dentry_ret)
908 {
909         int ret;
910         struct wim_dentry *dentry;
911
912         ret = new_dentry_with_inode(T(""), &dentry);
913         if (ret)
914                 return ret;
915         /* Leave the inode number as 0; this is allowed for non
916          * hard-linked files. */
917         dentry->d_inode->i_resolved = 1;
918         dentry->d_inode->i_attributes = FILE_ATTRIBUTE_DIRECTORY;
919         *dentry_ret = dentry;
920         return 0;
921 }
922
923 static int
924 dentry_clear_inode_visited(struct wim_dentry *dentry, void *_ignore)
925 {
926         dentry->d_inode->i_visited = 0;
927         return 0;
928 }
929
930 void
931 dentry_tree_clear_inode_visited(struct wim_dentry *root)
932 {
933         for_dentry_in_tree(root, dentry_clear_inode_visited, NULL);
934 }
935
936 /*
937  * Free a WIM dentry.
938  *
939  * In addition to freeing the dentry itself, this decrements the link count of
940  * the corresponding inode (if any).  If the inode's link count reaches 0, the
941  * inode is freed as well.
942  */
943 void
944 free_dentry(struct wim_dentry *dentry)
945 {
946         if (dentry) {
947                 FREE(dentry->file_name);
948                 FREE(dentry->short_name);
949                 FREE(dentry->_full_path);
950                 if (dentry->d_inode)
951                         put_inode(dentry->d_inode);
952                 FREE(dentry);
953         }
954 }
955
956 static int
957 do_free_dentry(struct wim_dentry *dentry, void *_ignore)
958 {
959         free_dentry(dentry);
960         return 0;
961 }
962
963 static int
964 do_free_dentry_and_unref_streams(struct wim_dentry *dentry, void *lookup_table)
965 {
966         inode_unref_streams(dentry->d_inode, lookup_table);
967         free_dentry(dentry);
968         return 0;
969 }
970
971 /*
972  * Recursively frees all directory entries in the specified tree.
973  *
974  * @root:
975  *      The root of the tree.
976  *
977  * @lookup_table:
978  *      The lookup table for dentries.  If non-NULL, the reference counts in the
979  *      lookup table for the lookup table entries corresponding to the dentries
980  *      will be decremented.
981  *
982  * This also puts references to the corresponding inodes.
983  *
984  * This does *not* unlink @root from its parent directory (if it has one).
985  */
986 void
987 free_dentry_tree(struct wim_dentry *root, struct wim_lookup_table *lookup_table)
988 {
989         int (*f)(struct wim_dentry *, void *);
990
991         if (lookup_table)
992                 f = do_free_dentry_and_unref_streams;
993         else
994                 f = do_free_dentry;
995
996         for_dentry_in_tree_depth(root, f, lookup_table);
997 }
998
999 /* Insert the @child dentry into the case sensitive index of the @dir directory.
1000  * Return NULL if successfully inserted, otherwise a pointer to the
1001  * already-inserted duplicate.  */
1002 static struct wim_dentry *
1003 dir_index_child(struct wim_inode *dir, struct wim_dentry *child)
1004 {
1005         struct avl_tree_node *duplicate;
1006
1007         duplicate = avl_tree_insert(&dir->i_children,
1008                                     &child->d_index_node,
1009                                     _avl_dentry_compare_names);
1010         if (!duplicate)
1011                 return NULL;
1012         return avl_tree_entry(duplicate, struct wim_dentry, d_index_node);
1013 }
1014
1015 /* Insert the @child dentry into the case insensitive index of the @dir
1016  * directory.  Return NULL if successfully inserted, otherwise a pointer to the
1017  * already-inserted duplicate.  */
1018 static struct wim_dentry *
1019 dir_index_child_ci(struct wim_inode *dir, struct wim_dentry *child)
1020 {
1021         struct avl_tree_node *duplicate;
1022
1023         duplicate = avl_tree_insert(&dir->i_children_ci,
1024                                     &child->d_index_node_ci,
1025                                     _avl_dentry_compare_names_ci);
1026         if (!duplicate)
1027                 return NULL;
1028         return avl_tree_entry(duplicate, struct wim_dentry, d_index_node_ci);
1029 }
1030
1031 /* Removes the specified dentry from its directory's case-sensitive index.  */
1032 static void
1033 dir_unindex_child(struct wim_inode *dir, struct wim_dentry *child)
1034 {
1035         avl_tree_remove(&dir->i_children, &child->d_index_node);
1036 }
1037
1038 /* Removes the specified dentry from its directory's case-insensitive index.  */
1039 static void
1040 dir_unindex_child_ci(struct wim_inode *dir, struct wim_dentry *child)
1041 {
1042         avl_tree_remove(&dir->i_children_ci, &child->d_index_node_ci);
1043 }
1044
1045 /* Returns true iff the specified dentry is in its parent directory's
1046  * case-insensitive index.  */
1047 static bool
1048 dentry_in_ci_index(const struct wim_dentry *dentry)
1049 {
1050         return !avl_tree_node_is_unlinked(&dentry->d_index_node_ci);
1051 }
1052
1053 /*
1054  * Links a dentry into the directory tree.
1055  *
1056  * @parent: The dentry that will be the parent of @child.
1057  * @child: The dentry to link.
1058  *
1059  * Returns NULL if successful.  If @parent already contains a dentry with the
1060  * same case-sensitive name as @child, returns a pointer to this duplicate
1061  * dentry.
1062  */
1063 struct wim_dentry *
1064 dentry_add_child(struct wim_dentry *parent, struct wim_dentry *child)
1065 {
1066         struct wim_dentry *duplicate;
1067         struct wim_inode *dir;
1068
1069         wimlib_assert(parent != child);
1070
1071         dir = parent->d_inode;
1072
1073         wimlib_assert(inode_is_directory(dir));
1074
1075         duplicate = dir_index_child(dir, child);
1076         if (duplicate)
1077                 return duplicate;
1078
1079         duplicate = dir_index_child_ci(dir, child);
1080         if (duplicate) {
1081                 list_add(&child->d_ci_conflict_list, &duplicate->d_ci_conflict_list);
1082                 avl_tree_node_set_unlinked(&child->d_index_node_ci);
1083         } else {
1084                 INIT_LIST_HEAD(&child->d_ci_conflict_list);
1085         }
1086         child->d_parent = parent;
1087         return NULL;
1088 }
1089
1090 /* Unlink a WIM dentry from the directory entry tree.  */
1091 void
1092 unlink_dentry(struct wim_dentry *dentry)
1093 {
1094         struct wim_inode *dir;
1095
1096         if (dentry_is_root(dentry))
1097                 return;
1098
1099         dir = dentry->d_parent->d_inode;
1100
1101         dir_unindex_child(dir, dentry);
1102
1103         if (dentry_in_ci_index(dentry)) {
1104
1105                 dir_unindex_child_ci(dir, dentry);
1106
1107                 if (!list_empty(&dentry->d_ci_conflict_list)) {
1108                         /* Make a different case-insensitively-the-same dentry
1109                          * be the "representative" in the search index. */
1110                         struct list_head *next;
1111                         struct wim_dentry *other;
1112                         struct wim_dentry *existing;
1113
1114                         next = dentry->d_ci_conflict_list.next;
1115                         other = list_entry(next, struct wim_dentry, d_ci_conflict_list);
1116                         existing = dir_index_child_ci(dir, other);
1117                         wimlib_assert(existing == NULL);
1118                 }
1119         }
1120         list_del(&dentry->d_ci_conflict_list);
1121 }
1122
1123 static int
1124 read_extra_data(const u8 *p, const u8 *end, struct wim_inode *inode)
1125 {
1126         while (((uintptr_t)p & 7) && p < end)
1127                 p++;
1128
1129         if (unlikely(p < end)) {
1130                 inode->i_extra = memdup(p, end - p);
1131                 if (!inode->i_extra)
1132                         return WIMLIB_ERR_NOMEM;
1133                 inode->i_extra_size = end - p;
1134         }
1135         return 0;
1136 }
1137
1138 /* Reads a WIM directory entry, including all alternate data stream entries that
1139  * follow it, from the WIM image's metadata resource.  */
1140 static int
1141 read_dentry(const u8 * restrict buf, size_t buf_len,
1142             u64 *offset_p, struct wim_dentry **dentry_ret)
1143 {
1144         u64 offset = *offset_p;
1145         u64 length;
1146         const u8 *p;
1147         const struct wim_dentry_on_disk *disk_dentry;
1148         struct wim_dentry *dentry;
1149         struct wim_inode *inode;
1150         u16 short_name_nbytes;
1151         u16 file_name_nbytes;
1152         u64 calculated_size;
1153         int ret;
1154
1155         BUILD_BUG_ON(sizeof(struct wim_dentry_on_disk) != WIM_DENTRY_DISK_SIZE);
1156
1157         /* Before reading the whole dentry, we need to read just the length.
1158          * This is because a dentry of length 8 (that is, just the length field)
1159          * terminates the list of sibling directory entries. */
1160
1161         /* Check for buffer overrun.  */
1162         if (unlikely(offset + sizeof(u64) > buf_len ||
1163                      offset + sizeof(u64) < offset))
1164         {
1165                 ERROR("Directory entry starting at %"PRIu64" ends past the "
1166                       "end of the metadata resource (size %zu)",
1167                       offset, buf_len);
1168                 return WIMLIB_ERR_INVALID_METADATA_RESOURCE;
1169         }
1170
1171         /* Get pointer to the dentry data.  */
1172         p = &buf[offset];
1173         disk_dentry = (const struct wim_dentry_on_disk*)p;
1174
1175         /* Get dentry length.  */
1176         length = le64_to_cpu(disk_dentry->length);
1177
1178         /* Check for end-of-directory.  */
1179         if (length <= 8) {
1180                 *dentry_ret = NULL;
1181                 return 0;
1182         }
1183
1184         /* Validate dentry length.  */
1185         if (unlikely(length < sizeof(struct wim_dentry_on_disk))) {
1186                 ERROR("Directory entry has invalid length of %"PRIu64" bytes",
1187                       length);
1188                 return WIMLIB_ERR_INVALID_METADATA_RESOURCE;
1189         }
1190
1191         /* Check for buffer overrun.  */
1192         if (unlikely(offset + length > buf_len ||
1193                      offset + length < offset))
1194         {
1195                 ERROR("Directory entry at offset %"PRIu64" and with size "
1196                       "%"PRIu64" ends past the end of the metadata resource "
1197                       "(size %zu)", offset, length, buf_len);
1198                 return WIMLIB_ERR_INVALID_METADATA_RESOURCE;
1199         }
1200
1201         /* Allocate new dentry structure, along with a preliminary inode.  */
1202         ret = new_dentry_with_timeless_inode(T(""), &dentry);
1203         if (ret)
1204                 return ret;
1205
1206         inode = dentry->d_inode;
1207
1208         /* Read more fields: some into the dentry, and some into the inode.  */
1209         inode->i_attributes = le32_to_cpu(disk_dentry->attributes);
1210         inode->i_security_id = le32_to_cpu(disk_dentry->security_id);
1211         dentry->subdir_offset = le64_to_cpu(disk_dentry->subdir_offset);
1212         inode->i_creation_time = le64_to_cpu(disk_dentry->creation_time);
1213         inode->i_last_access_time = le64_to_cpu(disk_dentry->last_access_time);
1214         inode->i_last_write_time = le64_to_cpu(disk_dentry->last_write_time);
1215         copy_hash(inode->i_hash, disk_dentry->unnamed_stream_hash);
1216
1217         /* I don't know what's going on here.  It seems like M$ screwed up the
1218          * reparse points, then put the fields in the same place and didn't
1219          * document it.  So we have some fields we read for reparse points, and
1220          * some fields in the same place for non-reparse-points.  */
1221         if (inode->i_attributes & FILE_ATTRIBUTE_REPARSE_POINT) {
1222                 inode->i_rp_unknown_1 = le32_to_cpu(disk_dentry->reparse.rp_unknown_1);
1223                 inode->i_reparse_tag = le32_to_cpu(disk_dentry->reparse.reparse_tag);
1224                 inode->i_rp_unknown_2 = le16_to_cpu(disk_dentry->reparse.rp_unknown_2);
1225                 inode->i_not_rpfixed = le16_to_cpu(disk_dentry->reparse.not_rpfixed);
1226                 /* Leave inode->i_ino at 0.  Note that this means the WIM file
1227                  * cannot archive hard-linked reparse points.  Such a thing
1228                  * doesn't really make sense anyway, although I believe it's
1229                  * theoretically possible to have them on NTFS.  */
1230         } else {
1231                 inode->i_rp_unknown_1 = le32_to_cpu(disk_dentry->nonreparse.rp_unknown_1);
1232                 inode->i_ino = le64_to_cpu(disk_dentry->nonreparse.hard_link_group_id);
1233         }
1234         inode->i_num_ads = le16_to_cpu(disk_dentry->num_alternate_data_streams);
1235
1236         /* Now onto reading the names.  There are two of them: the (long) file
1237          * name, and the short name.  */
1238
1239         short_name_nbytes = le16_to_cpu(disk_dentry->short_name_nbytes);
1240         file_name_nbytes = le16_to_cpu(disk_dentry->file_name_nbytes);
1241
1242         if (unlikely((short_name_nbytes & 1) | (file_name_nbytes & 1))) {
1243                 ERROR("Dentry name is not valid UTF-16 (odd number of bytes)!");
1244                 ret = WIMLIB_ERR_INVALID_METADATA_RESOURCE;
1245                 goto err_free_dentry;
1246         }
1247
1248         /* We now know the length of the file name and short name.  Make sure
1249          * the length of the dentry is large enough to actually hold them.
1250          *
1251          * The calculated length here is unaligned to allow for the possibility
1252          * that the dentry's length is unaligned, although this would be
1253          * unexpected.  */
1254         calculated_size = dentry_min_len_with_names(file_name_nbytes,
1255                                                     short_name_nbytes);
1256
1257         if (unlikely(length < calculated_size)) {
1258                 ERROR("Unexpected end of directory entry! (Expected "
1259                       "at least %"PRIu64" bytes, got %"PRIu64" bytes.)",
1260                       calculated_size, length);
1261                 ret = WIMLIB_ERR_INVALID_METADATA_RESOURCE;
1262                 goto err_free_dentry;
1263         }
1264
1265         /* Advance p to point past the base dentry, to the first name.  */
1266         p += sizeof(struct wim_dentry_on_disk);
1267
1268         /* Read the filename if present.  Note: if the filename is empty, there
1269          * is no null terminator following it.  */
1270         if (file_name_nbytes) {
1271                 dentry->file_name = utf16le_dupz((const utf16lechar *)p,
1272                                                  file_name_nbytes);
1273                 if (dentry->file_name == NULL) {
1274                         ret = WIMLIB_ERR_NOMEM;
1275                         goto err_free_dentry;
1276                 }
1277                 dentry->file_name_nbytes = file_name_nbytes;
1278                 p += file_name_nbytes + 2;
1279         }
1280
1281         /* Read the short filename if present.  Note: if there is no short
1282          * filename, there is no null terminator following it. */
1283         if (short_name_nbytes) {
1284                 dentry->short_name = utf16le_dupz((const utf16lechar *)p,
1285                                                   short_name_nbytes);
1286                 if (dentry->short_name == NULL) {
1287                         ret = WIMLIB_ERR_NOMEM;
1288                         goto err_free_dentry;
1289                 }
1290                 dentry->short_name_nbytes = short_name_nbytes;
1291                 p += short_name_nbytes + 2;
1292         }
1293
1294         /* Read extra data at end of dentry (but before alternate data stream
1295          * entries).  This may contain tagged items.  */
1296         ret = read_extra_data(p, &buf[offset + length], inode);
1297         if (ret)
1298                 goto err_free_dentry;
1299
1300         /* Align the dentry length.  */
1301         length = (length + 7) & ~7;
1302
1303         offset += length;
1304
1305         /* Read the alternate data streams, if present.  inode->i_num_ads tells
1306          * us how many they are, and they will directly follow the dentry in the
1307          * metadata resource buffer.
1308          *
1309          * Note that each alternate data stream entry begins on an 8-byte
1310          * aligned boundary, and the alternate data stream entries seem to NOT
1311          * be included in the dentry->length field for some reason.  */
1312         if (unlikely(inode->i_num_ads != 0)) {
1313                 size_t orig_bytes_remaining;
1314                 size_t bytes_remaining;
1315
1316                 if (offset > buf_len) {
1317                         ret = WIMLIB_ERR_INVALID_METADATA_RESOURCE;
1318                         goto err_free_dentry;
1319                 }
1320                 bytes_remaining = buf_len - offset;
1321                 orig_bytes_remaining = bytes_remaining;
1322                 ret = read_ads_entries(&buf[offset], inode, &bytes_remaining);
1323                 if (ret)
1324                         goto err_free_dentry;
1325                 offset += (orig_bytes_remaining - bytes_remaining);
1326         }
1327
1328         *offset_p = offset;  /* Sets offset of next dentry in directory  */
1329         *dentry_ret = dentry;
1330         return 0;
1331
1332 err_free_dentry:
1333         free_dentry(dentry);
1334         return ret;
1335 }
1336
1337 static bool
1338 dentry_is_dot_or_dotdot(const struct wim_dentry *dentry)
1339 {
1340         if (dentry->file_name_nbytes <= 4) {
1341                 if (dentry->file_name_nbytes == 4) {
1342                         if (dentry->file_name[0] == cpu_to_le16('.') &&
1343                             dentry->file_name[1] == cpu_to_le16('.'))
1344                                 return true;
1345                 } else if (dentry->file_name_nbytes == 2) {
1346                         if (dentry->file_name[0] == cpu_to_le16('.'))
1347                                 return true;
1348                 }
1349         }
1350         return false;
1351 }
1352
1353 static int
1354 read_dentry_tree_recursive(const u8 * restrict buf, size_t buf_len,
1355                            struct wim_dentry * restrict dir)
1356 {
1357         u64 cur_offset = dir->subdir_offset;
1358
1359         /* Check for cyclic directory structure, which would cause infinite
1360          * recursion if not handled.  */
1361         for (struct wim_dentry *d = dir->d_parent;
1362              !dentry_is_root(d); d = d->d_parent)
1363         {
1364                 if (unlikely(d->subdir_offset == cur_offset)) {
1365                         ERROR("Cyclic directory structure detected: children "
1366                               "of \"%"TS"\" coincide with children of \"%"TS"\"",
1367                               dentry_full_path(dir), dentry_full_path(d));
1368                         return WIMLIB_ERR_INVALID_METADATA_RESOURCE;
1369                 }
1370         }
1371
1372         for (;;) {
1373                 struct wim_dentry *child;
1374                 struct wim_dentry *duplicate;
1375                 int ret;
1376
1377                 /* Read next child of @dir.  */
1378                 ret = read_dentry(buf, buf_len, &cur_offset, &child);
1379                 if (ret)
1380                         return ret;
1381
1382                 /* Check for end of directory.  */
1383                 if (child == NULL)
1384                         return 0;
1385
1386                 /* All dentries except the root should be named.  */
1387                 if (unlikely(!dentry_has_long_name(child))) {
1388                         WARNING("Ignoring unnamed dentry in "
1389                                 "directory \"%"TS"\"", dentry_full_path(dir));
1390                         free_dentry(child);
1391                         continue;
1392                 }
1393
1394                 /* Don't allow files named "." or "..".  */
1395                 if (unlikely(dentry_is_dot_or_dotdot(child))) {
1396                         WARNING("Ignoring file named \".\" or \"..\"; "
1397                                 "potentially malicious archive!!!");
1398                         free_dentry(child);
1399                         continue;
1400                 }
1401
1402                 /* Link the child into the directory.  */
1403                 duplicate = dentry_add_child(dir, child);
1404                 if (unlikely(duplicate)) {
1405                         /* We already found a dentry with this same
1406                          * case-sensitive long name.  Only keep the first one.
1407                          */
1408                         WARNING("Ignoring duplicate file \"%"TS"\" "
1409                                 "(the WIM image already contains a file "
1410                                 "at that path with the exact same name)",
1411                                 dentry_full_path(duplicate));
1412                         free_dentry(child);
1413                         continue;
1414                 }
1415
1416                 /* If this child is a directory that itself has children, call
1417                  * this procedure recursively.  */
1418                 if (child->subdir_offset != 0) {
1419                         if (likely(dentry_is_directory(child))) {
1420                                 ret = read_dentry_tree_recursive(buf,
1421                                                                  buf_len,
1422                                                                  child);
1423                                 if (ret)
1424                                         return ret;
1425                         } else {
1426                                 WARNING("Ignoring children of "
1427                                         "non-directory file \"%"TS"\"",
1428                                         dentry_full_path(child));
1429                         }
1430                 }
1431         }
1432 }
1433
1434 /*
1435  * Read a tree of dentries (directory entries) from a WIM metadata resource.
1436  *
1437  * @buf:
1438  *      Buffer containing an uncompressed WIM metadata resource.
1439  *
1440  * @buf_len:
1441  *      Length of the uncompressed metadata resource, in bytes.
1442  *
1443  * @root_offset
1444  *      Offset in the metadata resource of the root of the dentry tree.
1445  *
1446  * @root_ret:
1447  *      On success, either NULL or a pointer to the root dentry is written to
1448  *      this location.  The former case only occurs in the unexpected case that
1449  *      the tree began with an end-of-directory entry.
1450  *
1451  * Return values:
1452  *      WIMLIB_ERR_SUCCESS (0)
1453  *      WIMLIB_ERR_INVALID_METADATA_RESOURCE
1454  *      WIMLIB_ERR_NOMEM
1455  */
1456 int
1457 read_dentry_tree(const u8 *buf, size_t buf_len,
1458                  u64 root_offset, struct wim_dentry **root_ret)
1459 {
1460         int ret;
1461         struct wim_dentry *root;
1462
1463         DEBUG("Reading dentry tree (root_offset=%"PRIu64")", root_offset);
1464
1465         ret = read_dentry(buf, buf_len, &root_offset, &root);
1466         if (ret)
1467                 return ret;
1468
1469         if (likely(root != NULL)) {
1470                 if (unlikely(dentry_has_long_name(root) ||
1471                              dentry_has_short_name(root)))
1472                 {
1473                         WARNING("The root directory has a nonempty name; "
1474                                 "removing it.");
1475                         FREE(root->file_name);
1476                         FREE(root->short_name);
1477                         root->file_name = NULL;
1478                         root->short_name = NULL;
1479                         root->file_name_nbytes = 0;
1480                         root->short_name_nbytes = 0;
1481                 }
1482
1483                 if (unlikely(!dentry_is_directory(root))) {
1484                         ERROR("The root of the WIM image is not a directory!");
1485                         ret = WIMLIB_ERR_INVALID_METADATA_RESOURCE;
1486                         goto err_free_dentry_tree;
1487                 }
1488
1489                 if (likely(root->subdir_offset != 0)) {
1490                         ret = read_dentry_tree_recursive(buf, buf_len, root);
1491                         if (ret)
1492                                 goto err_free_dentry_tree;
1493                 }
1494         } else {
1495                 WARNING("The metadata resource has no directory entries; "
1496                         "treating as an empty image.");
1497         }
1498         *root_ret = root;
1499         return 0;
1500
1501 err_free_dentry_tree:
1502         free_dentry_tree(root, NULL);
1503         return ret;
1504 }
1505
1506 /*
1507  * Writes a WIM alternate data stream (ADS) entry to an output buffer.
1508  *
1509  * @ads_entry:  The ADS entry structure.
1510  * @hash:       The hash field to use (instead of the one in the ADS entry).
1511  * @p:          The memory location to write the data to.
1512  *
1513  * Returns a pointer to the byte after the last byte written.
1514  */
1515 static u8 *
1516 write_ads_entry(const struct wim_ads_entry *ads_entry,
1517                 const u8 *hash, u8 * restrict p)
1518 {
1519         struct wim_ads_entry_on_disk *disk_ads_entry =
1520                         (struct wim_ads_entry_on_disk*)p;
1521         u8 *orig_p = p;
1522
1523         disk_ads_entry->reserved = cpu_to_le64(ads_entry->reserved);
1524         copy_hash(disk_ads_entry->hash, hash);
1525         disk_ads_entry->stream_name_nbytes = cpu_to_le16(ads_entry->stream_name_nbytes);
1526         p += sizeof(struct wim_ads_entry_on_disk);
1527         if (ads_entry->stream_name_nbytes) {
1528                 p = mempcpy(p, ads_entry->stream_name,
1529                             ads_entry->stream_name_nbytes + 2);
1530         }
1531         /* Align to 8-byte boundary */
1532         while ((uintptr_t)p & 7)
1533                 *p++ = 0;
1534         disk_ads_entry->length = cpu_to_le64(p - orig_p);
1535         return p;
1536 }
1537
1538 /*
1539  * Writes a WIM dentry to an output buffer.
1540  *
1541  * @dentry:  The dentry structure.
1542  * @p:       The memory location to write the data to.
1543  *
1544  * Returns the pointer to the byte after the last byte we wrote as part of the
1545  * dentry, including any alternate data stream entries.
1546  */
1547 static u8 *
1548 write_dentry(const struct wim_dentry * restrict dentry, u8 * restrict p)
1549 {
1550         const struct wim_inode *inode;
1551         struct wim_dentry_on_disk *disk_dentry;
1552         const u8 *orig_p;
1553         const u8 *hash;
1554         bool use_dummy_stream;
1555         u16 num_ads;
1556
1557         wimlib_assert(((uintptr_t)p & 7) == 0); /* 8 byte aligned */
1558         orig_p = p;
1559
1560         inode = dentry->d_inode;
1561         use_dummy_stream = inode_needs_dummy_stream(inode);
1562         disk_dentry = (struct wim_dentry_on_disk*)p;
1563
1564         disk_dentry->attributes = cpu_to_le32(inode->i_attributes);
1565         disk_dentry->security_id = cpu_to_le32(inode->i_security_id);
1566         disk_dentry->subdir_offset = cpu_to_le64(dentry->subdir_offset);
1567
1568         /* UNIX data uses the two 8-byte reserved fields.  So if no UNIX data
1569          * exists, they get set to 0, just as we would do anyway.  */
1570         disk_dentry->unused_1 = cpu_to_le64(0);
1571         disk_dentry->unused_2 = cpu_to_le64(0);
1572
1573         disk_dentry->creation_time = cpu_to_le64(inode->i_creation_time);
1574         disk_dentry->last_access_time = cpu_to_le64(inode->i_last_access_time);
1575         disk_dentry->last_write_time = cpu_to_le64(inode->i_last_write_time);
1576         if (use_dummy_stream)
1577                 hash = zero_hash;
1578         else
1579                 hash = inode_stream_hash(inode, 0);
1580         copy_hash(disk_dentry->unnamed_stream_hash, hash);
1581         if (inode->i_attributes & FILE_ATTRIBUTE_REPARSE_POINT) {
1582                 disk_dentry->reparse.rp_unknown_1 = cpu_to_le32(inode->i_rp_unknown_1);
1583                 disk_dentry->reparse.reparse_tag = cpu_to_le32(inode->i_reparse_tag);
1584                 disk_dentry->reparse.rp_unknown_2 = cpu_to_le16(inode->i_rp_unknown_2);
1585                 disk_dentry->reparse.not_rpfixed = cpu_to_le16(inode->i_not_rpfixed);
1586         } else {
1587                 disk_dentry->nonreparse.rp_unknown_1 = cpu_to_le32(inode->i_rp_unknown_1);
1588                 disk_dentry->nonreparse.hard_link_group_id =
1589                         cpu_to_le64((inode->i_nlink == 1) ? 0 : inode->i_ino);
1590         }
1591         num_ads = inode->i_num_ads;
1592         if (use_dummy_stream)
1593                 num_ads++;
1594         disk_dentry->num_alternate_data_streams = cpu_to_le16(num_ads);
1595         disk_dentry->short_name_nbytes = cpu_to_le16(dentry->short_name_nbytes);
1596         disk_dentry->file_name_nbytes = cpu_to_le16(dentry->file_name_nbytes);
1597         p += sizeof(struct wim_dentry_on_disk);
1598
1599         wimlib_assert(dentry_is_root(dentry) != dentry_has_long_name(dentry));
1600
1601         if (dentry_has_long_name(dentry))
1602                 p = mempcpy(p, dentry->file_name, dentry->file_name_nbytes + 2);
1603
1604         if (dentry_has_short_name(dentry))
1605                 p = mempcpy(p, dentry->short_name, dentry->short_name_nbytes + 2);
1606
1607         /* Align to 8-byte boundary */
1608         while ((uintptr_t)p & 7)
1609                 *p++ = 0;
1610
1611         if (inode->i_extra_size) {
1612                 /* Extra tagged items --- not usually present.  */
1613                 p = mempcpy(p, inode->i_extra, inode->i_extra_size);
1614                 while ((uintptr_t)p & 7)
1615                         *p++ = 0;
1616         }
1617
1618         disk_dentry->length = cpu_to_le64(p - orig_p);
1619
1620         if (use_dummy_stream) {
1621                 hash = inode_unnamed_stream_hash(inode);
1622                 p = write_ads_entry(&(struct wim_ads_entry){}, hash, p);
1623         }
1624
1625         /* Write the alternate data streams entries, if any. */
1626         for (u16 i = 0; i < inode->i_num_ads; i++) {
1627                 hash = inode_stream_hash(inode, i + 1);
1628                 p = write_ads_entry(&inode->i_ads_entries[i], hash, p);
1629         }
1630
1631         return p;
1632 }
1633
1634 static int
1635 write_dir_dentries(struct wim_dentry *dir, void *_pp)
1636 {
1637         if (dir->subdir_offset != 0) {
1638                 u8 **pp = _pp;
1639                 u8 *p = *pp;
1640                 struct wim_dentry *child;
1641
1642                 /* write child dentries */
1643                 for_dentry_child(child, dir)
1644                         p = write_dentry(child, p);
1645
1646                 /* write end of directory entry */
1647                 *(u64*)p = 0;
1648                 p += 8;
1649                 *pp = p;
1650         }
1651         return 0;
1652 }
1653
1654 /* Writes a directory tree to the metadata resource.
1655  *
1656  * @root:       Root of the dentry tree.
1657  * @p:          Pointer to a buffer with enough space for the dentry tree.
1658  *
1659  * Returns pointer to the byte after the last byte we wrote.
1660  */
1661 u8 *
1662 write_dentry_tree(struct wim_dentry *root, u8 *p)
1663 {
1664         DEBUG("Writing dentry tree.");
1665         wimlib_assert(dentry_is_root(root));
1666
1667         /* write root dentry and end-of-directory entry following it */
1668         p = write_dentry(root, p);
1669         *(u64*)p = 0;
1670         p += 8;
1671
1672         /* write the rest of the dentry tree */
1673         for_dentry_in_tree(root, write_dir_dentries, &p);
1674
1675         return p;
1676 }