X-Git-Url: https://wimlib.net/git/?p=wimlib;a=blobdiff_plain;f=src%2Fextract.c;h=7fe23ef76d5380b15164f668549544f2b34c4d5e;hp=2f7a5d838f9dbcea3099e281b213667b84811b12;hb=85cc44d618877b8dbedf56fd8f5454a948a636a3;hpb=140c0920af14b19292e8b7694bb91864c8f52f3c diff --git a/src/extract.c b/src/extract.c index 2f7a5d83..7fe23ef7 100644 --- a/src/extract.c +++ b/src/extract.c @@ -30,15 +30,21 @@ */ +#include "config.h" + #include #include #include #include #include #include + +#ifdef HAVE_UTIME_H +#include +#endif + #include -#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) @@ -239,12 +245,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 +286,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 +325,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 +367,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 +409,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);