diff options
author | Martin Pärtel <martin.partel@gmail.com> | 2014-05-10 12:37:38 +0100 |
---|---|---|
committer | Martin Pärtel <martin.partel@gmail.com> | 2014-05-10 12:37:38 +0100 |
commit | dc0cf937e50ea1abb7ce439a011531ddb3bbda02 (patch) | |
tree | 222fbf368ca78c6ef67787c0790280ae3614b385 | |
parent | 60fc1f3f085983aa3fbb74102c270be8de15f9e5 (diff) | |
download | bindfs-dc0cf937e50ea1abb7ce439a011531ddb3bbda02.tar.gz |
Use lutimes() when utimensat() unavailable (#6).
-rw-r--r-- | configure.ac | 3 | ||||
-rw-r--r-- | src/bindfs.c | 37 | ||||
-rwxr-xr-x | tests/test_bindfs.rb | 25 | ||||
-rw-r--r-- | tests/utimens_nofollow.c | 35 |
4 files changed, 50 insertions, 50 deletions
diff --git a/configure.ac b/configure.ac index 878b9ff..085eeed 100644 --- a/configure.ac +++ b/configure.ac @@ -40,7 +40,8 @@ AC_SUBST([my_CPPFLAGS]) AC_SUBST([my_CFLAGS]) AC_SUBST([my_LDFLAGS]) -# Check for xattrs +# Checks for platform-specific stuff +AC_CHECK_FUNCS([lutimes utimensat]) AC_CHECK_FUNCS([setxattr getxattr listxattr removexattr]) AC_CHECK_FUNCS([lsetxattr lgetxattr llistxattr lremovexattr]) diff --git a/src/bindfs.c b/src/bindfs.c index c2fd76f..1138592 100644 --- a/src/bindfs.c +++ b/src/bindfs.c @@ -34,6 +34,10 @@ /* For >= 500 for pread/pwrite and readdir_r; >= 700 for utimensat */ #define _XOPEN_SOURCE 700 +#if !HAVE_UTIMENSAT && HAVE_LUTIMES +#define _BSD_SOURCE +#endif + #include <stdlib.h> #include <stddef.h> #include <stdio.h> @@ -45,6 +49,7 @@ #ifdef HAVE_SYS_STAT_H #include <sys/stat.h> #endif +#include <sys/time.h> #include <sys/statvfs.h> #include <unistd.h> #include <fcntl.h> @@ -177,11 +182,7 @@ static int bindfs_chown(const char *path, uid_t uid, gid_t gid); static int bindfs_truncate(const char *path, off_t size); static int bindfs_ftruncate(const char *path, off_t size, struct fuse_file_info *fi); -#ifdef __APPLE__ -static int bindfs_utime(const char *path, struct utimbuf *buf); -#else static int bindfs_utimens(const char *path, const struct timespec tv[2]); -#endif static int bindfs_create(const char *path, mode_t mode, struct fuse_file_info *fi); static int bindfs_open(const char *path, struct fuse_file_info *fi); static int bindfs_read(const char *path, char *buf, size_t size, off_t offset, @@ -694,21 +695,25 @@ static int bindfs_ftruncate(const char *path, off_t size, return 0; } -#ifdef __APPLE__ -static int bindfs_utime(const char *path, struct utimbuf *buf) -#else -static int bindfs_utimens(const char *path, const struct timespec tv[2]) -#endif +static int bindfs_utimens(const char *path, const struct timespec ts[2]) { int res; path = process_path(path); - #ifdef __APPLE__ - res = utime(path, buf); - #else - res = utimensat(settings.mntsrc_fd, path, tv, AT_SYMLINK_NOFOLLOW); - #endif +#ifdef HAVE_UTIMENSAT + res = utimensat(settings.mntsrc_fd, path, ts, AT_SYMLINK_NOFOLLOW); +#elif HAVE_LUTIMES + struct timeval tv[2]; + tv[0].tv_sec = ts[0].tv_sec; + tv[0].tv_usec = ts[0].tv_nsec / 1000; + tv[1].tv_sec = ts[1].tv_sec; + tv[1].tv_usec = ts[1].tv_nsec / 1000; + res = lutimes(path, tv); +#else +#error "No symlink-compatible utime* function available." +#endif + if (res == -1) return -errno; @@ -918,11 +923,7 @@ static struct fuse_operations bindfs_oper = { .chown = bindfs_chown, .truncate = bindfs_truncate, .ftruncate = bindfs_ftruncate, - #ifdef __APPLE__ - .utime = bindfs_utime, - #else .utimens = bindfs_utimens, - #endif .create = bindfs_create, .open = bindfs_open, .read = bindfs_read, diff --git a/tests/test_bindfs.rb b/tests/test_bindfs.rb index a1f1526..54521f0 100755 --- a/tests/test_bindfs.rb +++ b/tests/test_bindfs.rb @@ -370,22 +370,19 @@ root_testenv("", :title => "setgid directories") do assert { File.stat('mnt/dir/file').gid == $nogroup_gid } end -# utimensat() unavailable on OS X -unless RUBY_PLATFORM =~ /darwin/ - root_testenv("", :title => "utimens on symlinks") do - touch('mnt/file') - Dir.chdir "mnt" do - system('ln -sf file link') - end +testenv("", :title => "utimens on symlinks") do + touch('mnt/file') + Dir.chdir "mnt" do + system('ln -sf file link') + end - system("#{$tests_dir}/utimens_nofollow mnt/link 12 34 56 78") - raise "Failed to run utimens_nofollow: #{$?.inspect}" unless $?.success? + system("#{$tests_dir}/utimens_nofollow mnt/link 12 34 56 78") + raise "Failed to run utimens_nofollow: #{$?.inspect}" unless $?.success? - assert { File.lstat('mnt/link').atime.to_i < 100 } - assert { File.lstat('mnt/link').mtime.to_i < 100 } - assert { File.lstat('mnt/file').atime.to_i > 100 } - assert { File.lstat('mnt/file').mtime.to_i > 100 } - end + assert { File.lstat('mnt/link').atime.to_i < 50 } + assert { File.lstat('mnt/link').mtime.to_i < 100 } + assert { File.lstat('mnt/file').atime.to_i > 100 } + assert { File.lstat('mnt/file').mtime.to_i > 100 } end # FIXME: this stuff around testenv is a hax, and testenv may also exit(), which defeats the 'ensure' below. diff --git a/tests/utimens_nofollow.c b/tests/utimens_nofollow.c index 8316b26..02fcf58 100644 --- a/tests/utimens_nofollow.c +++ b/tests/utimens_nofollow.c @@ -1,45 +1,46 @@ -#ifndef __APPLE__ - -#define _BSD_SOURCE /* For atoll */ +#define _BSD_SOURCE /* For atoll and lutimes */ +#include <config.h> #include <stdlib.h> #include <stdio.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> +#include <sys/time.h> #include <fcntl.h> #include <errno.h> int main(int argc, char* argv[]) { - struct timespec times[2]; - if (argc != 6) { fprintf(stderr, "Usage: utimens_nofollow path atime atime_nsec mtime mtime_nsec\n"); return 1; } +#ifdef HAVE_UTIMENSAT + struct timespec times[2]; times[0].tv_sec = (time_t)atoll(argv[2]); times[0].tv_nsec = atoll(argv[3]); times[1].tv_sec = (time_t)atoll(argv[4]); times[1].tv_nsec = atoll(argv[5]); - if (utimensat(AT_FDCWD, argv[1], times, AT_SYMLINK_NOFOLLOW) == -1) { perror("failed to utimensat the given path"); return 2; } +#elif HAVE_LUTIMES + struct timeval times[2]; + times[0].tv_sec = (time_t)atoll(argv[2]); + times[0].tv_usec = (suseconds_t)atoll(argv[3]) / 1000; + times[1].tv_sec = (time_t)atoll(argv[4]); + times[1].tv_usec = (suseconds_t)atoll(argv[5]) / 1000; + if (lutimes(argv[1], times) == -1) { + perror("failed to lutimes the given path"); + return 2; + } +#else +#error "No symlink-compatible utime* function available." +#endif return 0; } - -#else /* #ifndef __APPLE__ */ - -#include <stdio.h> -int main() -{ - fprintf("utimensat() unavailable on this platform\n"); - return 1; -} - -#endif /* #ifndef __APPLE__ */ |