]> wimlib.net Git - wimlib/blobdiff - src/extract_image.c
{symlink,fd}_apply_unix_data(): Print path name
[wimlib] / src / extract_image.c
index 48a916ab5517652e4a2663c42446f983f7cd111e..cd23e45d4b4cf050da22bb1ae1ca431f7c761255 100644 (file)
@@ -152,9 +152,11 @@ symlink_apply_unix_data(const char *link,
        if (lchown(link, unix_data->uid, unix_data->gid)) {
                if (errno == EPERM) {
                        /* Ignore */
-                       WARNING_WITH_ERRNO("failed to set symlink UNIX owner/group");
+                       WARNING_WITH_ERRNO("failed to set symlink UNIX "
+                                          "owner/group on \"%s\"", link);
                } else {
-                       ERROR_WITH_ERRNO("failed to set symlink UNIX owner/group");
+                       ERROR_WITH_ERRNO("failed to set symlink UNIX "
+                                        "owner/group on \"%s\"", link);
                        return WIMLIB_ERR_INVALID_DENTRY;
                }
        }
@@ -162,24 +164,29 @@ symlink_apply_unix_data(const char *link,
 }
 
 static int
-fd_apply_unix_data(int fd, const struct wimlib_unix_data *unix_data)
+fd_apply_unix_data(int fd, const char *path,
+                  const struct wimlib_unix_data *unix_data)
 {
        if (fchown(fd, unix_data->uid, unix_data->gid)) {
                if (errno == EPERM) {
-                       WARNING_WITH_ERRNO("failed to set file UNIX owner/group");
+                       WARNING_WITH_ERRNO("failed to set file UNIX "
+                                          "owner/group on \"%s\"", path);
                        /* Ignore? */
                } else {
-                       ERROR_WITH_ERRNO("failed to set file UNIX owner/group");
+                       ERROR_WITH_ERRNO("failed to set file UNIX "
+                                        "owner/group on \"%s\"", path);
                        return WIMLIB_ERR_INVALID_DENTRY;
                }
        }
 
        if (fchmod(fd, unix_data->mode)) {
                if (errno == EPERM) {
-                       WARNING_WITH_ERRNO("failed to set UNIX file mode");
+                       WARNING_WITH_ERRNO("failed to set UNIX file mode "
+                                          "on \"%s\"", path);
                        /* Ignore? */
                } else {
-                       ERROR_WITH_ERRNO("failed to set UNIX file mode");
+                       ERROR_WITH_ERRNO("failed to set UNIX file mode "
+                                        "on \"%s\"", path);
                        return WIMLIB_ERR_INVALID_DENTRY;
                }
        }
@@ -192,7 +199,7 @@ dir_apply_unix_data(const char *dir, const struct wimlib_unix_data *unix_data)
        int dfd = open(dir, O_RDONLY);
        int ret;
        if (dfd >= 0) {
-               ret = fd_apply_unix_data(dfd, unix_data);
+               ret = fd_apply_unix_data(dfd, dir, unix_data);
                if (close(dfd)) {
                        ERROR_WITH_ERRNO("can't close directory `%s'", dir);
                        ret = WIMLIB_ERR_MKDIR;
@@ -280,8 +287,8 @@ out_extract_unix_data:
                else if (ret < 0)
                        ret = 0;
                else
-                       ret = fd_apply_unix_data(out_fd, &unix_data);
-               if (ret != 0)
+                       ret = fd_apply_unix_data(out_fd, output_path, &unix_data);
+               if (ret)
                        goto out;
        }
        if (lte)
@@ -326,11 +333,11 @@ extract_symlink(struct wim_dentry *dentry,
 {
        char target[4096 + args->target_realpath_len];
        char *fixed_target;
+       const struct wim_inode *inode = dentry->d_inode;
 
-       ssize_t ret = inode_readlink(dentry->d_inode,
-                                    target + args->target_realpath_len,
-                                    sizeof(target) - args->target_realpath_len - 1,
-                                    args->w, false);
+       ssize_t ret = wim_inode_readlink(inode,
+                                        target + args->target_realpath_len,
+                                        sizeof(target) - args->target_realpath_len - 1);
        struct wim_lookup_table_entry *lte;
 
        if (ret <= 0) {
@@ -342,10 +349,13 @@ extract_symlink(struct wim_dentry *dentry,
        if (target[args->target_realpath_len] == '/' &&
            args->extract_flags & WIMLIB_EXTRACT_FLAG_RPFIX)
        {
+               /* Fix absolute symbolic link target to point into the actual
+                * extraction destination */
                memcpy(target, args->target_realpath,
                       args->target_realpath_len);
                fixed_target = target;
        } else {
+               /* Keep same link target */
                fixed_target = target + args->target_realpath_len;
        }
        ret = symlink(fixed_target, output_path);
@@ -354,11 +364,9 @@ extract_symlink(struct wim_dentry *dentry,
                                 output_path, fixed_target);
                return WIMLIB_ERR_LINK;
        }
-       lte = inode_unnamed_lte_resolved(dentry->d_inode);
-       wimlib_assert(lte != NULL);
        if (args->extract_flags & WIMLIB_EXTRACT_FLAG_UNIX_DATA) {
                struct wimlib_unix_data unix_data;
-               ret = inode_get_unix_data(dentry->d_inode, &unix_data, NULL);
+               ret = inode_get_unix_data(inode, &unix_data, NULL);
                if (ret > 0)
                        ;
                else if (ret < 0)
@@ -368,6 +376,8 @@ extract_symlink(struct wim_dentry *dentry,
                if (ret)
                        return ret;
        }
+       lte = inode_unnamed_lte_resolved(inode);
+       wimlib_assert(lte != NULL);
        args->progress.extract.completed_bytes += wim_resource_size(lte);
        return 0;
 }
@@ -421,10 +431,9 @@ dir_exists:
 }
 
 #ifndef __WIN32__
-static int unix_do_apply_dentry(const char *output_path,
-                               size_t output_path_len,
-                               struct wim_dentry *dentry,
-                               struct apply_args *args)
+static int
+unix_do_apply_dentry(const char *output_path, size_t output_path_len,
+                    struct wim_dentry *dentry, struct apply_args *args)
 {
        const struct wim_inode *inode = dentry->d_inode;
 
@@ -504,8 +513,8 @@ static int
 apply_dentry_normal(struct wim_dentry *dentry, void *arg)
 {
        struct apply_args *args = arg;
-       tchar *output_path;
        size_t len;
+       tchar *output_path;
 
        len = tstrlen(args->target);
        if (dentry_is_root(dentry)) {
@@ -546,7 +555,6 @@ apply_dentry_timestamps_normal(struct wim_dentry *dentry, void *arg)
                output_path[len] = T('\0');
        }
 
-
 #ifdef __WIN32__
        return win32_do_apply_dentry_timestamps(output_path, len, dentry, args);
 #else
@@ -554,8 +562,9 @@ apply_dentry_timestamps_normal(struct wim_dentry *dentry, void *arg)
 #endif
 }
 
-/* Extract a dentry if it hasn't already been extracted, and either the dentry
- * has no streams or WIMLIB_EXTRACT_FLAG_NO_STREAMS is not specified. */
+/* Extract a dentry if it hasn't already been extracted and either
+ * WIMLIB_EXTRACT_FLAG_NO_STREAMS is not specified, or the dentry is a directory
+ * and/or has no unnamed stream. */
 static int
 maybe_apply_dentry(struct wim_dentry *dentry, void *arg)
 {
@@ -565,9 +574,10 @@ maybe_apply_dentry(struct wim_dentry *dentry, void *arg)
        if (dentry->is_extracted)
                return 0;
 
-       if (args->extract_flags & WIMLIB_EXTRACT_FLAG_NO_STREAMS)
-               if (inode_unnamed_lte_resolved(dentry->d_inode))
-                       return 0;
+       if (args->extract_flags & WIMLIB_EXTRACT_FLAG_NO_STREAMS &&
+           !dentry_is_directory(dentry) &&
+           inode_unnamed_lte_resolved(dentry->d_inode) != NULL)
+               return 0;
 
        if ((args->extract_flags & WIMLIB_EXTRACT_FLAG_VERBOSE) &&
             args->progress_func) {
@@ -637,8 +647,21 @@ inode_find_streams_for_extraction(struct wim_inode *inode,
                list_add_tail(&inode->i_lte_inode_list, &lte->inode_list);
                inode_added = true;
        }
-#ifdef WITH_NTFS_3G
-       if (extract_flags & WIMLIB_EXTRACT_FLAG_NTFS) {
+
+       /* Determine whether to include alternate data stream entries or not.
+        *
+        * UNIX:  Include them if extracting using NTFS-3g.
+        *
+        * Windows: Include them undconditionally, although if the filesystem is
+        * not NTFS we won't actually be able to extract them. */
+#if defined(WITH_NTFS_3G)
+       if (extract_flags & WIMLIB_EXTRACT_FLAG_NTFS)
+#elif defined(__WIN32__)
+       if (1)
+#else
+       if (0)
+#endif
+       {
                for (unsigned i = 0; i < inode->i_num_ads; i++) {
                        if (inode->i_ads_entries[i].stream_name_nbytes != 0) {
                                lte = inode->i_ads_entries[i].lte;
@@ -654,7 +677,6 @@ inode_find_streams_for_extraction(struct wim_inode *inode,
                        }
                }
        }
-#endif
 }
 
 static void
@@ -725,7 +747,7 @@ apply_stream_list(struct list_head *stream_list,
                                /* Extract the dentry if it was not already
                                 * extracted */
                                ret = maybe_apply_dentry(dentry, args);
-                               if (ret != 0)
+                               if (ret)
                                        return ret;
                                if (progress_func &&
                                    args->progress.extract.completed_bytes >= next_progress)
@@ -796,7 +818,6 @@ extract_single_image(WIMStruct *w, int image,
 
        struct apply_args args;
        const struct apply_operations *ops;
-       tchar *target_realpath;
 
        memset(&args, 0, sizeof(args));