Browse files

linux: add futimes() fallback

The utimensat() syscall was added in 2.6.22. Add a fallback mode for
older kernels that uses utimes("/proc/self/fd/<fd>").

Fixes #687.
  • Loading branch information...
1 parent 629a59b commit 9d4a16eefe9d579d0c4eafaa3124f78c7ad526ec @bnoordhuis bnoordhuis committed Jan 17, 2013
Showing with 28 additions and 1 deletion.
  1. +28 −1 src/unix/fs.c
View
29 src/unix/fs.c
@@ -113,12 +113,39 @@ static ssize_t uv__fs_futime(uv_fs_t* req) {
/* utimesat() has nanosecond resolution but we stick to microseconds
* for the sake of consistency with other platforms.
*/
+ static int no_utimesat;
struct timespec ts[2];
+ struct timeval tv[2];
+ char path[sizeof("/proc/self/fd/") + 3 * sizeof(int)];
+ int r;
+
+ if (no_utimesat)
@indutny
indutny added a note Jan 17, 2013

Missing initialization?

It's static so it defaults to zero.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+ goto skip;
+
ts[0].tv_sec = req->atime;
ts[0].tv_nsec = (unsigned long)(req->atime * 1000000) % 1000000 * 1000;
ts[1].tv_sec = req->mtime;
ts[1].tv_nsec = (unsigned long)(req->mtime * 1000000) % 1000000 * 1000;
- return uv__utimesat(req->file, NULL, ts, 0);
+
+ r = uv__utimesat(req->file, NULL, ts, 0);
+ if (r == 0)
+ return r;
+
+ if (errno != ENOSYS)
+ return r;
+
+ no_utimesat = 1;
+
+skip:
+
+ tv[0].tv_sec = req->atime;
+ tv[0].tv_usec = (unsigned long)(req->atime * 1000000) % 1000000;
+ tv[1].tv_sec = req->mtime;
+ tv[1].tv_usec = (unsigned long)(req->mtime * 1000000) % 1000000;
+ snprintf(path, sizeof(path), "/proc/self/fd/%d", (int) req->file);
+
+ return utimes(path, tv);
+
#elif defined(__APPLE__) \
|| defined(__DragonFly__) \
|| defined(__FreeBSD__) \

1 comment on commit 9d4a16e

@indutny

Otherwise, lgtm

Please sign in to comment.