/* 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;
};
/*
- * 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)
{
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);
}
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);
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);
+ }
}
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;
}
}
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;
}
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;
}
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)
{
#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
#include "wimlib_internal.h"
#include "endianness.h"
#include "sha1.h"
+#include "timestamp.h"
+#include <sys/time.h>
#include <iconv.h>
p++;
}
}
+
+u64 get_wim_timestamp()
+{
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+ return timeval_to_wim_timestamp(&tv);
+}
+
+
#include "xml.h"
#include "timestamp.h"
#include <string.h>
-
+#include <time.h>
#include <libxml/parser.h>
#include <libxml/tree.h>
#include <libxml/xmlwriter.h>
&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. */
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;
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)));