]> wimlib.net Git - wimlib/blobdiff - src/unix_capture.c
New format for UNIX data
[wimlib] / src / unix_capture.c
index a76fbc37f7689b7c329f55a821783152e31bd451..281cbcb7b98da0d0d0e4a4b9a6db716edaccfe57 100644 (file)
@@ -201,6 +201,54 @@ unix_scan_directory(struct wim_dentry *dir_dentry,
        return ret;
 }
 
+/* Given an absolute symbolic link target @dest (UNIX-style, beginning
+ * with '/'), determine whether it points into the directory specified by
+ * @ino and @dev.  If so, return the target modified to be "absolute"
+ * relative to this directory.  Otherwise, return NULL.  */
+static char *
+unix_fixup_abslink(char *dest, u64 ino, u64 dev)
+{
+       char *p = dest;
+
+       do {
+               char save;
+               struct stat stbuf;
+               int ret;
+
+               /* Skip non-slashes.  */
+               while (*p && *p != '/')
+                       p++;
+
+               /* Skip slashes.  */
+               while (*p && *p == '/')
+                       p++;
+
+               /* Get inode and device for this prefix.  */
+               save = *p;
+               *p = '\0';
+               ret = stat(dest, &stbuf);
+               *p = save;
+
+               if (ret) {
+                       /* stat() failed.  Assume the link points outside the
+                        * directory tree being captured.  */
+                       break;
+               }
+
+               if (stbuf.st_ino == ino && stbuf.st_dev == dev) {
+                       /* Link points inside directory tree being captured.
+                        * Return abbreviated path.  */
+                       *--p = '/';
+                       while (p > dest && *(p - 1) == '/')
+                               p--;
+                       return p;
+               }
+       } while (*p);
+
+       /* Link does not point inside directory tree being captured.  */
+       return NULL;
+}
+
 static int
 unix_scan_symlink(struct wim_dentry **root_p, const char *full_path,
                  int dirfd, const char *relpath,
@@ -232,9 +280,9 @@ unix_scan_symlink(struct wim_dentry **root_p, const char *full_path,
        if ((params->add_flags & WIMLIB_ADD_FLAG_RPFIX) &&
             dest[0] == '/')
        {
-               dest = capture_fixup_absolute_symlink(dest,
-                                                     params->capture_root_ino,
-                                                     params->capture_root_dev);
+               dest = unix_fixup_abslink(dest,
+                                         params->capture_root_ino,
+                                         params->capture_root_dev);
                if (!dest) {
                        /* RPFIX (reparse point fixup) mode:  Ignore
                         * absolute symbolic link that points out of the
@@ -340,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) {