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:
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);