logo

utils

~/.local/bin tools and git-hooks git clone https://hacktivis.me/git/utils.git
commit: 2b7c2e96b970a727f4d3a5956dc6175a54af1c80
parent 7388639c77f0a4760932fcef994bf8aa7ff73aaf
Author: Haelwenn (lanodan) Monnier <contact@hacktivis.me>
Date:   Sat,  3 Jun 2023 11:18:59 +0200

cmd/touch: Use utimensat on directories

Diffstat:

Mcmd/touch.14+---
Mcmd/touch.c15++++++++++++++-
Mtest-cmd/touch14++++++++++++++
3 files changed, 29 insertions(+), 4 deletions(-)

diff --git a/cmd/touch.1 b/cmd/touch.1 @@ -78,9 +78,7 @@ is mostly compliant with the .St -p1003.1-2008 specification. .Fl t -is intentionally missing and -.Xr futimens 3 -is always used. +is intentionally missing. .Fl h is an extension. .Sh AUTHORS diff --git a/cmd/touch.c b/cmd/touch.c @@ -12,7 +12,7 @@ #include <stdio.h> /* perror, sscanf */ #include <stdlib.h> /* exit */ #include <string.h> /* memset */ -#include <sys/stat.h> /* futimens, stat */ +#include <sys/stat.h> /* futimens, stat, utimensat */ #include <time.h> /* strptime, tm */ #include <unistd.h> /* access */ @@ -83,6 +83,7 @@ main(int argc, char *argv[]) }; struct timespec target = {0, UTIME_NOW}; int open_flags = O_WRONLY | O_CREAT | O_NOCTTY; + int utimensat_flags = 0; int c = 0; while((c = getopt(argc, argv, ":achmr:t:d:")) != -1) @@ -97,6 +98,7 @@ main(int argc, char *argv[]) break; case 'h': open_flags |= O_NOFOLLOW; + utimensat_flags |= AT_SYMLINK_NOFOLLOW; break; case 'm': ch_mtime = true; @@ -161,7 +163,18 @@ main(int argc, char *argv[]) int fd = open(argv[i], open_flags, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); if(fd == -1) { + if(errno == EISDIR) + { + if(utimensat(AT_FDCWD, argv[i], times, utimensat_flags) != 0) + { + perror("touch: utimensat"); + return 1; + } + + return 0; + } if(errno != ENOENT) perror("touch: open"); + return 1; } diff --git a/test-cmd/touch b/test-cmd/touch @@ -122,6 +122,18 @@ ref_amtime_body() { atf_check -o "inline:$(./stat_mtime ../cmd/touch)\n" ./stat_mtime ./foo } +atf_test_case dir +dir_body() { + mkdir -p ./foo.d + atime="$(./stat_atime ./foo.d)" + mtime="$(./stat_mtime ./foo.d)" + + maybe_sleep + atf_check ../cmd/touch ./foo.d + atf_check -o "not-inline:${atime}\n" ./stat_atime ./foo.d + atf_check -o "not-inline:${mtime}\n" ./stat_mtime ./foo.d +} + atf_test_case optd optd_body() { atf_check touch -a ./foo @@ -171,6 +183,8 @@ atf_init_test_cases() { atf_add_test_case ref_mtime atf_add_test_case ref_amtime + atf_add_test_case dir + atf_add_test_case optd # No support for displaying fractional seconds on FreeBSD stat(1)