logo

utils-std

Collection of commonly available Unix tools git clone https://anongit.hacktivis.me/git/utils-std.git
commit: f5d3de45fe20ecf2c1fe97587b89c83ef2a20469
parent e5d158506c7001999b47fe5b21e187f7e8b0f0e9
Author: Haelwenn (lanodan) Monnier <contact@hacktivis.me>
Date:   Fri, 20 Sep 2024 18:35:36 +0200

cmd/mktemp: add support for -u

Diffstat:

Mcmd/mktemp.18++++++--
Mcmd/mktemp.c61+++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
2 files changed, 63 insertions(+), 6 deletions(-)

diff --git a/cmd/mktemp.1 b/cmd/mktemp.1 @@ -1,7 +1,7 @@ .\" utils-std: Collection of commonly available Unix tools .\" Copyright 2017 Haelwenn (lanodan) Monnier <contact+utils@hacktivis.me> .\" SPDX-License-Identifier: MPL-2.0 -.Dd 2024-07-30 +.Dd 2024-09-20 .Dt MKTEMP 1 .Os .Sh NAME @@ -9,7 +9,7 @@ .Nd make a new randomly-named file or directory .Sh SYNOPSIS .Nm -.Op Fl dqt +.Op Fl dqtu .Op Fl p Ar tempdir .Op Ar template .Sh DESCRIPTION @@ -46,6 +46,10 @@ Use or if unset, .Pa /tmp , as an existing directory to create into. +.It Fl u +Unsafe mode, generate filename and print it out without creating it. +.Pp +Only present for compatibility with existing scripts, do not use. .El .Sh EXIT STATUS .Ex -std diff --git a/cmd/mktemp.c b/cmd/mktemp.c @@ -2,26 +2,74 @@ // SPDX-FileCopyrightText: 2017 Haelwenn (lanodan) Monnier <contact+utils@hacktivis.me> // SPDX-License-Identifier: MPL-2.0 -#define _POSIX_C_SOURCE 200809L +// getentropy got in POSIX.1-2024 but defining _POSIX_C_SOURCE causes too much side-effects +#define _DEFAULT_SOURCE // getentropy + #include <errno.h> #include <limits.h> // PATH_MAX #include <stdbool.h> #include <stdio.h> // fprintf #include <stdlib.h> // getenv #include <string.h> // strerror -#include <unistd.h> // getopt +#include <unistd.h> // getopt, getentropy const char *argv0 = "mktemp"; +static int +unsafe_mktemp(char *template) +{ + size_t l = strlen(template); + + size_t len = 0; + size_t off = l - 1; + while(off > 0 && template[off] == 'X') + off--, len++; + + if(len < 6) + { + fprintf(stderr, + "%s: error: Template '%s' is invalid (need >= 6 final X, got %zd)\n", + argv0, + template, + len); + return 1; + } + + for(int retries = 100; 0 < retries; retries--) + { + unsigned long r = 0; + if(getentropy(&r, sizeof(r)) != 0) + { + fprintf(stderr, + "%s: error: Failed to get entropy for random filename: %s\n", + argv0, + strerror(errno)); + return 1; + } + + for(int i = len; i > 0; i--, r >>= 5) + template[off + i] = 'A' + (r & 15) + (r & 16) * 2; + + if(access(template, F_OK) != 0 && errno == ENOENT) + { + puts(template); + return 0; + } + } + + fprintf(stderr, "%s: error: Exhausted all 100 attempts at generating a filename\n", argv0); + return 1; +} + int main(int argc, char *argv[]) { - bool o_create_dir = false, o_quiet = false; + bool o_create_dir = false, o_quiet = false, o_unsafe = false; char template[PATH_MAX] = "tmp.XXXXXXXXXX"; const char *tmpdir = NULL; int c = -1; - while((c = getopt(argc, argv, ":dqp:t")) != -1) + while((c = getopt(argc, argv, ":dqp:tu")) != -1) { switch(c) { @@ -38,6 +86,9 @@ main(int argc, char *argv[]) if(tmpdir == NULL) tmpdir = getenv("TMPDIR"); if(tmpdir == NULL) tmpdir = "/tmp"; break; + case 'u': + o_unsafe = true; + break; case '?': fprintf(stderr, "%s: error: Unrecognised option: '-%c'\n", argv0, optopt); return 1; @@ -75,6 +126,8 @@ main(int argc, char *argv[]) printf("%s/", tmpdir); } + if(o_unsafe) return unsafe_mktemp(template); + if(o_create_dir) { char *dir = mkdtemp(template);