[PATCH 1/3] touch: implement nanosecond precision times
Xabier Oneca -- xOneca
xoneca at gmail.com
Mon Apr 12 21:31:16 UTC 2021
Using utimensat(2) allows us to set times in nanosecond precision. Also logic is
simplified and code shrinked.
function old new delta
touch_main 513 479 -34
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 0/1 up/down: 0/-34) Total: -34 bytes
Signed-off-by: Xabier Oneca <xoneca at gmail.com>
---
coreutils/touch.c | 65 +++++++++++++++++++++--------------------------
1 file changed, 29 insertions(+), 36 deletions(-)
diff --git a/coreutils/touch.c b/coreutils/touch.c
index 690517e66..a00ee0ba4 100644
--- a/coreutils/touch.c
+++ b/coreutils/touch.c
@@ -25,7 +25,6 @@
//config: depends on TOUCH
//config: help
//config: Enable touch to have the -h option.
-//config: This requires libc support for lutimes() function.
//config:
//config:config FEATURE_TOUCH_SUSV3
//config: bool "Add support for SUSV3 features (-a -d -m -t -r)"
@@ -98,7 +97,7 @@ int touch_main(int argc UNUSED_PARAM, char **argv)
OPT_m = (1 << (5+ENABLE_FEATURE_TOUCH_NODEREF)) *
ENABLE_FEATURE_TOUCH_SUSV3,
};
/* NULL = use current time */
- const struct timeval *newtime = NULL;
+ const struct timespec *newtime = NULL;
#if ENABLE_LONG_OPTS
static const char touch_longopts[] ALIGN1 =
/* name, has_arg, val */
@@ -112,12 +111,13 @@ int touch_main(int argc UNUSED_PARAM, char **argv)
char *reference_file = NULL;
char *date_str = NULL;
/* timebuf[0] is atime, timebuf[1] is mtime */
- struct timeval timebuf[2];
- timebuf[1].tv_usec = timebuf[0].tv_usec = 0;
+ struct timespec timebuf[2];
+ //timebuf[0].tv_sec = timebuf[1].tv_sec = 0; /* -- needed on
Linux <=v2.6.26? */
+ timebuf[0].tv_nsec = timebuf[1].tv_nsec = UTIME_NOW;
#else
# define reference_file NULL
# define date_str NULL
-# define timebuf ((struct timeval*)NULL)
+# define timebuf NULL
#endif
/* -d and -t both set time. In coreutils,
@@ -143,12 +143,11 @@ int touch_main(int argc UNUSED_PARAM, char **argv)
if (reference_file) {
struct stat stbuf;
xstat(reference_file, &stbuf);
- timebuf[0].tv_sec = stbuf.st_atime;
- timebuf[1].tv_sec = stbuf.st_mtime;
- /* Can use .st_mtim.tv_nsec
- * (or is it .st_mtimensec?? see date.c)
- * to set microseconds too.
+ /* NOTE: Some toolchains use .st_atime and .st_atimensec instead of
+ * .st_atim.
*/
+ memcpy(&timebuf[0], &stbuf.st_atim, sizeof(timebuf[0]));
+ memcpy(&timebuf[1], &stbuf.st_mtim, sizeof(timebuf[1]));
newtime = timebuf;
}
@@ -166,39 +165,33 @@ int touch_main(int argc UNUSED_PARAM, char **argv)
tm_time.tm_isdst = -1; /* Be sure to recheck dst */
t = validate_tm_time(date_str, &tm_time);
- timebuf[1].tv_sec = timebuf[0].tv_sec = t;
+ /* atime */
+ timebuf[0].tv_sec = t;
+ timebuf[0].tv_nsec = 0;
+
+ /* mtime */
+ timebuf[1].tv_sec = t;
+ timebuf[1].tv_nsec = 0;
+
newtime = timebuf;
}
- if ((opts & (OPT_a | OPT_m)) && !newtime) {
- time(&timebuf[0].tv_sec);
- timebuf[1].tv_sec = timebuf[0].tv_sec;
+ if ((opts & OPT_a) && !(opts & OPT_m)) {
+ /* only -a: do not update mtime */
+ //timebuf[1].tv_sec = 0;
+ timebuf[1].tv_nsec = UTIME_OMIT;
+ newtime = timebuf;
+ } else if ((opts & OPT_m) && !(opts & OPT_a)) {
+ /* only -m: do not update atime */
+ //timebuf[0].tv_sec = 0;
+ timebuf[0].tv_nsec = UTIME_OMIT;
newtime = timebuf;
}
do {
int result;
- if (opts & (OPT_a | OPT_m)) {
- /* Save original times */
- struct stat stbuf;
- if (stat(*argv, &stbuf) == 0) {
- /* As we must set both times, we lose original
- * file time microseconds.
- * Can use .st_mtim.tv_nsec
- * (or is it .st_mtimensec?? see date.c)
- * to set microseconds too.
- * Also, utimensat(2) allows to omit one of the
- * times to be set. But it is SUSv4.
- */
- if (!(opts & OPT_a))
- timebuf[0].tv_sec = stbuf.st_atime;
- if (!(opts & OPT_m))
- timebuf[1].tv_sec = stbuf.st_mtime;
- }
- }
-
- result = (ENABLE_FEATURE_TOUCH_NODEREF && (opts & OPT_h) ?
lutimes : utimes)(*argv, newtime);
+ result = utimensat(AT_FDCWD, *argv, newtime, (opts & OPT_h) ?
AT_SYMLINK_NOFOLLOW : 0);
if (result != 0) {
if (errno == ENOENT) { /* no such file? */
@@ -209,9 +202,9 @@ int touch_main(int argc UNUSED_PARAM, char **argv)
/* Try to create the file */
fd = open(*argv, O_RDWR | O_CREAT, 0666);
if (fd >= 0) {
- xclose(fd);
if (reference_file || date_str)
- utimes(*argv, newtime);
+ futimens(fd, newtime);
+ xclose(fd);
continue;
}
}
--
2.30.2
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0001-touch-implement-nanosecond-precision-times.patch
Type: application/x-patch
Size: 4845 bytes
Desc: not available
URL: <http://lists.busybox.net/pipermail/busybox/attachments/20210412/c2688907/attachment-0001.bin>
More information about the busybox
mailing list