]> wimlib.net Git - wimlib/blob - src/inode.c
A few cleanups and fixes from recent changes
[wimlib] / src / inode.c
1 /*
2  * inode.c
3  *
4  * Functions that operate on WIM inodes.
5  *
6  * See dentry.c for a description of the relationship between WIM dentries and
7  * WIM inodes.
8  */
9
10 /*
11  * Copyright (C) 2012, 2013, 2014 Eric Biggers
12  *
13  * This file is free software; you can redistribute it and/or modify it under
14  * the terms of the GNU Lesser General Public License as published by the Free
15  * Software Foundation; either version 3 of the License, or (at your option) any
16  * later version.
17  *
18  * This file is distributed in the hope that it will be useful, but WITHOUT
19  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
20  * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
21  * details.
22  *
23  * You should have received a copy of the GNU Lesser General Public License
24  * along with this file; if not, see http://www.gnu.org/licenses/.
25  */
26
27 #ifdef HAVE_CONFIG_H
28 #  include "config.h"
29 #endif
30
31 #include <errno.h>
32
33 #include "wimlib/assert.h"
34 #include "wimlib/dentry.h"
35 #include "wimlib/encoding.h"
36 #include "wimlib/endianness.h"
37 #include "wimlib/error.h"
38 #include "wimlib/inode.h"
39 #include "wimlib/lookup_table.h"
40 #include "wimlib/security.h"
41 #include "wimlib/timestamp.h"
42
43 /* Allocate a new inode.  Set the timestamps to the current time.  */
44 struct wim_inode *
45 new_inode(void)
46 {
47         struct wim_inode *inode = new_timeless_inode();
48         if (inode) {
49                 u64 now = now_as_wim_timestamp();
50                 inode->i_creation_time = now;
51                 inode->i_last_access_time = now;
52                 inode->i_last_write_time = now;
53         }
54         return inode;
55 }
56
57 /* Allocate a new inode.  Leave the timestamps zeroed out.  */
58 struct wim_inode *
59 new_timeless_inode(void)
60 {
61         struct wim_inode *inode = CALLOC(1, sizeof(struct wim_inode));
62         if (inode) {
63                 inode->i_security_id = -1;
64                 /*inode->i_nlink = 0;*/
65                 inode->i_next_stream_id = 1;
66                 inode->i_not_rpfixed = 1;
67                 inode->i_canonical_streams = 1;
68                 INIT_LIST_HEAD(&inode->i_list);
69                 INIT_LIST_HEAD(&inode->i_dentry);
70         }
71         return inode;
72 }
73
74 /* Free memory allocated within an alternate data stream entry.  */
75 static void
76 destroy_ads_entry(struct wim_ads_entry *ads_entry)
77 {
78         FREE(ads_entry->stream_name);
79 }
80
81 static void
82 free_inode(struct wim_inode *inode)
83 {
84         if (unlikely(inode->i_ads_entries)) {
85                 for (unsigned i = 0; i < inode->i_num_ads; i++)
86                         destroy_ads_entry(&inode->i_ads_entries[i]);
87                 FREE(inode->i_ads_entries);
88         }
89         if (unlikely(inode->i_extra))
90                 FREE(inode->i_extra);
91         /* HACK: This may instead delete the inode from i_list, but hlist_del()
92          * behaves the same as list_del(). */
93         if (!hlist_unhashed(&inode->i_hlist))
94                 hlist_del(&inode->i_hlist);
95         FREE(inode);
96 }
97
98 static inline void
99 free_inode_if_unneeded(struct wim_inode *inode)
100 {
101         if (inode->i_nlink)
102                 return;
103 #ifdef WITH_FUSE
104         if (inode->i_num_opened_fds)
105                 return;
106 #endif
107         free_inode(inode);
108 }
109
110 /* Associate a dentry with the specified inode.  */
111 void
112 d_associate(struct wim_dentry *dentry, struct wim_inode *inode)
113 {
114         wimlib_assert(!dentry->d_inode);
115
116         list_add_tail(&dentry->d_alias, &inode->i_dentry);
117         dentry->d_inode = inode;
118         inode->i_nlink++;
119 }
120
121 /* Disassociate a dentry from its inode, if any.  Following this, free the inode
122  * if it is no longer in use.  */
123 void
124 d_disassociate(struct wim_dentry *dentry)
125 {
126         struct wim_inode *inode = dentry->d_inode;
127
128         if (unlikely(!inode))
129                 return;
130
131         wimlib_assert(inode->i_nlink > 0);
132
133         list_del(&dentry->d_alias);
134         dentry->d_inode = NULL;
135         inode->i_nlink--;
136
137         free_inode_if_unneeded(inode);
138 }
139
140 #ifdef WITH_FUSE
141 void
142 inode_dec_num_opened_fds(struct wim_inode *inode)
143 {
144         wimlib_assert(inode->i_num_opened_fds > 0);
145
146         if (--inode->i_num_opened_fds == 0) {
147                 /* The last file descriptor to this inode was closed.  */
148                 FREE(inode->i_fds);
149                 inode->i_fds = NULL;
150                 inode->i_num_allocated_fds = 0;
151
152                 free_inode_if_unneeded(inode);
153         }
154 }
155 #endif
156
157 /*
158  * Returns the alternate data stream entry belonging to @inode that has the
159  * stream name @stream_name, or NULL if the inode has no alternate data stream
160  * with that name.
161  *
162  * If @p stream_name is the empty string, NULL is returned --- that is, this
163  * function will not return "unnamed" alternate data stream entries.
164  *
165  * If NULL is returned, errno is set.
166  */
167 struct wim_ads_entry *
168 inode_get_ads_entry(struct wim_inode *inode, const tchar *stream_name)
169 {
170         int ret;
171         const utf16lechar *stream_name_utf16le;
172         size_t stream_name_utf16le_nbytes;
173         unsigned i;
174         struct wim_ads_entry *result;
175
176         if (inode->i_num_ads == 0) {
177                 errno = ENOENT;
178                 return NULL;
179         }
180
181         if (stream_name[0] == T('\0')) {
182                 errno = ENOENT;
183                 return NULL;
184         }
185
186         ret = tstr_get_utf16le_and_len(stream_name, &stream_name_utf16le,
187                                        &stream_name_utf16le_nbytes);
188         if (ret)
189                 return NULL;
190
191         i = 0;
192         result = NULL;
193         do {
194                 if (!cmp_utf16le_strings(inode->i_ads_entries[i].stream_name,
195                                          inode->i_ads_entries[i].stream_name_nbytes /
196                                                 sizeof(utf16lechar),
197                                          stream_name_utf16le,
198                                          stream_name_utf16le_nbytes /
199                                                 sizeof(utf16lechar),
200                                          default_ignore_case))
201                 {
202                         result = &inode->i_ads_entries[i];
203                         break;
204                 }
205         } while (++i != inode->i_num_ads);
206
207         tstr_put_utf16le(stream_name_utf16le);
208
209         if (!result)
210                 errno = ENOENT;
211         return result;
212 }
213
214 static struct wim_ads_entry *
215 do_inode_add_ads(struct wim_inode *inode,
216                  utf16lechar *stream_name, size_t stream_name_nbytes)
217 {
218         unsigned num_ads;
219         struct wim_ads_entry *ads_entries;
220         struct wim_ads_entry *new_entry;
221
222         if (unlikely(inode->i_num_ads >= 0xfffe)) {
223                 ERROR("File \"%"TS"\" has too many alternate data streams!",
224                       inode_first_full_path(inode));
225                 errno = EFBIG;
226                 return NULL;
227         }
228         num_ads = inode->i_num_ads + 1;
229         ads_entries = REALLOC(inode->i_ads_entries,
230                               num_ads * sizeof(inode->i_ads_entries[0]));
231         if (!ads_entries)
232                 return NULL;
233
234         inode->i_ads_entries = ads_entries;
235
236         new_entry = &inode->i_ads_entries[num_ads - 1];
237
238         memset(new_entry, 0, sizeof(struct wim_ads_entry));
239         new_entry->stream_name = stream_name;
240         new_entry->stream_name_nbytes = stream_name_nbytes;
241         new_entry->stream_id = inode->i_next_stream_id++;
242         inode->i_num_ads = num_ads;
243         return new_entry;
244 }
245
246 /*
247  * Add an alternate data stream entry to a WIM inode (UTF-16LE version).  On
248  * success, returns a pointer to the new entry.  Note that this pointer might
249  * become invalid if another ADS entry is added to the inode.  On failure,
250  * returns NULL and sets errno.
251  */
252 struct wim_ads_entry *
253 inode_add_ads_utf16le(struct wim_inode *inode,
254                       const utf16lechar *stream_name, size_t stream_name_nbytes)
255 {
256         utf16lechar *dup = NULL;
257         struct wim_ads_entry *result;
258
259         if (stream_name_nbytes) {
260                 dup = utf16le_dupz(stream_name, stream_name_nbytes);
261                 if (!dup)
262                         return NULL;
263         }
264
265         result = do_inode_add_ads(inode, dup, stream_name_nbytes);
266         if (!result)
267                 FREE(dup);
268         return result;
269 }
270
271 /*
272  * Add an alternate data stream entry to a WIM inode (tchar version).  On
273  * success, returns a pointer to the new entry.  Note that this pointer might
274  * become invalid if another ADS entry is added to the inode.  On failure,
275  * returns NULL and sets errno.
276  */
277 struct wim_ads_entry *
278 inode_add_ads(struct wim_inode *inode, const tchar *stream_name)
279 {
280         utf16lechar *stream_name_utf16le = NULL;
281         size_t stream_name_utf16le_nbytes = 0;
282         struct wim_ads_entry *result;
283
284         if (stream_name && *stream_name)
285                 if (tstr_to_utf16le(stream_name,
286                                     tstrlen(stream_name) * sizeof(tchar),
287                                     &stream_name_utf16le,
288                                     &stream_name_utf16le_nbytes))
289                         return NULL;
290
291         result = do_inode_add_ads(inode, stream_name_utf16le,
292                                   stream_name_utf16le_nbytes);
293         if (!result)
294                 FREE(stream_name_utf16le);
295         return result;
296 }
297
298 /*
299  * Add an data alternate stream entry to a WIM inode, where the contents of the
300  * new stream are specified in a data buffer.  The inode must be resolved.
301  *
302  * On success, returns a pointer to the new alternate data stream entry.  Note
303  * that this pointer might become invalid if another ADS entry is added to the
304  * inode.  On failure, returns NULL and sets errno.
305  */
306 struct wim_ads_entry *
307 inode_add_ads_with_data(struct wim_inode *inode, const tchar *name,
308                         const void *value, size_t size,
309                         struct wim_lookup_table *lookup_table)
310 {
311         struct wim_ads_entry *new_entry;
312
313         wimlib_assert(inode->i_resolved);
314
315         new_entry = inode_add_ads(inode, name);
316         if (unlikely(!new_entry))
317                 return NULL;
318
319         new_entry->lte = new_stream_from_data_buffer(value, size, lookup_table);
320         if (unlikely(!new_entry->lte)) {
321                 inode_remove_ads(inode, new_entry, NULL);
322                 return NULL;
323         }
324         return new_entry;
325 }
326
327 /* Remove an alternate data stream from a WIM inode.  */
328 void
329 inode_remove_ads(struct wim_inode *inode, struct wim_ads_entry *entry,
330                  struct wim_lookup_table *lookup_table)
331 {
332         struct wim_lookup_table_entry *lte;
333         unsigned idx = entry - inode->i_ads_entries;
334
335         wimlib_assert(idx < inode->i_num_ads);
336         wimlib_assert(inode->i_resolved);
337
338         lte = entry->lte;
339         if (lte)
340                 lte_decrement_refcnt(lte, lookup_table);
341
342         destroy_ads_entry(entry);
343
344         memmove(&inode->i_ads_entries[idx],
345                 &inode->i_ads_entries[idx + 1],
346                 (inode->i_num_ads - idx - 1) * sizeof(inode->i_ads_entries[0]));
347         inode->i_num_ads--;
348 }
349
350 /* Return true iff the specified inode has at least one named data stream.  */
351 bool
352 inode_has_named_stream(const struct wim_inode *inode)
353 {
354         for (unsigned i = 0; i < inode->i_num_ads; i++)
355                 if (inode->i_ads_entries[i].stream_name_nbytes)
356                         return true;
357         return false;
358 }
359
360 /* Set the unnamed stream of a WIM inode, given a data buffer containing the
361  * stream contents.  The inode must be resolved and cannot already have an
362  * unnamed stream.  */
363 int
364 inode_set_unnamed_stream(struct wim_inode *inode, const void *data, size_t len,
365                          struct wim_lookup_table *lookup_table)
366 {
367         wimlib_assert(inode->i_resolved);
368         wimlib_assert(!inode->i_lte);
369
370         inode->i_lte = new_stream_from_data_buffer(data, len, lookup_table);
371         if (!inode->i_lte)
372                 return WIMLIB_ERR_NOMEM;
373         return 0;
374 }
375
376 /*
377  * Resolve an inode's single-instance streams.
378  *
379  * This takes each SHA-1 message digest stored in the inode or one of its ADS
380  * entries and replaces it with a pointer directly to the appropriate 'struct
381  * wim_lookup_table_entry' currently inserted into @table to represent the
382  * single-instance stream having that SHA-1 message digest.
383  *
384  * If @force is %false:
385  *      If any of the needed single-instance streams do not exist in @table,
386  *      return WIMLIB_ERR_RESOURCE_NOT_FOUND and leave the inode unmodified.
387  * If @force is %true:
388  *      If any of the needed single-instance streams do not exist in @table,
389  *      allocate new entries for them and insert them into @table.  This does
390  *      not, of course, cause these streams to magically exist, but this is
391  *      needed by the code for extraction from a pipe.
392  *
393  * If the inode is already resolved, this function does nothing.
394  *
395  * Returns 0 on success; WIMLIB_ERR_NOMEM if out of memory; or
396  * WIMLIB_ERR_RESOURCE_NOT_FOUND if @force is %false and at least one
397  * single-instance stream referenced by the inode was missing.
398  */
399 int
400 inode_resolve_streams(struct wim_inode *inode, struct wim_lookup_table *table,
401                       bool force)
402 {
403         const u8 *hash;
404         struct wim_lookup_table_entry *lte, *ads_lte;
405
406         if (inode->i_resolved)
407                 return 0;
408
409         struct wim_lookup_table_entry *ads_ltes[inode->i_num_ads];
410
411         /* Resolve the default data stream */
412         lte = NULL;
413         hash = inode->i_hash;
414         if (!is_zero_hash(hash)) {
415                 lte = lookup_stream(table, hash);
416                 if (!lte) {
417                         if (force) {
418                                 lte = new_lookup_table_entry();
419                                 if (!lte)
420                                         return WIMLIB_ERR_NOMEM;
421                                 copy_hash(lte->hash, hash);
422                                 lookup_table_insert(table, lte);
423                         } else {
424                                 goto stream_not_found;
425                         }
426                 }
427         }
428
429         /* Resolve the alternate data streams */
430         for (unsigned i = 0; i < inode->i_num_ads; i++) {
431                 struct wim_ads_entry *cur_entry;
432
433                 ads_lte = NULL;
434                 cur_entry = &inode->i_ads_entries[i];
435                 hash = cur_entry->hash;
436                 if (!is_zero_hash(hash)) {
437                         ads_lte = lookup_stream(table, hash);
438                         if (!ads_lte) {
439                                 if (force) {
440                                         ads_lte = new_lookup_table_entry();
441                                         if (!ads_lte)
442                                                 return WIMLIB_ERR_NOMEM;
443                                         copy_hash(ads_lte->hash, hash);
444                                         lookup_table_insert(table, ads_lte);
445                                 } else {
446                                         goto stream_not_found;
447                                 }
448                         }
449                 }
450                 ads_ltes[i] = ads_lte;
451         }
452         inode->i_lte = lte;
453         for (unsigned i = 0; i < inode->i_num_ads; i++)
454                 inode->i_ads_entries[i].lte = ads_ltes[i];
455         inode->i_resolved = 1;
456         return 0;
457
458 stream_not_found:
459         return stream_not_found_error(inode, hash);
460 }
461
462 /*
463  * Undo the effects of inode_resolve_streams().
464  *
465  * If the inode is not resolved, this function does nothing.
466  */
467 void
468 inode_unresolve_streams(struct wim_inode *inode)
469 {
470         if (!inode->i_resolved)
471                 return;
472
473         if (inode->i_lte)
474                 copy_hash(inode->i_hash, inode->i_lte->hash);
475         else
476                 zero_out_hash(inode->i_hash);
477
478         for (unsigned i = 0; i < inode->i_num_ads; i++) {
479                 if (inode->i_ads_entries[i].lte)
480                         copy_hash(inode->i_ads_entries[i].hash,
481                                   inode->i_ads_entries[i].lte->hash);
482                 else
483                         zero_out_hash(inode->i_ads_entries[i].hash);
484         }
485         inode->i_resolved = 0;
486 }
487
488 int
489 stream_not_found_error(const struct wim_inode *inode, const u8 *hash)
490 {
491         if (wimlib_print_errors) {
492                 tchar hashstr[SHA1_HASH_SIZE * 2 + 1];
493
494                 sprint_hash(hash, hashstr);
495
496                 ERROR("\"%"TS"\": stream not found\n"
497                       "        SHA-1 message digest of missing stream:\n"
498                       "        %"TS"",
499                       inode_first_full_path(inode), hashstr);
500         }
501         return WIMLIB_ERR_RESOURCE_NOT_FOUND;
502 }
503
504 /*
505  * Return the lookup table entry for the specified stream of the inode, or NULL
506  * if the specified stream is empty or not available.
507  *
508  * stream_idx = 0: default data stream
509  * stream_idx > 0: alternate data stream
510  */
511 struct wim_lookup_table_entry *
512 inode_stream_lte(const struct wim_inode *inode, unsigned stream_idx,
513                  const struct wim_lookup_table *table)
514 {
515         if (inode->i_resolved)
516                 return inode_stream_lte_resolved(inode, stream_idx);
517         if (stream_idx == 0)
518                 return lookup_stream(table, inode->i_hash);
519         return lookup_stream(table, inode->i_ads_entries[stream_idx - 1].hash);
520 }
521
522 /*
523  * Return the lookup table entry for the unnamed data stream of a *resolved*
524  * inode, or NULL if the inode's unnamed data stream is empty.  Also return the
525  * 0-based index of the unnamed data stream in *stream_idx_ret.
526  */
527 struct wim_lookup_table_entry *
528 inode_unnamed_stream_resolved(const struct wim_inode *inode,
529                               unsigned *stream_idx_ret)
530 {
531         wimlib_assert(inode->i_resolved);
532
533         *stream_idx_ret = 0;
534         if (likely(inode->i_lte))
535                 return inode->i_lte;
536
537         for (unsigned i = 0; i < inode->i_num_ads; i++) {
538                 if (inode->i_ads_entries[i].stream_name_nbytes == 0 &&
539                     inode->i_ads_entries[i].lte)
540                 {
541                         *stream_idx_ret = i + 1;
542                         return inode->i_ads_entries[i].lte;
543                 }
544         }
545         return NULL;
546 }
547
548 /*
549  * Return the lookup table entry for the unnamed data stream of an inode, or
550  * NULL if the inode's unnamed data stream is empty or not available.
551  *
552  * Note: this is complicated by the fact that WIMGAPI may put the unnamed data
553  * stream in an alternate data stream entry rather than in the dentry itself.
554  */
555 struct wim_lookup_table_entry *
556 inode_unnamed_lte(const struct wim_inode *inode,
557                   const struct wim_lookup_table *table)
558 {
559         struct wim_lookup_table_entry *lte;
560
561         if (inode->i_resolved)
562                 return inode_unnamed_lte_resolved(inode);
563
564         lte = lookup_stream(table, inode->i_hash);
565         if (likely(lte))
566                 return lte;
567
568         for (unsigned i = 0; i < inode->i_num_ads; i++) {
569                 if (inode->i_ads_entries[i].stream_name_nbytes)
570                         continue;
571                 lte = lookup_stream(table, inode->i_ads_entries[i].hash);
572                 if (lte)
573                         return lte;
574         }
575         return NULL;
576 }
577
578 /* Return the SHA-1 message digest of the specified stream of the inode, or a
579  * void SHA-1 of all zeroes if the specified stream is empty.   */
580 const u8 *
581 inode_stream_hash(const struct wim_inode *inode, unsigned stream_idx)
582 {
583         if (inode->i_resolved) {
584                 struct wim_lookup_table_entry *lte;
585
586                 lte = inode_stream_lte_resolved(inode, stream_idx);
587                 if (lte)
588                         return lte->hash;
589                 return zero_hash;
590         }
591         if (stream_idx == 0)
592                 return inode->i_hash;
593         return inode->i_ads_entries[stream_idx - 1].hash;
594 }
595
596 /* Return the SHA-1 message digest of the unnamed data stream of the inode, or a
597  * void SHA-1 of all zeroes if the inode's unnamed data stream is empty.   */
598 const u8 *
599 inode_unnamed_stream_hash(const struct wim_inode *inode)
600 {
601         const u8 *hash;
602
603         for (unsigned i = 0; i <= inode->i_num_ads; i++) {
604                 if (inode_stream_name_nbytes(inode, i) == 0) {
605                         hash = inode_stream_hash(inode, i);
606                         if (!is_zero_hash(hash))
607                                 return hash;
608                 }
609         }
610         return zero_hash;
611 }
612
613 /* Acquire another reference to each single-instance stream referenced by this
614  * inode.  This is necessary when creating a hard link to this inode.
615  *
616  * The inode must be resolved.  */
617 void
618 inode_ref_streams(struct wim_inode *inode)
619 {
620         wimlib_assert(inode->i_resolved);
621
622         if (inode->i_lte)
623                 inode->i_lte->refcnt++;
624         for (unsigned i = 0; i < inode->i_num_ads; i++)
625                 if (inode->i_ads_entries[i].lte)
626                         inode->i_ads_entries[i].lte->refcnt++;
627 }
628
629 /* Drop a reference to each single-instance stream referenced by this inode.
630  * This is necessary when deleting a hard link to this inode.  */
631 void
632 inode_unref_streams(struct wim_inode *inode,
633                     struct wim_lookup_table *lookup_table)
634 {
635         for (unsigned i = 0; i <= inode->i_num_ads; i++) {
636                 struct wim_lookup_table_entry *lte;
637
638                 lte = inode_stream_lte(inode, i, lookup_table);
639                 if (lte)
640                         lte_decrement_refcnt(lte, lookup_table);
641         }
642 }
643
644 /*
645  * Read the alternate data stream entries of a WIM dentry.
646  *
647  * @p:
648  *      Pointer to buffer that starts with the first alternate stream entry.
649  *
650  * @inode:
651  *      Inode to load the alternate data streams into.  @inode->i_num_ads must
652  *      have been set to the number of alternate data streams that are expected.
653  *
654  * @nbytes_remaining_p:
655  *      Number of bytes of data remaining in the buffer pointed to by @p.
656  *      On success this will be updated to point just past the ADS entries.
657  *
658  * On success, inode->i_ads_entries is set to an array of `struct
659  * wim_ads_entry's of length inode->i_num_ads.  On failure, @inode is not
660  * modified.
661  *
662  * Return values:
663  *      WIMLIB_ERR_SUCCESS (0)
664  *      WIMLIB_ERR_INVALID_METADATA_RESOURCE
665  *      WIMLIB_ERR_NOMEM
666  */
667 int
668 read_ads_entries(const u8 * restrict p, struct wim_inode * restrict inode,
669                  size_t *nbytes_remaining_p)
670 {
671         size_t nbytes_remaining = *nbytes_remaining_p;
672         unsigned num_ads;
673         struct wim_ads_entry *ads_entries;
674         int ret;
675
676         BUILD_BUG_ON(sizeof(struct wim_ads_entry_on_disk) != WIM_ADS_ENTRY_DISK_SIZE);
677
678         /* Allocate an array for our in-memory representation of the alternate
679          * data stream entries. */
680         num_ads = inode->i_num_ads;
681         ads_entries = CALLOC(num_ads, sizeof(inode->i_ads_entries[0]));
682         if (!ads_entries)
683                 goto out_of_memory;
684
685         /* Read the entries into our newly allocated buffer. */
686         for (unsigned i = 0; i < num_ads; i++) {
687                 u64 length;
688                 struct wim_ads_entry *cur_entry;
689                 const struct wim_ads_entry_on_disk *disk_entry =
690                         (const struct wim_ads_entry_on_disk*)p;
691
692                 cur_entry = &ads_entries[i];
693                 ads_entries[i].stream_id = i + 1;
694
695                 /* Do we have at least the size of the fixed-length data we know
696                  * need? */
697                 if (nbytes_remaining < sizeof(struct wim_ads_entry_on_disk))
698                         goto out_invalid;
699
700                 /* Read the length field */
701                 length = le64_to_cpu(disk_entry->length);
702
703                 /* Make sure the length field is neither so small it doesn't
704                  * include all the fixed-length data nor so large it overflows
705                  * the metadata resource buffer. */
706                 if (length < sizeof(struct wim_ads_entry_on_disk) ||
707                     length > nbytes_remaining)
708                         goto out_invalid;
709
710                 /* Read the rest of the fixed-length data. */
711
712                 cur_entry->reserved = le64_to_cpu(disk_entry->reserved);
713                 copy_hash(cur_entry->hash, disk_entry->hash);
714                 cur_entry->stream_name_nbytes = le16_to_cpu(disk_entry->stream_name_nbytes);
715
716                 /* If stream_name_nbytes != 0, this is a named stream.
717                  * Otherwise this is an unnamed stream, or in some cases (bugs
718                  * in Microsoft's software I guess) a meaningless entry
719                  * distinguished from the real unnamed stream entry, if any, by
720                  * the fact that the real unnamed stream entry has a nonzero
721                  * hash field. */
722                 if (cur_entry->stream_name_nbytes) {
723                         /* The name is encoded in UTF16-LE, which uses 2-byte
724                          * coding units, so the length of the name had better be
725                          * an even number of bytes... */
726                         if (cur_entry->stream_name_nbytes & 1)
727                                 goto out_invalid;
728
729                         /* Add the length of the stream name to get the length
730                          * we actually need to read.  Make sure this isn't more
731                          * than the specified length of the entry. */
732                         if (sizeof(struct wim_ads_entry_on_disk) +
733                             cur_entry->stream_name_nbytes > length)
734                                 goto out_invalid;
735
736                         cur_entry->stream_name = utf16le_dupz(disk_entry->stream_name,
737                                                               cur_entry->stream_name_nbytes);
738                         if (!cur_entry->stream_name)
739                                 goto out_of_memory;
740                 } else {
741                         /* Mark inode as having weird stream entries.  */
742                         inode->i_canonical_streams = 0;
743                 }
744
745                 /* It's expected that the size of every ADS entry is a multiple
746                  * of 8.  However, to be safe, I'm allowing the possibility of
747                  * an ADS entry at the very end of the metadata resource ending
748                  * unaligned.  So although we still need to increment the input
749                  * pointer by @length to reach the next ADS entry, it's possible
750                  * that less than @length is actually remaining in the metadata
751                  * resource. We should set the remaining bytes to 0 if this
752                  * happens. */
753                 length = (length + 7) & ~7;
754                 p += length;
755                 if (nbytes_remaining < length)
756                         nbytes_remaining = 0;
757                 else
758                         nbytes_remaining -= length;
759         }
760         inode->i_ads_entries = ads_entries;
761         inode->i_next_stream_id = inode->i_num_ads + 1;
762         *nbytes_remaining_p = nbytes_remaining;
763         ret = 0;
764         goto out;
765 out_of_memory:
766         ret = WIMLIB_ERR_NOMEM;
767         goto out_free_ads_entries;
768 out_invalid:
769         ERROR("An alternate data stream entry is invalid");
770         ret = WIMLIB_ERR_INVALID_METADATA_RESOURCE;
771 out_free_ads_entries:
772         if (ads_entries) {
773                 for (unsigned i = 0; i < num_ads; i++)
774                         destroy_ads_entry(&ads_entries[i]);
775                 FREE(ads_entries);
776         }
777 out:
778         return ret;
779 }
780
781 /* Check a WIM inode for unusual field values.  */
782 void
783 check_inode(struct wim_inode *inode, const struct wim_security_data *sd)
784 {
785         /* Check the security ID.  -1 is valid and means "no security
786          * descriptor".  Anything else has to be a valid index into the WIM
787          * image's security descriptors table. */
788         if (inode->i_security_id < -1 ||
789             (inode->i_security_id >= 0 &&
790              inode->i_security_id >= sd->num_entries))
791         {
792                 WARNING("\"%"TS"\" has an invalid security ID (%d)",
793                         inode_first_full_path(inode), inode->i_security_id);
794                 inode->i_security_id = -1;
795         }
796
797         /* Make sure there is only one unnamed data stream. */
798         unsigned num_unnamed_streams = 0;
799         for (unsigned i = 0; i <= inode->i_num_ads; i++) {
800                 const u8 *hash;
801                 hash = inode_stream_hash(inode, i);
802                 if (inode_stream_name_nbytes(inode, i) == 0 && !is_zero_hash(hash))
803                         num_unnamed_streams++;
804         }
805         if (num_unnamed_streams > 1) {
806                 WARNING("\"%"TS"\" has multiple (%u) unnamed streams",
807                         inode_first_full_path(inode), num_unnamed_streams);
808                 /* We currently don't treat this as an error and will just end
809                  * up using the first unnamed data stream in the inode.  */
810         }
811 }
812
813 /*
814  * Translate a single-instance stream entry into the pointer contained in the
815  * inode (or ads entry of an inode) that references it.
816  *
817  * This is only possible for "unhashed" streams, which are guaranteed to have
818  * only one reference, and that reference is guaranteed to be in a resolved
819  * inode.  (It can't be in an unresolved inode, since that would imply the hash
820  * is known!)
821  */
822 struct wim_lookup_table_entry **
823 retrieve_lte_pointer(struct wim_lookup_table_entry *lte)
824 {
825         wimlib_assert(lte->unhashed);
826         struct wim_inode *inode = lte->back_inode;
827         u32 stream_id = lte->back_stream_id;
828         if (stream_id == 0)
829                 return &inode->i_lte;
830         for (unsigned i = 0; i < inode->i_num_ads; i++)
831                 if (inode->i_ads_entries[i].stream_id == stream_id)
832                         return &inode->i_ads_entries[i].lte;
833         wimlib_assert(0);
834         return NULL;
835 }