summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile5
-rw-r--r--Makefile.depend1
-rw-r--r--compat_mkstemps.c63
-rwxr-xr-xconfigure9
-rw-r--r--test-mkstemps.c12
5 files changed, 88 insertions, 2 deletions
diff --git a/Makefile b/Makefile
index 01a4b7ad..ad4c175b 100644
--- a/Makefile
+++ b/Makefile
@@ -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;
+}
diff --git a/configure b/configure
index 64509513..3d4cd743 100755
--- a/configure
+++ b/configure
@@ -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;
+}