diff options
-rw-r--r-- | Makefile | 5 | ||||
-rw-r--r-- | Makefile.depend | 1 | ||||
-rw-r--r-- | compat_mkstemps.c | 63 | ||||
-rwxr-xr-x | configure | 9 | ||||
-rw-r--r-- | test-mkstemps.c | 12 |
5 files changed, 88 insertions, 2 deletions
@@ -1,6 +1,6 @@ # $Id$ # -# Copyright (c) 2011, 2013-2020 Ingo Schwarze <schwarze@openbsd.org> +# Copyright (c) 2011, 2013-2021 Ingo Schwarze <schwarze@openbsd.org> # Copyright (c) 2010, 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv> # # Permission to use, copy, modify, and distribute this software for any @@ -30,6 +30,7 @@ TESTSRCS = test-attribute.c \ test-getsubopt.c \ test-isblank.c \ test-mkdtemp.c \ + test-mkstemps.c \ test-nanosleep.c \ test-noop.c \ test-ntohl.c \ @@ -66,6 +67,7 @@ SRCS = arch.c \ compat_getsubopt.c \ compat_isblank.c \ compat_mkdtemp.c \ + compat_mkstemps.c \ compat_ohash.c \ compat_progname.c \ compat_reallocarray.c \ @@ -257,6 +259,7 @@ ALL_COBJS = compat_err.o \ compat_getsubopt.o \ compat_isblank.o \ compat_mkdtemp.o \ + compat_mkstemps.o \ compat_ohash.o \ compat_progname.o \ compat_reallocarray.o \ diff --git a/Makefile.depend b/Makefile.depend index 55916ce1..d5f6556c 100644 --- a/Makefile.depend +++ b/Makefile.depend @@ -9,6 +9,7 @@ compat_getline.o: compat_getline.c config.h compat_getsubopt.o: compat_getsubopt.c config.h compat_isblank.o: compat_isblank.c config.h compat_mkdtemp.o: compat_mkdtemp.c config.h +compat_mkstemps.o: compat_mkstemps.c config.h compat_ohash.o: compat_ohash.c config.h compat_ohash.h compat_progname.o: compat_progname.c config.h compat_reallocarray.o: compat_reallocarray.c config.h diff --git a/compat_mkstemps.c b/compat_mkstemps.c new file mode 100644 index 00000000..8dc4dd2b --- /dev/null +++ b/compat_mkstemps.c @@ -0,0 +1,63 @@ +/* $Id$ */ +/* + * Copyright (c) 2015, 2021 Ingo Schwarze <schwarze@openbsd.org> + * + * Permission to use, copy, modify, and 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. + * + * Parts of the algorithm of this function are inspired by OpenBSD + * mkdtemp(3) by Theo de Raadt and Todd Miller, but the code differs. + */ +#include "config.h" + +#include <sys/stat.h> +#include <errno.h> +#include <fcntl.h> +#include <limits.h> +#include <stdlib.h> +#include <string.h> + +int +mkstemps(char *path, int suffixlen) +{ + char *start, *end, *cp; + int fd, tries; + char backup; + + end = strchr(path, '\0'); + if (suffixlen < 0 || suffixlen > end - path - 6) { + errno = EINVAL; + return -1; + } + end -= suffixlen; + for (start = end; start > path; start--) + if (start[-1] != 'X') + break; + + backup = *end; + for (tries = INT_MAX; tries; tries--) { + *end = '\0'; + cp = mktemp(path); + *end = backup; + if (cp == NULL) + return -1; + fd = open(path, O_CREAT | O_EXCL | O_RDWR, S_IRUSR | S_IWUSR); + if (fd != -1) + return fd; + for (cp = start; cp < end; cp++) + *cp = 'X'; + if (errno != EEXIST) + return -1; + } + errno = EEXIST; + return -1; +} @@ -2,7 +2,7 @@ # # $Id$ # -# Copyright (c) 2014-2020 Ingo Schwarze <schwarze@openbsd.org> +# Copyright (c) 2014-2021 Ingo Schwarze <schwarze@openbsd.org> # # Permission to use, copy, modify, and distribute this software for any # purpose with or without fee is hereby granted, provided that the above @@ -68,6 +68,7 @@ HAVE_GETSUBOPT= HAVE_ISBLANK= HAVE_LESS_T= HAVE_MKDTEMP= +HAVE_MKSTEMPS= HAVE_NANOSLEEP= HAVE_NTOHL= HAVE_O_DIRECTORY= @@ -307,6 +308,7 @@ runtest getline GETLINE || true runtest getsubopt GETSUBOPT "" -D_GNU_SOURCE || true runtest isblank ISBLANK || true runtest mkdtemp MKDTEMP || true +runtest mkstemps MKSTEMPS || true runtest nanosleep NANOSLEEP "${LD_NANOSLEEP}" "-lrt" || true runtest ntohl NTOHL || true runtest O_DIRECTORY O_DIRECTORY || true @@ -483,6 +485,7 @@ cat << __HEREDOC__ #define HAVE_ISBLANK ${HAVE_ISBLANK} #define HAVE_LESS_T ${HAVE_LESS_T} #define HAVE_MKDTEMP ${HAVE_MKDTEMP} +#define HAVE_MKSTEMPS ${HAVE_MKSTEMPS} #define HAVE_NTOHL ${HAVE_NTOHL} #define HAVE_PLEDGE ${HAVE_PLEDGE} #define HAVE_PROGNAME ${HAVE_PROGNAME} @@ -543,6 +546,10 @@ if [ ${HAVE_MKDTEMP} -eq 0 ]; then echo "extern char *mkdtemp(char *);" MANDOC_COBJS="${MANDOC_COBJS} compat_mkdtemp.o" fi +if [ ${HAVE_MKSTEMPS} -eq 0 ]; then + echo "extern int mkstemps(char *, int);" + MANDOC_COBJS="${MANDOC_COBJS} compat_mkstemps.o" +fi if [ ${HAVE_OHASH} -eq 0 ]; then MANDOC_COBJS="${MANDOC_COBJS} compat_ohash.o" fi diff --git a/test-mkstemps.c b/test-mkstemps.c new file mode 100644 index 00000000..31460dca --- /dev/null +++ b/test-mkstemps.c @@ -0,0 +1,12 @@ +#include <stdlib.h> +#include <unistd.h> + +int +main(void) +{ + char filename[] = "/tmp/temp.XXXXXX.suffix"; + + if (mkstemps(filename, 7) == -1) + return 1; + return unlink(filename) == -1; +} |