]> wimlib.net Git - wimlib/blobdiff - src/mount_image.c
Update timestamp code; use utimensat()
[wimlib] / src / mount_image.c
index b9b63450868866832b3a24b5f10254c7057f12b4..d9688765514f81baff478c2c39b15b877b2a25d6 100644 (file)
@@ -8,7 +8,7 @@
  */
 
 /*
- * Copyright (C) 2012 Eric Biggers
+ * Copyright (C) 2012, 2013 Eric Biggers
  *
  * This file is part of wimlib, a library for working with WIM files.
  *
 
 #ifdef WITH_FUSE
 
-#include "sha1.h"
-#include "lookup_table.h"
-#include "xml.h"
 #include "buffer_io.h"
+#include "lookup_table.h"
+#include "sha1.h"
 #include "timestamp.h"
+#include "xml.h"
+
+#include <errno.h>
+#include <ftw.h>
 #include <limits.h>
+#include <mqueue.h>
+#include <signal.h>
 #include <stdlib.h>
-#include <unistd.h>
-#include <sys/wait.h>
-#define FUSE_USE_VERSION 26
-#include <errno.h>
 #include <string.h>
+#include <sys/stat.h>
 #include <sys/time.h>
-#include <fuse.h>
-#include <ftw.h>
-#include <mqueue.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
 #include <utime.h>
-#include <signal.h>
+
+#define FUSE_USE_VERSION 26
+#include <fuse.h>
 
 #ifdef ENABLE_XATTR
 #include <attr/xattr.h>
@@ -109,6 +113,9 @@ struct wimfs_context {
 
        uid_t default_uid;
        gid_t default_gid;
+
+       int status;
+       bool have_status;
 };
 
 static void init_wimfs_context(struct wimfs_context *ctx)
@@ -413,13 +420,26 @@ static int inode_to_stbuf(const struct wim_inode *inode,
                stbuf->st_size = 0;
        }
 
+#ifdef HAVE_STAT_NANOSECOND_PRECISION
+       stbuf->st_atim = wim_timestamp_to_timespec(inode->i_last_access_time);
+       stbuf->st_mtim = wim_timestamp_to_timespec(inode->i_last_write_time);
+       stbuf->st_ctim = stbuf->st_mtim;
+#else
        stbuf->st_atime = wim_timestamp_to_unix(inode->i_last_access_time);
        stbuf->st_mtime = wim_timestamp_to_unix(inode->i_last_write_time);
-       stbuf->st_ctime = wim_timestamp_to_unix(inode->i_creation_time);
+       stbuf->st_ctime = stbuf->st_mtime;
+#endif
        stbuf->st_blocks = (stbuf->st_size + 511) / 512;
        return 0;
 }
 
+static void touch_inode(struct wim_inode *inode)
+{
+       u64 now = get_wim_timestamp();
+       inode->i_last_access_time = now;
+       inode->i_last_write_time = now;
+}
+
 /* Creates a new staging file and returns its file descriptor opened for
  * writing.
  *
@@ -1236,7 +1256,8 @@ out:
                                status = ret;
                }
        }
-       send_unmount_finished_msg(wimfs_ctx->daemon_to_unmount_mq, status);
+       wimfs_ctx->status = status;
+       wimfs_ctx->have_status = true;
        return MSG_BREAK_LOOP;
 }
 
@@ -1565,7 +1586,6 @@ static void wimfs_destroy(void *p)
                message_loop(wimfs_ctx->unmount_to_daemon_mq,
                             &daemon_msg_handler_callbacks,
                             &handler_ctx.hdr);
-               close_message_queues(wimfs_ctx);
        }
 }
 
@@ -2112,7 +2132,6 @@ static int wimfs_setxattr(const char *path, const char *name,
        if (existing_ads_entry) {
                if (flags & XATTR_CREATE)
                        return -EEXIST;
-               inode_remove_ads(inode, ads_idx, ctx->wim->lookup_table);
        } else {
                if (flags & XATTR_REPLACE)
                        return -ENOATTR;
@@ -2120,7 +2139,13 @@ static int wimfs_setxattr(const char *path, const char *name,
 
        ret = inode_add_ads_with_data(inode, name, (const u8*)value,
                                      size, ctx->wim->lookup_table);
-       return ret ? -ENOMEM : 0;
+       if (ret == 0) {
+               if (existing_ads_entry)
+                       inode_remove_ads(inode, ads_idx, ctx->wim->lookup_table);
+       } else {
+               ret = -ENOMEM;
+       }
+       return ret;
 }
 #endif
 
@@ -2229,13 +2254,13 @@ static int wimfs_utimens(const char *path, const struct timespec tv[2])
                if (tv[0].tv_nsec == UTIME_NOW)
                        inode->i_last_access_time = get_wim_timestamp();
                else
-                       inode->i_last_access_time = timespec_to_wim_timestamp(&tv[0]);
+                       inode->i_last_access_time = timespec_to_wim_timestamp(tv[0]);
        }
        if (tv[1].tv_nsec != UTIME_OMIT) {
                if (tv[1].tv_nsec == UTIME_NOW)
                        inode->i_last_write_time = get_wim_timestamp();
                else
-                       inode->i_last_write_time = timespec_to_wim_timestamp(&tv[1]);
+                       inode->i_last_write_time = timespec_to_wim_timestamp(tv[1]);
        }
        return 0;
 }
@@ -2284,9 +2309,8 @@ static int wimfs_write(const char *path, const char *buf, size_t size,
        if (ret == -1)
                return -errno;
 
-       now = get_wim_timestamp();
-       fd->f_inode->i_last_write_time = now;
-       fd->f_inode->i_last_access_time = now;
+       /* Update timestamps */
+       touch_inode(fd->f_inode);
        return ret;
 }
 
@@ -2530,14 +2554,23 @@ WIMLIBAPI int wimlib_mount_image(WIMStruct *wim, int image, const char *dir,
 
        DEBUG("Returned from fuse_main() (ret = %d)", ret);
 
-       if (ret)
+       if (ret) {
                ret = WIMLIB_ERR_FUSE;
+       } else {
+               if (ctx.have_status)
+                       ret = ctx.status;
+               else
+                       ret = WIMLIB_ERR_TIMEOUT;
+       }
+       if (ctx.daemon_to_unmount_mq != (mqd_t)(-1)) {
+               send_unmount_finished_msg(ctx.daemon_to_unmount_mq, ret);
+               close_message_queues(&ctx);
+       }
 
        /* Try to delete the staging directory if a deletion wasn't yet
         * attempted due to an earlier error */
        if (ctx.staging_dir_name)
                delete_staging_dir(&ctx);
-
 out_free_dir_copy:
        FREE(dir_copy);
 out_unlock:
@@ -2608,8 +2641,12 @@ out:
 
 static inline int mount_unsupported_error()
 {
+#if defined(__WIN32__)
+       ERROR("Sorry-- Mounting WIM images is not supported on Windows!");
+#else
        ERROR("wimlib was compiled with --without-fuse, which disables support "
              "for mounting WIMs.");
+#endif
        return WIMLIB_ERR_UNSUPPORTED;
 }