]> wimlib.net Git - wimlib/blobdiff - src/extract.c
Make different threads use different FILE*'s
[wimlib] / src / extract.c
index 2f7a5d838f9dbcea3099e281b213667b84811b12..6e341cc0f396c414992efe0c5e7935750a26cd71 100644 (file)
  */
 
 
+#include "config.h"
+
 #include <dirent.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <string.h>
 #include <sys/stat.h>
 #include <sys/time.h>
+
+#ifdef HAVE_UTIME_H
+#include <utime.h>
+#endif
+
 #include <unistd.h>
 
-#include "config.h"
 #include "dentry.h"
 #include "lookup_table.h"
 #include "timestamp.h"
@@ -48,7 +54,7 @@
 /* Internal */
 #define WIMLIB_EXTRACT_FLAG_MULTI_IMAGE 0x80000000
 
-static int extract_regular_file_linked(const struct dentry *dentry, 
+static int extract_regular_file_linked(const struct dentry *dentry,
                                       const char *output_dir,
                                       const char *output_path,
                                       int extract_flags,
@@ -77,7 +83,7 @@ static int extract_regular_file_linked(const struct dentry *dentry,
 
                wimlib_assert(extract_flags & WIMLIB_EXTRACT_FLAG_SYMLINK);
 
-               num_path_components = 
+               num_path_components =
                        get_num_path_components(dentry->full_path_utf8) - 1;
                num_output_dir_path_components =
                        get_num_path_components(output_dir);
@@ -114,7 +120,7 @@ static int extract_regular_file_linked(const struct dentry *dentry,
 }
 
 static int extract_regular_file_unlinked(WIMStruct *w,
-                                        struct dentry *dentry, 
+                                        struct dentry *dentry,
                                         const char *output_path,
                                         int extract_flags,
                                         struct lookup_table_entry *lte)
@@ -188,11 +194,11 @@ out:
        return ret;
 }
 
-/* 
- * Extracts a regular file from the WIM archive. 
+/*
+ * Extracts a regular file from the WIM archive.
  */
-static int extract_regular_file(WIMStruct *w, 
-                               struct dentry *dentry, 
+static int extract_regular_file(WIMStruct *w,
+                               struct dentry *dentry,
                                const char *output_dir,
                                const char *output_path,
                                int extract_flags)
@@ -224,7 +230,8 @@ static int extract_symlink(const struct dentry *dentry, const char *output_path,
                           const WIMStruct *w)
 {
        char target[4096];
-       ssize_t ret = inode_readlink(dentry->d_inode, target, sizeof(target), w);
+       ssize_t ret = inode_readlink(dentry->d_inode, target,
+                                    sizeof(target), w, 0);
        if (ret <= 0) {
                ERROR("Could not read the symbolic link from dentry `%s'",
                      dentry->full_path_utf8);
@@ -239,12 +246,12 @@ static int extract_symlink(const struct dentry *dentry, const char *output_path,
        return 0;
 }
 
-/* 
- * Extracts a directory from the WIM archive. 
+/*
+ * Extracts a directory from the WIM archive.
  *
  * @dentry:            The directory entry for the directory.
  * @output_path:       The path to which the directory is to be extracted to.
- * @return:            True on success, false on failure. 
+ * @return:            True on success, false on failure.
  */
 static int extract_directory(const char *output_path, bool is_root)
 {
@@ -280,9 +287,10 @@ struct extract_args {
        WIMStruct *w;
        int extract_flags;
        const char *output_dir;
+       unsigned num_lutimes_warnings;
 };
 
-/* 
+/*
  * Extracts a file, directory, or symbolic link from the WIM archive.  For use
  * in for_dentry_in_tree().
  */
@@ -318,17 +326,37 @@ static int apply_dentry_timestamps(struct dentry *dentry, void *arg)
        struct extract_args *args = arg;
        size_t len = strlen(args->output_dir);
        char output_path[len + dentry->full_path_utf8_len + 1];
+       const struct inode *inode = dentry->d_inode;
+       int ret;
 
        memcpy(output_path, args->output_dir, len);
        memcpy(output_path + len, dentry->full_path_utf8, dentry->full_path_utf8_len);
        output_path[len + dentry->full_path_utf8_len] = '\0';
 
        struct timeval tv[2];
-       wim_timestamp_to_timeval(dentry->d_inode->last_access_time, &tv[0]);
-       wim_timestamp_to_timeval(dentry->d_inode->last_write_time, &tv[1]);
-       if (lutimes(output_path, tv) != 0) {
-               WARNING("Failed to set timestamp on file `%s': %s",
-                       output_path, strerror(errno));
+       wim_timestamp_to_timeval(inode->last_access_time, &tv[0]);
+       wim_timestamp_to_timeval(inode->last_write_time, &tv[1]);
+       #ifdef HAVE_LUTIMES
+       ret = lutimes(output_path, tv);
+       #else
+       ret = -1;
+       errno = ENOSYS;
+       #endif
+       if (ret != 0) {
+               #ifdef HAVE_UTIME
+               if (errno == ENOSYS) {
+                       struct utimbuf buf;
+                       buf.actime = wim_timestamp_to_unix(inode->last_access_time);
+                       buf.modtime = wim_timestamp_to_unix(inode->last_write_time);
+                       if (utime(output_path, &buf) == 0)
+                               return 0;
+               }
+               #endif
+               if (errno != ENOSYS || args->num_lutimes_warnings < 10) {
+                       WARNING("Failed to set timestamp on file `%s': %s",
+                               output_path, strerror(errno));
+                       args->num_lutimes_warnings++;
+               }
        }
        return 0;
 }
@@ -340,14 +368,15 @@ static int extract_single_image(WIMStruct *w, int image,
        DEBUG("Extracting image %d", image);
 
        int ret;
-       ret = wimlib_select_image(w, image);
+       ret = select_wim_image(w, image);
        if (ret != 0)
                return ret;
 
        struct extract_args args = {
-               .w = w,
-               .extract_flags = extract_flags,
-               .output_dir = output_dir,
+               .w                    = w,
+               .extract_flags        = extract_flags,
+               .output_dir           = output_dir,
+               .num_lutimes_warnings = 0,
        };
 
        ret = for_dentry_in_tree(wim_root_dentry(w), extract_dentry, &args);
@@ -381,7 +410,7 @@ static int extract_all_images(WIMStruct *w, const char *output_dir,
        memcpy(buf, output_dir, output_path_len);
        buf[output_path_len] = '/';
        for (image = 1; image <= w->hdr.image_count; image++) {
-               
+
                image_name = wimlib_get_image_name(w, image);
                if (*image_name) {
                        strcpy(buf + output_path_len + 1, image_name);