From 9e6b1bf258170e62dac555fc82ff0536dfe01d29 Mon Sep 17 00:00:00 2001 From: Noah Misch Date: Sat, 14 Jun 2014 09:41:13 -0400 Subject: [PATCH] Add mkdtemp() to libpgport. This function is pervasive on free software operating systems; import NetBSD's implementation. Back-patch to 8.4, like the commit that will harness it. --- configure | 13 ++ configure.in | 2 +- src/include/pg_config.h.in | 3 + src/include/pg_config.h.win32 | 3 + src/include/port.h | 3 + src/port/mkdtemp.c | 293 ++++++++++++++++++++++++++++++++++ src/tools/msvc/Mkvcbuild.pm | 2 +- 7 files changed, 317 insertions(+), 2 deletions(-) create mode 100644 src/port/mkdtemp.c diff --git a/configure b/configure index ee72c3c7f7..da89c69260 100755 --- a/configure +++ b/configure @@ -11650,6 +11650,19 @@ esac fi +ac_fn_c_check_func "$LINENO" "mkdtemp" "ac_cv_func_mkdtemp" +if test "x$ac_cv_func_mkdtemp" = xyes; then : + $as_echo "#define HAVE_MKDTEMP 1" >>confdefs.h + +else + case " $LIBOBJS " in + *" mkdtemp.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS mkdtemp.$ac_objext" + ;; +esac + +fi + ac_fn_c_check_func "$LINENO" "random" "ac_cv_func_random" if test "x$ac_cv_func_random" = xyes; then : $as_echo "#define HAVE_RANDOM 1" >>confdefs.h diff --git a/configure.in b/configure.in index 42d0a2bf3a..7dfbe9f569 100644 --- a/configure.in +++ b/configure.in @@ -1357,7 +1357,7 @@ else AC_CHECK_FUNCS([fpclass fp_class fp_class_d class], [break]) fi -AC_REPLACE_FUNCS([crypt fls getopt getrusage inet_aton random rint srandom strerror strlcat strlcpy]) +AC_REPLACE_FUNCS([crypt fls getopt getrusage inet_aton mkdtemp random rint srandom strerror strlcat strlcpy]) case $host_os in diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in index 5ff9e41212..4fb7288710 100644 --- a/src/include/pg_config.h.in +++ b/src/include/pg_config.h.in @@ -330,6 +330,9 @@ /* Define to 1 if the system has the type `MINIDUMP_TYPE'. */ #undef HAVE_MINIDUMP_TYPE +/* Define to 1 if you have the `mkdtemp' function. */ +#undef HAVE_MKDTEMP + /* Define to 1 if you have the header file. */ #undef HAVE_NETINET_IN_H diff --git a/src/include/pg_config.h.win32 b/src/include/pg_config.h.win32 index 38dee90e87..30a9a6ae0b 100644 --- a/src/include/pg_config.h.win32 +++ b/src/include/pg_config.h.win32 @@ -249,6 +249,9 @@ /* Define to 1 if the system has the type `MINIDUMP_TYPE'. */ #define HAVE_MINIDUMP_TYPE 1 +/* Define to 1 if you have the `mkdtemp' function. */ +/* #undef HAVE_MKDTEMP */ + /* Define to 1 if you have the header file. */ #define HAVE_NETINET_IN_H 1 diff --git a/src/include/port.h b/src/include/port.h index c9226f3dac..3d97481834 100644 --- a/src/include/port.h +++ b/src/include/port.h @@ -462,6 +462,9 @@ extern int pg_check_dir(const char *dir); /* port/pgmkdirp.c */ extern int pg_mkdir_p(char *path, int omode); +/* port/mkdtemp.c */ +extern char *mkdtemp(char *path); + /* port/pqsignal.c */ typedef void (*pqsigfunc) (int signo); extern pqsigfunc pqsignal(int signo, pqsigfunc func); diff --git a/src/port/mkdtemp.c b/src/port/mkdtemp.c new file mode 100644 index 0000000000..a5e991f7f6 --- /dev/null +++ b/src/port/mkdtemp.c @@ -0,0 +1,293 @@ +/*------------------------------------------------------------------------- + * + * mkdtemp.c + * create a mode-0700 temporary directory + * + * Portions Copyright (c) 1996-2014, PostgreSQL Global Development Group + * + * + * IDENTIFICATION + * src/port/mkdtemp.c + * + * This code was taken from NetBSD to provide an implementation for platforms + * that lack it. (Among compatibly-licensed implementations, the OpenBSD + * version better resists denial-of-service attacks. However, it has a + * cryptographic dependency.) The NetBSD copyright terms follow. + *------------------------------------------------------------------------- + */ + +#include "c.h" + +#define _DIAGASSERT(x) do {} while (0) + + +/* $NetBSD: gettemp.c,v 1.17 2014/01/21 19:09:48 seanb Exp $ */ + +/* + * Copyright (c) 1987, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if HAVE_NBTOOL_CONFIG_H +#include "nbtool_config.h" +#endif + +#if !HAVE_NBTOOL_CONFIG_H || !HAVE_MKSTEMP || !HAVE_MKDTEMP + +#ifdef NOT_POSTGRESQL +#include +#if defined(LIBC_SCCS) && !defined(lint) +#if 0 +static char sccsid[] = "@(#)mktemp.c 8.1 (Berkeley) 6/4/93"; +#else +__RCSID("$NetBSD: gettemp.c,v 1.17 2014/01/21 19:09:48 seanb Exp $"); +#endif +#endif /* LIBC_SCCS and not lint */ +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#ifdef NOT_POSTGRESQL +#if HAVE_NBTOOL_CONFIG_H +#define GETTEMP __nbcompat_gettemp +#else +#include "reentrant.h" +#include "local.h" +#define GETTEMP __gettemp +#endif +#endif + +static int +GETTEMP(char *path, int *doopen, int domkdir) +{ + char *start, + *trv; + struct stat sbuf; + u_int pid; + + /* + * To guarantee multiple calls generate unique names even if the file is + * not created. 676 different possibilities with 7 or more X's, 26 with 6 + * or less. + */ + static char xtra[2] = "aa"; + int xcnt = 0; + + _DIAGASSERT(path != NULL); + /* doopen may be NULL */ + + pid = getpid(); + + /* Move to end of path and count trailing X's. */ + for (trv = path; *trv; ++trv) + if (*trv == 'X') + xcnt++; + else + xcnt = 0; + + /* Use at least one from xtra. Use 2 if more than 6 X's. */ + if (xcnt > 0) + { + *--trv = xtra[0]; + xcnt--; + } + if (xcnt > 5) + { + *--trv = xtra[1]; + xcnt--; + } + + /* Set remaining X's to pid digits with 0's to the left. */ + for (; xcnt > 0; xcnt--) + { + *--trv = (pid % 10) + '0'; + pid /= 10; + } + + /* update xtra for next call. */ + if (xtra[0] != 'z') + xtra[0]++; + else + { + xtra[0] = 'a'; + if (xtra[1] != 'z') + xtra[1]++; + else + xtra[1] = 'a'; + } + + /* + * check the target directory; if you have six X's and it doesn't exist + * this runs for a *very* long time. + */ + for (start = trv + 1;; --trv) + { + if (trv <= path) + break; + if (*trv == '/') + { + int e; + + *trv = '\0'; + e = stat(path, &sbuf); + *trv = '/'; + if (e == -1) + return doopen == NULL && !domkdir; + if (!S_ISDIR(sbuf.st_mode)) + { + errno = ENOTDIR; + return doopen == NULL && !domkdir; + } + break; + } + } + + for (;;) + { + if (doopen) + { + if ((*doopen = + open(path, O_CREAT | O_EXCL | O_RDWR, 0600)) >= 0) + return 1; + if (errno != EEXIST) + return 0; + } + else if (domkdir) + { + if (mkdir(path, 0700) >= 0) + return 1; + if (errno != EEXIST) + return 0; + } + else if (lstat(path, &sbuf)) + return errno == ENOENT ? 1 : 0; + + /* tricky little algorithm for backward compatibility */ + for (trv = start;;) + { + if (!*trv) + return 0; + if (*trv == 'z') + *trv++ = 'a'; + else + { + if (isdigit((unsigned char) *trv)) + *trv = 'a'; + else + ++* trv; + break; + } + } + } + /* NOTREACHED */ +} + +#endif /* !HAVE_NBTOOL_CONFIG_H || !HAVE_MKSTEMP || + * !HAVE_MKDTEMP */ + + +/* $NetBSD: mkdtemp.c,v 1.11 2012/03/15 18:22:30 christos Exp $ */ + +/* + * Copyright (c) 1987, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if HAVE_NBTOOL_CONFIG_H +#include "nbtool_config.h" +#endif + +#if !HAVE_NBTOOL_CONFIG_H || !HAVE_MKDTEMP + +#ifdef NOT_POSTGRESQL + +#include +#if defined(LIBC_SCCS) && !defined(lint) +#if 0 +static char sccsid[] = "@(#)mktemp.c 8.1 (Berkeley) 6/4/93"; +#else +__RCSID("$NetBSD: mkdtemp.c,v 1.11 2012/03/15 18:22:30 christos Exp $"); +#endif +#endif /* LIBC_SCCS and not lint */ + +#if HAVE_NBTOOL_CONFIG_H +#define GETTEMP __nbcompat_gettemp +#else +#include +#include +#include +#include +#include +#include "reentrant.h" +#include "local.h" +#define GETTEMP __gettemp +#endif + +#endif + +char * +mkdtemp(char *path) +{ + _DIAGASSERT(path != NULL); + + return GETTEMP(path, NULL, 1) ? path : NULL; +} + +#endif /* !HAVE_NBTOOL_CONFIG_H || !HAVE_MKDTEMP */ diff --git a/src/tools/msvc/Mkvcbuild.pm b/src/tools/msvc/Mkvcbuild.pm index 270e9c69f0..8002f23487 100644 --- a/src/tools/msvc/Mkvcbuild.pm +++ b/src/tools/msvc/Mkvcbuild.pm @@ -69,7 +69,7 @@ sub mkvcbuild srandom.c getaddrinfo.c gettimeofday.c inet_net_ntop.c kill.c open.c erand48.c snprintf.c strlcat.c strlcpy.c dirmod.c noblock.c path.c pgcheckdir.c pg_crc.c pgmkdirp.c pgsleep.c pgstrcasecmp.c pqsignal.c - qsort.c qsort_arg.c quotes.c system.c + mkdtemp.c qsort.c qsort_arg.c quotes.c system.c sprompt.c tar.c thread.c getopt.c getopt_long.c dirent.c win32env.c win32error.c win32setlocale.c); -- 2.40.0