]> wimlib.net Git - wimlib/blob - src/inode.c
545a940c0916a61ed6f4772c1a8c5f253b75e9e2
[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, 2015 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/blob_table.h"
35 #include "wimlib/dentry.h"
36 #include "wimlib/encoding.h"
37 #include "wimlib/error.h"
38 #include "wimlib/inode.h"
39 #include "wimlib/timestamp.h"
40
41 /*
42  * The 'stream_name' field of unnamed streams always points to this array, which
43  * is an empty UTF-16 string.
44  */
45 const utf16lechar NO_STREAM_NAME[1];
46
47 /* Allocate a new inode and associate the specified dentry with it.  */
48 struct wim_inode *
49 new_inode(struct wim_dentry *dentry, bool set_timestamps)
50 {
51         struct wim_inode *inode;
52
53         inode = CALLOC(1, sizeof(struct wim_inode));
54         if (!inode)
55                 return NULL;
56
57         inode->i_security_id = -1;
58         /*inode->i_nlink = 0;*/
59         inode->i_not_rpfixed = 1;
60         INIT_LIST_HEAD(&inode->i_list);
61         INIT_LIST_HEAD(&inode->i_dentry);
62         inode->i_streams = inode->i_embedded_streams;
63         if (set_timestamps) {
64                 u64 now = now_as_wim_timestamp();
65                 inode->i_creation_time = now;
66                 inode->i_last_access_time = now;
67                 inode->i_last_write_time = now;
68         }
69         d_associate(dentry, inode);
70         return inode;
71 }
72
73 static inline void
74 destroy_stream(struct wim_inode_stream *strm)
75 {
76         if (strm->stream_name != NO_STREAM_NAME)
77                 FREE(strm->stream_name);
78 }
79
80 static void
81 free_inode(struct wim_inode *inode)
82 {
83         for (unsigned i = 0; i < inode->i_num_streams; i++)
84                 destroy_stream(&inode->i_streams[i]);
85         if (inode->i_streams != inode->i_embedded_streams)
86                 FREE(inode->i_streams);
87         if (inode->i_extra)
88                 FREE(inode->i_extra);
89         /* HACK: This may instead delete the inode from i_list, but hlist_del()
90          * behaves the same as list_del(). */
91         if (!hlist_unhashed(&inode->i_hlist))
92                 hlist_del(&inode->i_hlist);
93         FREE(inode);
94 }
95
96 static inline void
97 free_inode_if_unneeded(struct wim_inode *inode)
98 {
99         if (inode->i_nlink)
100                 return;
101 #ifdef WITH_FUSE
102         if (inode->i_num_opened_fds)
103                 return;
104 #endif
105         free_inode(inode);
106 }
107
108 /* Associate a dentry with the specified inode.  */
109 void
110 d_associate(struct wim_dentry *dentry, struct wim_inode *inode)
111 {
112         wimlib_assert(!dentry->d_inode);
113
114         list_add_tail(&dentry->d_alias, &inode->i_dentry);
115         dentry->d_inode = inode;
116         inode->i_nlink++;
117 }
118
119 /* Disassociate a dentry from its inode, if any.  Following this, free the inode
120  * if it is no longer in use.  */
121 void
122 d_disassociate(struct wim_dentry *dentry)
123 {
124         struct wim_inode *inode = dentry->d_inode;
125
126         if (unlikely(!inode))
127                 return;
128
129         wimlib_assert(inode->i_nlink > 0);
130
131         list_del(&dentry->d_alias);
132         dentry->d_inode = NULL;
133         inode->i_nlink--;
134
135         free_inode_if_unneeded(inode);
136 }
137
138 #ifdef WITH_FUSE
139 void
140 inode_dec_num_opened_fds(struct wim_inode *inode)
141 {
142         wimlib_assert(inode->i_num_opened_fds > 0);
143
144         if (--inode->i_num_opened_fds == 0) {
145                 /* The last file descriptor to this inode was closed.  */
146                 FREE(inode->i_fds);
147                 inode->i_fds = NULL;
148                 inode->i_num_allocated_fds = 0;
149
150                 free_inode_if_unneeded(inode);
151         }
152 }
153 #endif
154
155 /*
156  * Retrieve a stream of an inode.
157  *
158  * @inode
159  *      The inode from which the stream is desired
160  * @stream_type
161  *      The type of the stream desired
162  * @stream_name
163  *      The name of the stream desired as a null-terminated UTF-16LE string, or
164  *      NO_STREAM_NAME if an unnamed stream is desired
165  *
166  * Returns a pointer to the stream if found, otherwise NULL.
167  */
168 struct wim_inode_stream *
169 inode_get_stream(const struct wim_inode *inode, int stream_type,
170                  const utf16lechar *stream_name)
171 {
172         if (stream_name == NO_STREAM_NAME)  /* Optimization  */
173                 return inode_get_unnamed_stream(inode, stream_type);
174
175         for (unsigned i = 0; i < inode->i_num_streams; i++) {
176                 struct wim_inode_stream *strm = &inode->i_streams[i];
177                 if (strm->stream_type == stream_type &&
178                     !cmp_utf16le_strings_z(strm->stream_name, stream_name,
179                                            default_ignore_case))
180                 {
181                         return strm;
182                 }
183         }
184         return NULL;
185 }
186
187 /*
188  * This is equivalent to inode_get_stream(inode, stream_type, NO_STREAM_NAME),
189  * but this optimizes for the unnamed case by not doing full string comparisons.
190  */
191 struct wim_inode_stream *
192 inode_get_unnamed_stream(const struct wim_inode *inode, int stream_type)
193 {
194         for (unsigned i = 0; i < inode->i_num_streams; i++) {
195                 struct wim_inode_stream *strm = &inode->i_streams[i];
196                 if (strm->stream_type == stream_type &&
197                     strm->stream_name == NO_STREAM_NAME)
198                 {
199                         return strm;
200                 }
201         }
202         return NULL;
203 }
204
205
206 static void
207 inode_set_stream_blob(struct wim_inode *inode, struct wim_inode_stream *strm,
208                       struct blob_descriptor *new_blob)
209 {
210         strm->_stream_blob = new_blob;
211         strm->stream_resolved = 1;
212         if (new_blob)
213                 new_blob->refcnt += inode->i_nlink;
214 }
215
216 static void
217 inode_unset_stream_blob(struct wim_inode *inode, struct wim_inode_stream *strm,
218                         struct blob_table *blob_table)
219 {
220         struct blob_descriptor *old_blob;
221
222         old_blob = stream_blob(strm, blob_table);
223         if (old_blob)
224                 blob_subtract_refcnt(old_blob, blob_table, inode->i_nlink);
225         strm->_stream_blob = NULL;
226         strm->stream_resolved = 1;
227 }
228
229 /*
230  * Replace the blob associated with the specified stream.
231  *
232  * @inode
233  *      The inode containing @strm
234  * @strm
235  *      The stream whose data needs to be replaced
236  * @new_blob
237  *      The new blob descriptor to assign
238  * @blob_table
239  *      Pointer to the blob table in which data blobs are being indexed
240  */
241 void
242 inode_replace_stream_blob(struct wim_inode *inode,
243                           struct wim_inode_stream *strm,
244                           struct blob_descriptor *new_blob,
245                           struct blob_table *blob_table)
246 {
247         inode_unset_stream_blob(inode, strm, blob_table);
248         inode_set_stream_blob(inode, strm, new_blob);
249 }
250
251 /*
252  * Add a new stream to the specified inode.
253  *
254  * @inode
255  *      The inode to which to add the stream
256  * @stream_type
257  *      The type of the stream being added
258  * @stream_name
259  *      The name of the stream being added as a null-terminated UTF-16LE string,
260  *      or NO_STREAM_NAME if the stream is unnamed
261  * @blob
262  *      The blob that the new stream will initially reference, or NULL
263  *
264  * Returns a pointer to the new stream, or NULL with errno set if it could not
265  * be added.
266  */
267 struct wim_inode_stream *
268 inode_add_stream(struct wim_inode *inode, int stream_type,
269                  const utf16lechar *stream_name, struct blob_descriptor *blob)
270 {
271         if (inode->i_num_streams >= 0xFFFF) {
272                 ERROR("Inode has too many streams! Path=\"%"TS"\"",
273                       inode_first_full_path(inode));
274                 errno = EFBIG;
275                 return NULL;
276         }
277
278         struct wim_inode_stream *streams;
279         struct wim_inode_stream *new_strm;
280
281         if (inode->i_streams == inode->i_embedded_streams) {
282                 if (inode->i_num_streams < ARRAY_LEN(inode->i_embedded_streams)) {
283                         streams = inode->i_embedded_streams;
284                 } else {
285                         streams = MALLOC((inode->i_num_streams + 1) *
286                                                 sizeof(inode->i_streams[0]));
287                         if (!streams)
288                                 return NULL;
289                         memcpy(streams, inode->i_streams,
290                                (inode->i_num_streams *
291                                         sizeof(inode->i_streams[0])));
292                         inode->i_streams = streams;
293                 }
294         } else {
295                 streams = REALLOC(inode->i_streams,
296                                   (inode->i_num_streams + 1) *
297                                         sizeof(inode->i_streams[0]));
298                 if (!streams)
299                         return NULL;
300                 inode->i_streams = streams;
301         }
302         new_strm = &streams[inode->i_num_streams];
303
304         memset(new_strm, 0, sizeof(*new_strm));
305
306         new_strm->stream_type = stream_type;
307         if (!*stream_name) {
308                 /* Unnamed stream  */
309                 new_strm->stream_name = (utf16lechar *)NO_STREAM_NAME;
310         } else {
311                 /* Named stream  */
312                 new_strm->stream_name = utf16le_dup(stream_name);
313                 if (!new_strm->stream_name)
314                         return NULL;
315         }
316
317         new_strm->stream_id = inode->i_next_stream_id++;
318
319         inode_set_stream_blob(inode, new_strm, blob);
320
321         inode->i_num_streams++;
322
323         return new_strm;
324 }
325
326 /*
327  * Replace the data of the specified stream.
328  *
329  * @inode
330  *      The inode containing @strm
331  * @strm
332  *      The stream whose data needs to be replaced
333  * @data
334  *      The buffer of data to assign to the stream
335  * @size
336  *      Size of the @data buffer, in bytes
337  * @blob_table
338  *      Pointer to the blob table in which data blobs are being indexed
339  *
340  * Returns true if successful; false with errno set if unsuccessful.
341  */
342 bool
343 inode_replace_stream_data(struct wim_inode *inode,
344                           struct wim_inode_stream *strm,
345                           const void *data, size_t size,
346                           struct blob_table *blob_table)
347 {
348         struct blob_descriptor *new_blob;
349
350         new_blob = new_blob_from_data_buffer(data, size, blob_table);
351         if (!new_blob)
352                 return false;
353
354         inode_replace_stream_blob(inode, strm, new_blob, blob_table);
355         return true;
356 }
357
358 /*
359  * Add a new stream to the specified inode and assign it the specified data.
360  *
361  * @inode
362  *      The inode to which to add the stream
363  * @stream_type
364  *      The type of the stream being added
365  * @stream_name
366  *      The name of the stream being added as a null-terminated UTF-16LE string,
367  *      or NO_STREAM_NAME if the stream is unnamed
368  * @data
369  *      The buffer of data to assign to the new stream
370  * @size
371  *      Size of the @data buffer, in bytes
372  * @blob_table
373  *      Pointer to the blob table in which data blobs are being indexed
374  *
375  * Returns true if successful; false with errno set if unsuccessful.
376  */
377 bool
378 inode_add_stream_with_data(struct wim_inode *inode,
379                            int stream_type, const utf16lechar *stream_name,
380                            const void *data, size_t size,
381                            struct blob_table *blob_table)
382 {
383         struct wim_inode_stream *strm;
384         struct blob_descriptor *blob;
385
386         strm = inode_add_stream(inode, stream_type, stream_name, NULL);
387         if (!strm)
388                 return false;
389
390         blob = new_blob_from_data_buffer(data, size, blob_table);
391         if (!blob) {
392                 inode_remove_stream(inode, strm, blob_table);
393                 return false;
394         }
395
396         inode_set_stream_blob(inode, strm, blob);
397         return true;
398 }
399
400 /*
401  * Remove a stream from the specified inode.
402  *
403  * This handles releasing the references to the blob descriptor, if any.
404  */
405 void
406 inode_remove_stream(struct wim_inode *inode, struct wim_inode_stream *strm,
407                     struct blob_table *blob_table)
408 {
409         unsigned idx = strm - inode->i_streams;
410
411         wimlib_assert(idx < inode->i_num_streams);
412
413         inode_unset_stream_blob(inode, strm, blob_table);
414
415         destroy_stream(strm);
416
417         memmove(strm, strm + 1,
418                 (inode->i_num_streams - idx - 1) * sizeof(inode->i_streams[0]));
419         inode->i_num_streams--;
420 }
421
422 /* Returns true iff the specified inode has at least one named data stream.  */
423 bool
424 inode_has_named_data_stream(const struct wim_inode *inode)
425 {
426         for (unsigned i = 0; i < inode->i_num_streams; i++)
427                 if (stream_is_named_data_stream(&inode->i_streams[i]))
428                         return true;
429         return false;
430 }
431
432 /*
433  * Resolve an inode's streams.
434  *
435  * For each stream, this replaces the SHA-1 message digest of the blob data with
436  * a pointer to the 'struct blob_descriptor' for the blob.  Blob descriptors are
437  * looked up in @table.
438  *
439  * If @force is %false:
440  *      If any of the needed blobs do not exist in @table, return
441  *      WIMLIB_ERR_RESOURCE_NOT_FOUND.
442  * If @force is %true:
443  *      If any of the needed blobs do not exist in @table, allocate new blob
444  *      descriptors for them and insert them into @table.  This does not, of
445  *      course, cause the data of these blobs to magically exist, but this is
446  *      needed by the code for extraction from a pipe.
447  *
448  * Returns 0 on success; WIMLIB_ERR_NOMEM if out of memory; or
449  * WIMLIB_ERR_RESOURCE_NOT_FOUND if @force is %false and at least one blob
450  * referenced by the inode was missing.
451  */
452 int
453 inode_resolve_streams(struct wim_inode *inode, struct blob_table *table,
454                       bool force)
455 {
456         for (unsigned i = 0; i < inode->i_num_streams; i++) {
457                 struct wim_inode_stream *strm = &inode->i_streams[i];
458
459                 if (strm->stream_resolved)
460                         continue;
461
462                 const u8 *hash = stream_hash(strm);
463                 struct blob_descriptor *blob = NULL;
464
465                 if (!is_zero_hash(hash)) {
466                         blob = lookup_blob(table, hash);
467                         if (!blob) {
468                                 if (!force)
469                                         return blob_not_found_error(inode, hash);
470                                 blob = new_blob_descriptor();
471                                 if (!blob)
472                                         return WIMLIB_ERR_NOMEM;
473                                 copy_hash(blob->hash, hash);
474                                 blob_table_insert(table, blob);
475                         }
476                 }
477                 strm->_stream_blob = blob;
478                 strm->stream_resolved = 1;
479         }
480         return 0;
481 }
482
483 /* Undo the effects of inode_resolve_streams().  */
484 void
485 inode_unresolve_streams(struct wim_inode *inode)
486 {
487         for (unsigned i = 0; i < inode->i_num_streams; i++) {
488
489                 if (!inode->i_streams[i].stream_resolved)
490                         continue;
491
492                 copy_hash(inode->i_streams[i]._stream_hash,
493                           stream_hash(&inode->i_streams[i]));
494                 inode->i_streams[i].stream_resolved = 0;
495         }
496 }
497
498 int
499 blob_not_found_error(const struct wim_inode *inode, const u8 *hash)
500 {
501         if (wimlib_print_errors) {
502                 tchar hashstr[SHA1_HASH_SIZE * 2 + 1];
503
504                 sprint_hash(hash, hashstr);
505
506                 ERROR("\"%"TS"\": blob not found\n"
507                       "        SHA-1 message digest of missing blob:\n"
508                       "        %"TS"",
509                       inode_first_full_path(inode), hashstr);
510         }
511         return WIMLIB_ERR_RESOURCE_NOT_FOUND;
512 }
513
514 /*
515  * Return the blob descriptor for the specified stream, or NULL if the blob for
516  * the stream is empty or not available.
517  */
518 struct blob_descriptor *
519 stream_blob(const struct wim_inode_stream *strm, const struct blob_table *table)
520 {
521         if (strm->stream_resolved)
522                 return strm->_stream_blob;
523         else
524                 return lookup_blob(table, strm->_stream_hash);
525 }
526
527 /* Return the SHA-1 message digest of the data of the specified stream, or a
528  * void SHA-1 of all zeroes if the specified stream is empty.   */
529 const u8 *
530 stream_hash(const struct wim_inode_stream *strm)
531 {
532         if (strm->stream_resolved)
533                 return strm->_stream_blob ? strm->_stream_blob->hash : zero_hash;
534         else
535                 return strm->_stream_hash;
536 }
537
538 /*
539  * Return the blob descriptor for the unnamed data stream of the inode, or NULL
540  * if the inode does not have an unnamed data stream, the blob for the inode's
541  * unnamed data stream is empty, or the blob for the inode's unnamed data stream
542  * is not available in @blob_table.
543  */
544 struct blob_descriptor *
545 inode_get_blob_for_unnamed_data_stream(const struct wim_inode *inode,
546                                        const struct blob_table *blob_table)
547 {
548         const struct wim_inode_stream *strm;
549
550         strm = inode_get_unnamed_stream(inode, STREAM_TYPE_DATA);
551         if (!strm)
552                 return NULL;
553
554         return stream_blob(strm, blob_table);
555 }
556
557 /* Like inode_get_blob_for_unnamed_data_stream(), but assumes the unnamed data
558  * stream is resolved.  */
559 struct blob_descriptor *
560 inode_get_blob_for_unnamed_data_stream_resolved(const struct wim_inode *inode)
561 {
562         const struct wim_inode_stream *strm;
563
564         strm = inode_get_unnamed_stream(inode, STREAM_TYPE_DATA);
565         if (!strm)
566                 return NULL;
567
568         return stream_blob_resolved(strm);
569 }
570
571 /*
572  * Return the SHA-1 message digest of the unnamed data stream of the inode, or a
573  * void SHA-1 of all zeroes if the inode does not have an unnamed data stream or
574  * if the inode's unnamed data stream is empty.
575  */
576 const u8 *
577 inode_get_hash_of_unnamed_data_stream(const struct wim_inode *inode)
578 {
579         const struct wim_inode_stream *strm;
580
581         strm = inode_get_unnamed_stream(inode, STREAM_TYPE_DATA);
582         if (!strm)
583                 return zero_hash;
584
585         return stream_hash(strm);
586 }
587
588 /* Acquire another reference to each blob referenced by this inode.  This is
589  * necessary when creating a hard link to this inode.
590  *
591  * All streams of the inode must be resolved.  */
592 void
593 inode_ref_blobs(struct wim_inode *inode)
594 {
595         for (unsigned i = 0; i < inode->i_num_streams; i++) {
596                 struct blob_descriptor *blob;
597
598                 blob = stream_blob_resolved(&inode->i_streams[i]);
599                 if (blob)
600                         blob->refcnt++;
601         }
602 }
603
604 /* Release a reference to each blob referenced by this inode.  This is necessary
605  * when deleting a hard link to this inode.  */
606 void
607 inode_unref_blobs(struct wim_inode *inode, struct blob_table *blob_table)
608 {
609         for (unsigned i = 0; i < inode->i_num_streams; i++) {
610                 struct blob_descriptor *blob;
611
612                 blob = stream_blob(&inode->i_streams[i], blob_table);
613                 if (blob)
614                         blob_decrement_refcnt(blob, blob_table);
615         }
616 }
617
618 /*
619  * Given a blob descriptor, return a pointer to the pointer contained in the
620  * stream that references it.
621  *
622  * This is only possible for "unhashed" blobs, which are guaranteed to have only
623  * one referencing stream, and that reference is guaranteed to be in a resolved
624  * stream.  (It can't be in an unresolved stream, since that would imply the
625  * hash is known!)
626  */
627 struct blob_descriptor **
628 retrieve_pointer_to_unhashed_blob(struct blob_descriptor *blob)
629 {
630         wimlib_assert(blob->unhashed);
631
632         struct wim_inode *inode = blob->back_inode;
633         for (unsigned i = 0; i < inode->i_num_streams; i++) {
634                 if (inode->i_streams[i].stream_id == blob->back_stream_id) {
635                         wimlib_assert(inode->i_streams[i]._stream_blob == blob);
636                         return &inode->i_streams[i]._stream_blob;
637                 }
638         }
639
640         wimlib_assert(0);
641         return NULL;
642 }