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