New format for UNIX data
authorEric Biggers <ebiggers3@gmail.com>
Thu, 22 May 2014 03:21:20 +0000 (22:21 -0500)
committerEric Biggers <ebiggers3@gmail.com>
Thu, 22 May 2014 03:55:23 +0000 (22:55 -0500)
This moves the UNIX data into reserved fields of the WIM dentry.

This is theoretically less extensible than the previous format, which was
to add a specially-named alternate data stream entry to each file with
UNIX data.  However, having the UNIX data present in the metadata
resource is simpler and avoids problems when doing sequential extraction.

For now, this also seems to maintain compatibility with the MS
implementation, since it seems simply ignore the reserve fields.

Also, use 32-bit uids, gids, and modes.

13 files changed:
NEWS
doc/man1/imagex-capture.1.in
include/wimlib.h
include/wimlib/inode.h
include/wimlib/unix_data.h
programs/imagex.c
src/dentry.c
src/extract.c
src/inode.c
src/iterate_dir.c
src/mount_image.c
src/unix_apply.c
src/unix_capture.c

diff --git a/NEWS b/NEWS
index 26dad0f3af911b70161612cd52aa4fd7a1d3e9a5..3a79d47f96c7c57c2ce3cf4c12b725411d2ed4f6 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -13,6 +13,11 @@ Version 1.6.3-BETA:
        documentation for the new '--wimboot' option to wimcapture and wimapply
        for more information.
 
+       The format of UNIX data has been changed.  If you captured any WIMs with
+       the --unix-data option, to upgrade them you'll need to apply them with
+       --unix-data using wimlib v1.6.2, then re-capture them with --unix-data
+       using this version.
+
        Removed the --hardlink and --symlink options to wimapply, since I don't
        think they are too useful and they got in the way of improving the code.
 
index 9f1e6a68e38db5f4dc72fc36d8316278142610ad..073e1cab000c5ce2616d25e3cc85de723e204c08 100644 (file)
@@ -347,8 +347,7 @@ files.  This is done by adding a special alternate data stream to each directory
 entry that contains this information.  Please note that this flag is for
 convenience only, in case you want to use \fB@IMAGEX_PROGNAME@\fR to archive
 files on UNIX.  Microsoft's software will not understand this special
-information.  You also may run into problems when applying an image with UNIX
-data from a pipable WIM.
+information.
 .TP
 \fB--no-acls\fR
 Do not capture files' security descriptors.
@@ -580,7 +579,9 @@ pointing out that Windows' own default filesystem, NTFS, supports these
 characters, although Windows does not!)
 .IP \[bu]
 WIMs captured with \fB--unix-data\fR should be assumed to be incompatible with
-Microsoft's software.
+Microsoft's software.  However, the UNIX data format used in wimlib v1.6.3 and
+later uses reserved fields in the WIM dentries which seem to be ignored by the
+Microsoft implementation as of Windows 8.1.
 .IP \[bu]
 Pipable WIMs are incompatible with Microsoft's software.  Pipable WIMs are
 created only if \fIWIMFILE\fR was specified as "-" (standard output) or if
