- timeval[0].tv_sec = timespec[0].tv_sec;
- timeval[0].tv_usec = timespec[0].tv_nsec / 1000;
- timeval[1].tv_sec = timespec[1].tv_sec;
- timeval[1].tv_usec = timespec[1].tv_nsec / 1000;
- return utimes (file, timeval);
-#else
- struct utimbuf utimbuf;
- utimbuf.actime = timespec[0].tv_sec;
- utimbuf.modtime = timespec[1].tv_sec;
- return utime (file, &utimbuf);
+ struct timeval const *t;
+ if (timespec)
+ {
+ timeval[0].tv_sec = timespec[0].tv_sec;
+ timeval[0].tv_usec = timespec[0].tv_nsec / 1000;
+ timeval[1].tv_sec = timespec[1].tv_sec;
+ timeval[1].tv_usec = timespec[1].tv_nsec / 1000;
+ t = timeval;
+ }
+ else
+ t = NULL;
+
+# if HAVE_FUTIMESAT
+ return fd < 0 ? futimesat (AT_FDCWD, file, t) : futimesat (fd, NULL, t);
+# elif HAVE_FUTIMES
+ if (0 <= fd)
+ {
+ if (futimes (fd, t) == 0)
+ return 0;
+
+ /* Don't worry about trying to speed things up by returning right
+ away here. glibc futimes can incorrectly fail with errno ==
+ ENOENT if /proc isn't mounted. Also, Mandrake 10.0 in high
+ security mode doesn't allow ordinary users to read /proc/self, so
+ glibc futimes incorrectly fails with errno == EACCES. If futimes
+ fails with errno == EIO, EPERM, or EROFS, it's probably safe to
+ fail right away, but these cases are rare enough that they're not
+ worth optimizing, and who knows what other messed-up systems are
+ out there? So play it safe and fall back on the code below. */
+ }
+# endif