X-Git-Url: https://wimlib.net/git/?p=wimlib;a=blobdiff_plain;f=src%2Finode.c;h=690eb22f3abf657ef51b354e030e85fe00eec8ac;hp=1114a15358205acee00cbdb7db834b8126b3b5d1;hb=ebdba490384924ef422b1df675ba11d5030faf09;hpb=3de1ec66f778edda19865482d685bc6f4e17faf7 diff --git a/src/inode.c b/src/inode.c index 1114a153..690eb22f 100644 --- a/src/inode.c +++ b/src/inode.c @@ -44,32 +44,28 @@ */ const utf16lechar NO_STREAM_NAME[1]; -/* Allocate a new inode. Set the timestamps to the current time. */ +/* Allocate a new inode and associate the specified dentry with it. */ struct wim_inode * -new_inode(void) +new_inode(struct wim_dentry *dentry, bool set_timestamps) { - struct wim_inode *inode = new_timeless_inode(); - if (inode) { + struct wim_inode *inode; + + inode = CALLOC(1, sizeof(struct wim_inode)); + if (!inode) + return NULL; + + inode->i_security_id = -1; + /*inode->i_nlink = 0;*/ + inode->i_not_rpfixed = 1; + INIT_LIST_HEAD(&inode->i_dentry); + inode->i_streams = inode->i_embedded_streams; + if (set_timestamps) { u64 now = now_as_wim_timestamp(); inode->i_creation_time = now; inode->i_last_access_time = now; inode->i_last_write_time = now; } - return inode; -} - -/* Allocate a new inode. Leave the timestamps zeroed out. */ -struct wim_inode * -new_timeless_inode(void) -{ - struct wim_inode *inode = CALLOC(1, sizeof(struct wim_inode)); - if (inode) { - inode->i_security_id = -1; - /*inode->i_nlink = 0;*/ - inode->i_not_rpfixed = 1; - INIT_LIST_HEAD(&inode->i_list); - INIT_LIST_HEAD(&inode->i_dentry); - } + d_associate(dentry, inode); return inode; } @@ -89,8 +85,6 @@ free_inode(struct wim_inode *inode) FREE(inode->i_streams); if (inode->i_extra) FREE(inode->i_extra); - /* HACK: This may instead delete the inode from i_list, but hlist_del() - * behaves the same as list_del(). */ if (!hlist_unhashed(&inode->i_hlist)) hlist_del(&inode->i_hlist); FREE(inode); @@ -205,6 +199,52 @@ inode_get_unnamed_stream(const struct wim_inode *inode, int stream_type) return NULL; } + +static void +inode_set_stream_blob(struct wim_inode *inode, struct wim_inode_stream *strm, + struct blob_descriptor *new_blob) +{ + strm->_stream_blob = new_blob; + strm->stream_resolved = 1; + if (new_blob) + new_blob->refcnt += inode->i_nlink; +} + +static void +inode_unset_stream_blob(struct wim_inode *inode, struct wim_inode_stream *strm, + struct blob_table *blob_table) +{ + struct blob_descriptor *old_blob; + + old_blob = stream_blob(strm, blob_table); + if (old_blob) + blob_subtract_refcnt(old_blob, blob_table, inode->i_nlink); + strm->_stream_blob = NULL; + strm->stream_resolved = 1; +} + +/* + * Replace the blob associated with the specified stream. + * + * @inode + * The inode containing @strm + * @strm + * The stream whose data needs to be replaced + * @new_blob + * The new blob descriptor to assign + * @blob_table + * Pointer to the blob table in which data blobs are being indexed + */ +void +inode_replace_stream_blob(struct wim_inode *inode, + struct wim_inode_stream *strm, + struct blob_descriptor *new_blob, + struct blob_table *blob_table) +{ + inode_unset_stream_blob(inode, strm, blob_table); + inode_set_stream_blob(inode, strm, new_blob); +} + /* * Add a new stream to the specified inode. * @@ -270,9 +310,10 @@ inode_add_stream(struct wim_inode *inode, int stream_type, if (!new_strm->stream_name) return NULL; } + new_strm->stream_id = inode->i_next_stream_id++; - stream_set_blob(new_strm, blob); + inode_set_stream_blob(inode, new_strm, blob); inode->i_num_streams++; @@ -280,10 +321,41 @@ inode_add_stream(struct wim_inode *inode, int stream_type, } /* - * Create a new blob descriptor for the specified data buffer or use an existing - * blob descriptor in @blob_table for an identical blob, then add a stream of - * the specified type and name to the specified inode and set it to initially - * reference the blob. + * Replace the data of the specified stream. + * + * @inode + * The inode containing @strm + * @strm + * The stream whose data needs to be replaced + * @data + * The buffer of data to assign to the stream + * @size + * Size of the @data buffer, in bytes + * @blob_table + * Pointer to the blob table in which data blobs are being indexed + * + * Returns true if successful; false with errno set if unsuccessful. + */ +bool +inode_replace_stream_data(struct wim_inode *inode, + struct wim_inode_stream *strm, + const void *data, size_t size, + struct blob_table *blob_table) +{ + struct blob_descriptor *new_blob = NULL; + + if (size) { + new_blob = new_blob_from_data_buffer(data, size, blob_table); + if (!new_blob) + return false; + } + + inode_replace_stream_blob(inode, strm, new_blob, blob_table); + return true; +} + +/* + * Add a new stream to the specified inode and assign it the specified data. * * @inode * The inode to which to add the stream @@ -293,54 +365,57 @@ inode_add_stream(struct wim_inode *inode, int stream_type, * The name of the stream being added as a null-terminated UTF-16LE string, * or NO_STREAM_NAME if the stream is unnamed * @data - * The uncompressed data of the blob + * The buffer of data to assign to the new stream * @size - * The size, in bytes, of the blob data + * Size of the @data buffer, in bytes * @blob_table - * Pointer to the blob table in which the blob needs to be indexed. + * Pointer to the blob table in which data blobs are being indexed * - * Returns a pointer to the new stream if successfully added, otherwise NULL - * with errno set. + * Returns true if successful; false with errno set if unsuccessful. */ -struct wim_inode_stream * +bool inode_add_stream_with_data(struct wim_inode *inode, int stream_type, const utf16lechar *stream_name, const void *data, size_t size, struct blob_table *blob_table) { - struct blob_descriptor *blob; struct wim_inode_stream *strm; + struct blob_descriptor *blob = NULL; - blob = new_blob_from_data_buffer(data, size, blob_table); - if (!blob) - return NULL; - strm = inode_add_stream(inode, stream_type, stream_name, blob); + strm = inode_add_stream(inode, stream_type, stream_name, NULL); if (!strm) - blob_decrement_refcnt(blob, blob_table); - return strm; + return false; + + if (size) { + blob = new_blob_from_data_buffer(data, size, blob_table); + if (unlikely(!blob)) { + inode_remove_stream(inode, strm, blob_table); + return false; + } + } + + inode_set_stream_blob(inode, strm, blob); + return true; } /* - * Remove a stream from the specified inode and release the reference to the - * blob descriptor, if any. + * Remove a stream from the specified inode. + * + * This handles releasing the references to the blob descriptor, if any. */ void inode_remove_stream(struct wim_inode *inode, struct wim_inode_stream *strm, struct blob_table *blob_table) { - struct blob_descriptor *blob; unsigned idx = strm - inode->i_streams; wimlib_assert(idx < inode->i_num_streams); - blob = stream_blob(strm, blob_table); - if (blob) - blob_decrement_refcnt(blob, blob_table); + inode_unset_stream_blob(inode, strm, blob_table); destroy_stream(strm); - memmove(&inode->i_streams[idx], - &inode->i_streams[idx + 1], + memmove(strm, strm + 1, (inode->i_num_streams - idx - 1) * sizeof(inode->i_streams[0])); inode->i_num_streams--; } @@ -364,7 +439,7 @@ inode_has_named_data_stream(const struct wim_inode *inode) * * If @force is %false: * If any of the needed blobs do not exist in @table, return - * WIMLIB_ERR_RESOURCE_NOT_FOUND and leave the inode unmodified. + * WIMLIB_ERR_RESOURCE_NOT_FOUND. * If @force is %true: * If any of the needed blobs do not exist in @table, allocate new blob * descriptors for them and insert them into @table. This does not, of @@ -379,14 +454,13 @@ int inode_resolve_streams(struct wim_inode *inode, struct blob_table *table, bool force) { - struct blob_descriptor *blobs[inode->i_num_streams]; - for (unsigned i = 0; i < inode->i_num_streams; i++) { + struct wim_inode_stream *strm = &inode->i_streams[i]; - if (inode->i_streams[i].stream_resolved) + if (strm->stream_resolved) continue; - const u8 *hash = stream_hash(&inode->i_streams[i]); + const u8 *hash = stream_hash(strm); struct blob_descriptor *blob = NULL; if (!is_zero_hash(hash)) { @@ -401,30 +475,12 @@ inode_resolve_streams(struct wim_inode *inode, struct blob_table *table, blob_table_insert(table, blob); } } - blobs[i] = blob; + strm->_stream_blob = blob; + strm->stream_resolved = 1; } - - for (unsigned i = 0; i < inode->i_num_streams; i++) - if (!inode->i_streams[i].stream_resolved) - stream_set_blob(&inode->i_streams[i], blobs[i]); return 0; } -/* Undo the effects of inode_resolve_streams(). */ -void -inode_unresolve_streams(struct wim_inode *inode) -{ - for (unsigned i = 0; i < inode->i_num_streams; i++) { - - if (!inode->i_streams[i].stream_resolved) - continue; - - copy_hash(inode->i_streams[i]._stream_hash, - stream_hash(&inode->i_streams[i])); - inode->i_streams[i].stream_resolved = 0; - } -} - int blob_not_found_error(const struct wim_inode *inode, const u8 *hash) { @@ -442,8 +498,8 @@ blob_not_found_error(const struct wim_inode *inode, const u8 *hash) } /* - * Return the blob descriptor for the specified stream, or NULL if the blob for - * the stream is empty or not available. + * Return the blob descriptor for the specified stream, or NULL if the stream is + * empty or its blob is not available in @table. */ struct blob_descriptor * stream_blob(const struct wim_inode_stream *strm, const struct blob_table *table) @@ -467,9 +523,9 @@ stream_hash(const struct wim_inode_stream *strm) /* * Return the blob descriptor for the unnamed data stream of the inode, or NULL - * if the inode does not have an unnamed data stream, the blob for the inode's - * unnamed data stream is empty, or the blob for the inode's unnamed data stream - * is not available in @blob_table. + * if the inode does not have an unnamed data stream, the inode's unnamed data + * stream is empty, or the blob for the inode's unnamed data stream is not + * available in @blob_table. */ struct blob_descriptor * inode_get_blob_for_unnamed_data_stream(const struct wim_inode *inode, @@ -477,7 +533,7 @@ inode_get_blob_for_unnamed_data_stream(const struct wim_inode *inode, { const struct wim_inode_stream *strm; - strm = inode_get_unnamed_stream(inode, STREAM_TYPE_DATA); + strm = inode_get_unnamed_data_stream(inode); if (!strm) return NULL; @@ -491,7 +547,7 @@ inode_get_blob_for_unnamed_data_stream_resolved(const struct wim_inode *inode) { const struct wim_inode_stream *strm; - strm = inode_get_unnamed_stream(inode, STREAM_TYPE_DATA); + strm = inode_get_unnamed_data_stream(inode); if (!strm) return NULL; @@ -508,7 +564,7 @@ inode_get_hash_of_unnamed_data_stream(const struct wim_inode *inode) { const struct wim_inode_stream *strm; - strm = inode_get_unnamed_stream(inode, STREAM_TYPE_DATA); + strm = inode_get_unnamed_data_stream(inode); if (!strm) return zero_hash;