From e9a910b33c7837b4b868e3abda18eb4810df7f02 Mon Sep 17 00:00:00 2001 From: Leah Rowe Date: Sat, 4 Oct 2025 09:14:33 +0100 Subject: config/git: import suckless sbase i currently use the output of sha512sum in several places of xbmk, which is a bit unreliable in case output changes. other cases where i use util outputs in variables are probably reliable, because i'm using mostly posix utilities in those. to mitigate this, i now import suckless sbase, which has a reasonable sha512sum implementation. *every* binary it builds is being placed in build.list, because i'll probably start using more of them. for example, i may start modifying the "date" implementation, adding the GNU-specific options that i need as mentioned on init.sh i'm importing it in util/ because the sha512sum util is needed for verifying project sources, so if sbase itself is a "project source", that means we can into a chicken and egg bootstrapping problem. this is sbase at revision: 055cc1ae1b3a13c3d8f25af0a4a3316590efcd48 Signed-off-by: Leah Rowe --- util/sbase/touch.c | 159 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 159 insertions(+) create mode 100644 util/sbase/touch.c (limited to 'util/sbase/touch.c') diff --git a/util/sbase/touch.c b/util/sbase/touch.c new file mode 100644 index 00000000..6e63bf80 --- /dev/null +++ b/util/sbase/touch.c @@ -0,0 +1,159 @@ +/* See LICENSE file for copyright and license details. */ +#include + +#include +#include +#include +#include +#include +#include + +#include "util.h" + +static int aflag; +static int cflag; +static int mflag; +static struct timespec times[2] = {{.tv_nsec = UTIME_NOW}}; + +static void +touch(const char *file) +{ + int fd, ret; + + if (utimensat(AT_FDCWD, file, times, 0) == 0) + return; + if (errno != ENOENT) + eprintf("utimensat %s:", file); + if (cflag) + return; + if ((fd = open(file, O_WRONLY | O_CREAT | O_EXCL, 0666)) < 0) + eprintf("open %s:", file); + ret = futimens(fd, times); + close(fd); + if (ret < 0) + eprintf("futimens %s:", file); +} + +static time_t +parsetime(char *str) +{ + time_t now; + struct tm *cur, t = { 0 }; + int zulu = 0; + char *format; + size_t len = strlen(str); + + if ((now = time(NULL)) == -1) + eprintf("time:"); + if (!(cur = localtime(&now))) + eprintf("localtime:"); + t.tm_isdst = -1; + + switch (len) { + /* -t flag argument */ + case 8: + t.tm_year = cur->tm_year; + format = "%m%d%H%M"; + break; + case 10: + format = "%y%m%d%H%M"; + break; + case 11: + t.tm_year = cur->tm_year; + format = "%m%d%H%M.%S"; + break; + case 12: + format = "%Y%m%d%H%M"; + break; + case 13: + format = "%y%m%d%H%M.%S"; + break; + case 15: + format = "%Y%m%d%H%M.%S"; + break; + /* -d flag argument */ + case 19: + format = "%Y-%m-%dT%H:%M:%S"; + break; + case 20: + /* only Zulu-timezone supported */ + if (str[19] != 'Z') + eprintf("Invalid time zone\n"); + str[19] = 0; + zulu = 1; + format = "%Y-%m-%dT%H:%M:%S"; + break; + default: + eprintf("Invalid date format length\n", str); + } + + if (!strptime(str, format, &t)) + eprintf("strptime %s: Invalid date format\n", str); + if (zulu) { + t.tm_hour += t.tm_gmtoff / 60; + t.tm_gmtoff = 0; + t.tm_zone = "Z"; + } + + return mktime(&t); +} + +static void +usage(void) +{ + eprintf("usage: %s [-acm] [-d time | -r ref_file | -t time | -T time] " + "file ...\n", argv0); +} + +int +main(int argc, char *argv[]) +{ + struct stat st; + char *ref = NULL; + + ARGBEGIN { + case 'a': + aflag = 1; + break; + case 'c': + cflag = 1; + break; + case 'd': + case 't': + times[0].tv_sec = parsetime(EARGF(usage())); + times[0].tv_nsec = 0; + break; + case 'm': + mflag = 1; + break; + case 'r': + ref = EARGF(usage()); + if (stat(ref, &st) < 0) + eprintf("stat '%s':", ref); + times[0] = st.st_atim; + times[1] = st.st_mtim; + break; + case 'T': + times[0].tv_sec = estrtonum(EARGF(usage()), 0, LLONG_MAX); + times[0].tv_nsec = 0; + break; + default: + usage(); + } ARGEND + + if (!argc) + usage(); + if (!aflag && !mflag) + aflag = mflag = 1; + if (!ref) + times[1] = times[0]; + if (!aflag) + times[0].tv_nsec = UTIME_OMIT; + if (!mflag) + times[1].tv_nsec = UTIME_OMIT; + + for (; *argv; argc--, argv++) + touch(*argv); + + return 0; +} -- cgit v1.2.1