More accurate timestamps
authorEric Biggers <ebiggers3@gmail.com>
Mon, 20 Aug 2012 23:04:51 +0000 (18:04 -0500)
committerEric Biggers <ebiggers3@gmail.com>
Mon, 20 Aug 2012 23:04:51 +0000 (18:04 -0500)
src/dentry.c
src/extract.c
src/mount.c
src/symlink.c
src/timestamp.h
src/util.c
src/xml.c

index 2f0cabd3d577f4eef9581c15fb58e370337e2cb0..c31655446521b4bd2b5e3eb0bbfcf65c73049001 100644 (file)
@@ -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;
index 8c3aedb97e49e9d2c60adfeffbdcc9c40ec57dbe..121966022b77bcc7c089b059e87c97fcef156622 100644 (file)
@@ -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);
+       }
 
 }
index adfb7d6649eced85c7c267732c8381be7134b0d7..de8fe001d8009a053668a537ef06362a22b74d28 100644 (file)
@@ -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;
 }
 
index 03f78370bb7442bb56f95c20cf79813eb25996a7..dc5af4c6e4bf88fb8eaba1d6beb61920112557f7 100644 (file)
@@ -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)
 {
index 5ad0b3556343a937e5bb76587af97a6c5913f779..9c82c23e2081dab9d8f3212bfd6c8e5ba1286a92 100644 (file)
@@ -2,9 +2,11 @@
 #define _WIMLIB_TIMESTAMP_H
 
 #include "util.h"
-#include <time.h>
+#include <sys/types.h>
 
 #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)
 #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
index 8bcfa2028807422302fa543c1c1dcb9c53bd763a..a2a50faa0614d873d8611db6fd4ee3179616d502 100644 (file)
@@ -25,6 +25,8 @@
 #include "wimlib_internal.h"
 #include "endianness.h"
 #include "sha1.h"
+#include "timestamp.h"
+#include <sys/time.h>
 
 
 #include <iconv.h>
@@ -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);
+}
+
+
index 77e58757bea26042b8364696a9d10ec17d1d06bd..8132671a29dd6313ef2a680ff0f69584661efeae 100644 (file)
--- a/src/xml.c
+++ b/src/xml.c
@@ -28,7 +28,7 @@
 #include "xml.h"
 #include "timestamp.h"
 #include <string.h>
-
+#include <time.h>
 #include <libxml/parser.h>
 #include <libxml/tree.h>
 #include <libxml/xmlwriter.h>
@@ -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)));