]> wimlib.net Git - wimlib/blob - src/dentry.c
warning if null filename terminator is not null
[wimlib] / src / dentry.c
1 /*
2  * dentry.c
3  *
4  * A dentry (directory entry) contains the metadata for a file.  In the WIM file
5  * format, the dentries are stored in the "metadata resource" section right
6  * after the security data.  Each image in the WIM file has its own metadata
7  * resource with its own security data and dentry tree.  Dentries in different
8  * images may share file resources by referring to the same lookup table
9  * entries.
10  */
11
12 /*
13  *
14  * Copyright (C) 2010 Carl Thijssen
15  * Copyright (C) 2012 Eric Biggers
16  *
17  * This file is part of wimlib, a library for working with WIM files.
18  *
19  * wimlib is free software; you can redistribute it and/or modify it under the
20  * terms of the GNU Lesser General Public License as published by the Free
21  * Software Foundation; either version 2.1 of the License, or (at your option)
22  * any later version.
23  *
24  * wimlib is distributed in the hope that it will be useful, but WITHOUT ANY
25  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
26  * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
27  * details.
28  *
29  * You should have received a copy of the GNU Lesser General Public License
30  * along with wimlib; if not, see http://www.gnu.org/licenses/.
31  */
32
33 #include <errno.h>
34 #include <sys/stat.h>
35 #include <time.h>
36 #include <unistd.h>
37
38 #include "dentry.h"
39 #include "io.h"
40 #include "lookup_table.h"
41 #include "sha1.h"
42 #include "timestamp.h"
43 #include "wimlib_internal.h"
44
45 /*
46  * Returns true if @dentry has the UTF-8 file name @name that has length
47  * @name_len.
48  */
49 static bool dentry_has_name(const struct dentry *dentry, const char *name, 
50                             size_t name_len)
51 {
52         if (dentry->file_name_utf8_len != name_len)
53                 return false;
54         return memcmp(dentry->file_name_utf8, name, name_len) == 0;
55 }
56
57 /* Real length of a dentry, including the alternate data stream entries, which
58  * are not included in the dentry->length field... */
59 u64 dentry_total_length(const struct dentry *dentry)
60 {
61         u64 length = (dentry->length + 7) & ~7;
62         for (u16 i = 0; i < dentry->num_ads; i++)
63                 length += ads_entry_total_length(&dentry->ads_entries[i]);
64         return length;
65 }
66
67 /* Transfers file attributes from a `stat' buffer to a struct dentry. */
68 void stbuf_to_dentry(const struct stat *stbuf, struct dentry *dentry)
69 {
70         if (S_ISLNK(stbuf->st_mode)) {
71                 dentry->attributes = FILE_ATTRIBUTE_REPARSE_POINT;
72                 dentry->reparse_tag = WIM_IO_REPARSE_TAG_SYMLINK;
73         } else if (S_ISDIR(stbuf->st_mode)) {
74                 dentry->attributes = FILE_ATTRIBUTE_DIRECTORY;
75         } else {
76                 dentry->attributes = FILE_ATTRIBUTE_NORMAL;
77         }
78         if (sizeof(ino_t) >= 8)
79                 dentry->hard_link = (u64)stbuf->st_ino;
80         else
81                 dentry->hard_link = (u64)stbuf->st_ino |
82                                    ((u64)stbuf->st_dev << (sizeof(ino_t) * 8));
83         /* Set timestamps */
84         dentry->creation_time = timespec_to_wim_timestamp(&stbuf->st_mtim);
85         dentry->last_write_time = timespec_to_wim_timestamp(&stbuf->st_mtim);
86         dentry->last_access_time = timespec_to_wim_timestamp(&stbuf->st_atim);
87 }
88
89
90 /* Sets all the timestamp fields of the dentry to the current time. */
91 void dentry_update_all_timestamps(struct dentry *dentry)
92 {
93         u64 now = get_wim_timestamp();
94         dentry->creation_time    = now;
95         dentry->last_access_time = now;
96         dentry->last_write_time  = now;
97 }
98
99 /* Returns the alternate data stream entry belonging to @dentry that has the
100  * stream name @stream_name. */
101 struct ads_entry *dentry_get_ads_entry(struct dentry *dentry,
102                                        const char *stream_name)
103 {
104         size_t stream_name_len;
105         if (!stream_name)
106                 return NULL;
107         if (dentry->num_ads) {
108                 u16 i = 0;
109                 stream_name_len = strlen(stream_name);
110                 do {
111                         if (ads_entry_has_name(&dentry->ads_entries[i],
112                                                stream_name, stream_name_len))
113                                 return &dentry->ads_entries[i];
114                 } while (++i != dentry->num_ads);
115         }
116         return NULL;
117 }
118
119 static void ads_entry_init(struct ads_entry *ads_entry)
120 {
121         memset(ads_entry, 0, sizeof(struct ads_entry));
122         INIT_LIST_HEAD(&ads_entry->lte_group_list.list);
123         ads_entry->lte_group_list.type = STREAM_TYPE_ADS;
124 }
125
126 /* 
127  * Add an alternate stream entry to a dentry and return a pointer to it, or NULL
128  * if memory could not be allocated.
129  */
130 struct ads_entry *dentry_add_ads(struct dentry *dentry, const char *stream_name)
131 {
132         u16 num_ads;
133         struct ads_entry *ads_entries;
134         struct ads_entry *new_entry;
135
136         DEBUG("Add alternate data stream %s:%s",
137                dentry->file_name_utf8, stream_name);
138
139         if (dentry->num_ads == 0xffff)
140                 return NULL;
141         num_ads = dentry->num_ads + 1;
142         ads_entries = REALLOC(dentry->ads_entries,
143                               num_ads * sizeof(struct ads_entry));
144         if (!ads_entries)
145                 return NULL;
146         if (ads_entries != dentry->ads_entries) {
147                 /* We moved the ADS entries.  Adjust the stream lists. */
148                 for (u16 i = 0; i < dentry->num_ads; i++) {
149                         struct list_head *cur = &ads_entries[i].lte_group_list.list;
150                         cur->prev->next = cur;
151                         cur->next->prev = cur;
152                 }
153         }
154
155         new_entry = &ads_entries[num_ads - 1];
156         ads_entry_init(new_entry);
157         if (change_ads_name(new_entry, stream_name) != 0)
158                 return NULL;
159         dentry->ads_entries = ads_entries;
160         dentry->num_ads = num_ads;
161         return new_entry;
162 }
163
164 /* Remove an alternate data stream from a dentry.
165  *
166  * The corresponding lookup table entry for the stream is NOT changed.
167  *
168  * @dentry:     The dentry
169  * @ads_entry:  The alternate data stream entry (it MUST be one of the
170  *                 ads_entry's in the array dentry->ads_entries).
171  */
172 void dentry_remove_ads(struct dentry *dentry, struct ads_entry *ads_entry)
173 {
174         u16 idx;
175         u16 following;
176
177         wimlib_assert(dentry->num_ads);
178         idx = ads_entry - dentry->ads_entries;
179         wimlib_assert(idx < dentry->num_ads);
180         following = dentry->num_ads - idx - 1;
181
182         destroy_ads_entry(ads_entry);
183         memcpy(ads_entry, ads_entry + 1, following * sizeof(struct ads_entry));
184
185         /* We moved the ADS entries.  Adjust the stream lists. */
186         for (u16 i = 0; i < following; i++) {
187                 struct list_head *cur = &ads_entry[i].lte_group_list.list;
188                 cur->prev->next = cur;
189                 cur->next->prev = cur;
190         }
191
192         dentry->num_ads--;
193 }
194
195 /* 
196  * Calls a function on all directory entries in a directory tree.  It is called
197  * on a parent before its children.
198  */
199 int for_dentry_in_tree(struct dentry *root, 
200                        int (*visitor)(struct dentry*, void*), void *arg)
201 {
202         int ret;
203         struct dentry *child;
204
205         ret = visitor(root, arg);
206
207         if (ret != 0)
208                 return ret;
209
210         child = root->children;
211
212         if (!child)
213                 return 0;
214
215         do {
216                 ret = for_dentry_in_tree(child, visitor, arg);
217                 if (ret != 0)
218                         return ret;
219                 child = child->next;
220         } while (child != root->children);
221         return 0;
222 }
223
224 /* 
225  * Like for_dentry_in_tree(), but the visitor function is always called on a
226  * dentry's children before on itself.
227  */
228 int for_dentry_in_tree_depth(struct dentry *root, 
229                              int (*visitor)(struct dentry*, void*), void *arg)
230 {
231         int ret;
232         struct dentry *child;
233         struct dentry *next;
234
235         child = root->children;
236         if (child) {
237                 do {
238                         next = child->next;
239                         ret = for_dentry_in_tree_depth(child, visitor, arg);
240                         if (ret != 0)
241                                 return ret;
242                         child = next;
243                 } while (child != root->children);
244         }
245         return visitor(root, arg);
246 }
247
248 /* 
249  * Calculate the full path of @dentry, based on its parent's full path and on
250  * its UTF-8 file name. 
251  */
252 int calculate_dentry_full_path(struct dentry *dentry, void *ignore)
253 {
254         char *full_path;
255         u32 full_path_len;
256         if (dentry_is_root(dentry)) {
257                 full_path = MALLOC(2);
258                 if (!full_path)
259                         goto oom;
260                 full_path[0] = '/';
261                 full_path[1] = '\0';
262                 full_path_len = 1;
263         } else {
264                 char *parent_full_path;
265                 u32 parent_full_path_len;
266                 const struct dentry *parent = dentry->parent;
267
268                 if (dentry_is_root(parent)) {
269                         parent_full_path = "";
270                         parent_full_path_len = 0;
271                 } else {
272                         parent_full_path = parent->full_path_utf8;
273                         parent_full_path_len = parent->full_path_utf8_len;
274                 }
275
276                 full_path_len = parent_full_path_len + 1 +
277                                 dentry->file_name_utf8_len;
278                 full_path = MALLOC(full_path_len + 1);
279                 if (!full_path)
280                         goto oom;
281
282                 memcpy(full_path, parent_full_path, parent_full_path_len);
283                 full_path[parent_full_path_len] = '/';
284                 memcpy(full_path + parent_full_path_len + 1,
285                        dentry->file_name_utf8,
286                        dentry->file_name_utf8_len);
287                 full_path[full_path_len] = '\0';
288         }
289         FREE(dentry->full_path_utf8);
290         dentry->full_path_utf8 = full_path;
291         dentry->full_path_utf8_len = full_path_len;
292         return 0;
293 oom:
294         ERROR("Out of memory while calculating dentry full path");
295         return WIMLIB_ERR_NOMEM;
296 }
297
298 /* 
299  * Recursively calculates the subdir offsets for a directory tree. 
300  *
301  * @dentry:  The root of the directory tree.
302  * @subdir_offset_p:  The current subdirectory offset; i.e., the subdirectory
303  *      offset for @dentry. 
304  */
305 void calculate_subdir_offsets(struct dentry *dentry, u64 *subdir_offset_p)
306 {
307         struct dentry *child;
308
309         child = dentry->children;
310         dentry->subdir_offset = *subdir_offset_p;
311
312         if (child) {
313                 /* Advance the subdir offset by the amount of space the children
314                  * of this dentry take up. */
315                 do {
316                         *subdir_offset_p += dentry_total_length(child);
317                         child = child->next;
318                 } while (child != dentry->children);
319
320                 /* End-of-directory dentry on disk. */
321                 *subdir_offset_p += 8;
322
323                 /* Recursively call calculate_subdir_offsets() on all the
324                  * children. */
325                 do {
326                         calculate_subdir_offsets(child, subdir_offset_p);
327                         child = child->next;
328                 } while (child != dentry->children);
329         } else {
330                 /* On disk, childless directories have a valid subdir_offset
331                  * that points to an 8-byte end-of-directory dentry.  Regular
332                  * files or reparse points have a subdir_offset of 0. */
333                 if (dentry_is_directory(dentry))
334                         *subdir_offset_p += 8;
335                 else
336                         dentry->subdir_offset = 0;
337         }
338 }
339
340
341 /* Returns the child of @dentry that has the file name @name.  
342  * Returns NULL if no child has the name. */
343 struct dentry *get_dentry_child_with_name(const struct dentry *dentry, 
344                                           const char *name)
345 {
346         struct dentry *child;
347         size_t name_len;
348         
349         child = dentry->children;
350         if (child) {
351                 name_len = strlen(name);
352                 do {
353                         if (dentry_has_name(child, name, name_len))
354                                 return child;
355                         child = child->next;
356                 } while (child != dentry->children);
357         }
358         return NULL;
359 }
360
361 /* Retrieves the dentry that has the UTF-8 @path relative to the dentry
362  * @cur_dir.  Returns NULL if no dentry having the path is found. */
363 static struct dentry *get_dentry_relative_path(struct dentry *cur_dir,
364                                                const char *path)
365 {
366         struct dentry *child;
367         size_t base_len;
368         const char *new_path;
369
370         if (*path == '\0')
371                 return cur_dir;
372
373         child = cur_dir->children;
374         if (child) {
375                 new_path = path_next_part(path, &base_len);
376                 do {
377                         if (dentry_has_name(child, path, base_len))
378                                 return get_dentry_relative_path(child, new_path);
379                         child = child->next;
380                 } while (child != cur_dir->children);
381         }
382         return NULL;
383 }
384
385 /* Returns the dentry corresponding to the UTF-8 @path, or NULL if there is no
386  * such dentry. */
387 struct dentry *get_dentry(WIMStruct *w, const char *path)
388 {
389         struct dentry *root = wim_root_dentry(w);
390         while (*path == '/')
391                 path++;
392         return get_dentry_relative_path(root, path);
393 }
394
395 /* Returns the dentry that corresponds to the parent directory of @path, or NULL
396  * if the dentry is not found. */
397 struct dentry *get_parent_dentry(WIMStruct *w, const char *path)
398 {
399         size_t path_len = strlen(path);
400         char buf[path_len + 1];
401
402         memcpy(buf, path, path_len + 1);
403
404         to_parent_name(buf, path_len);
405
406         return get_dentry(w, buf);
407 }
408
409 /* Prints the full path of a dentry. */
410 int print_dentry_full_path(struct dentry *dentry, void *ignore)
411 {
412         if (dentry->full_path_utf8)
413                 puts(dentry->full_path_utf8);
414         return 0;
415 }
416
417 /* We want to be able to show the names of the file attribute flags that are
418  * set. */
419 struct file_attr_flag {
420         u32 flag;
421         const char *name;
422 };
423 struct file_attr_flag file_attr_flags[] = {
424         {FILE_ATTRIBUTE_READONLY,           "READONLY"},
425         {FILE_ATTRIBUTE_HIDDEN,             "HIDDEN"},
426         {FILE_ATTRIBUTE_SYSTEM,             "SYSTEM"},
427         {FILE_ATTRIBUTE_DIRECTORY,          "DIRECTORY"},
428         {FILE_ATTRIBUTE_ARCHIVE,            "ARCHIVE"},
429         {FILE_ATTRIBUTE_DEVICE,             "DEVICE"},
430         {FILE_ATTRIBUTE_NORMAL,             "NORMAL"},
431         {FILE_ATTRIBUTE_TEMPORARY,          "TEMPORARY"},
432         {FILE_ATTRIBUTE_SPARSE_FILE,        "SPARSE_FILE"},
433         {FILE_ATTRIBUTE_REPARSE_POINT,      "REPARSE_POINT"},
434         {FILE_ATTRIBUTE_COMPRESSED,         "COMPRESSED"},
435         {FILE_ATTRIBUTE_OFFLINE,            "OFFLINE"},
436         {FILE_ATTRIBUTE_NOT_CONTENT_INDEXED,"NOT_CONTENT_INDEXED"},
437         {FILE_ATTRIBUTE_ENCRYPTED,          "ENCRYPTED"},
438         {FILE_ATTRIBUTE_VIRTUAL,            "VIRTUAL"},
439 };
440
441 /* Prints a directory entry.  @lookup_table is a pointer to the lookup table, if
442  * available.  If the dentry is unresolved and the lookup table is NULL, the
443  * lookup table entries will not be printed.  Otherwise, they will be. */
444 int print_dentry(struct dentry *dentry, void *lookup_table)
445 {
446         const u8 *hash;
447         struct lookup_table_entry *lte;
448
449         printf("[DENTRY]\n");
450         printf("Length            = %"PRIu64"\n", dentry->length);
451         printf("Attributes        = 0x%x\n", dentry->attributes);
452         for (unsigned i = 0; i < ARRAY_LEN(file_attr_flags); i++)
453                 if (file_attr_flags[i].flag & dentry->attributes)
454                         printf("    FILE_ATTRIBUTE_%s is set\n",
455                                 file_attr_flags[i].name);
456         printf("Security ID       = %d\n", dentry->security_id);
457         printf("Subdir offset     = %"PRIu64"\n", dentry->subdir_offset);
458 #if 0
459         printf("Unused1           = 0x%"PRIu64"\n", dentry->unused1);
460         printf("Unused2           = %"PRIu64"\n", dentry->unused2);
461 #endif
462 #if 0
463         printf("Creation Time     = 0x%"PRIx64"\n");
464         printf("Last Access Time  = 0x%"PRIx64"\n");
465         printf("Last Write Time   = 0x%"PRIx64"\n");
466 #endif
467
468         /* Translate the timestamps into something readable */
469         time_t creat_time = wim_timestamp_to_unix(dentry->creation_time);
470         time_t access_time = wim_timestamp_to_unix(dentry->last_access_time);
471         time_t mod_time = wim_timestamp_to_unix(dentry->last_write_time);
472         printf("Creation Time     = %s", asctime(gmtime(&creat_time)));
473         printf("Last Access Time  = %s", asctime(gmtime(&access_time)));
474         printf("Last Write Time   = %s", asctime(gmtime(&mod_time)));
475
476         printf("Reparse Tag       = 0x%"PRIx32"\n", dentry->reparse_tag);
477         printf("Hard Link Group   = 0x%"PRIx64"\n", dentry->hard_link);
478         printf("Number of Alternate Data Streams = %hu\n", dentry->num_ads);
479         printf("Filename          = \"");
480         print_string(dentry->file_name, dentry->file_name_len);
481         puts("\"");
482         printf("Filename Length   = %hu\n", dentry->file_name_len);
483         printf("Filename (UTF-8)  = \"%s\"\n", dentry->file_name_utf8);
484         printf("Filename (UTF-8) Length = %hu\n", dentry->file_name_utf8_len);
485         printf("Short Name        = \"");
486         print_string(dentry->short_name, dentry->short_name_len);
487         puts("\"");
488         printf("Short Name Length = %hu\n", dentry->short_name_len);
489         printf("Full Path (UTF-8) = \"%s\"\n", dentry->full_path_utf8);
490         lte = dentry_stream_lte(dentry, 0, lookup_table);
491         if (lte) {
492                 print_lookup_table_entry(lte);
493         } else {
494                 hash = dentry_stream_hash(dentry, 0);
495                 if (hash) {
496                         printf("Hash              = 0x"); 
497                         print_hash(hash);
498                         putchar('\n');
499                         putchar('\n');
500                 }
501         }
502         for (u16 i = 0; i < dentry->num_ads; i++) {
503                 printf("[Alternate Stream Entry %u]\n", i);
504                 printf("Name = \"%s\"\n", dentry->ads_entries[i].stream_name_utf8);
505                 printf("Name Length (UTF-16) = %u\n",
506                                 dentry->ads_entries[i].stream_name_len);
507                 hash = dentry_stream_hash(dentry, i + 1);
508                 if (hash) {
509                         printf("Hash              = 0x"); 
510                         print_hash(hash);
511                         putchar('\n');
512                 }
513                 print_lookup_table_entry(dentry_stream_lte(dentry, i + 1,
514                                                            lookup_table));
515         }
516         return 0;
517 }
518
519 /* Initializations done on every `struct dentry'. */
520 static void dentry_common_init(struct dentry *dentry)
521 {
522         memset(dentry, 0, sizeof(struct dentry));
523         dentry->refcnt = 1;
524         dentry->security_id = -1;
525         dentry->ads_entries_status = ADS_ENTRIES_DEFAULT;
526         dentry->lte_group_list.type = STREAM_TYPE_NORMAL;
527 }
528
529 /* 
530  * Creates an unlinked directory entry.
531  *
532  * @name:  The UTF-8 filename of the new dentry.
533  *
534  * Returns a pointer to the new dentry, or NULL if out of memory.
535  */
536 struct dentry *new_dentry(const char *name)
537 {
538         struct dentry *dentry;
539         
540         dentry = MALLOC(sizeof(struct dentry));
541         if (!dentry)
542                 goto err;
543
544         dentry_common_init(dentry);
545         if (change_dentry_name(dentry, name) != 0)
546                 goto err;
547
548         dentry_update_all_timestamps(dentry);
549         dentry->next   = dentry;
550         dentry->prev   = dentry;
551         dentry->parent = dentry;
552         INIT_LIST_HEAD(&dentry->link_group_list);
553         return dentry;
554 err:
555         FREE(dentry);
556         ERROR("Failed to allocate new dentry");
557         return NULL;
558 }
559
560 void dentry_free_ads_entries(struct dentry *dentry)
561 {
562         for (u16 i = 0; i < dentry->num_ads; i++)
563                 destroy_ads_entry(&dentry->ads_entries[i]);
564         FREE(dentry->ads_entries);
565         dentry->ads_entries = NULL;
566         dentry->num_ads = 0;
567 }
568
569 static void __destroy_dentry(struct dentry *dentry)
570 {
571         FREE(dentry->file_name);
572         FREE(dentry->file_name_utf8);
573         FREE(dentry->short_name);
574         FREE(dentry->full_path_utf8);
575         FREE(dentry->extracted_file);
576 }
577
578 /* Frees a WIM dentry. */
579 void free_dentry(struct dentry *dentry)
580 {
581         wimlib_assert(dentry);
582         __destroy_dentry(dentry);
583         /* Don't destroy the ADS entries if they "belong" to a different dentry
584          * */
585         if (dentry->ads_entries_status != ADS_ENTRIES_USER)
586                 dentry_free_ads_entries(dentry);
587         FREE(dentry);
588 }
589
590 /* Like free_dentry(), but assigns a new ADS entries owner if this dentry was
591  * the previous owner, and also deletes the dentry from its link_group_list */
592 void put_dentry(struct dentry *dentry)
593 {
594         if (dentry->ads_entries_status == ADS_ENTRIES_OWNER) {
595                 struct dentry *new_owner;
596                 list_for_each_entry(new_owner, &dentry->link_group_list,
597                                     link_group_list)
598                 {
599                         if (new_owner->ads_entries_status == ADS_ENTRIES_USER) {
600                                 new_owner->ads_entries_status = ADS_ENTRIES_OWNER;
601                                 break;
602                         }
603                 }
604                 dentry->ads_entries_status = ADS_ENTRIES_USER;
605         }
606         struct list_head *next;
607         list_del(&dentry->link_group_list);
608         free_dentry(dentry);
609 }
610
611
612 /* Partically clones a dentry.
613  *
614  * Beware:
615  *      - memory for file names is not cloned (the pointers are all set to NULL
616  *        and the lengths are set to zero)
617  *      - next, prev, and children pointers and not touched
618  *      - stream entries are not cloned (pointer left untouched).
619  */
620 struct dentry *clone_dentry(struct dentry *old)
621 {
622         struct dentry *new = MALLOC(sizeof(struct dentry));
623         if (!new)
624                 return NULL;
625         memcpy(new, old, sizeof(struct dentry));
626         new->file_name          = NULL;
627         new->file_name_len      = 0;
628         new->file_name_utf8     = NULL;
629         new->file_name_utf8_len = 0;
630         new->short_name         = NULL;
631         new->short_name_len     = 0;
632         return new;
633 }
634
635 /* 
636  * This function is passed as an argument to for_dentry_in_tree_depth() in order
637  * to free a directory tree.  __args is a pointer to a `struct free_dentry_args'.
638  */
639 static int do_free_dentry(struct dentry *dentry, void *__lookup_table)
640 {
641         struct lookup_table *lookup_table = __lookup_table;
642         struct lookup_table_entry *lte;
643         unsigned i;
644
645         if (lookup_table) {
646                 for (i = 0; i <= dentry->num_ads; i++) {
647                         lte = dentry_stream_lte(dentry, i, lookup_table);
648                         lte_decrement_refcnt(lte, lookup_table);
649                 }
650         }
651
652         wimlib_assert(dentry->refcnt != 0);
653         if (--dentry->refcnt == 0)
654                 free_dentry(dentry);
655         return 0;
656 }
657
658 /* 
659  * Unlinks and frees a dentry tree.
660  *
661  * @root:               The root of the tree.
662  * @lookup_table:       The lookup table for dentries.  If non-NULL, the
663  *                      reference counts in the lookup table for the lookup
664  *                      table entries corresponding to the dentries will be
665  *                      decremented.
666  */
667 void free_dentry_tree(struct dentry *root, struct lookup_table *lookup_table)
668 {
669         if (!root || !root->parent)
670                 return;
671         for_dentry_in_tree_depth(root, do_free_dentry, lookup_table);
672 }
673
674 int increment_dentry_refcnt(struct dentry *dentry, void *ignore)
675 {
676         dentry->refcnt++;
677         return 0;
678 }
679
680 /* 
681  * Links a dentry into the directory tree.
682  *
683  * @dentry: The dentry to link.
684  * @parent: The dentry that will be the parent of @dentry.
685  */
686 void link_dentry(struct dentry *dentry, struct dentry *parent)
687 {
688         wimlib_assert(dentry_is_directory(parent));
689         dentry->parent = parent;
690         if (parent->children) {
691                 /* Not an only child; link to siblings. */
692                 dentry->next = parent->children;
693                 dentry->prev = parent->children->prev;
694                 dentry->next->prev = dentry;
695                 dentry->prev->next = dentry;
696         } else {
697                 /* Only child; link to parent. */
698                 parent->children = dentry;
699                 dentry->next = dentry;
700                 dentry->prev = dentry;
701         }
702 }
703
704
705 /* Unlink a dentry from the directory tree. 
706  *
707  * Note: This merely removes it from the in-memory tree structure.  See
708  * remove_dentry() in mount.c for a function implemented on top of this one that
709  * frees the dentry and implements reference counting for the lookup table
710  * entries. */
711 void unlink_dentry(struct dentry *dentry)
712 {
713         if (dentry_is_root(dentry))
714                 return;
715         if (dentry_is_only_child(dentry)) {
716                 dentry->parent->children = NULL;
717         } else {
718                 if (dentry_is_first_sibling(dentry))
719                         dentry->parent->children = dentry->next;
720                 dentry->next->prev = dentry->prev;
721                 dentry->prev->next = dentry->next;
722         }
723 }
724
725
726 /* Recalculates the length of @dentry based on its file name length and short
727  * name length.  */
728 static inline void recalculate_dentry_size(struct dentry *dentry)
729 {
730         dentry->length = WIM_DENTRY_DISK_SIZE + dentry->file_name_len + 
731                          2 + dentry->short_name_len;
732         /* Must be multiple of 8. */
733         dentry->length = (dentry->length + 7) & ~7;
734 }
735
736 /* Duplicates a UTF-8 name into UTF-8 and UTF-16 strings and returns the strings
737  * and their lengths in the pointer arguments */
738 int get_names(char **name_utf16_ret, char **name_utf8_ret,
739               u16 *name_utf16_len_ret, u16 *name_utf8_len_ret,
740               const char *name)
741 {
742         size_t utf8_len;
743         size_t utf16_len;
744         char *name_utf16, *name_utf8;
745
746         utf8_len = strlen(name);
747
748         name_utf16 = utf8_to_utf16(name, utf8_len, &utf16_len);
749
750         if (!name_utf16)
751                 return WIMLIB_ERR_NOMEM;
752
753         name_utf8 = MALLOC(utf8_len + 1);
754         if (!name_utf8) {
755                 FREE(name_utf8);
756                 return WIMLIB_ERR_NOMEM;
757         }
758         memcpy(name_utf8, name, utf8_len + 1);
759         FREE(*name_utf8_ret);
760         FREE(*name_utf16_ret);
761         *name_utf8_ret      = name_utf8;
762         *name_utf16_ret     = name_utf16;
763         *name_utf8_len_ret  = utf8_len;
764         *name_utf16_len_ret = utf16_len;
765         return 0;
766 }
767
768 /* Changes the name of a dentry to @new_name.  Only changes the file_name and
769  * file_name_utf8 fields; does not change the short_name, short_name_utf8, or
770  * full_path_utf8 fields.  Also recalculates its length. */
771 int change_dentry_name(struct dentry *dentry, const char *new_name)
772 {
773         int ret;
774
775         ret = get_names(&dentry->file_name, &dentry->file_name_utf8,
776                         &dentry->file_name_len, &dentry->file_name_utf8_len,
777                          new_name);
778         if (ret == 0)
779                 recalculate_dentry_size(dentry);
780         return ret;
781 }
782
783 /*
784  * Changes the name of an alternate data stream */
785 int change_ads_name(struct ads_entry *entry, const char *new_name)
786 {
787         return get_names(&entry->stream_name, &entry->stream_name_utf8,
788                          &entry->stream_name_len,
789                          &entry->stream_name_utf8_len,
790                          new_name);
791 }
792
793 /* Parameters for calculate_dentry_statistics(). */
794 struct image_statistics {
795         struct lookup_table *lookup_table;
796         u64 *dir_count;
797         u64 *file_count;
798         u64 *total_bytes;
799         u64 *hard_link_bytes;
800 };
801
802 static int calculate_dentry_statistics(struct dentry *dentry, void *arg)
803 {
804         struct image_statistics *stats;
805         struct lookup_table_entry *lte; 
806         
807         stats = arg;
808
809         if (dentry_is_directory(dentry) && !dentry_is_root(dentry))
810                 ++*stats->dir_count;
811         else
812                 ++*stats->file_count;
813
814         for (unsigned i = 0; i <= dentry->num_ads; i++) {
815                 lte = dentry_stream_lte(dentry, i, stats->lookup_table);
816                 if (lte) {
817                         *stats->total_bytes += wim_resource_size(lte);
818                         if (++lte->out_refcnt == 1)
819                                 *stats->hard_link_bytes += wim_resource_size(lte);
820                 }
821         }
822         return 0;
823 }
824
825 /* Calculates some statistics about a dentry tree. */
826 void calculate_dir_tree_statistics(struct dentry *root, struct lookup_table *table, 
827                                    u64 *dir_count_ret, u64 *file_count_ret, 
828                                    u64 *total_bytes_ret, 
829                                    u64 *hard_link_bytes_ret)
830 {
831         struct image_statistics stats;
832         *dir_count_ret         = 0;
833         *file_count_ret        = 0;
834         *total_bytes_ret       = 0;
835         *hard_link_bytes_ret   = 0;
836         stats.lookup_table     = table;
837         stats.dir_count       = dir_count_ret;
838         stats.file_count      = file_count_ret;
839         stats.total_bytes     = total_bytes_ret;
840         stats.hard_link_bytes = hard_link_bytes_ret;
841         for_lookup_table_entry(table, zero_out_refcnts, NULL);
842         for_dentry_in_tree(root, calculate_dentry_statistics, &stats);
843 }
844
845
846 /* 
847  * Reads the alternate data stream entries for a dentry.
848  *
849  * @p:  Pointer to buffer that starts with the first alternate stream entry.
850  *
851  * @dentry:     Dentry to load the alternate data streams into.
852  *                      @dentry->num_ads must have been set to the number of
853  *                      alternate data streams that are expected.
854  *
855  * @remaining_size:     Number of bytes of data remaining in the buffer pointed
856  *                              to by @p.
857  *
858  * The format of the on-disk alternate stream entries is as follows:
859  *
860  * struct ads_entry_on_disk {
861  *      u64  length;          // Length of the entry, in bytes.  This includes
862  *                                  all fields (including the stream name, the
863  *                                  null terminator, AND the padding!).
864  *      u64  reserved;        // Seems to be unused
865  *      u8   hash[20];        // SHA1 message digest of the uncompressed stream
866  *      u16  stream_name_len; // Length of the stream name, in bytes
867  *      char stream_name[];   // Stream name in UTF-16LE, @stream_name_len bytes long,
868  *                                  not including null terminator
869  *      u16  zero;            // UTF-16 null terminator for the stream name, NOT
870  *                                  included in @stream_name_len
871  *      char padding[];       // Padding to make the size a multiple of 8 bytes.
872  * };
873  *
874  * In addition, the entries are 8-byte aligned.
875  *
876  * Return 0 on success or nonzero on failure.  On success, dentry->ads_entries
877  * is set to an array of `struct ads_entry's of length dentry->num_ads.  On
878  * failure, @dentry is not modified.
879  */
880 static int read_ads_entries(const u8 *p, struct dentry *dentry,
881                             u64 remaining_size)
882 {
883         u16 num_ads;
884         struct ads_entry *ads_entries;
885         int ret;
886
887         num_ads = dentry->num_ads;
888         ads_entries = CALLOC(num_ads, sizeof(struct ads_entry));
889         if (!ads_entries) {
890                 ERROR("Could not allocate memory for %"PRIu16" "
891                       "alternate data stream entries", num_ads);
892                 return WIMLIB_ERR_NOMEM;
893         }
894
895         for (u16 i = 0; i < num_ads; i++) {
896                 struct ads_entry *cur_entry = &ads_entries[i];
897                 u64 length;
898                 u64 length_no_padding;
899                 u64 total_length;
900                 size_t utf8_len;
901                 const char *p_save = p;
902
903                 /* Read the base stream entry, excluding the stream name. */
904                 if (remaining_size < WIM_ADS_ENTRY_DISK_SIZE) {
905                         ERROR("Stream entries go past end of metadata resource");
906                         ERROR("(remaining_size = %"PRIu64")", remaining_size);
907                         ret = WIMLIB_ERR_INVALID_DENTRY;
908                         goto out_free_ads_entries;
909                 }
910
911                 p = get_u64(p, &length);
912                 p += 8;
913                 p = get_bytes(p, SHA1_HASH_SIZE, (u8*)cur_entry->hash);
914                 p = get_u16(p, &cur_entry->stream_name_len);
915
916                 cur_entry->stream_name = NULL;
917                 cur_entry->stream_name_utf8 = NULL;
918
919                 /* Length including neither the null terminator nor the padding
920                  * */
921                 length_no_padding = WIM_ADS_ENTRY_DISK_SIZE +
922                                     cur_entry->stream_name_len;
923
924                 /* Length including the null terminator and the padding */
925                 total_length = ((length_no_padding + 2) + 7) & ~7;
926
927                 wimlib_assert(total_length == ads_entry_total_length(cur_entry));
928
929                 if (remaining_size < length_no_padding) {
930                         ERROR("Stream entries go past end of metadata resource");
931                         ERROR("(remaining_size = %"PRIu64" bytes, "
932                               "length_no_padding = %"PRIu16" bytes",
933                               remaining_size, length_no_padding);
934                         ret = WIMLIB_ERR_INVALID_DENTRY;
935                         goto out_free_ads_entries;
936                 }
937
938                 /* The @length field in the on-disk ADS entry is expected to be
939                  * equal to @total_length, which includes all of the entry and
940                  * the padding that follows it to align the next ADS entry to an
941                  * 8-byte boundary.  However, to be safe, we'll accept the
942                  * length field as long as it's not less than the un-padded
943                  * total length and not more than the padded total length. */
944                 if (length < length_no_padding || length > total_length) {
945                         ERROR("Stream entry has unexpected length "
946                               "field (length field = %"PRIu64", "
947                               "unpadded total length = %"PRIu64", "
948                               "padded total length = %"PRIu64")",
949                               length, length_no_padding, total_length);
950                         ret = WIMLIB_ERR_INVALID_DENTRY;
951                         goto out_free_ads_entries;
952                 }
953
954                 cur_entry->stream_name = MALLOC(cur_entry->stream_name_len);
955                 if (!cur_entry->stream_name) {
956                         ret = WIMLIB_ERR_NOMEM;
957                         goto out_free_ads_entries;
958                 }
959                 get_bytes(p, cur_entry->stream_name_len,
960                           (u8*)cur_entry->stream_name);
961                 cur_entry->stream_name_utf8 = utf16_to_utf8(cur_entry->stream_name,
962                                                             cur_entry->stream_name_len,
963                                                             &utf8_len);
964                 cur_entry->stream_name_utf8_len = utf8_len;
965
966                 if (!cur_entry->stream_name_utf8) {
967                         ret = WIMLIB_ERR_NOMEM;
968                         goto out_free_ads_entries;
969                 }
970                 /* It's expected that the size of every ADS entry is a multiple
971                  * of 8.  However, to be safe, I'm allowing the possibility of
972                  * an ADS entry at the very end of the metadata resource ending
973                  * un-aligned.  So although we still need to increment the input
974                  * pointer by @total_length to reach the next ADS entry, it's
975                  * possible that less than @total_length is actually remaining
976                  * in the metadata resource. We should set the remaining size to
977                  * 0 bytes if this happens. */
978                 p = p_save + total_length;
979                 if (remaining_size < total_length)
980                         remaining_size = 0;
981                 else
982                         remaining_size -= total_length;
983         }
984         dentry->ads_entries = ads_entries;
985         return 0;
986 out_free_ads_entries:
987         for (u16 i = 0; i < num_ads; i++) {
988                 FREE(ads_entries[i].stream_name);
989                 FREE(ads_entries[i].stream_name_utf8);
990         }
991         FREE(ads_entries);
992         return ret;
993 }
994
995 /* 
996  * Reads a directory entry, including all alternate data stream entries that
997  * follow it, from the WIM image's metadata resource.
998  *
999  * @metadata_resource:  Buffer containing the uncompressed metadata resource.
1000  * @metadata_resource_len:   Length of the metadata resource.
1001  * @offset:     Offset of this directory entry in the metadata resource.
1002  * @dentry:     A `struct dentry' that will be filled in by this function.
1003  *
1004  * Return 0 on success or nonzero on failure.  On failure, @dentry have been
1005  * modified, bu it will be left with no pointers to any allocated buffers.
1006  * On success, the dentry->length field must be examined.  If zero, this was a
1007  * special "end of directory" dentry and not a real dentry.  If nonzero, this
1008  * was a real dentry.
1009  */
1010 int read_dentry(const u8 metadata_resource[], u64 metadata_resource_len, 
1011                 u64 offset, struct dentry *dentry)
1012 {
1013         const u8 *p;
1014         u64 calculated_size;
1015         char *file_name;
1016         char *file_name_utf8;
1017         char *short_name;
1018         u16 short_name_len;
1019         u16 file_name_len;
1020         size_t file_name_utf8_len;
1021         int ret;
1022
1023         dentry_common_init(dentry);
1024
1025         /*Make sure the dentry really fits into the metadata resource.*/
1026         if (offset + 8 > metadata_resource_len) {
1027                 ERROR("Directory entry starting at %"PRIu64" ends past the "
1028                       "end of the metadata resource (size %"PRIu64")",
1029                       offset, metadata_resource_len);
1030                 return WIMLIB_ERR_INVALID_DENTRY;
1031         }
1032
1033         /* Before reading the whole dentry, we need to read just the length.
1034          * This is because a dentry of length 8 (that is, just the length field)
1035          * terminates the list of sibling directory entries. */
1036
1037         p = get_u64(&metadata_resource[offset], &dentry->length);
1038
1039         /* A zero length field (really a length of 8, since that's how big the
1040          * directory entry is...) indicates that this is the end of directory
1041          * dentry.  We do not read it into memory as an actual dentry, so just
1042          * return successfully in that case. */
1043         if (dentry->length == 0)
1044                 return 0;
1045
1046         /* If the dentry does not overflow the metadata resource buffer and is
1047          * not too short, read the rest of it (excluding the alternate data
1048          * streams, but including the file name and short name variable-length
1049          * fields) into memory. */
1050         if (offset + dentry->length >= metadata_resource_len) {
1051                 ERROR("Directory entry at offset %"PRIu64" and with size "
1052                       "%"PRIu64" ends past the end of the metadata resource "
1053                       "(size %"PRIu64")",
1054                       offset, dentry->length, metadata_resource_len);
1055                 return WIMLIB_ERR_INVALID_DENTRY;
1056         }
1057
1058         if (dentry->length < WIM_DENTRY_DISK_SIZE) {
1059                 ERROR("Directory entry has invalid length of %"PRIu64" bytes",
1060                       dentry->length);
1061                 return WIMLIB_ERR_INVALID_DENTRY;
1062         }
1063
1064         p = get_u32(p, &dentry->attributes);
1065         p = get_u32(p, (u32*)&dentry->security_id);
1066         p = get_u64(p, &dentry->subdir_offset);
1067
1068         /* 2 unused fields */
1069         p += 2 * sizeof(u64);
1070         /*p = get_u64(p, &dentry->unused1);*/
1071         /*p = get_u64(p, &dentry->unused2);*/
1072
1073         p = get_u64(p, &dentry->creation_time);
1074         p = get_u64(p, &dentry->last_access_time);
1075         p = get_u64(p, &dentry->last_write_time);
1076
1077         p = get_bytes(p, SHA1_HASH_SIZE, dentry->hash);
1078         
1079         /*
1080          * I don't know what's going on here.  It seems like M$ screwed up the
1081          * reparse points, then put the fields in the same place and didn't
1082          * document it.  The WIM_HDR_FLAG_RP_FIX flag in the WIM header might
1083          * have something to do with this, but it's not documented.
1084          */
1085         if (dentry->attributes & FILE_ATTRIBUTE_REPARSE_POINT) {
1086                 /* ??? */
1087                 p += 4;
1088                 p = get_u32(p, &dentry->reparse_tag);
1089                 p += 4;
1090         } else {
1091                 p = get_u32(p, &dentry->reparse_tag);
1092                 p = get_u64(p, &dentry->hard_link);
1093         }
1094
1095         /* By the way, the reparse_reserved field does not actually exist (at
1096          * least when the file is not a reparse point) */
1097         
1098         p = get_u16(p, &dentry->num_ads);
1099
1100         p = get_u16(p, &short_name_len);
1101         p = get_u16(p, &file_name_len);
1102
1103         /* We now know the length of the file name and short name.  These should
1104          * be included in the dentry length, but make sure the numbers are
1105          * consistent. */
1106         calculated_size = WIM_DENTRY_DISK_SIZE + file_name_len + 2 +
1107                           short_name_len;
1108
1109         if (dentry->length < calculated_size) {
1110                 ERROR("Unexpected end of directory entry! (Expected "
1111                       "%"PRIu64" bytes, got %"PRIu64" bytes. "
1112                       "short_name_len = %hu, file_name_len = %hu)", 
1113                       calculated_size, dentry->length,
1114                       short_name_len, file_name_len);
1115                 return WIMLIB_ERR_INVALID_DENTRY;
1116         }
1117
1118         /* Read the filename. */
1119         file_name = MALLOC(file_name_len);
1120         if (!file_name) {
1121                 ERROR("Failed to allocate %hu bytes for dentry file name",
1122                       file_name_len);
1123                 return WIMLIB_ERR_NOMEM;
1124         }
1125         p = get_bytes(p, file_name_len, file_name);
1126
1127         /* Convert filename to UTF-8. */
1128         file_name_utf8 = utf16_to_utf8(file_name, file_name_len, 
1129                                        &file_name_utf8_len);
1130
1131         if (!file_name_utf8) {
1132                 ERROR("Failed to allocate memory to convert UTF-16 "
1133                       "filename (%hu bytes) to UTF-8", file_name_len);
1134                 ret = WIMLIB_ERR_NOMEM;
1135                 goto out_free_file_name;
1136         }
1137
1138         /* Before the short name begins, there is a null terminator of two zero
1139          * bytes that follow the long filename, even if the long file name is of
1140          * zero length. */
1141
1142         /* XXX There seems to be no null terminator following the short name;
1143          * verify this. */
1144         if (*(u16*)p)
1145                 WARNING("Expected two zero bytes following the file name "
1146                         "`%s', but found non-zero bytes", file_name_utf8);
1147         p += 2;
1148
1149         /* Read the short filename. */
1150         short_name = MALLOC(short_name_len);
1151         if (!short_name) {
1152                 ERROR("Failed to allocate %hu bytes for short filename",
1153                       short_name_len);
1154                 ret = WIMLIB_ERR_NOMEM;
1155                 goto out_free_file_name_utf8;
1156         }
1157
1158         p = get_bytes(p, short_name_len, short_name);
1159
1160         /* Some directory entries inexplicably have a little over 70 bytes of
1161          * extra data.  The exact amount of data seems to be 72 bytes, but it is
1162          * aligned on the next 8-byte boundary.  It does NOT seem to be
1163          * alternate data stream entries.  Here's an example of the aligned
1164          * data:
1165          *
1166          * 01000000 40000000 6c786bba c58ede11 b0bb0026 1870892a b6adb76f
1167          * e63a3e46 8fca8653 0d2effa1 6c786bba c58ede11 b0bb0026 1870892a
1168          * 00000000 00000000 00000000 00000000
1169          *
1170          * Here's one interpretation of how the data is laid out.
1171          *
1172          * struct unknown {
1173          *      u32 field1; (always 0x00000001)
1174          *      u32 field2; (always 0x40000000)
1175          *      u8  data[48]; (???)
1176          *      u64 reserved1; (always 0)
1177          *      u64 reserved2; (always 0)
1178          * };*/
1179 #if 0
1180         if (dentry->length - calculated_size >= WIM_ADS_ENTRY_DISK_SIZE) {
1181                 printf("%s: %lu / %lu (", file_name_utf8, 
1182                                 calculated_size, dentry->length);
1183                 print_string(p + WIM_ADS_ENTRY_DISK_SIZE, dentry->length - calculated_size - WIM_ADS_ENTRY_DISK_SIZE);
1184                 puts(")");
1185                 print_byte_field(p, dentry->length - calculated_size);
1186                 putchar('\n');
1187         }
1188 #endif
1189
1190         /* 
1191          * Read the alternate data streams, if present.  dentry->num_ads tells
1192          * us how many they are, and they will directly follow the dentry
1193          * on-disk.
1194          *
1195          * Note that each alternate data stream entry begins on an 8-byte
1196          * aligned boundary, and the alternate data stream entries are NOT
1197          * included in the dentry->length field for some reason.
1198          */
1199         if (dentry->num_ads != 0) {
1200                 calculated_size = (calculated_size + 7) & ~7;
1201                 if (calculated_size > metadata_resource_len - offset) {
1202                         ERROR("Not enough space in metadata resource for "
1203                               "alternate stream entries");
1204                         ret = WIMLIB_ERR_INVALID_DENTRY;
1205                         goto out_free_short_name;
1206                 }
1207                 ret = read_ads_entries(&metadata_resource[offset + calculated_size],
1208                                        dentry,
1209                                        metadata_resource_len - offset - calculated_size);
1210                 if (ret != 0)
1211                         goto out_free_short_name;
1212         }
1213
1214         /* We've read all the data for this dentry.  Set the names and their
1215          * lengths, and we've done. */
1216         dentry->file_name          = file_name;
1217         dentry->file_name_utf8     = file_name_utf8;
1218         dentry->short_name         = short_name;
1219         dentry->file_name_len      = file_name_len;
1220         dentry->file_name_utf8_len = file_name_utf8_len;
1221         dentry->short_name_len     = short_name_len;
1222         return 0;
1223 out_free_short_name:
1224         FREE(short_name);
1225 out_free_file_name_utf8:
1226         FREE(file_name_utf8);
1227 out_free_file_name:
1228         FREE(file_name);
1229         return ret;
1230 }
1231
1232 /* 
1233  * Writes a WIM dentry to an output buffer.
1234  *
1235  * @dentry:  The dentry structure.
1236  * @p:       The memory location to write the data to.
1237  * @return:  Pointer to the byte after the last byte we wrote as part of the
1238  *              dentry.
1239  */
1240 static u8 *write_dentry(const struct dentry *dentry, u8 *p)
1241 {
1242         u8 *orig_p = p;
1243         unsigned padding;
1244         const u8 *hash;
1245
1246         p = put_u64(p, dentry->length);
1247         p = put_u32(p, dentry->attributes);
1248         p = put_u32(p, dentry->security_id);
1249         p = put_u64(p, dentry->subdir_offset);
1250         p = put_u64(p, 0); /* unused1 */
1251         p = put_u64(p, 0); /* unused2 */
1252         p = put_u64(p, dentry->creation_time);
1253         p = put_u64(p, dentry->last_access_time);
1254         p = put_u64(p, dentry->last_write_time);
1255         if (dentry->resolved && dentry->lte)
1256                 hash = dentry->lte->hash;
1257         else
1258                 hash = dentry->hash;
1259         p = put_bytes(p, SHA1_HASH_SIZE, hash);
1260         if (dentry->attributes & FILE_ATTRIBUTE_REPARSE_POINT) {
1261                 p = put_zeroes(p, 4);
1262                 p = put_u32(p, dentry->reparse_tag);
1263                 p = put_zeroes(p, 4);
1264         } else {
1265                 u64 hard_link;
1266                 p = put_u32(p, 0);
1267                 if (dentry->link_group_list.next == &dentry->link_group_list)
1268                         hard_link = 0;
1269                 else
1270                         hard_link = dentry->hard_link;
1271                 p = put_u64(p, hard_link);
1272         }
1273         p = put_u16(p, dentry->num_ads);
1274         p = put_u16(p, dentry->short_name_len);
1275         p = put_u16(p, dentry->file_name_len);
1276         p = put_bytes(p, dentry->file_name_len, (u8*)dentry->file_name);
1277         p = put_u16(p, 0); /* filename padding, 2 bytes. */
1278         p = put_bytes(p, dentry->short_name_len, (u8*)dentry->short_name);
1279
1280         wimlib_assert(p - orig_p <= dentry->length);
1281         if (p - orig_p < dentry->length)
1282                 p = put_zeroes(p, dentry->length - (p - orig_p));
1283
1284         /* Align to 8-byte boundary */
1285         p = put_zeroes(p, (8 - dentry->length % 8) % 8);
1286
1287         /* Write the alternate data streams, if there are any.  Please see
1288          * read_ads_entries() for comments about the format of the on-disk
1289          * alternate data stream entries. */
1290         for (u16 i = 0; i < dentry->num_ads; i++) {
1291                 p = put_u64(p, ads_entry_total_length(&dentry->ads_entries[i]));
1292                 p = put_u64(p, 0); /* Unused */
1293                 if (dentry->resolved && dentry->ads_entries[i].lte)
1294                         hash = dentry->ads_entries[i].lte->hash;
1295                 else
1296                         hash = dentry->ads_entries[i].hash;
1297                 p = put_bytes(p, SHA1_HASH_SIZE, hash);
1298                 p = put_u16(p, dentry->ads_entries[i].stream_name_len);
1299                 p = put_bytes(p, dentry->ads_entries[i].stream_name_len,
1300                                  (u8*)dentry->ads_entries[i].stream_name);
1301                 p = put_u16(p, 0);
1302                 p = put_zeroes(p, (8 - (p - orig_p) % 8) % 8);
1303         }
1304         return p;
1305 }
1306
1307 /* Recursive function that writes a dentry tree rooted at @parent, not including
1308  * @parent itself, which has already been written. */
1309 static u8 *write_dentry_tree_recursive(const struct dentry *parent, u8 *p)
1310 {
1311         const struct dentry *child;
1312
1313         /* Nothing to do if this dentry has no children. */
1314         if (parent->subdir_offset == 0)
1315                 return p;
1316
1317         /* Write child dentries and end-of-directory entry. 
1318          *
1319          * Note: we need to write all of this dentry's children before
1320          * recursively writing the directory trees rooted at each of the child
1321          * dentries, since the on-disk dentries for a dentry's children are
1322          * always located at consecutive positions in the metadata resource! */
1323         child = parent->children;
1324         if (child) {
1325                 do {
1326                         p = write_dentry(child, p);
1327                         child = child->next;
1328                 } while (child != parent->children);
1329         }
1330
1331         /* write end of directory entry */
1332         p = put_u64(p, 0);
1333
1334         /* Recurse on children. */
1335         if (child) {
1336                 do {
1337                         p = write_dentry_tree_recursive(child, p);
1338                         child = child->next;
1339                 } while (child != parent->children);
1340         }
1341         return p;
1342 }
1343
1344 /* Writes a directory tree to the metadata resource.
1345  *
1346  * @root:       Root of the dentry tree.
1347  * @p:          Pointer to a buffer with enough space for the dentry tree.
1348  *
1349  * Returns pointer to the byte after the last byte we wrote.
1350  */
1351 u8 *write_dentry_tree(const struct dentry *root, u8 *p)
1352 {
1353         wimlib_assert(dentry_is_root(root));
1354
1355         /* If we're the root dentry, we have no parent that already
1356          * wrote us, so we need to write ourselves. */
1357         p = write_dentry(root, p);
1358
1359         /* Write end of directory entry after the root dentry just to be safe;
1360          * however the root dentry obviously cannot have any siblings. */
1361         p = put_u64(p, 0);
1362
1363         /* Recursively write the rest of the dentry tree. */
1364         return write_dentry_tree_recursive(root, p);
1365 }
1366
1367 /* Reads the children of a dentry, and all their children, ..., etc. from the
1368  * metadata resource and into the dentry tree.
1369  *
1370  * @metadata_resource:  An array that contains the uncompressed metadata
1371  *                      resource for the WIM file.
1372  *
1373  * @metadata_resource_len:  The length of the uncompressed metadata resource, in
1374  *                          bytes.
1375  *
1376  * @dentry:     A pointer to a `struct dentry' that is the root of the directory
1377  *              tree and has already been read from the metadata resource.  It
1378  *              does not need to be the real root because this procedure is
1379  *              called recursively.
1380  *
1381  * @return:     Zero on success, nonzero on failure.
1382  */
1383 int read_dentry_tree(const u8 metadata_resource[], u64 metadata_resource_len,
1384                      struct dentry *dentry)
1385 {
1386         u64 cur_offset = dentry->subdir_offset;
1387         struct dentry *prev_child = NULL;
1388         struct dentry *first_child = NULL;
1389         struct dentry *child;
1390         struct dentry cur_child;
1391         int ret;
1392
1393         /* 
1394          * If @dentry has no child dentries, nothing more needs to be done for
1395          * this branch.  This is the case for regular files, symbolic links, and
1396          * *possibly* empty directories (although an empty directory may also
1397          * have one child dentry that is the special end-of-directory dentry)
1398          */
1399         if (cur_offset == 0)
1400                 return 0;
1401
1402         /* Find and read all the children of @dentry. */
1403         while (1) {
1404
1405                 /* Read next child of @dentry into @cur_child. */
1406                 ret = read_dentry(metadata_resource, metadata_resource_len, 
1407                                   cur_offset, &cur_child);
1408                 if (ret != 0)
1409                         break;
1410
1411                 /* Check for end of directory. */
1412                 if (cur_child.length == 0)
1413                         break;
1414
1415                 /* Not end of directory.  Allocate this child permanently and
1416                  * link it to the parent and previous child. */
1417                 child = MALLOC(sizeof(struct dentry));
1418                 if (!child) {
1419                         ERROR("Failed to allocate %zu bytes for new dentry",
1420                               sizeof(struct dentry));
1421                         ret = WIMLIB_ERR_NOMEM;
1422                         break;
1423                 }
1424                 memcpy(child, &cur_child, sizeof(struct dentry));
1425
1426                 if (prev_child) {
1427                         prev_child->next = child;
1428                         child->prev = prev_child;
1429                 } else {
1430                         first_child = child;
1431                 }
1432
1433                 child->parent = dentry;
1434                 prev_child = child;
1435
1436                 /* If there are children of this child, call this procedure
1437                  * recursively. */
1438                 if (child->subdir_offset != 0) {
1439                         ret = read_dentry_tree(metadata_resource, 
1440                                                metadata_resource_len, child);
1441                         if (ret != 0)
1442                                 break;
1443                 }
1444
1445                 /* Advance to the offset of the next child. */
1446                 cur_offset += dentry_total_length(child);
1447         }
1448
1449         /* Link last child to first one, and set parent's children pointer to
1450          * the first child.  */
1451         if (prev_child) {
1452                 prev_child->next = first_child;
1453                 first_child->prev = prev_child;
1454         }
1455         dentry->children = first_child;
1456         return ret;
1457 }