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