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