Hello, Roland, Flávio worked on adding a file_utimens RPC, which handles nanosecond-precision utimes, as well as implementing UTIME_NOW and UTIME_OMIT, here is first the RPC definition and documentation:
diff --git a/hurd/fs.defs b/hurd/fs.defs index a4a48cc..171e43f 100644 --- a/hurd/fs.defs +++ b/hurd/fs.defs @@ -371,3 +371,13 @@ routine file_get_source ( file: file_t; RPT out source: string_t); + +/* Change access and modify times with nanosecond precision */ +/* If the nanoseconds value is UTIME_NOW then the time should be + set to the current time and the remainder of the time_value_t ignored. + If the nanoseconds value is UTIME_OMIT then the time is ignored. */ +routine file_utimens ( + utimes_file: file_t; + RPT + new_atime: timespec_t; + new_mtime: timespec_t); diff --git a/doc/hurd.texi b/doc/hurd.texi index 2f36bdc..26e51e1 100644 --- a/doc/hurd.texi +++ b/doc/hurd.texi @@ -2723,6 +2723,14 @@ the file. Making this call must cause the @var{ctime} to be updated as well, even if no actual change to either the @var{mtime} or the @var{atime} occurs. +@findex file_utimens +The @code{file_utimens} RPC changes the @var{atime} and @var{mtime} of +the file with nanosecond precision. Making this call must cause the +@var{ctime} to be updated as well, even if no actual change to either the +@var{mtime} or the @var{atime} occurs. The arguments @var{atime} and +@var{mtime} follow the POSIX standard and may use the flags +@code{UTIME_OMIT} and @code{UTIME_NOW}. + @findex file_set_size The @code{file_set_size} RPC is special; not only does it change the status word specifying the size of the file, but it also changes the Any objection to this? The entailed glibc changes are below. Samuel 2015-09-20 Flávio Cruz <flavioc...@gmail.com> Define and pass UTIME_NOW and UTIME_OMIT to new file_utimens RPC. * sysdeps/mach/hurd/bits/stat.h (UTIME_NOW, UTIME_OMIT): New macros. * sysdeps/mach/hurd/futimens.c (__futimens): Convert `tsp' to struct timespec to try to use the file_utimens RPC, before rolling back to using file_utimes. * sysdeps/mach/hurd/futimes (__futimes): Likewise. * sysdeps/mach/hurd/lutimes (__lutimes): Likewise. * sysdeps/mach/hurd/utimes (__utimes): Likewise. diff --git a/sysdeps/mach/hurd/bits/stat.h b/sysdeps/mach/hurd/bits/stat.h index f60a58a..c2d0cc2 100644 --- a/sysdeps/mach/hurd/bits/stat.h +++ b/sysdeps/mach/hurd/bits/stat.h @@ -246,6 +246,10 @@ struct stat64 # define SF_NOUNLINK 0x00100000 /* file may not be removed or renamed */ # define SF_SNAPSHOT 0x00200000 /* snapshot inode */ +/* Time flags for futimens. */ +#define UTIME_NOW -1 /* corresponds to the current time */ +#define UTIME_OMIT -2 /* target time is omitted */ + __BEGIN_DECLS /* Set file flags for FILE to FLAGS. */ diff --git a/sysdeps/mach/hurd/futimens.c b/sysdeps/mach/hurd/futimens.c index 4f82f1e..3159cb0 100644 --- a/sysdeps/mach/hurd/futimens.c +++ b/sysdeps/mach/hurd/futimens.c @@ -27,24 +27,51 @@ int __futimens (int fd, const struct timespec tsp[2]) { - time_value_t atime, mtime; + struct timespec atime, mtime; error_t err; if (tsp == NULL) { - /* Setting the number of microseconds to `-1' tells the + /* Setting the number of nanoseconds to UTIME_NOW tells the underlying filesystems to use the current time. */ - atime.microseconds = mtime.microseconds = -1; + atime.tv_sec = 0; + atime.tv_nsec = UTIME_NOW; + mtime.tv_sec = 0; + mtime.tv_nsec = UTIME_NOW; } else { - atime.seconds = tsp[0].tv_sec; - atime.microseconds = tsp[0].tv_nsec / 1000; - mtime.seconds = tsp[1].tv_sec; - mtime.microseconds = tsp[1].tv_nsec / 1000; + atime = tsp[0]; + mtime = tsp[1]; } - err = HURD_DPORT_USE (fd, __file_utimes (port, atime, mtime)); + err = HURD_DPORT_USE (fd, __file_utimens (port, atime, mtime)); + + if (err == MIG_BAD_ID || err == EOPNOTSUPP) + { + time_value_t atim, mtim; + + if (tsp == NULL) + /* Setting the number of microseconds to `-1' tells the + underlying filesystems to use the current time. */ + atim.microseconds = mtim.microseconds = -1; + else if (tsp[0].tv_nsec == UTIME_OMIT || tsp[1].tv_nsec == UTIME_OMIT) + return EOPNOTSUPP; + else + { + if (tsp[0].tv_nsec == UTIME_NOW) + atim.microseconds = -1; + else + TIMESPEC_TO_TIME_VALUE (&atim, &(tsp[0])); + if (tsp[1].tv_nsec == UTIME_NOW) + mtim.microseconds = -1; + else + TIMESPEC_TO_TIME_VALUE (&mtim, &(tsp[1])); + } + + err = HURD_DPORT_USE (fd, __file_utimes (port, atim, mtim)); + } + return err ? __hurd_dfail (fd, err) : 0; } weak_alias (__futimens, futimens) diff --git a/sysdeps/mach/hurd/futimes.c b/sysdeps/mach/hurd/futimes.c index c325d44..dc8ae61 100644 --- a/sysdeps/mach/hurd/futimes.c +++ b/sysdeps/mach/hurd/futimes.c @@ -27,24 +27,44 @@ int __futimes (int fd, const struct timeval tvp[2]) { - union tv - { - struct timeval tv; - time_value_t tvt; - }; - const union tv *u = (const union tv *) tvp; - union tv nulltv[2]; + struct timespec atime, mtime; error_t err; if (tvp == NULL) { - /* Setting the number of microseconds to `-1' tells the + /* Setting the number of nanoseconds to UTIME_NOW tells the underlying filesystems to use the current time. */ - nulltv[0].tvt.microseconds = nulltv[1].tvt.microseconds = -1; - u = nulltv; + atime.tv_sec = 0; + atime.tv_nsec = UTIME_NOW; + mtime.tv_sec = 0; + mtime.tv_nsec = UTIME_NOW; + } + else + { + TIMEVAL_TO_TIMESPEC (&tvp[0], &atime); + TIMEVAL_TO_TIMESPEC (&tvp[1], &mtime); + } + + err = HURD_DPORT_USE (fd, __file_utimens (port, atime, mtime)); + if (err == EMIG_BAD_ID || err == EOPNOTSUPP) + { + time_value_t atim, mtim; + + if (tvp == NULL) + /* Setting the number of microseconds to `-1' tells the + underlying filesystems to use the current time. */ + atim.microseconds = mtim.microseconds = -1; + else + { + atim.seconds = tvp[0].tv_sec; + atim.microseconds = tvp[0].tv_usec; + mtim.seconds = tvp[1].tv_sec; + mtim.microseconds = tvp[1].tv_usec; + } + + err = HURD_DPORT_USE (fd, __file_utimes (port, atim, mtim)); } - err = HURD_DPORT_USE (fd, __file_utimes (port, u[0].tvt, u[1].tvt)); return err ? __hurd_dfail (fd, err) : 0; } weak_alias (__futimes, futimes) diff --git a/sysdeps/mach/hurd/lutimes.c b/sysdeps/mach/hurd/lutimes.c index 260842d..c1d5566 100644 --- a/sysdeps/mach/hurd/lutimes.c +++ b/sysdeps/mach/hurd/lutimes.c @@ -27,28 +27,50 @@ int __lutimes (const char *file, const struct timeval tvp[2]) { - union tv - { - struct timeval tv; - time_value_t tvt; - }; - const union tv *u = (const union tv *) tvp; - union tv nulltv[2]; + struct timespec atime, mtime; error_t err; file_t port; + port = __file_name_lookup (file, O_NOLINK, 0); + if (port == MACH_PORT_NULL) + return -1; + if (tvp == NULL) { - /* Setting the number of microseconds to `-1' tells the + /* Setting the number of nanoseconds to UTIME_NOW tells the underlying filesystems to use the current time. */ - nulltv[0].tvt.microseconds = nulltv[1].tvt.microseconds = -1; - u = nulltv; + atime.tv_sec = 0; + atime.tv_nsec = UTIME_NOW; + mtime.tv_sec = 0; + mtime.tv_nsec = UTIME_NOW; + } + else + { + TIMEVAL_TO_TIMESPEC (&tvp[0], &atime); + TIMEVAL_TO_TIMESPEC (&tvp[1], &mtime); + } + + err = __file_utimens (port, atime, mtime); + + if (err == MIG_BAD_ID || err == EOPNOTSUPP) + { + time_value_t atim, mtim; + + if (tvp == NULL) + /* Setting the number of microseconds to `-1' tells the + underlying filesystems to use the current time. */ + atim.microseconds = mtim.microseconds = -1; + else + { + atim.seconds = tvp[0].tv_sec; + atim.microseconds = tvp[0].tv_usec; + mtim.seconds = tvp[1].tv_sec; + mtim.microseconds = tvp[1].tv_usec; + } + + err = __file_utimes (port, atim, mtim); } - port = __file_name_lookup (file, O_NOLINK, 0); - if (port == MACH_PORT_NULL) - return -1; - err = __file_utimes (port, u[0].tvt, u[1].tvt); __mach_port_deallocate (__mach_task_self (), port); if (err) return __hurd_fail (err); diff --git a/sysdeps/mach/hurd/utimes.c b/sysdeps/mach/hurd/utimes.c index 6739b79..1578637 100644 --- a/sysdeps/mach/hurd/utimes.c +++ b/sysdeps/mach/hurd/utimes.c @@ -27,28 +27,50 @@ __utimes (file, tvp) const char *file; const struct timeval tvp[2]; { - union tv - { - struct timeval tv; - time_value_t tvt; - }; - const union tv *u = (const union tv *) tvp; - union tv nulltv[2]; + struct timespec atime, mtime; error_t err; file_t port; + port = __file_name_lookup (file, 0, 0); + if (port == MACH_PORT_NULL) + return -1; + if (tvp == NULL) { - /* Setting the number of microseconds to `-1' tells the + /* Setting the number of nanoseconds to UTIME_NOW tells the underlying filesystems to use the current time. */ - nulltv[0].tvt.microseconds = nulltv[1].tvt.microseconds = -1; - u = nulltv; + atime.tv_sec = 0; + atime.tv_nsec = UTIME_NOW; + mtime.tv_sec = 0; + mtime.tv_nsec = UTIME_NOW; + } + else + { + TIMEVAL_TO_TIMESPEC (&tvp[0], &atime); + TIMEVAL_TO_TIMESPEC (&tvp[1], &mtime); + } + + err = __file_utimens (port, atime, mtime); + + if (err == MIG_BAD_ID || err == EOPNOTSUPP) + { + time_value_t atim, mtim; + + if (tvp == NULL) + /* Setting the number of microseconds to `-1' tells the + underlying filesystems to use the current time. */ + atim.microseconds = mtim.microseconds = -1; + else + { + atim.seconds = tvp[0].tv_sec; + atim.microseconds = tvp[0].tv_usec; + mtim.seconds = tvp[1].tv_sec; + mtim.microseconds = tvp[1].tv_usec; + } + + err = __file_utimes (port, atim, mtim); } - port = __file_name_lookup (file, 0, 0); - if (port == MACH_PORT_NULL) - return -1; - err = __file_utimes (port, u[0].tvt, u[1].tvt); __mach_port_deallocate (__mach_task_self (), port); if (err) return __hurd_fail (err);