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