]> wimlib.net Git - wimlib/blobdiff - src/inode.c
New helper: inode_get_unnamed_data_stream()
[wimlib] / src / inode.c
index 1114a15358205acee00cbdb7db834b8126b3b5d1..4b1b1d3eee8e108b3934ce5c6ba6f026cba7ac32 100644 (file)
  */
 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_list);
+       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;
 }
 
@@ -205,6 +202,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 +313,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 +324,39 @@ 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;
+
+       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 +366,55 @@ 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;
 
-       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;
+
+       blob = new_blob_from_data_buffer(data, size, blob_table);
+       if (!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 +438,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 +453,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,12 +474,9 @@ 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;
 }
 
@@ -477,7 +547,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 +561,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 +578,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;