]> wimlib.net Git - wimlib/blobdiff - src/dentry.c
New helper macro: ALIGN()
[wimlib] / src / dentry.c
index 55da50cff6834063df67cae38477f8db0b6215d2..a19e02c8f3df54dde88ad1b563d491dd1c5f309f 100644 (file)
@@ -347,7 +347,7 @@ stream_out_total_length(const struct wim_inode_stream *strm)
                len += utf16le_len_bytes(strm->stream_name) + 2;
 
        /* Account for any necessary padding to the next 8-byte boundary.  */
-       return (len + 7) & ~7;
+       return ALIGN(len, 8);
 }
 
 /*
@@ -364,12 +364,9 @@ dentry_out_total_length(const struct wim_dentry *dentry)
 
        len = dentry_min_len_with_names(dentry->file_name_nbytes,
                                        dentry->short_name_nbytes);
-       len = (len + 7) & ~7;
+       len = ALIGN(len, 8);
 
-       if (inode->i_extra_size) {
-               len += inode->i_extra_size;
-               len = (len + 7) & ~7;
-       }
+       len += ALIGN(inode->i_extra_size, 8);
 
        if (!(inode->i_attributes & FILE_ATTRIBUTE_ENCRYPTED)) {
                /*
@@ -396,8 +393,8 @@ dentry_out_total_length(const struct wim_dentry *dentry)
 
                if (have_named_data_stream || have_reparse_point_stream) {
                        if (have_reparse_point_stream)
-                               len += (sizeof(struct wim_extra_stream_entry_on_disk) + 7) & ~7;
-                       len += (sizeof(struct wim_extra_stream_entry_on_disk) + 7) & ~7;
+                               len += ALIGN(sizeof(struct wim_extra_stream_entry_on_disk), 8);
+                       len += ALIGN(sizeof(struct wim_extra_stream_entry_on_disk), 8);
                }
        }
 
@@ -914,7 +911,7 @@ get_parent_dentry(WIMStruct *wim, const tchar *path,
  * *dentry_ret.  On failure, returns WIMLIB_ERR_NOMEM or an error code resulting
  * from a failed string conversion.
  */
-int
+static int
 new_dentry(const tchar *name, struct wim_dentry **dentry_ret)
 {
        struct wim_dentry *dentry;
@@ -936,9 +933,12 @@ new_dentry(const tchar *name, struct wim_dentry **dentry_ret)
        return 0;
 }
 
