logo

utils-std

Collection of commonly available Unix tools
commit: 4cfef864133f164256fae611eeb598c66d3f10a1
parent 73090d1f5b34a8eaf35423037b1cf8ce8559c5a9
Author: Haelwenn (lanodan) Monnier <contact@hacktivis.me>
Date:   Tue, 30 Jul 2024 14:52:05 +0200

cmd/mktemp: new

Diffstat:

Acmd/mktemp.155+++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acmd/mktemp.c99+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mcoreutils.txt2+-
Mlsb_commands.txt2+-
Mtest-cmd/Kyuafile1+
Atest-cmd/mktemp.sh69+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
6 files changed, 226 insertions(+), 2 deletions(-)

diff --git a/cmd/mktemp.1 b/cmd/mktemp.1 @@ -0,0 +1,55 @@ +.\" 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 +.Dt MKTEMP 1 +.Os +.Sh NAME +.Nm mktemp +.Nd make a new randomly-named file or directory +.Sh SYNOPSIS +.Nm +.Op Fl dqt +.Op Fl p Ar tempdir +.Op Ar template +.Sh DESCRIPTION +.Nm +creates a new randomly-named file or directory, +and prints its name. +.Pp +.Ar template +must contain at least 6 consecutive +.Ql X +as last path component. +If +.Ar template +is not specified, +.Ql tmp.XXXXXXXXXX +is used instead. +.br +Files are created with u+rw permissions, directories with u+rwx. +.Sh OPTIONS +.Bl -tag -width _d +.It Fl d +Create a directory, not a file. +.It Fl q +Quiet messages about file/directory creation failure. +.It Fl p Ar tempdir +Specify +.Ar tempdir +as an existing directory to create into. +Overrides +.Ev TMPDIR . +.It Fl t +Use +.Ev TMPDIR +or if unset, +.Pa /tmp , +as an existing directory to create into. +.El +.Sh EXIT STATUS +.Ex -std +.Sh STANDARDS +None known. +.Sh AUTHORS +.An Haelwenn (lanodan) Monnier Aq Mt contact+utils@hacktivis.me diff --git a/cmd/mktemp.c b/cmd/mktemp.c @@ -0,0 +1,99 @@ +// utils-std: Collection of commonly available Unix tools +// SPDX-FileCopyrightText: 2017 Haelwenn (lanodan) Monnier <contact+utils@hacktivis.me> +// SPDX-License-Identifier: MPL-2.0 + +#define _POSIX_C_SOURCE 200809L +#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 + +int +main(int argc, char *argv[]) +{ + bool o_create_dir = false, o_quiet = false; + char template[PATH_MAX] = "tmp.XXXXXXXXXX"; + char *tmpdir = NULL; + + int c = -1; + while((c = getopt(argc, argv, ":dqp:t")) != -1) + { + switch(c) + { + case 'd': + o_create_dir = true; + break; + case 'q': + o_quiet = true; + break; + case 'p': + tmpdir = optarg; + break; + case 't': + if(tmpdir == NULL) tmpdir = getenv("TMPDIR"); + if(tmpdir == NULL) tmpdir = "/tmp"; + break; + default: + abort(); + } + } + + argc -= optind; + argv += optind; + + if(argc == 1) + { + strncpy(template, *argv, PATH_MAX); + } + else if(argc > 1) + { + fprintf(stderr, "mktemp: Only one template argument is supported, got %d\n", argc); + return 1; + } + + if(tmpdir) + { + if(chdir(tmpdir) < 0) + { + fprintf(stderr, + "mktemp: Failed changing directory into tmpdir '%s': %s\n", + tmpdir, + strerror(errno)); + return 1; + } + } + + if(o_create_dir) + { + char *dir = mkdtemp(template); + if(dir == NULL) + { + fprintf(stderr, "mktemp: Failed creating random directory: %s\n", strerror(errno)); + return 1; + } + + puts(dir); + + return 0; + } + + int fd = mkstemp(template); + if(fd < 0) + { + fprintf(stderr, "mktemp: Failed creating random file: %s\n", strerror(errno)); + return 1; + } + + puts(template); + + if(close(fd) < 0) + { + fprintf(stderr, "mktemp: Failed closing file descriptor: %s\n", strerror(errno)); + return 1; + } + + return 0; +} diff --git a/coreutils.txt b/coreutils.txt @@ -46,7 +46,7 @@ md5sum: No mkdir: Done mkfifo: Done mknod: Done -mktemp: Todo +mktemp: Done mv nice: Done nl: No, use sed diff --git a/lsb_commands.txt b/lsb_commands.txt @@ -80,7 +80,7 @@ md5sum: No mkdir: Done mkfifo: Done mknod: Done -mktemp: Todo +mktemp: Done more: No mount: out of scope msgfmt: out of scope diff --git a/test-cmd/Kyuafile b/test-cmd/Kyuafile @@ -25,6 +25,7 @@ tap_test_program{name="head.sh", required_files=basedir.."/cmd/head", timeout=1} tap_test_program{name="id.sh", required_files=basedir.."/cmd/id", timeout=1} tap_test_program{name="link.sh", required_files=basedir.."/cmd/link", timeout=1} tap_test_program{name="logname.sh", required_files=basedir.."/cmd/logname", timeout=1} +tap_test_program{name="mktemp.sh", required_files=basedir.."/cmd/mktemp", timeout=1} tap_test_program{name="pwd.sh", required_files=basedir.."/cmd/pwd", timeout=1} tap_test_program{name="realpath.sh", required_files=basedir.."/cmd/realpath", timeout=1} tap_test_program{name="seq.sh", required_files=basedir.."/cmd/seq", timeout=1} diff --git a/test-cmd/mktemp.sh b/test-cmd/mktemp.sh @@ -0,0 +1,69 @@ +#!/bin/sh +# SPDX-FileCopyrightText: 2017 Haelwenn (lanodan) Monnier <contact+utils@hacktivis.me> +# SPDX-License-Identifier: MPL-2.0 + +target="$(dirname "$0")/../cmd/mktemp" +plans=7 +. "$(dirname "$0")/tap.sh" + +t_mktemp() +{ + count=$((count+1)) + + # Append a final slash so sh(1) doesn't trims final newlines + out="$("${target?}" $2 2>&1;r=$?;echo -n /;exit $r)" + ret="$?" + out="${out%/}" + + test -f "$out" + test_ret="$?" + + rm -f "$out" + + if [ "$ret" != 0 ] && [ "$test_ret" != 0 ]; then + printf 'not ok %d - %s\n' "$count" "$1" + printf '# exit code: %d\n' "$ret" + printf '# test -f => %d\n' "$?" + err=1 + else + printf 'ok %d - %s\n' "$count" "$1" + fi + printf "$out" | sed -e 's;^;# ;' +} + +t_mkdtemp() +{ + count=$((count+1)) + + # Append a final slash so sh(1) doesn't trims final newlines + out="$("${target?}" $2 2>&1;r=$?;echo -n /;exit $r)" + ret="$?" + out="${out%/}" + + test -d "$out" + test_ret="$?" + + rm -fr "$out" + + if [ "$ret" != 0 ] && [ "$test_ret" != 0 ]; then + printf 'not ok %d - %s\n' "$count" "$1" + printf '# exit code: %d\n' "$ret" + printf '# test -d => %d\n' "$?" + err=1 + else + printf 'ok %d - %s\n' "$count" "$1" + fi + printf "$out" | sed -e 's;^;# ;' +} + +# TODO: Figure a way to do harsher tests, for example testing patterns, directory contents, … + +t_mktemp noargs '' +t_mktemp template 'template.XXXXXX' +t_mktemp tmpdir '-t' +t_mkdtemp dir '-d' +t_mkdtemp dir_template '-d template.XXXXXX' +t_mkdtemp dir_tmpdir '-dt' + +t --exit=1 templ2 'foo bar' 'mktemp: Only one template argument is supported, got 2 +'