diff options
author | Darren Tucker <dtucker@dtucker.net> | 2019-01-18 12:11:42 +1300 |
---|---|---|
committer | Darren Tucker <dtucker@dtucker.net> | 2019-01-18 10:16:11 +1100 |
commit | 091093d25802b87d3b2b09f2c88d9f33e1ae5562 (patch) | |
tree | 16a433e3317c60c7a245b70818726d0a85203b19 /openbsd-compat/bsd-misc.c | |
parent | 609644027dde1f82213699cb6599e584c7efcb75 (diff) |
Add a minimal implementation of utimensat().
Some systems (eg older OS X) do not have utimensat, so provide minimal
implementation in compat layer. Fixes build on at least El Capitan.
Diffstat (limited to 'openbsd-compat/bsd-misc.c')
-rw-r--r-- | openbsd-compat/bsd-misc.c | 37 |
1 files changed, 37 insertions, 0 deletions
diff --git a/openbsd-compat/bsd-misc.c b/openbsd-compat/bsd-misc.c index 5d7540a7..4bae9654 100644 --- a/openbsd-compat/bsd-misc.c +++ b/openbsd-compat/bsd-misc.c @@ -25,6 +25,7 @@ # include <sys/time.h> #endif +#include <fcntl.h> #include <string.h> #include <signal.h> #include <stdlib.h> @@ -117,6 +118,42 @@ int utimes(char *filename, struct timeval *tvp) } #endif +#ifndef HAVE_UTIMENSAT +/* + * A limited implementation of utimensat() that only implements the + * functionality used by OpenSSH, currently only AT_FDCWD and + * AT_SYMLINK_NOFOLLOW. + */ +int +utimensat(int fd, const char *path, const struct timespec times[2], + int flag) +{ + struct timeval tv[2]; + int ret, oflags = O_WRONLY; + + tv[0].tv_sec = times[0].tv_sec; + tv[0].tv_usec = times[0].tv_nsec / 1000; + tv[1].tv_sec = times[1].tv_sec; + tv[1].tv_usec = times[1].tv_nsec / 1000; + + if (fd != AT_FDCWD) { + errno = ENOSYS; + return -1; + } +# ifndef HAVE_FUTIMES + return utimes(path, tv); +# else + if (flag & AT_SYMLINK_NOFOLLOW) + oflags |= O_NOFOLLOW; + if ((fd = open(path, oflags)) == -1) + return -1; + ret = futimes(fd, tv); + close(fd); + return ret; +# endif +} +#endif + #ifndef HAVE_TRUNCATE int truncate(const char *path, off_t length) { |