diff --git a/tst/passthrough-fuse/passthrough-fuse.c b/tst/passthrough-fuse/passthrough-fuse.c index ef24fc6b..55cc7b4f 100644 --- a/tst/passthrough-fuse/passthrough-fuse.c +++ b/tst/passthrough-fuse/passthrough-fuse.c @@ -30,6 +30,8 @@ #include #endif +#define PTFS_UTIMENS + #define FSNAME "passthrough" #define PROGNAME "passthrough-fuse" @@ -112,12 +114,14 @@ static int ptfs_truncate(const char *path, fuse_off_t size) return -1 != truncate(path, size) ? 0 : -errno; } +#if !defined(PTFS_UTIMENS) static int ptfs_utime(const char *path, struct fuse_utimbuf *timbuf) { ptfs_impl_fullpath(path); return -1 != utime(path, timbuf) ? 0 : -errno; } +#endif static int ptfs_open(const char *path, struct fuse_file_info *fi) { @@ -246,6 +250,15 @@ static int ptfs_fgetattr(const char *path, struct fuse_stat *stbuf, struct fuse_ return -1 != fstat(fd, stbuf) ? 0 : -errno; } +#if defined(PTFS_UTIMENS) +static int ptfs_utimens(const char *path, const struct fuse_timespec tv[2]) +{ + ptfs_impl_fullpath(path); + + return -1 != utimensat(AT_FDCWD, path, tv) ? 0 : -errno; +} +#endif + #if defined(FSP_FUSE_USE_STAT_EX) static int ptfs_chflags(const char *path, uint32_t flags) { @@ -265,7 +278,9 @@ static struct fuse_operations ptfs_ops = .chmod = ptfs_chmod, .chown = ptfs_chown, .truncate = ptfs_truncate, +#if !defined(PTFS_UTIMENS) .utime = ptfs_utime, +#endif .open = ptfs_open, .read = ptfs_read, .write = ptfs_write, @@ -279,6 +294,9 @@ static struct fuse_operations ptfs_ops = .create = ptfs_create, .ftruncate = ptfs_ftruncate, .fgetattr = ptfs_fgetattr, +#if defined(PTFS_UTIMENS) + .utimens = ptfs_utimens, +#endif #if defined(FSP_FUSE_USE_STAT_EX) .chflags = ptfs_chflags, #endif diff --git a/tst/passthrough-fuse/winposix.c b/tst/passthrough-fuse/winposix.c index cada2977..f48f2a92 100644 --- a/tst/passthrough-fuse/winposix.c +++ b/tst/passthrough-fuse/winposix.c @@ -342,6 +342,23 @@ int truncate(const char *path, fuse_off_t size) int utime(const char *path, const struct fuse_utimbuf *timbuf) { + if (0 == timbuf) + return utimensat(AT_FDCWD, path, 0); + else + { + struct fuse_timespec times[2]; + times[0].tv_sec = timbuf->actime; + times[0].tv_nsec = 0; + times[1].tv_sec = timbuf->modtime; + times[1].tv_nsec = 0; + return utimensat(AT_FDCWD, path, times); + } +} + +int utimensat(int dirfd, const char *path, const struct fuse_timespec times[2]) +{ + /* ignore dirfd and assume that it is always AT_FDCWD */ + HANDLE h = CreateFileA(path, FILE_WRITE_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 0, @@ -349,8 +366,18 @@ int utime(const char *path, const struct fuse_utimbuf *timbuf) if (INVALID_HANDLE_VALUE == h) return error(); - UINT64 LastAccessTime = timbuf->actime * 10000000 + 116444736000000000; - UINT64 LastWriteTime = timbuf->modtime * 10000000 + 116444736000000000; + UINT64 LastAccessTime, LastWriteTime; + if (0 == times) + { + FILETIME FileTime; + GetSystemTimeAsFileTime(&FileTime); + LastAccessTime = LastWriteTime = *(PUINT64)&FileTime; + } + else + { + LastAccessTime = times[0].tv_sec * 10000000 + times[0].tv_nsec / 100 + 116444736000000000; + LastWriteTime = times[1].tv_sec * 10000000 + times[1].tv_nsec / 100 + 116444736000000000; + } int res = SetFileTime(h, 0, (PFILETIME)&LastAccessTime, (PFILETIME)&LastWriteTime) ? 0 : error(); diff --git a/tst/passthrough-fuse/winposix.h b/tst/passthrough-fuse/winposix.h index a7f8cff2..ea9c260e 100644 --- a/tst/passthrough-fuse/winposix.h +++ b/tst/passthrough-fuse/winposix.h @@ -27,6 +27,7 @@ #define O_TRUNC _O_TRUNC #define PATH_MAX 1024 +#define AT_FDCWD -2 typedef struct _DIR DIR; struct dirent @@ -53,6 +54,7 @@ int lchown(const char *path, fuse_uid_t uid, fuse_gid_t gid); int lchflags(const char *path, uint32_t flags); int truncate(const char *path, fuse_off_t size); int utime(const char *path, const struct fuse_utimbuf *timbuf); +int utimensat(int dirfd, const char *path, const struct fuse_timespec times[2]); int unlink(const char *path); int rename(const char *oldpath, const char *newpath);