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