From 2040569f0aa0367b63123a0bc7a22e5ec2d77ec5 Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Fri, 26 Mar 2021 12:37:26 +0100 Subject: [PATCH] Add touchf(), formatted version of touch() Signed-off-by: Joachim Wiberg --- README.md | 4 +++ src/Makefile.am | 2 +- src/lite.h | 2 ++ src/touchf.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++++ tests/touch.c | 26 +++++++++++++++++-- 5 files changed, 97 insertions(+), 3 deletions(-) create mode 100644 src/touchf.c diff --git a/README.md b/README.md index 203bb15..64a65b0 100644 --- a/README.md +++ b/README.md @@ -110,6 +110,10 @@ Helper Macros Create a file, or update mtime. Errors on `stderr` +- `touchf(fmt, ...)` + + Like `touch()` but takes a formatted printf-like string as argument. + - `S_ISEXEC(mode_t m)` Mysteriously missing from GLIBC diff --git a/src/Makefile.am b/src/Makefile.am index 73576c5..3b3b286 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -14,7 +14,7 @@ libite_la_SOURCES = chomp.c copyfile.c \ reallocarray.c rsync.c \ strlcpy.c strlcat.c strtonum.c \ strdupa.h strndupa.h strnlen.h \ - strmatch.c systemf.c \ + strmatch.c systemf.c touchf.c \ telnet.c tempfile.c truncatef.c \ yorn.c which.c \ lite.h strlite.h \ diff --git a/src/lite.h b/src/lite.h index b64e596..fdfc23c 100644 --- a/src/lite.h +++ b/src/lite.h @@ -107,6 +107,8 @@ int telnet_close (sdbuf_t *ctx); int telnet_expect (sdbuf_t *ctx, char *script[], FILE *output); int telnet_session (int addr, short port, char *script[], FILE *output); +int touchf (const char *fmt, ...); + int yorn (const char *fmt, ...); char *which (const char *cmd); diff --git a/src/touchf.c b/src/touchf.c new file mode 100644 index 0000000..ab4c7d5 --- /dev/null +++ b/src/touchf.c @@ -0,0 +1,66 @@ +/* Formatted touch() + * + * Copyright (c) 2021 Joachim Wiberg + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include + +#include "lite.h" + +/** + * touchf - Like touch() but with formatted string support + * @fmt: Formatted string to be composed into a pathname + * + * This is a wrapper for the touch() function in lite.h, lessening the + * burden of having to compose the filename from parts in a seprate + * buffer. + * + * Returns: + * Upon successful completion touchf() returns POSIX OK(0), otherwise, + * -1 is returned and errno is set to indicate the error. + */ +int touchf(const char *fmt, ...) +{ + va_list ap; + char *file; + int len; + + va_start(ap, fmt); + len = vsnprintf(NULL, 0, fmt, ap); + va_end(ap); + + file = alloca(len + 1); + if (!file) { + errno = ENOMEM; + return -1; + } + + va_start(ap, fmt); + vsnprintf(file, len + 1, fmt, ap); + va_end(ap); + + return touch(file); +} + +/** + * Local Variables: + * indent-tabs-mode: t + * c-file-style: "linux" + * End: + */ diff --git a/tests/touch.c b/tests/touch.c index 6300ff9..e11e3e8 100644 --- a/tests/touch.c +++ b/tests/touch.c @@ -6,6 +6,8 @@ #include "check.h" +#define FMT "%s-bar" + int verbose = 0; @@ -32,10 +34,30 @@ static int mtime(char *file) ret = timespec_newer(&after.st_mtim, &before.st_mtim); PRINT("Before: %s\n", timespec2str(&before.st_mtim, buf, sizeof(buf))); PRINT("After : %s\n", timespec2str(&after.st_mtim, buf, sizeof(buf))); + erase(file); return !ret; } +static int formatted(char *file) +{ + char vrfy[80]; + + if (touchf(FMT, file)) + err(1, "Failed creating " FMT, file); + + PRINT("Created " FMT "\n", file); + + snprintf(vrfy, sizeof(vrfy), FMT, file); + if (!fexist(vrfy)) + errx(1, "touchf() does not detect failure to create file " FMT, file); + + PRINT("File " FMT " really does exist!\n", file); + erase(vrfy); + + return 0; +} + int main(int argc, char *argv[]) { int fd; @@ -49,13 +71,13 @@ int main(int argc, char *argv[]) err(1, "Failed creating tempfile, %s", file); close(fd); - return mtime(file); + return mtime(file) || formatted(file); } /** * Local Variables: * indent-tabs-mode: t * c-file-style: "linux" - * compile-command: "make pidfile && ./pidfile -v" + * compile-command: "make touch && ./touch -v" * End: */