From 7c08b0b067f48e80226e6b5466fd95feb43139e6 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Mon, 20 Aug 2012 18:04:51 -0500 Subject: [PATCH] More accurate timestamps --- src/dentry.c | 2 +- src/extract.c | 55 ++++++++++++++++++++++--------------------------- src/mount.c | 32 +++++++++++++++++----------- src/symlink.c | 6 ++++-- src/timestamp.h | 33 +++++++++++++++++++---------- src/util.c | 11 ++++++++++ src/xml.c | 10 ++++----- 7 files changed, 88 insertions(+), 61 deletions(-) diff --git a/src/dentry.c b/src/dentry.c index 2f0cabd3..c3165544 100644 --- a/src/dentry.c +++ b/src/dentry.c @@ -84,7 +84,7 @@ void stbuf_to_dentry(const struct stat *stbuf, struct dentry *dentry) /* Makes all timestamp fields for the dentry be the current time. */ void dentry_update_all_timestamps(struct dentry *dentry) { - u64 now = get_timestamp(); + u64 now = get_wim_timestamp(); dentry->creation_time = now; dentry->last_access_time = now; dentry->last_write_time = now; diff --git a/src/extract.c b/src/extract.c index 8c3aedb9..12196602 100644 --- a/src/extract.c +++ b/src/extract.c @@ -283,11 +283,8 @@ struct extract_args { }; /* - * Extracts a file or directory from the WIM archive. For use in - * for_dentry_in_tree(). - * - * @dentry: The dentry to extract. - * @arg: A pointer to the WIMStruct for the WIM file. + * Extracts a file, directory, or symbolic link from the WIM archive. For use + * in for_dentry_in_tree(). */ static int extract_dentry(struct dentry *dentry, void *arg) { @@ -296,24 +293,23 @@ static int extract_dentry(struct dentry *dentry, void *arg) int extract_flags = args->extract_flags; size_t len = strlen(args->output_dir); char output_path[len + dentry->full_path_utf8_len + 1]; - int ret = 0; - if (extract_flags & WIMLIB_EXTRACT_FLAG_VERBOSE) + if (extract_flags & WIMLIB_EXTRACT_FLAG_VERBOSE) { + wimlib_assert(dentry->full_path_utf8); puts(dentry->full_path_utf8); + } 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'; - if (dentry_is_symlink(dentry)) { - ret = extract_symlink(dentry, output_path, w); - } else if (dentry_is_directory(dentry)) { - ret = extract_directory(output_path); - } else { - ret = extract_regular_file(w, dentry, args->output_dir, - output_path, extract_flags); - } - return ret; + if (dentry_is_symlink(dentry)) + return extract_symlink(dentry, output_path, w); + else if (dentry_is_directory(dentry)) + return extract_directory(output_path); + else + return extract_regular_file(w, dentry, args->output_dir, + output_path, extract_flags); } @@ -383,24 +379,18 @@ done: WIMLIBAPI int wimlib_extract_image(WIMStruct *w, int image, const char *output_dir, int flags) { - int ret; + if (!output_dir) return WIMLIB_ERR_INVALID_PARAM; + if ((flags & (WIMLIB_EXTRACT_FLAG_SYMLINK | WIMLIB_EXTRACT_FLAG_HARDLINK)) == (WIMLIB_EXTRACT_FLAG_SYMLINK | WIMLIB_EXTRACT_FLAG_HARDLINK)) return WIMLIB_ERR_INVALID_PARAM; - if (image == WIM_ALL_IMAGES) { - flags |= WIMLIB_EXTRACT_FLAG_MULTI_IMAGE; - for_lookup_table_entry(w->lookup_table, zero_out_refcnts, NULL); - } else { - flags &= ~WIMLIB_EXTRACT_FLAG_MULTI_IMAGE; - } - if ((flags & WIMLIB_EXTRACT_FLAG_NTFS)) { #ifdef WITH_NTFS_3G unsigned long mnt_flags; - ret = ntfs_check_if_mounted(output_dir, &mnt_flags); + int ret = ntfs_check_if_mounted(output_dir, &mnt_flags); if (ret != 0) { ERROR_WITH_ERRNO("NTFS-3g: Cannot determine if `%s' " "is mounted", output_dir); @@ -423,10 +413,15 @@ WIMLIBAPI int wimlib_extract_image(WIMStruct *w, int image, return WIMLIB_ERR_UNSUPPORTED; #endif } - if (image == WIM_ALL_IMAGES) - ret = extract_all_images(w, output_dir, flags); - else - ret = extract_single_image(w, image, output_dir, flags); - return ret; + + for_lookup_table_entry(w->lookup_table, zero_out_refcnts, NULL); + + if (image == WIM_ALL_IMAGES) { + flags |= WIMLIB_EXTRACT_FLAG_MULTI_IMAGE; + return extract_all_images(w, output_dir, flags); + } else { + flags &= ~WIMLIB_EXTRACT_FLAG_MULTI_IMAGE; + return extract_single_image(w, image, output_dir, flags); + } } diff --git a/src/mount.c b/src/mount.c index adfb7d66..de8fe001 100644 --- a/src/mount.c +++ b/src/mount.c @@ -220,9 +220,9 @@ int dentry_to_stbuf(const struct dentry *dentry, struct stat *stbuf) stbuf->st_size = 0; } - stbuf->st_atime = ms_timestamp_to_unix(dentry->last_access_time); - stbuf->st_mtime = ms_timestamp_to_unix(dentry->last_write_time); - stbuf->st_ctime = ms_timestamp_to_unix(dentry->creation_time); + stbuf->st_atime = wim_timestamp_to_unix(dentry->last_access_time); + stbuf->st_mtime = wim_timestamp_to_unix(dentry->last_write_time); + stbuf->st_ctime = wim_timestamp_to_unix(dentry->creation_time); stbuf->st_blocks = (stbuf->st_size + 511) / 512; return 0; } @@ -1286,7 +1286,7 @@ static int wimfs_release(const char *path, struct fuse_file_info *fi) } if (flags_writable(fi->flags) && fd->dentry) { - u64 now = get_timestamp(); + u64 now = get_wim_timestamp(); fd->dentry->last_access_time = now; fd->dentry->last_write_time = now; } @@ -1513,20 +1513,28 @@ static int wimfs_unlink(const char *path) return 0; } -/* Change the timestamp on a file dentry. +/* + * Change the timestamp on a file dentry. * - * There is no distinction between a file and its alternate data streams here. */ + * Note that alternate data streams do not have their own timestamps. + */ static int wimfs_utimens(const char *path, const struct timespec tv[2]) { struct dentry *dentry = get_dentry(w, path); if (!dentry) return -ENOENT; - time_t last_access_t = (tv[0].tv_nsec == UTIME_NOW) ? - time(NULL) : tv[0].tv_sec; - dentry->last_access_time = unix_timestamp_to_ms(last_access_t); - time_t last_mod_t = (tv[1].tv_nsec == UTIME_NOW) ? - time(NULL) : tv[1].tv_sec; - dentry->last_write_time = unix_timestamp_to_ms(last_mod_t); + if (tv[0].tv_nsec != UTIME_OMIT) { + if (tv[0].tv_nsec == UTIME_NOW) + dentry->last_access_time = get_wim_timestamp(); + else + dentry->last_access_time = timespec_to_wim_timestamp(&tv[0]); + } + if (tv[1].tv_nsec != UTIME_OMIT) { + if (tv[1].tv_nsec == UTIME_NOW) + dentry->last_write_time = get_wim_timestamp(); + else + dentry->last_write_time = timespec_to_wim_timestamp(&tv[1]); + } return 0; } diff --git a/src/symlink.c b/src/symlink.c index 03f78370..dc5af4c6 100644 --- a/src/symlink.c +++ b/src/symlink.c @@ -145,8 +145,10 @@ out: return buf; } -/* Get the symlink target from a dentry that's already checked to be either a - * "real" symlink or a junction point. */ +/* Get the symlink target from a dentry. + * + * The dentry may be either "real" symlink or a junction point. + */ ssize_t dentry_readlink(const struct dentry *dentry, char *buf, size_t buf_len, const WIMStruct *w) { diff --git a/src/timestamp.h b/src/timestamp.h index 5ad0b355..9c82c23e 100644 --- a/src/timestamp.h +++ b/src/timestamp.h @@ -2,9 +2,11 @@ #define _WIMLIB_TIMESTAMP_H #include "util.h" -#include +#include #define intervals_per_second (1000000000ULL / 100ULL) +#define intervals_per_microsecond (10) +#define nanoseconds_per_interval (100) #define days_per_year (365ULL) #define seconds_per_day (3600ULL * 24ULL) #define intervals_per_day (seconds_per_day * intervals_per_second) @@ -14,24 +16,33 @@ #define intervals_1601_to_1970 (years_1601_to_1970 * intervals_per_year \ + leap_years_1601_to_1970 * intervals_per_day) -static inline u64 unix_timestamp_to_ms(time_t t) +static inline u64 unix_timestamp_to_wim(time_t t) { return (u64)intervals_1601_to_1970 + t * intervals_per_second; } -/* - * Returns the number of 100-nanosecond intervals that have elapsed since - * 12:00 A.M., January 1, 1601 UTC. - */ -static inline u64 get_timestamp() -{ - return unix_timestamp_to_ms(time(NULL)); -} + /* Converts a timestamp as used in the WIM file to a UNIX timestamp as used in * the time() function. */ -static inline time_t ms_timestamp_to_unix(u64 timestamp) +static inline time_t wim_timestamp_to_unix(u64 timestamp) { return (timestamp - intervals_1601_to_1970) / intervals_per_second; } +static inline u64 timeval_to_wim_timestamp(const struct timeval *tv) +{ + return intervals_1601_to_1970 + + (u64)tv->tv_sec * intervals_per_second + + (u64)tv->tv_usec * intervals_per_microsecond; +} + +static inline u64 timespec_to_wim_timestamp(const struct timespec *ts) +{ + return intervals_1601_to_1970 + + (u64)ts->tv_sec * intervals_per_second + + (u64)ts->tv_nsec / nanoseconds_per_interval; +} + +extern u64 get_wim_timestamp(); + #endif diff --git a/src/util.c b/src/util.c index 8bcfa202..a2a50faa 100644 --- a/src/util.c +++ b/src/util.c @@ -25,6 +25,8 @@ #include "wimlib_internal.h" #include "endianness.h" #include "sha1.h" +#include "timestamp.h" +#include #include @@ -503,3 +505,12 @@ void print_string(const void *string, size_t len) p++; } } + +u64 get_wim_timestamp() +{ + struct timeval tv; + gettimeofday(&tv, NULL); + return timeval_to_wim_timestamp(&tv); +} + + diff --git a/src/xml.c b/src/xml.c index 77e58757..8132671a 100644 --- a/src/xml.c +++ b/src/xml.c @@ -28,7 +28,7 @@ #include "xml.h" #include "timestamp.h" #include - +#include #include #include #include @@ -977,7 +977,7 @@ void xml_update_image_info(WIMStruct *w, int image) &image_info->total_bytes, &image_info->hard_link_bytes); - image_info->last_modification_time = get_timestamp(); + image_info->last_modification_time = get_wim_timestamp(); } /* Adds an image to the XML information. */ @@ -1020,7 +1020,7 @@ int xml_add_image(WIMStruct *w, struct dentry *root_dentry, const char *name, w->wim_info = wim_info; image_info->index = wim_info->num_images; - image_info->creation_time = get_timestamp(); + image_info->creation_time = get_wim_timestamp(); xml_update_image_info(w, image_info->index); return 0; @@ -1082,8 +1082,8 @@ void print_image_info(const struct wim_info *wim_info, int image) printf("Hard Link Bytes: %"PRIu64"\n", image_info->hard_link_bytes); - ctime = ms_timestamp_to_unix(image_info->creation_time); - mtime = ms_timestamp_to_unix(image_info->last_modification_time); + ctime = wim_timestamp_to_unix(image_info->creation_time); + mtime = wim_timestamp_to_unix(image_info->last_modification_time); printf("Creation Time: %s", asctime(localtime(&ctime))); printf("Last Modification Time: %s", asctime(localtime(&mtime))); -- 2.43.0