index 0ac092fd7a01d5765cde3a9317f01a7859c1fbda..a958bd0acc15a869f06df848e8d76e8907020e01 100644 (file)
@@ -1208,7 +1208,14 @@ struct wimlib_dir_entry {
 
        /** Time this file was last accessed.  */
        struct timespec last_access_time;
-       uint64_t reserved[16];
+
+       /* UNIX data (wimlib extension), only valid if unix_mode != 0  */
+       uint32_t unix_uid;
+       uint32_t unix_gid;
+       uint32_t unix_mode;
+       uint32_t unix_reserved;
+
+       uint64_t reserved[14];
 
        /** Array of streams that make up this file.  The first entry will
         * always exist and will correspond to the unnamed data stream (default
index c787a9d2443395a093a2e0c4f7c9774cc8b7768c..9a94ce2fd8adff6a59da17b722c728e29b5f2c71 100644 (file)
@@ -142,6 +142,9 @@ struct wim_inode {
         * wim_dentry_on_disk'.  */
        u64 i_ino;
 
+       /* UNIX data (wimlib extension)  */
+       struct wimlib_unix_data i_unix_data;
+
        union {
                /* Device number, used only during image capture, so we can
                 * identify hard linked files by the combination of inode number
@@ -336,18 +339,15 @@ inode_remove_ads(struct wim_inode *inode, u16 idx,
                 struct wim_lookup_table *lookup_table);
 
 static inline bool
-ads_entry_is_unix_data(const struct wim_ads_entry *entry)
+ads_entry_is_named_stream(const struct wim_ads_entry *entry)
 {
-       return (entry->stream_name_nbytes ==
-                       WIMLIB_UNIX_DATA_TAG_UTF16LE_NBYTES) &&
-               !memcmp(entry->stream_name, WIMLIB_UNIX_DATA_TAG_UTF16LE,
-                       WIMLIB_UNIX_DATA_TAG_UTF16LE_NBYTES);
+       return entry->stream_name_nbytes != 0;
 }
 
 static inline bool
-ads_entry_is_named_stream(const struct wim_ads_entry *entry)
+inode_has_unix_data(const struct wim_inode *inode)
 {
-       return entry->stream_name_nbytes != 0 && !ads_entry_is_unix_data(entry);
+       return inode->i_unix_data.mode != 0;
 }
 
 /* Is the inode a directory?
index bf0ee46c0496555dc2ce574d2d417086b1c16c37..186214b9168ba5e4e1d09d57ea5f0e21384d876e 100644 (file)
@@ -2,44 +2,19 @@
 #define _WIMLIB_UNIX_DATA_H
 
 #include "wimlib/types.h"
-struct wim_inode;
-struct wim_lookup_table;
 
-#define WIMLIB_UNIX_DATA_TAG "$$__wimlib_UNIX_data"
-#define WIMLIB_UNIX_DATA_TAG_NBYTES (sizeof(WIMLIB_UNIX_DATA_TAG) - 1)
-
-#define WIMLIB_UNIX_DATA_TAG_UTF16LE "$\0$\0_\0_\0w\0i\0m\0l\0i\0b\0_\0U\0N\0I\0X\0_\0d\0a\0t\0a\0"
-#define WIMLIB_UNIX_DATA_TAG_UTF16LE_NBYTES (sizeof(WIMLIB_UNIX_DATA_TAG_UTF16LE) - 1)
-
-extern bool
-inode_has_unix_data(const struct wim_inode *inode);
-
-#ifndef __WIN32__
-/* Format for special alternate data stream entries to store UNIX data for files
- * and directories (see: WIMLIB_ADD_FLAG_UNIX_DATA) */
 struct wimlib_unix_data {
-       u16 version; /* Must be 0 */
-       u16 uid;
-       u16 gid;
-       u16 mode;
-} _packed_attribute;
-
-#define NO_UNIX_DATA (-1)
-#define BAD_UNIX_DATA (-2)
-extern int
-inode_get_unix_data(const struct wim_inode *inode,
-                   struct wimlib_unix_data *unix_data,
-                   u16 *stream_idx_ret);
-
-#define UNIX_DATA_UID    0x1
-#define UNIX_DATA_GID    0x2
-#define UNIX_DATA_MODE   0x4
-#define UNIX_DATA_ALL    (UNIX_DATA_UID | UNIX_DATA_GID | UNIX_DATA_MODE)
-#define UNIX_DATA_CREATE 0x8
-extern int
-inode_set_unix_data(struct wim_inode *inode, u16 uid, u16 gid, u16 mode,
-                   struct wim_lookup_table *lookup_table, int which);
-
-#endif /* __WIN32__  */
+       u32 uid;
+       u32 gid;
+       u32 mode;
+       u32 reserved;
+};
+
+struct wimlib_unix_data_disk {
+       le32 uid;
+       le32 gid;
+       le32 mode;
+       le32 reserved;
+};
 
 #endif /* _WIMLIB_UNIX_DATA_H  */
index 3501f4c861f88c4404ba33134002af66d4ba5a7e..7cb29890a16105601ba0c9dea74a1f248688bd9e 100644 (file)
@@ -2427,6 +2427,11 @@ print_dentry_detailed(const struct wimlib_dir_entry *dentry)
        tprintf(T("Link Group ID       = 0x%016"PRIx64"\n"), dentry->hard_link_group_id);
        tprintf(T("Link Count          = %"PRIu32"\n"), dentry->num_links);
 
+       if (dentry->unix_mode != 0) {
+               tprintf(T("UNIX Data           = uid:%"PRIu32" gid:%"PRIu32" mode:0%"PRIo32"\n"),
+                       dentry->unix_uid, dentry->unix_gid, dentry->unix_mode);
+       }
+
        for (uint32_t i = 0; i <= dentry->num_named_streams; i++) {
                if (dentry->streams[i].stream_name) {
                        tprintf(T("\tData stream \"%"TS"\":\n"),
index 5435a6487e3e6254eced961ef8ad962997234f97..42bc05ea58df5da6791fe5880f70633ea15b13fe 100644 (file)
@@ -81,9 +81,14 @@ struct wim_dentry_on_disk {
        le64 subdir_offset;
 
        /* Reserved fields */
-       le64 unused_1;
-       le64 unused_2;
-
+       /* As an extension, wimlib can store UNIX data here.  */
+       union {
+               struct {
+                       le64 unused_1;
+                       le64 unused_2;
+               };
+               struct wimlib_unix_data_disk unix_data;
+       };
 
        /* Creation time, last access time, and last write time, in
         * 100-nanosecond intervals since 12:00 a.m UTC January 1, 1601.  They
@@ -1207,6 +1212,12 @@ read_dentry(const u8 * restrict buf, size_t buf_len,
        inode->i_attributes = le32_to_cpu(disk_dentry->attributes);
        inode->i_security_id = le32_to_cpu(disk_dentry->security_id);
        dentry->subdir_offset = le64_to_cpu(disk_dentry->subdir_offset);
+
+       inode->i_unix_data.uid = le32_to_cpu(disk_dentry->unix_data.uid);
+       inode->i_unix_data.gid = le32_to_cpu(disk_dentry->unix_data.gid);
+       inode->i_unix_data.mode = le32_to_cpu(disk_dentry->unix_data.mode);
+       inode->i_unix_data.reserved = le32_to_cpu(disk_dentry->unix_data.reserved);
+
        inode->i_creation_time = le64_to_cpu(disk_dentry->creation_time);
        inode->i_last_access_time = le64_to_cpu(disk_dentry->last_access_time);
        inode->i_last_write_time = le64_to_cpu(disk_dentry->last_write_time);
@@ -1555,8 +1566,14 @@ write_dentry(const struct wim_dentry * restrict dentry, u8 * restrict p)
        disk_dentry->attributes = cpu_to_le32(inode->i_attributes);
        disk_dentry->security_id = cpu_to_le32(inode->i_security_id);
        disk_dentry->subdir_offset = cpu_to_le64(dentry->subdir_offset);
-       disk_dentry->unused_1 = cpu_to_le64(0);
-       disk_dentry->unused_2 = cpu_to_le64(0);
+
+       /* UNIX data uses the two 8-byte reserved fields.  So if no UNIX data
+        * exists, they get set to 0, just as we would do anyway.  */
+       disk_dentry->unix_data.uid = cpu_to_le32(inode->i_unix_data.uid);
+       disk_dentry->unix_data.gid = cpu_to_le32(inode->i_unix_data.gid);
+       disk_dentry->unix_data.mode = cpu_to_le32(inode->i_unix_data.mode);
+       disk_dentry->unix_data.reserved = cpu_to_le32(inode->i_unix_data.reserved);
+
        disk_dentry->creation_time = cpu_to_le64(inode->i_creation_time);
        disk_dentry->last_access_time = cpu_to_le64(inode->i_last_access_time);
        disk_dentry->last_write_time = cpu_to_le64(inode->i_last_write_time);
index 7b28dac7a9166cff83bfc8392a539ab8030f49a4..05c3d16b2551ce13932ba190b36e2f481dbaf573 100644 (file)
@@ -73,6 +73,7 @@
 /* Keep in sync with wimlib.h  */
 #define WIMLIB_EXTRACT_MASK_PUBLIC                             \
        (WIMLIB_EXTRACT_FLAG_NTFS                       |       \
+        WIMLIB_EXTRACT_FLAG_UNIX_DATA                  |       \
         WIMLIB_EXTRACT_FLAG_NO_ACLS                    |       \
         WIMLIB_EXTRACT_FLAG_STRICT_ACLS                |       \
         WIMLIB_EXTRACT_FLAG_RPFIX                      |       \
index a8214b3c371bf52888dc3711b5ea17d77a0190fa..9eab0d7b534ecb2e3f29b90997ca700b6268c50b 100644 (file)
@@ -326,87 +326,6 @@ inode_remove_ads(struct wim_inode *inode, u16 idx,
        inode->i_num_ads--;
 }
 
-bool
-inode_has_unix_data(const struct wim_inode *inode)
-{
-       for (u16 i = 0; i < inode->i_num_ads; i++)
-               if (ads_entry_is_unix_data(&inode->i_ads_entries[i]))
-                       return true;
-       return false;
-}
-
-#ifndef __WIN32__
-int
-inode_get_unix_data(const struct wim_inode *inode,
-                   struct wimlib_unix_data *unix_data,
-                   u16 *stream_idx_ret)
-{
-       const struct wim_ads_entry *ads_entry;
-       const struct wim_lookup_table_entry *lte;
-       size_t size;
-       int ret;
-
-       wimlib_assert(inode->i_resolved);
-
-       ads_entry = inode_get_ads_entry((struct wim_inode*)inode,
-                                       WIMLIB_UNIX_DATA_TAG, NULL);
-       if (ads_entry == NULL)
-               return NO_UNIX_DATA;
-
-       if (stream_idx_ret)
-               *stream_idx_ret = ads_entry - inode->i_ads_entries;
-
-       lte = ads_entry->lte;
-       if (lte == NULL)
-               return NO_UNIX_DATA;
-
-       size = lte->size;
-       if (size != sizeof(struct wimlib_unix_data))
-               return BAD_UNIX_DATA;
-
-       ret = read_full_stream_into_buf(lte, unix_data);
-       if (ret)
-               return ret;
-
-       if (unix_data->version != 0)
-               return BAD_UNIX_DATA;
-       return 0;
-}
-
-int
-inode_set_unix_data(struct wim_inode *inode, u16 uid, u16 gid, u16 mode,
-                   struct wim_lookup_table *lookup_table, int which)
-{
-       struct wimlib_unix_data unix_data;
-       int ret;
-       bool have_good_unix_data = false;
-       bool have_unix_data = false;
-       u16 stream_idx;
-
-       if (!(which & UNIX_DATA_CREATE)) {
-               ret = inode_get_unix_data(inode, &unix_data, &stream_idx);
-               if (ret == 0 || ret == BAD_UNIX_DATA || ret > 0)
-                       have_unix_data = true;
-               if (ret == 0)
-                       have_good_unix_data = true;
-       }
-       unix_data.version = 0;
-       if (which & UNIX_DATA_UID || !have_good_unix_data)
-               unix_data.uid = uid;
-       if (which & UNIX_DATA_GID || !have_good_unix_data)
-               unix_data.gid = gid;
-       if (which & UNIX_DATA_MODE || !have_good_unix_data)
-               unix_data.mode = mode;
-       ret = inode_add_ads_with_data(inode, WIMLIB_UNIX_DATA_TAG,
-                                     &unix_data,
-                                     sizeof(struct wimlib_unix_data),
-                                     lookup_table);
-       if (ret == 0 && have_unix_data)
-               inode_remove_ads(inode, stream_idx, lookup_table);
-       return ret;
-}
-#endif /* __WIN32__  */
-
 /*
  * Resolve an inode's lookup table entries.
  *
index 693245e56c03ce2c5543280c4f23fed600d663e8..dc953c75ac9d6448fc04158733b635600c182e9f 100644 (file)
@@ -82,6 +82,11 @@ init_wimlib_dentry(struct wimlib_dir_entry *wdentry, struct wim_dentry *dentry,
        wdentry->last_write_time = wim_timestamp_to_timespec(inode->i_last_write_time);
        wdentry->last_access_time = wim_timestamp_to_timespec(inode->i_last_access_time);
 
+       wdentry->unix_uid = inode->i_unix_data.uid;
+       wdentry->unix_gid = inode->i_unix_data.gid;
+       wdentry->unix_mode = inode->i_unix_data.mode;
+       wdentry->unix_reserved = inode->i_unix_data.reserved;
+
        lte = inode_unnamed_lte(inode, wim->lookup_table);
        if (lte) {
                lte_to_wimlib_resource_entry(lte, &wdentry->streams[0].resource);
index 1578353fe9ea21c560568b2e146dda78861b8767..06890dbca45cc7c2294683e041f2997a082ff400 100644 (file)
@@ -341,16 +341,9 @@ create_dentry(struct fuse_context *fuse_ctx, const char *path,
        new->d_inode->i_attributes = attributes;
 
        if (wimfs_ctx->mount_flags & WIMLIB_MOUNT_FLAG_UNIX_DATA) {
-               if (inode_set_unix_data(new->d_inode,
-                                       fuse_ctx->uid,
-                                       fuse_ctx->gid,
-                                       fuse_mask_mode(mode, fuse_ctx),
-                                       wimfs_ctx->wim->lookup_table,
-                                       UNIX_DATA_ALL | UNIX_DATA_CREATE))
-               {
-                       free_dentry(new);
-                       return -ENOMEM;
-               }
+               new->d_inode->i_unix_data.uid = fuse_ctx->uid;
+               new->d_inode->i_unix_data.gid = fuse_ctx->gid;
+               new->d_inode->i_unix_data.mode = fuse_mask_mode(mode, fuse_ctx);
        }
        dentry_add_child(parent, new);
        list_add_tail(&new->d_inode->i_list, wimfs_ctx->image_inode_list);
@@ -389,14 +382,20 @@ remove_dentry(struct wim_dentry *dentry,
 }
 
 static mode_t
-inode_default_unix_mode(const struct wim_inode *inode)
+inode_unix_file_type(const struct wim_inode *inode)
 {
        if (inode_is_symlink(inode))
-               return S_IFLNK | 0777;
+               return S_IFLNK;
        else if (inode_is_directory(inode))
-               return S_IFDIR | 0777;
+               return S_IFDIR;
        else
-               return S_IFREG | 0777;
+               return S_IFREG;
+}
+
+static mode_t
+inode_default_unix_mode(const struct wim_inode *inode)
+{
+       return inode_unix_file_type(inode) | 0777;
 }
 
 /* Transfers file attributes from a struct wim_inode to a `stat' buffer.
@@ -412,16 +411,16 @@ inode_to_stbuf(const struct wim_inode *inode,
        const struct wimfs_context *ctx = wimfs_get_context();
 
        memset(stbuf, 0, sizeof(struct stat));
-       stbuf->st_mode = inode_default_unix_mode(inode);
-       stbuf->st_uid = ctx->default_uid;
-       stbuf->st_gid = ctx->default_gid;
-       if (ctx->mount_flags & WIMLIB_MOUNT_FLAG_UNIX_DATA) {
-               struct wimlib_unix_data unix_data;
-               if (inode_get_unix_data(inode, &unix_data, NULL) == 0) {
-                       stbuf->st_uid = unix_data.uid;
-                       stbuf->st_gid = unix_data.gid;
-                       stbuf->st_mode = unix_data.mode;
-               }
+       if ((ctx->mount_flags & WIMLIB_MOUNT_FLAG_UNIX_DATA) &&
+           inode_has_unix_data(inode))
+       {
+               stbuf->st_uid = inode->i_unix_data.uid;
+               stbuf->st_gid = inode->i_unix_data.gid;
+               stbuf->st_mode = inode->i_unix_data.mode;
+       } else {
+               stbuf->st_uid = ctx->default_uid;
+               stbuf->st_gid = ctx->default_gid;
+               stbuf->st_mode = inode_default_unix_mode(inode);
        }
        stbuf->st_ino = (ino_t)inode->i_ino;
        stbuf->st_nlink = inode->i_nlink;
@@ -1609,6 +1608,7 @@ static int
 wimfs_chmod(const char *path, mode_t mask)
 {
        struct wim_dentry *dentry;
+       struct wim_inode *inode;
        struct wimfs_context *ctx = wimfs_get_context();
        int ret;
 
@@ -1620,16 +1620,21 @@ wimfs_chmod(const char *path, mode_t mask)
        if (ret)
                return ret;
 
-       ret = inode_set_unix_data(dentry->d_inode, ctx->default_uid,
-                                 ctx->default_gid, mask,
-                                 ctx->wim->lookup_table, UNIX_DATA_MODE);
-       return ret ? -ENOMEM : 0;
+       inode = dentry->d_inode;
+
+       if (!inode_has_unix_data(inode)) {
+               inode->i_unix_data.uid = ctx->default_uid;
+               inode->i_unix_data.gid = ctx->default_gid;
+       }
+       inode->i_unix_data.mode = mask;
+       return 0;
 }
 
 static int
 wimfs_chown(const char *path, uid_t uid, gid_t gid)
 {
        struct wim_dentry *dentry;
+       struct wim_inode *inode;
        struct wimfs_context *ctx = wimfs_get_context();
        int ret;
 
@@ -1641,11 +1646,13 @@ wimfs_chown(const char *path, uid_t uid, gid_t gid)
        if (ret)
                return ret;
 
-       ret = inode_set_unix_data(dentry->d_inode, uid, gid,
-                                 inode_default_unix_mode(dentry->d_inode),
-                                 ctx->wim->lookup_table,
-                                 UNIX_DATA_UID | UNIX_DATA_GID);
-       return ret ? -ENOMEM : 0;
+       inode = dentry->d_inode;
+
+       if (!inode_has_unix_data(inode))
+               inode->i_unix_data.mode = inode_default_unix_mode(inode);
+       inode->i_unix_data.uid = uid;
+       inode->i_unix_data.gid = gid;
+       return 0;
 }
 
 /* Called when the filesystem is unmounted. */
index c4f5318b23b0694c0e6737c19128e0dab9cc6798..bf9c2911d57630ed2f847f68e4a35df9e00d92bb 100644 (file)
@@ -219,6 +219,26 @@ unix_set_timestamps(int fd, const char *path, u64 atime, u64 mtime)
        }
 }
 
+static int
+unix_set_owner_and_group(int fd, const char *path, uid_t uid, gid_t gid)
+{
+       if (fd >= 0 && !fchown(fd, uid, gid))
+               return 0;
+       if (fd < 0 && !lchown(path, uid, gid))
+               return 0;
+       return WIMLIB_ERR_SET_SECURITY;
+}
+
+static int
+unix_set_mode(int fd, const char *path, mode_t mode)
+{
+       if (fd >= 0 && !fchmod(fd, mode))
+               return 0;
+       if (fd < 0 && !chmod(path, mode))
+               return 0;
+       return WIMLIB_ERR_SET_SECURITY;
+}
+
 /*
  * Set metadata on an extracted file.
  *
@@ -236,6 +256,50 @@ unix_set_metadata(int fd, const struct wim_inode *inode,
        if (fd < 0 && !path)
                path = unix_build_inode_extraction_path(inode, ctx);
 
+       if ((ctx->common.extract_flags & WIMLIB_EXTRACT_FLAG_UNIX_DATA)
+           && inode_has_unix_data(inode))
+       {
+               u32 uid = inode->i_unix_data.uid;
+               u32 gid = inode->i_unix_data.gid;
+               u32 mode = inode->i_unix_data.mode;
+
+               ret = unix_set_owner_and_group(fd, path, uid, gid);
+               if (ret) {
+                       if (!path)
+                               path = unix_build_inode_extraction_path(inode, ctx);
+                       if (ctx->common.extract_flags &
+                           WIMLIB_EXTRACT_FLAG_STRICT_ACLS)
+                       {
+                               ERROR_WITH_ERRNO("Can't set uid=%"PRIu32" and "
+                                                "gid=%"PRIu32" on \"%s\"",
+                                                uid, gid, path);
+                               return ret;
+                       } else {
+                               WARNING_WITH_ERRNO("Can't set uid=%"PRIu32" and "
+                                                  "gid=%"PRIu32" on \"%s\"",
+                                                  uid, gid, path);
+                       }
+               }
+
+               ret = 0;
+               if (!inode_is_symlink(inode))
+                       ret = unix_set_mode(fd, path, mode);
+               if (ret) {
+                       if (!path)
+                               path = unix_build_inode_extraction_path(inode, ctx);
+                       if (ctx->common.extract_flags &
+                           WIMLIB_EXTRACT_FLAG_STRICT_ACLS)
+                       {
+                               ERROR_WITH_ERRNO("Can't set mode=0%"PRIo32" "
+                                                "on \"%s\"", mode, path);
+                               return ret;
+                       } else {
+                               WARNING_WITH_ERRNO("Can't set mode=0%"PRIo32" "
+                                                  "on \"%s\"", mode, path);
+                       }
+               }
+       }
+
        ret = unix_set_timestamps(fd, path,
                                  inode->i_last_access_time,
                                  inode->i_last_write_time);
index c6619b00d1e402acf84d1dea3df0eb0d88a0e7e6..281cbcb7b98da0d0d0e4a4b9a6db716edaccfe57 100644 (file)
@@ -388,13 +388,9 @@ unix_build_dentry_tree_recursive(struct wim_dentry **tree_ret,
 #endif
        inode->i_resolved = 1;
        if (params->add_flags & WIMLIB_ADD_FLAG_UNIX_DATA) {
-               ret = inode_set_unix_data(inode, stbuf.st_uid,
-                                         stbuf.st_gid,
-                                         stbuf.st_mode,
-                                         params->lookup_table,
-                                         UNIX_DATA_ALL | UNIX_DATA_CREATE);
-               if (ret)
-                       goto out;
+               inode->i_unix_data.uid = stbuf.st_uid;
+               inode->i_unix_data.gid = stbuf.st_gid;
+               inode->i_unix_data.mode = stbuf.st_mode;
        }
 
        if (params->add_flags & WIMLIB_ADD_FLAG_ROOT) {