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 line comment Jan 17, 2013

Missing initialization?

@bnoordhuis
bnoordhuis added a line comment Jan 17, 2013

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.