4 * Functions that operate on WIM inodes.
6 * See dentry.c for a description of the relationship between WIM dentries and
11 * Copyright (C) 2012, 2013, 2014, 2015 Eric Biggers
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
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
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/.
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"
42 * The 'stream_name' field of unnamed streams always points to this array, which
43 * is an empty UTF-16 string.
45 const utf16lechar NO_STREAM_NAME[1];
47 /* Allocate a new inode and associate the specified dentry with it. */
49 new_inode(struct wim_dentry *dentry, bool set_timestamps)
51 struct wim_inode *inode;
53 inode = CALLOC(1, sizeof(struct wim_inode));
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);
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;
68 d_associate(dentry, inode);
73 destroy_stream(struct wim_inode_stream *strm)
75 if (strm->stream_name != NO_STREAM_NAME)
76 FREE(strm->stream_name);
80 free_inode(struct wim_inode *inode)
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);
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);
96 free_inode_if_unneeded(struct wim_inode *inode)
101 if (inode->i_num_opened_fds)
107 /* Associate a dentry with the specified inode. */
109 d_associate(struct wim_dentry *dentry, struct wim_inode *inode)
111 wimlib_assert(!dentry->d_inode);
113 list_add_tail(&dentry->d_alias, &inode->i_dentry);
114 dentry->d_inode = inode;
118 /* Disassociate a dentry from its inode, if any. Following this, free the inode
119 * if it is no longer in use. */
121 d_disassociate(struct wim_dentry *dentry)
123 struct wim_inode *inode = dentry->d_inode;
125 if (unlikely(!inode))
128 wimlib_assert(inode->i_nlink > 0);
130 list_del(&dentry->d_alias);
131 dentry->d_inode = NULL;
134 free_inode_if_unneeded(inode);
139 inode_dec_num_opened_fds(struct wim_inode *inode)
141 wimlib_assert(inode->i_num_opened_fds > 0);
143 if (--inode->i_num_opened_fds == 0) {
144 /* The last file descriptor to this inode was closed. */
147 inode->i_num_allocated_fds = 0;
149 free_inode_if_unneeded(inode);
155 * Retrieve a stream of an inode.
158 * The inode from which the stream is desired
160 * The type of the stream desired
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
165 * Returns a pointer to the stream if found, otherwise NULL.
167 struct wim_inode_stream *
168 inode_get_stream(const struct wim_inode *inode, int stream_type,
169 const utf16lechar *stream_name)
171 if (stream_name == NO_STREAM_NAME) /* Optimization */
172 return inode_get_unnamed_stream(inode, stream_type);
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))
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.
190 struct wim_inode_stream *
191 inode_get_unnamed_stream(const struct wim_inode *inode, int stream_type)
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)
205 * Add a new stream to the specified inode.
208 * The inode to which to add the stream
210 * The type of the stream being added
212 * The name of the stream being added as a null-terminated UTF-16LE string,
213 * or NO_STREAM_NAME if the stream is unnamed
215 * The blob that the new stream will initially reference, or NULL
217 * Returns a pointer to the new stream, or NULL with errno set if it could not
220 struct wim_inode_stream *
221 inode_add_stream(struct wim_inode *inode, int stream_type,
222 const utf16lechar *stream_name, struct blob_descriptor *blob)
224 if (inode->i_num_streams >= 0xFFFF) {
225 ERROR("Inode has too many streams! Path=\"%"TS"\"",
226 inode_first_full_path(inode));
231 struct wim_inode_stream *streams;
232 struct wim_inode_stream *new_strm;
234 if (inode->i_streams == inode->i_embedded_streams) {
235 if (inode->i_num_streams < ARRAY_LEN(inode->i_embedded_streams)) {
236 streams = inode->i_embedded_streams;
238 streams = MALLOC((inode->i_num_streams + 1) *
239 sizeof(inode->i_streams[0]));
242 memcpy(streams, inode->i_streams,
243 (inode->i_num_streams *
244 sizeof(inode->i_streams[0])));
245 inode->i_streams = streams;
248 streams = REALLOC(inode->i_streams,
249 (inode->i_num_streams + 1) *
250 sizeof(inode->i_streams[0]));
253 inode->i_streams = streams;
255 new_strm = &streams[inode->i_num_streams];
257 memset(new_strm, 0, sizeof(*new_strm));
259 new_strm->stream_type = stream_type;
262 new_strm->stream_name = (utf16lechar *)NO_STREAM_NAME;
265 new_strm->stream_name = utf16le_dup(stream_name);
266 if (!new_strm->stream_name)
269 new_strm->stream_id = inode->i_next_stream_id++;
271 stream_set_blob(new_strm, blob);
273 inode->i_num_streams++;
279 * Create a new blob descriptor for the specified data buffer or use an existing
280 * blob descriptor in @blob_table for an identical blob, then add a stream of
281 * the specified type and name to the specified inode and set it to initially
282 * reference the blob.
285 * The inode to which to add the stream
287 * The type of the stream being added
289 * The name of the stream being added as a null-terminated UTF-16LE string,
290 * or NO_STREAM_NAME if the stream is unnamed
292 * The uncompressed data of the blob
294 * The size, in bytes, of the blob data
296 * Pointer to the blob table in which the blob needs to be indexed.
298 * Returns a pointer to the new stream if successfully added, otherwise NULL
301 struct wim_inode_stream *
302 inode_add_stream_with_data(struct wim_inode *inode,
303 int stream_type, const utf16lechar *stream_name,
304 const void *data, size_t size,
305 struct blob_table *blob_table)
307 struct blob_descriptor *blob;
308 struct wim_inode_stream *strm;
310 blob = new_blob_from_data_buffer(data, size, blob_table);
313 strm = inode_add_stream(inode, stream_type, stream_name, blob);
315 blob_decrement_refcnt(blob, blob_table);
320 * Remove a stream from the specified inode and release the reference to the
321 * blob descriptor, if any.
324 inode_remove_stream(struct wim_inode *inode, struct wim_inode_stream *strm,
325 struct blob_table *blob_table)
327 struct blob_descriptor *blob;
328 unsigned idx = strm - inode->i_streams;
330 wimlib_assert(idx < inode->i_num_streams);
332 blob = stream_blob(strm, blob_table);
334 blob_decrement_refcnt(blob, blob_table);
336 destroy_stream(strm);
338 memmove(&inode->i_streams[idx],
339 &inode->i_streams[idx + 1],
340 (inode->i_num_streams - idx - 1) * sizeof(inode->i_streams[0]));
341 inode->i_num_streams--;
344 /* Returns true iff the specified inode has at least one named data stream. */
346 inode_has_named_data_stream(const struct wim_inode *inode)
348 for (unsigned i = 0; i < inode->i_num_streams; i++)
349 if (stream_is_named_data_stream(&inode->i_streams[i]))
355 * Resolve an inode's streams.
357 * For each stream, this replaces the SHA-1 message digest of the blob data with
358 * a pointer to the 'struct blob_descriptor' for the blob. Blob descriptors are
359 * looked up in @table.
361 * If @force is %false:
362 * If any of the needed blobs do not exist in @table, return
363 * WIMLIB_ERR_RESOURCE_NOT_FOUND and leave the inode unmodified.
364 * If @force is %true:
365 * If any of the needed blobs do not exist in @table, allocate new blob
366 * descriptors for them and insert them into @table. This does not, of
367 * course, cause the data of these blobs to magically exist, but this is
368 * needed by the code for extraction from a pipe.
370 * Returns 0 on success; WIMLIB_ERR_NOMEM if out of memory; or
371 * WIMLIB_ERR_RESOURCE_NOT_FOUND if @force is %false and at least one blob
372 * referenced by the inode was missing.
375 inode_resolve_streams(struct wim_inode *inode, struct blob_table *table,
378 struct blob_descriptor *blobs[inode->i_num_streams];
380 for (unsigned i = 0; i < inode->i_num_streams; i++) {
382 if (inode->i_streams[i].stream_resolved)
385 const u8 *hash = stream_hash(&inode->i_streams[i]);
386 struct blob_descriptor *blob = NULL;
388 if (!is_zero_hash(hash)) {
389 blob = lookup_blob(table, hash);
392 return blob_not_found_error(inode, hash);
393 blob = new_blob_descriptor();
395 return WIMLIB_ERR_NOMEM;
396 copy_hash(blob->hash, hash);
397 blob_table_insert(table, blob);
403 for (unsigned i = 0; i < inode->i_num_streams; i++)
404 if (!inode->i_streams[i].stream_resolved)
405 stream_set_blob(&inode->i_streams[i], blobs[i]);
409 /* Undo the effects of inode_resolve_streams(). */
411 inode_unresolve_streams(struct wim_inode *inode)
413 for (unsigned i = 0; i < inode->i_num_streams; i++) {
415 if (!inode->i_streams[i].stream_resolved)
418 copy_hash(inode->i_streams[i]._stream_hash,
419 stream_hash(&inode->i_streams[i]));
420 inode->i_streams[i].stream_resolved = 0;
425 blob_not_found_error(const struct wim_inode *inode, const u8 *hash)
427 if (wimlib_print_errors) {
428 tchar hashstr[SHA1_HASH_SIZE * 2 + 1];
430 sprint_hash(hash, hashstr);
432 ERROR("\"%"TS"\": blob not found\n"
433 " SHA-1 message digest of missing blob:\n"
435 inode_first_full_path(inode), hashstr);
437 return WIMLIB_ERR_RESOURCE_NOT_FOUND;
441 * Return the blob descriptor for the specified stream, or NULL if the blob for
442 * the stream is empty or not available.
444 struct blob_descriptor *
445 stream_blob(const struct wim_inode_stream *strm, const struct blob_table *table)
447 if (strm->stream_resolved)
448 return strm->_stream_blob;
450 return lookup_blob(table, strm->_stream_hash);
453 /* Return the SHA-1 message digest of the data of the specified stream, or a
454 * void SHA-1 of all zeroes if the specified stream is empty. */
456 stream_hash(const struct wim_inode_stream *strm)
458 if (strm->stream_resolved)
459 return strm->_stream_blob ? strm->_stream_blob->hash : zero_hash;
461 return strm->_stream_hash;
465 * Return the blob descriptor for the unnamed data stream of the inode, or NULL
466 * if the inode does not have an unnamed data stream, the blob for the inode's
467 * unnamed data stream is empty, or the blob for the inode's unnamed data stream
468 * is not available in @blob_table.
470 struct blob_descriptor *
471 inode_get_blob_for_unnamed_data_stream(const struct wim_inode *inode,
472 const struct blob_table *blob_table)
474 const struct wim_inode_stream *strm;
476 strm = inode_get_unnamed_stream(inode, STREAM_TYPE_DATA);
480 return stream_blob(strm, blob_table);
483 /* Like inode_get_blob_for_unnamed_data_stream(), but assumes the unnamed data
484 * stream is resolved. */
485 struct blob_descriptor *
486 inode_get_blob_for_unnamed_data_stream_resolved(const struct wim_inode *inode)
488 const struct wim_inode_stream *strm;
490 strm = inode_get_unnamed_stream(inode, STREAM_TYPE_DATA);
494 return stream_blob_resolved(strm);
498 * Return the SHA-1 message digest of the unnamed data stream of the inode, or a
499 * void SHA-1 of all zeroes if the inode does not have an unnamed data stream or
500 * if the inode's unnamed data stream is empty.
503 inode_get_hash_of_unnamed_data_stream(const struct wim_inode *inode)
505 const struct wim_inode_stream *strm;
507 strm = inode_get_unnamed_stream(inode, STREAM_TYPE_DATA);
511 return stream_hash(strm);
514 /* Acquire another reference to each blob referenced by this inode. This is
515 * necessary when creating a hard link to this inode.
517 * All streams of the inode must be resolved. */
519 inode_ref_blobs(struct wim_inode *inode)
521 for (unsigned i = 0; i < inode->i_num_streams; i++) {
522 struct blob_descriptor *blob;
524 blob = stream_blob_resolved(&inode->i_streams[i]);
530 /* Release a reference to each blob referenced by this inode. This is necessary
531 * when deleting a hard link to this inode. */
533 inode_unref_blobs(struct wim_inode *inode, struct blob_table *blob_table)
535 for (unsigned i = 0; i < inode->i_num_streams; i++) {
536 struct blob_descriptor *blob;
538 blob = stream_blob(&inode->i_streams[i], blob_table);
540 blob_decrement_refcnt(blob, blob_table);
545 * Given a blob descriptor, return a pointer to the pointer contained in the
546 * stream that references it.
548 * This is only possible for "unhashed" blobs, which are guaranteed to have only
549 * one referencing stream, and that reference is guaranteed to be in a resolved
550 * stream. (It can't be in an unresolved stream, since that would imply the
553 struct blob_descriptor **
554 retrieve_pointer_to_unhashed_blob(struct blob_descriptor *blob)
556 wimlib_assert(blob->unhashed);
558 struct wim_inode *inode = blob->back_inode;
559 for (unsigned i = 0; i < inode->i_num_streams; i++) {
560 if (inode->i_streams[i].stream_id == blob->back_stream_id) {
561 wimlib_assert(inode->i_streams[i]._stream_blob == blob);
562 return &inode->i_streams[i]._stream_blob;