From 9d4a16eefe9d579d0c4eafaa3124f78c7ad526ec Mon Sep 17 00:00:00 2001 From: Ben Noordhuis Date: Thu, 17 Jan 2013 14:19:58 +0100 Subject: [PATCH] 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/"). Fixes #687. --- src/unix/fs.c | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/src/unix/fs.c b/src/unix/fs.c index f01c83b4..eaccb294 100644 --- a/src/unix/fs.c +++ b/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) + 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__) \