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