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