diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2020-01-21 22:24:39 -0800 |
---|---|---|
committer | Kaz Kyheku <kaz@kylheku.com> | 2020-01-21 22:24:39 -0800 |
commit | 2f9a61fab155d577b8618a64fef8a755cc15f2f8 (patch) | |
tree | 940fccab0345f22181c35f0ef73f7ffc5b277a1d /sysif.c | |
parent | 72eff372aefb86ca8ae5ad2e95f01d4cc9e0ec78 (diff) | |
download | txr-2f9a61fab155d577b8618a64fef8a755cc15f2f8.tar.gz txr-2f9a61fab155d577b8618a64fef8a755cc15f2f8.tar.bz2 txr-2f9a61fab155d577b8618a64fef8a755cc15f2f8.zip |
New functions utimes, lutimes.
* configure: Detect various functions for setting file
timestamps.
* sysif.c (get_fd): Define this function for use by utimes
also.
(timens, do_utimes): New static functions.
(wrap_utimes, wrap_lutimes): New static functions.
(sysif_init): Register utimes and lutimes intrinsics.
* txr.1: Documented.
Diffstat (limited to 'sysif.c')
-rw-r--r-- | sysif.c | 114 |
1 files changed, 113 insertions, 1 deletions
@@ -52,6 +52,9 @@ #if HAVE_SYS_TYPES_H #include <sys/types.h> #endif +#if HAVE_SYS_TIME +#include <sys/time.h> +#endif #if HAVE_SYS_SYSMACROS_H #include <sys/sysmacros.h> #endif @@ -79,6 +82,9 @@ #if HAVE_CRYPT_R #include <crypt.h> #endif +#if HAVE_UTIME +#include <utime.h> +#endif #include "alloca.h" #include "lib.h" #include "stream.h" @@ -449,7 +455,7 @@ static val mknod_wrap(val path, val mode, val dev) #endif -#if HAVE_CHMOD || HAVE_SYS_STAT +#if HAVE_CHMOD || HAVE_SYS_STAT || HAVE_FILE_STAMP_CHANGE static int get_fd(val stream, val self) { val fd_in = if3(integerp(stream), stream, stream_get_prop(stream, fd_k)); @@ -905,6 +911,107 @@ val fstat_wrap(val stream) return stat_impl(stream, do_fstat, lit("fstat"), nil); } +#if HAVE_FILE_STAMP_CHANGE + +#if HAVE_FUTIMENS +static long timens(val arg, val self) +{ + return if3(arg == t, UTIME_NOW, if3(arg, c_long(arg, self), UTIME_OMIT)); +} +#endif + +static val do_utimes(val target, val atime, val atimens, + val mtime, val mtimens, + val symlink_nofollow, val self) +{ + int res = -1; + + if (stringp(target)) { + char *u8path = utf8_dup_to(c_str(target)); +#if HAVE_FUTIMENS + int flags = if3(symlink_nofollow, AT_SYMLINK_NOFOLLOW, 0); + struct timespec times[2]; + times[0].tv_sec = c_time(atime); + times[0].tv_nsec = timens(atimens, self); + times[1].tv_sec = c_time(mtime); + times[1].tv_nsec = timens(mtimens, self); + res = utimensat(AT_FDCWD, u8path, times, flags); +#else + errno = -EINVAL; + if (integerp(atimens) || integerp(mtimens)) { + struct timeval times[2]; + times[0].tv_sec = c_time(atime); + times[0].tv_usec = c_long(trunc(atimens, num_fast(1000)), self); + times[1].tv_sec = c_time(mtime); + times[1].tv_usec = c_long(trunc(mtimens, num_fast(1000)), self); + if (symlink_nofollow) { +#if HAVE_LUTIMES + res = lutimes(u8path, times); +#endif + } else { +#if HAVE_UTIMES + res = utimes(u8path, times); +#elif HAVE_UTIME + struct utimbuf utb; + utb.actime = times[0].tv_sec; + utb.modtime = times[1].tv_sec; + res = utime(u8path, &utb); +#endif + } + } +#endif + free(u8path); + } else { +#if HAVE_FUTIMENS + struct timespec times[2]; + int fd = get_fd(target, self); + times[0].tv_sec = c_time(atime); + times[0].tv_nsec = timens(atimens, self); + times[1].tv_sec = c_time(mtime); + times[1].tv_nsec = timens(mtimens, self); + res = futimens(fd, times); +#elif HAVE_FUTIMES + struct timeval times[2]; + int fd = get_fd(target, self); + errno = -EINVAL; + if (integerp(atimens) || integerp(mtimens)) { + times[0].tv_sec = c_time(atime); + times[0].tv_usec = c_long(trunc(atimens, num_fast(1000)), self); + times[1].tv_sec = c_time(mtime); + times[1].tv_usec = c_long(trunc(mtimens, num_fast(1000)), self); + res = futimes(fd, times); + } +#else + errno = -EINVAL; +#endif + } + + if (res == -1) { + int eno = errno; + uw_throwf(errno_to_file_error(eno), lit("~s: failed: ~d/~s"), + self, num(eno), string_utf8(strerror(eno)), nao); + } + + return t; +} + +static val wrap_utimes(val target, val atime, val atimens, + val mtime, val mtimens) +{ + val self = lit("utimes"); + return do_utimes(target, atime, atimens, mtime, mtimens, nil, self); +} + +static val wrap_lutimes(val target, val atime, val atimens, + val mtime, val mtimens) +{ + val self = lit("lutimes"); + return do_utimes(target, atime, atimens, mtime, mtimens, t, self); +} + +#endif + + #if HAVE_SYS_STAT static val umask_wrap(val mask) @@ -2018,6 +2125,11 @@ void sysif_init(void) reg_fun(intern(lit("fcntl"), user_package), func_n3o(fcntl_wrap, 2)); #endif +#if HAVE_FILE_STAMP_CHANGE + reg_fun(intern(lit("utimes"), user_package), func_n5(wrap_utimes)); + reg_fun(intern(lit("lutimes"), user_package), func_n5(wrap_lutimes)); +#endif + reg_fun(intern(lit("stat"), user_package), func_n1(stat_wrap)); reg_fun(intern(lit("lstat"), user_package), func_n1(lstat_wrap)); reg_fun(intern(lit("fstat"), user_package), func_n1(fstat_wrap)); |