-static int
-_new_dentry_with_inode(const tchar *name, struct wim_dentry **dentry_ret,
-                      bool timeless)
+/* Like new_dentry(), but also allocate an inode and associate it with the
+ * dentry.  If set_timestamps=true, the timestamps for the inode will be set to
+ * the current time; otherwise, they will be left 0.  */
+int
+new_dentry_with_new_inode(const tchar *name, bool set_timestamps,
+                         struct wim_dentry **dentry_ret)
 {
        struct wim_dentry *dentry;
        struct wim_inode *inode;
@@ -948,36 +948,28 @@ _new_dentry_with_inode(const tchar *name, struct wim_dentry **dentry_ret,
        if (ret)
                return ret;
 
-       if (timeless)
-               inode = new_timeless_inode();
-       else
-               inode = new_inode();
+       inode = new_inode(dentry, set_timestamps);
        if (!inode) {
                free_dentry(dentry);
                return WIMLIB_ERR_NOMEM;
        }
 
-       d_associate(dentry, inode);
-
        *dentry_ret = dentry;
        return 0;
 }
 
-/* Like new_dentry(), but also allocate an inode and associate it with the
- * dentry.  The timestamps for the inode will be set to the current time.  */
+/* Like new_dentry(), but also associate the new dentry with the specified inode
+ * and acquire a reference to each of the inode's blobs.  */
 int
-new_dentry_with_inode(const tchar *name, struct wim_dentry **dentry_ret)
+new_dentry_with_existing_inode(const tchar *name, struct wim_inode *inode,
+                              struct wim_dentry **dentry_ret)
 {
-       return _new_dentry_with_inode(name, dentry_ret, false);
-}
-
-/* Like new_dentry_with_inode(), but don't bother setting the timestamps for the
- * new inode; instead, just leave them as 0, under the presumption that the
- * caller will set them itself.  */
-int
-new_dentry_with_timeless_inode(const tchar *name, struct wim_dentry **dentry_ret)
-{
-       return _new_dentry_with_inode(name, dentry_ret, true);
+       int ret = new_dentry(name, dentry_ret);
+       if (ret)
+               return ret;
+       d_associate(*dentry_ret, inode);
+       inode_ref_blobs(inode);
+       return 0;
 }
 
 /* Create an unnamed dentry with a new inode for a directory with the default
@@ -988,7 +980,7 @@ new_filler_directory(struct wim_dentry **dentry_ret)
        int ret;
        struct wim_dentry *dentry;
 
-       ret = new_dentry_with_inode(NULL, &dentry);
+       ret = new_dentry_with_new_inode(NULL, true, &dentry);
        if (ret)
                return ret;
        /* Leave the inode number as 0; this is allowed for non
@@ -1304,9 +1296,7 @@ setup_inode_streams(const u8 *p, const u8 *end, struct wim_inode *inode,
 
        inode->i_num_streams = 1 + num_extra_streams;
 
-       if (likely(inode->i_num_streams <= ARRAY_LEN(inode->i_embedded_streams))) {
-               inode->i_streams = inode->i_embedded_streams;
-       } else {
+       if (unlikely(inode->i_num_streams > ARRAY_LEN(inode->i_embedded_streams))) {
                inode->i_streams = CALLOC(inode->i_num_streams,
                                          sizeof(inode->i_streams[0]));
                if (!inode->i_streams)
@@ -1338,10 +1328,7 @@ setup_inode_streams(const u8 *p, const u8 *end, struct wim_inode *inode,
                disk_strm = (const struct wim_extra_stream_entry_on_disk *)p;
 
                /* Read the length field  */
-               length = le64_to_cpu(disk_strm->length);
-
-               /* 8-byte align the length  */
-               length = (length + 7) & ~7;
+               length = ALIGN(le64_to_cpu(disk_strm->length), 8);
 
                /* Make sure the length field is neither so small it doesn't
                 * include all the fixed-length data nor so large it overflows
@@ -1431,7 +1418,7 @@ read_dentry(const u8 * restrict buf, size_t buf_len,
        disk_dentry = (const struct wim_dentry_on_disk*)p;
 
        /* Get dentry length.  */
-       length = (le64_to_cpu(disk_dentry->length) + 7) & ~7;
+       length = ALIGN(le64_to_cpu(disk_dentry->length), 8);
 
        /* Check for end-of-directory.  */
        if (length <= 8) {
@@ -1449,7 +1436,7 @@ read_dentry(const u8 * restrict buf, size_t buf_len,
                return WIMLIB_ERR_INVALID_METADATA_RESOURCE;
 
        /* Allocate new dentry structure, along with a preliminary inode.  */
-       ret = new_dentry_with_timeless_inode(NULL, &dentry);
+       ret = new_dentry_with_new_inode(NULL, false, &dentry);
        if (ret)
                return ret;
 
@@ -1826,8 +1813,7 @@ write_dentry(const struct wim_dentry * restrict dentry, u8 * restrict p)
                const struct wim_inode_stream *efs_strm;
                const u8 *efs_hash;
 
-               efs_strm = inode_get_stream(inode, STREAM_TYPE_EFSRPC_RAW_DATA,
-                                           NO_STREAM_NAME);
+               efs_strm = inode_get_unnamed_stream(inode, STREAM_TYPE_EFSRPC_RAW_DATA);
                efs_hash = efs_strm ? stream_hash(efs_strm) : zero_hash;
                copy_hash(disk_dentry->default_hash, efs_hash);
                disk_dentry->num_extra_streams = cpu_to_le16(0);
@@ -1843,7 +1829,6 @@ write_dentry(const struct wim_dentry * restrict dentry, u8 * restrict p)
                 */
                bool have_named_data_stream = false;
                bool have_reparse_point_stream = false;
-               u16 num_extra_streams = 0;
                const u8 *unnamed_data_stream_hash = zero_hash;
                const u8 *reparse_point_hash;
                for (unsigned i = 0; i < inode->i_num_streams; i++) {
@@ -1859,7 +1844,9 @@ write_dentry(const struct wim_dentry * restrict dentry, u8 * restrict p)
                        }
                }
 
-               if (have_reparse_point_stream || have_named_data_stream) {
+               if (unlikely(have_reparse_point_stream || have_named_data_stream)) {
+
+                       unsigned num_extra_streams = 0;
 
                        copy_hash(disk_dentry->default_hash, zero_hash);
 
@@ -1872,19 +1859,22 @@ write_dentry(const struct wim_dentry * restrict dentry, u8 * restrict p)
                        p = write_extra_stream_entry(p, NO_STREAM_NAME,
                                                     unnamed_data_stream_hash);
                        num_extra_streams++;
-               } else {
-                       copy_hash(disk_dentry->default_hash, unnamed_data_stream_hash);
-               }
 
-               for (unsigned i = 0; i < inode->i_num_streams; i++) {
-                       const struct wim_inode_stream *strm = &inode->i_streams[i];
-                       if (stream_is_named_data_stream(strm)) {
-                               p = write_extra_stream_entry(p, strm->stream_name,
-                                                            stream_hash(strm));
-                               num_extra_streams++;
+                       for (unsigned i = 0; i < inode->i_num_streams; i++) {
+                               const struct wim_inode_stream *strm = &inode->i_streams[i];
+                               if (stream_is_named_data_stream(strm)) {
+                                       p = write_extra_stream_entry(p, strm->stream_name,
+                                                                    stream_hash(strm));
+                                       num_extra_streams++;
+                               }
                        }
+                       wimlib_assert(num_extra_streams <= 0xFFFF);
+
+                       disk_dentry->num_extra_streams = cpu_to_le16(num_extra_streams);
+               } else {
+                       copy_hash(disk_dentry->default_hash, unnamed_data_stream_hash);
+                       disk_dentry->num_extra_streams = cpu_to_le16(0);
                }
-               disk_dentry->num_extra_streams = cpu_to_le16(num_extra_streams);
        }
 
        return p;