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