logo

utils

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

cmd/touch: Split iso_parse to lib/iso_parse.c

Diffstat:

M.gitignore1+
MMakefile6+++++-
Mcmd/touch.c69+++++----------------------------------------------------------------
Alib/iso_parse.c68++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Alib/iso_parse.h6++++++
5 files changed, 85 insertions(+), 65 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -8,6 +8,7 @@ !/cmd/*.ha !/cmd/*.1 *.t.err +*.o # Kyua /html/ diff --git a/Makefile b/Makefile @@ -49,7 +49,7 @@ cmd-install: coverage: $(GCOV) -b $(EXE) -C_SOURCES = cmd/*.c +C_SOURCES = cmd/*.c lib/*.h lib/*.c format: $(C_SOURCES) clang-format -style=file -assume-filename=.clang-format -i $(C_SOURCES) @@ -72,3 +72,7 @@ cmd/strings: cmd/strings.c Makefile cmd/sleep: cmd/sleep.c Makefile rm -f ${<:=.gcov} ${@:=.gcda} ${@:=.gcno} $(CC) -std=c99 $(CFLAGS) $(LIBBSD_CFLAGS) -o $@ cmd/sleep.c $(LIBBSD_LIBS) $(LDFLAGS) + +cmd/touch: cmd/touch.c lib/iso_parse.c Makefile + rm -f ${<:=.gcov} ${@:=.gcda} ${@:=.gcno} + $(CC) -std=c99 $(CFLAGS) -o $@ cmd/touch.c lib/iso_parse.c $(LDFLAGS) diff --git a/cmd/touch.c b/cmd/touch.c @@ -2,75 +2,16 @@ // SPDX-FileCopyrightText: 2023 Haelwenn (lanodan) Monnier <contact+utils@hacktivis.me> // SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only -#define _DEFAULT_SOURCE // tm_gmtoff/tm_zone -#define _XOPEN_SOURCE 700 // strptime (NetBSD) -#define _POSIX_C_SOURCE 200809L // O_NOFOLLOW, st_atim/st_mtim +#define _POSIX_C_SOURCE 200809L // O_NOFOLLOW + +#include "../lib/iso_parse.h" /* iso_parse */ #include <errno.h> /* errno */ #include <fcntl.h> /* open */ #include <stdbool.h> /* bool */ -#include <stdio.h> /* perror, sscanf */ -#include <stdlib.h> /* exit */ -#include <string.h> /* memset */ +#include <stdio.h> /* perror */ #include <sys/stat.h> /* futimens, stat, utimensat */ -#include <time.h> /* strptime, tm */ -#include <unistd.h> /* access */ - -// Calls exit() on failure -struct timespec -iso_parse(char *arg) -{ - // YYYY-MM-DD[T ]hh:mm:SS([,\.]frac)?Z? - // Dammit Unixes why no nanoseconds in `struct tm` nor `strptime` - struct timespec time = {.tv_sec = 0, .tv_nsec = 0}; - - // For Alpine's abuild compatibility - if(arg[0] == '@') - { - arg++; - if(sscanf(arg, "%ld", &time.tv_sec) < 1) exit(EXIT_FAILURE); - return time; - } - - struct tm tm; - memset(&tm, 0, sizeof(tm)); - - // No %F in POSIX - char *s = strptime(arg, "%Y-%m-%d", &tm); - - if(s[0] != 'T' && s[0] != ' ') exit(EXIT_FAILURE); - s++; - - s = strptime(s, "%H:%M:%S", &tm); - - if(s[0] == ',' || s[0] == '.') - { - float fraction = 0.0; - int parsed = 0; - - if(s[0] == ',') s[0] = '.'; - - if(sscanf(s, "%f%n", &fraction, &parsed) < 1) exit(EXIT_FAILURE); - - time.tv_nsec = fraction * 1000000000; - s += parsed; - } - - if(s[0] == 'Z') - { - tm.tm_gmtoff = 0; - tm.tm_zone = "UTC"; - } - - time.tv_sec = mktime(&tm); - if(time.tv_sec == (time_t)-1) - { - perror("touch: mktime"); - exit(EXIT_FAILURE); - } - - return time; -} +#include <unistd.h> /* getopt, opt*, close */ int main(int argc, char *argv[]) diff --git a/lib/iso_parse.c b/lib/iso_parse.c @@ -0,0 +1,68 @@ +// Collection of Unix tools, comparable to coreutils +// SPDX-FileCopyrightText: 2023 Haelwenn (lanodan) Monnier <contact+utils@hacktivis.me> +// SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only + +#define _DEFAULT_SOURCE // tm_gmtoff/tm_zone +#define _XOPEN_SOURCE 700 // strptime (NetBSD) +#define _POSIX_C_SOURCE 200809L // st_atim/st_mtim + +#include <stdio.h> /* perror, sscanf */ +#include <stdlib.h> /* exit */ +#include <string.h> /* memset */ +#include <time.h> /* strptime, tm */ + +// Calls exit() on failure +struct timespec +iso_parse(char *arg) +{ + // YYYY-MM-DD[T ]hh:mm:SS([,\.]frac)?Z? + // Dammit Unixes why no nanoseconds in `struct tm` nor `strptime` + struct timespec time = {.tv_sec = 0, .tv_nsec = 0}; + + // For Alpine's abuild compatibility + if(arg[0] == '@') + { + arg++; + if(sscanf(arg, "%ld", &time.tv_sec) < 1) exit(EXIT_FAILURE); + return time; + } + + struct tm tm; + memset(&tm, 0, sizeof(tm)); + + // No %F in POSIX + char *s = strptime(arg, "%Y-%m-%d", &tm); + + if(s[0] != 'T' && s[0] != ' ') exit(EXIT_FAILURE); + s++; + + s = strptime(s, "%H:%M:%S", &tm); + + if(s[0] == ',' || s[0] == '.') + { + float fraction = 0.0; + int parsed = 0; + + if(s[0] == ',') s[0] = '.'; + + if(sscanf(s, "%f%n", &fraction, &parsed) < 1) exit(EXIT_FAILURE); + + time.tv_nsec = fraction * 1000000000; + s += parsed; + } + + if(s[0] == 'Z') + { + tm.tm_gmtoff = 0; + tm.tm_zone = "UTC"; + } + + time.tv_sec = mktime(&tm); + if(time.tv_sec == (time_t)-1) + { + perror("mktime"); + exit(EXIT_FAILURE); + } + + return time; +} diff --git a/lib/iso_parse.h b/lib/iso_parse.h @@ -0,0 +1,6 @@ +// Collection of Unix tools, comparable to coreutils +// SPDX-FileCopyrightText: 2023 Haelwenn (lanodan) Monnier <contact+utils@hacktivis.me> +// SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only + +#include <time.h> /* struct timespec */ +extern struct timespec iso_parse(char *);