]> wimlib.net Git - wimlib/blob - src/inode.c
wim_inode: Remove i_list, leaving only i_hlist
[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_dentry);
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))
89                 hlist_del(&inode->i_hlist);
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         list_add_tail(&dentry->d_alias, &inode->i_dentry);
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         list_del(&dentry->d_alias);
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_first_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;
346
347         new_blob = new_blob_from_data_buffer(data, size, blob_table);
348         if (!new_blob)
349                 return false;
350
351         inode_replace_stream_blob(inode, strm, new_blob, blob_table);
352         return true;
353 }
354
355 /*
356  * Add a new stream to the specified inode and assign it the specified data.
357  *
358  * @inode
359  *      The inode to which to add the stream
360  * @stream_type
361  *      The type of the stream being added
362  * @stream_name
363  *      The name of the stream being added as a null-terminated UTF-16LE string,
364  *      or NO_STREAM_NAME if the stream is unnamed
365  * @data
366  *      The buffer of data to assign to the new stream
367  * @size
368  *      Size of the @data buffer, in bytes
369  * @blob_table
370  *      Pointer to the blob table in which data blobs are being indexed
371  *
372  * Returns true if successful; false with errno set if unsuccessful.
373  */
374 bool
375 inode_add_stream_with_data(struct wim_inode *inode,
376                            int stream_type, const utf16lechar *stream_name,
377                            const void *data, size_t size,
378                            struct blob_table *blob_table)
379 {
380         struct wim_inode_stream *strm;
381         struct blob_descriptor *blob;
382
383         strm = inode_add_stream(inode, stream_type, stream_name, NULL);
384         if (!strm)
385                 return false;
386
387         blob = new_blob_from_data_buffer(data, size, blob_table);
388         if (!blob) {
389                 inode_remove_stream(inode, strm, blob_table);
390                 return false;
391         }
392
393         inode_set_stream_blob(inode, strm, blob);
394         return true;
395 }
396
397 /*
398  * Remove a stream from the specified inode.
399  *
400  * This handles releasing the references to the blob descriptor, if any.
401  */
402 void
403 inode_remove_stream(struct wim_inode *inode, struct wim_inode_stream *strm,
404                     struct blob_table *blob_table)
405 {
406         unsigned idx = strm - inode->i_streams;
407
408         wimlib_assert(idx < inode->i_num_streams);
409
410         inode_unset_stream_blob(inode, strm, blob_table);
411
412         destroy_stream(strm);
413
414         memmove(strm, strm + 1,
415                 (inode->i_num_streams - idx - 1) * sizeof(inode->i_streams[0]));
416         inode->i_num_streams--;
417 }
418
419 /* Returns true iff the specified inode has at least one named data stream.  */
420 bool
421 inode_has_named_data_stream(const struct wim_inode *inode)
422 {
423         for (unsigned i = 0; i < inode->i_num_streams; i++)
424                 if (stream_is_named_data_stream(&inode->i_streams[i]))
425                         return true;
426         return false;
427 }
428
429 /*
430  * Resolve an inode's streams.
431  *
432  * For each stream, this replaces the SHA-1 message digest of the blob data with
433  * a pointer to the 'struct blob_descriptor' for the blob.  Blob descriptors are
434  * looked up in @table.
435  *
436  * If @force is %false:
437  *      If any of the needed blobs do not exist in @table, return
438  *      WIMLIB_ERR_RESOURCE_NOT_FOUND.
439  * If @force is %true:
440  *      If any of the needed blobs do not exist in @table, allocate new blob
441  *      descriptors for them and insert them into @table.  This does not, of
442  *      course, cause the data of these blobs to magically exist, but this is
443  *      needed by the code for extraction from a pipe.
444  *
445  * Returns 0 on success; WIMLIB_ERR_NOMEM if out of memory; or
446  * WIMLIB_ERR_RESOURCE_NOT_FOUND if @force is %false and at least one blob
447  * referenced by the inode was missing.
448  */
449 int
450 inode_resolve_streams(struct wim_inode *inode, struct blob_table *table,
451                       bool force)
452 {
453         for (unsigned i = 0; i < inode->i_num_streams; i++) {
454                 struct wim_inode_stream *strm = &inode->i_streams[i];
455
456                 if (strm->stream_resolved)
457                         continue;
458
459                 const u8 *hash = stream_hash(strm);
460                 struct blob_descriptor *blob = NULL;
461
462                 if (!is_zero_hash(hash)) {
463                         blob = lookup_blob(table, hash);
464                         if (!blob) {
465                                 if (!force)
466                                         return blob_not_found_error(inode, hash);
467                                 blob = new_blob_descriptor();
468                                 if (!blob)
469                                         return WIMLIB_ERR_NOMEM;
470                                 copy_hash(blob->hash, hash);
471                                 blob_table_insert(table, blob);
472                         }
473                 }
474                 strm->_stream_blob = blob;
475                 strm->stream_resolved = 1;
476         }
477         return 0;
478 }
479
480 int
481 blob_not_found_error(const struct wim_inode *inode, const u8 *hash)
482 {
483         if (wimlib_print_errors) {
484                 tchar hashstr[SHA1_HASH_SIZE * 2 + 1];
485
486                 sprint_hash(hash, hashstr);
487
488                 ERROR("\"%"TS"\": blob not found\n"
489                       "        SHA-1 message digest of missing blob:\n"
490                       "        %"TS"",
491                       inode_first_full_path(inode), hashstr);
492         }
493         return WIMLIB_ERR_RESOURCE_NOT_FOUND;
494 }
495
496 /*
497  * Return the blob descriptor for the specified stream, or NULL if the blob for
498  * the stream is empty or not available.
499  */
500 struct blob_descriptor *
501 stream_blob(const struct wim_inode_stream *strm, const struct blob_table *table)
502 {
503         if (strm->stream_resolved)
504                 return strm->_stream_blob;
505         else
506                 return lookup_blob(table, strm->_stream_hash);
507 }
508
509 /* Return the SHA-1 message digest of the data of the specified stream, or a
510  * void SHA-1 of all zeroes if the specified stream is empty.   */
511 const u8 *
512 stream_hash(const struct wim_inode_stream *strm)
513 {
514         if (strm->stream_resolved)
515                 return strm->_stream_blob ? strm->_stream_blob->hash : zero_hash;
516         else
517                 return strm->_stream_hash;
518 }
519
520 /*
521  * Return the blob descriptor for the unnamed data stream of the inode, or NULL
522  * if the inode does not have an unnamed data stream, the blob for the inode's
523  * unnamed data stream is empty, or the blob for the inode's unnamed data stream
524  * is not available in @blob_table.
525  */
526 struct blob_descriptor *
527 inode_get_blob_for_unnamed_data_stream(const struct wim_inode *inode,
528                                        const struct blob_table *blob_table)
529 {
530         const struct wim_inode_stream *strm;
531
532         strm = inode_get_unnamed_data_stream(inode);
533         if (!strm)
534                 return NULL;
535
536         return stream_blob(strm, blob_table);
537 }
538
539 /* Like inode_get_blob_for_unnamed_data_stream(), but assumes the unnamed data
540  * stream is resolved.  */
541 struct blob_descriptor *
542 inode_get_blob_for_unnamed_data_stream_resolved(const struct wim_inode *inode)
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_resolved(strm);
551 }
552
553 /*
554  * Return the SHA-1 message digest of the unnamed data stream of the inode, or a
555  * void SHA-1 of all zeroes if the inode does not have an unnamed data stream or
556  * if the inode's unnamed data stream is empty.
557  */
558 const u8 *
559 inode_get_hash_of_unnamed_data_stream(const struct wim_inode *inode)
560 {
561         const struct wim_inode_stream *strm;
562
563         strm = inode_get_unnamed_data_stream(inode);
564         if (!strm)
565                 return zero_hash;
566
567         return stream_hash(strm);
568 }
569
570 /* Acquire another reference to each blob referenced by this inode.  This is
571  * necessary when creating a hard link to this inode.
572  *
573  * All streams of the inode must be resolved.  */
574 void
575 inode_ref_blobs(struct wim_inode *inode)
576 {
577         for (unsigned i = 0; i < inode->i_num_streams; i++) {
578                 struct blob_descriptor *blob;
579
580                 blob = stream_blob_resolved(&inode->i_streams[i]);
581                 if (blob)
582                         blob->refcnt++;
583         }
584 }
585
586 /* Release a reference to each blob referenced by this inode.  This is necessary
587  * when deleting a hard link to this inode.  */
588 void
589 inode_unref_blobs(struct wim_inode *inode, struct blob_table *blob_table)
590 {
591         for (unsigned i = 0; i < inode->i_num_streams; i++) {
592                 struct blob_descriptor *blob;
593
594                 blob = stream_blob(&inode->i_streams[i], blob_table);
595                 if (blob)
596                         blob_decrement_refcnt(blob, blob_table);
597         }
598 }
599
600 /*
601  * Given a blob descriptor, return a pointer to the pointer contained in the
602  * stream that references it.
603  *
604  * This is only possible for "unhashed" blobs, which are guaranteed to have only
605  * one referencing stream, and that reference is guaranteed to be in a resolved
606  * stream.  (It can't be in an unresolved stream, since that would imply the
607  * hash is known!)
608  */
609 struct blob_descriptor **
610 retrieve_pointer_to_unhashed_blob(struct blob_descriptor *blob)
611 {
612         wimlib_assert(blob->unhashed);
613
614         struct wim_inode *inode = blob->back_inode;
615         for (unsigned i = 0; i < inode->i_num_streams; i++) {
616                 if (inode->i_streams[i].stream_id == blob->back_stream_id) {
617                         wimlib_assert(inode->i_streams[i]._stream_blob == blob);
618                         return &inode->i_streams[i]._stream_blob;
619                 }
620         }
621
622         wimlib_assert(0);
623         return NULL;
624 }