From: Bruno Haible Date: Mon, 17 Feb 2003 22:49:11 +0000 (+0000) Subject: mkdtemp() function: create a private temporary directory. X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=717fa45711884ed1fdd5c92c535b7b5ccb6222c2;p=pspp mkdtemp() function: create a private temporary directory. --- diff --git a/ChangeLog b/ChangeLog index c63b62b824..7129a62fe0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2003-02-17 Bruno Haible + + * modules/mkdtemp: New module. + * MODULES.html.sh (func_all_modules): Add it. + 2003-01-30 Bruno Haible * modules/vasnprintf, modules/vasprintf: New modules. diff --git a/MODULES.html.sh b/MODULES.html.sh index 2872aba411..90cc3a2971 100755 --- a/MODULES.html.sh +++ b/MODULES.html.sh @@ -1659,7 +1659,7 @@ func_all_modules () func_module gettimeofday func_module mkdir func_module mkstemp - #func_module mkdtemp + func_module mkdtemp func_module stat func_module lstat func_module timespec diff --git a/lib/ChangeLog b/lib/ChangeLog index 9bc4367532..1279061323 100644 --- a/lib/ChangeLog +++ b/lib/ChangeLog @@ -1,3 +1,8 @@ +2003-02-17 Bruno Haible + + * mkdtemp.h: New file, from GNU gettext. + * mkdtemp.c: New file, from GNU gettext. + 2003-01-31 Bruno Haible * rename.c: #undef rename before defining rpl_rename. diff --git a/lib/mkdtemp.c b/lib/mkdtemp.c new file mode 100644 index 0000000000..8434acf9cb --- /dev/null +++ b/lib/mkdtemp.c @@ -0,0 +1,198 @@ +/* Copyright (C) 1999, 2001-2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* Extracted from misc/mkdtemp.c and sysdeps/posix/tempname.c. */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +/* Specification. */ +#include "mkdtemp.h" + +#include +#ifndef __set_errno +# define __set_errno(Val) errno = (Val) +#endif + +#include +#include +#include + +#include +#ifndef TMP_MAX +# define TMP_MAX 238328 +#endif + +#if HAVE_STDINT_H || _LIBC +# include +#endif +#if HAVE_INTTYPES_H +# include +#endif + +#if HAVE_UNISTD_H || _LIBC +# include +#endif + +#if HAVE_GETTIMEOFDAY || _LIBC +# if HAVE_SYS_TIME_H || _LIBC +# include +# endif +#else +# if HAVE_TIME_H || _LIBC +# include +# endif +#endif + +#include +#if STAT_MACROS_BROKEN +# undef S_ISDIR +#endif +#if !defined S_ISDIR && defined S_IFDIR +# define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR) +#endif +#if !S_IRUSR && S_IREAD +# define S_IRUSR S_IREAD +#endif +#if !S_IRUSR +# define S_IRUSR 00400 +#endif +#if !S_IWUSR && S_IWRITE +# define S_IWUSR S_IWRITE +#endif +#if !S_IWUSR +# define S_IWUSR 00200 +#endif +#if !S_IXUSR && S_IEXEC +# define S_IXUSR S_IEXEC +#endif +#if !S_IXUSR +# define S_IXUSR 00100 +#endif + +#if !_LIBC +# define __getpid getpid +# define __gettimeofday gettimeofday +# define __mkdir mkdir +#endif + +/* Use the widest available unsigned type if uint64_t is not + available. The algorithm below extracts a number less than 62**6 + (approximately 2**35.725) from uint64_t, so ancient hosts where + uintmax_t is only 32 bits lose about 3.725 bits of randomness, + which is better than not having mkstemp at all. */ +#if !defined UINT64_MAX && !defined uint64_t +# define uint64_t uintmax_t +#endif + +/* These are the characters used in temporary filenames. */ +static const char letters[] = +"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + +/* Generate a temporary file name based on TMPL. TMPL must match the + rules for mk[s]temp (i.e. end in "XXXXXX"). The name constructed + does not exist at the time of the call to __gen_tempname. TMPL is + overwritten with the result. + + KIND is: + __GT_DIR: create a directory, which will be mode 0700. + + We use a clever algorithm to get hard-to-predict names. */ +static int +gen_tempname (char *tmpl) +{ + int len; + char *XXXXXX; + static uint64_t value; + uint64_t random_time_bits; + int count, fd = -1; + int save_errno = errno; + + len = strlen (tmpl); + if (len < 6 || strcmp (&tmpl[len - 6], "XXXXXX")) + { + __set_errno (EINVAL); + return -1; + } + + /* This is where the Xs start. */ + XXXXXX = &tmpl[len - 6]; + + /* Get some more or less random data. */ +#ifdef RANDOM_BITS + RANDOM_BITS (random_time_bits); +#else +# if HAVE_GETTIMEOFDAY || _LIBC + { + struct timeval tv; + __gettimeofday (&tv, NULL); + random_time_bits = ((uint64_t) tv.tv_usec << 16) ^ tv.tv_sec; + } +# else + random_time_bits = time (NULL); +# endif +#endif + value += random_time_bits ^ __getpid (); + + for (count = 0; count < TMP_MAX; value += 7777, ++count) + { + uint64_t v = value; + + /* Fill in the random bits. */ + XXXXXX[0] = letters[v % 62]; + v /= 62; + XXXXXX[1] = letters[v % 62]; + v /= 62; + XXXXXX[2] = letters[v % 62]; + v /= 62; + XXXXXX[3] = letters[v % 62]; + v /= 62; + XXXXXX[4] = letters[v % 62]; + v /= 62; + XXXXXX[5] = letters[v % 62]; + + fd = __mkdir (tmpl, S_IRUSR | S_IWUSR | S_IXUSR); + + if (fd >= 0) + { + __set_errno (save_errno); + return fd; + } + else if (errno != EEXIST) + return -1; + } + + /* We got out of the loop because we ran out of combinations to try. */ + __set_errno (EEXIST); + return -1; +} + +/* Generate a unique temporary directory from TEMPLATE. + The last six characters of TEMPLATE must be "XXXXXX"; + they are replaced with a string that makes the filename unique. + The directory is created, mode 700, and its name is returned. + (This function comes from OpenBSD.) */ +char * +mkdtemp (char *template) +{ + if (gen_tempname (template)) + return NULL; + else + return template; +} diff --git a/lib/mkdtemp.h b/lib/mkdtemp.h new file mode 100644 index 0000000000..65ee99eff3 --- /dev/null +++ b/lib/mkdtemp.h @@ -0,0 +1,32 @@ +/* Creating a private temporary directory. + Copyright (C) 2001-2002 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#if HAVE_MKDTEMP + +/* Get mkdtemp() declaration. */ +#include + +#else + +/* Create a unique temporary directory from TEMPLATE. + The last six characters of TEMPLATE must be "XXXXXX"; + they are replaced with a string that makes the directory name unique. + Returns TEMPLATE, or a null pointer if it cannot get a unique name. + The directory is created mode 700. */ +extern char * mkdtemp (char *template); + +#endif diff --git a/m4/ChangeLog b/m4/ChangeLog index b631697c75..d714710a23 100644 --- a/m4/ChangeLog +++ b/m4/ChangeLog @@ -1,3 +1,7 @@ +2003-02-17 Bruno Haible + + * mkdtemp.m4: New file, from GNU gettext with modifications. + 2003-02-02 Jim Meyering * regex.m4 (jm_INCLUDED_REGEX): Detect broken re_search in diff --git a/m4/mkdtemp.m4 b/m4/mkdtemp.m4 new file mode 100644 index 0000000000..a729b44fe9 --- /dev/null +++ b/m4/mkdtemp.m4 @@ -0,0 +1,25 @@ +# mkdtemp.m4 serial 2 +dnl Copyright (C) 2001-2003 Free Software Foundation, Inc. +dnl This file is free software, distributed under the terms of the GNU +dnl General Public License. As a special exception to the GNU General +dnl Public License, this file may be distributed as part of a program +dnl that contains a configuration script generated by Autoconf, under +dnl the same distribution terms as the rest of that program. + +AC_DEFUN([gt_FUNC_MKDTEMP], +[ + AC_REPLACE_FUNCS(mkdtemp) + if test $ac_cv_func_mkdtemp = no; then + gl_PREREQ_MKDTEMP + fi +]) + +# Prerequisites of lib/mkdtemp.c +AC_DEFUN([gl_PREREQ_MKDTEMP], +[ + AC_REQUIRE([AC_HEADER_STAT]) + AC_CHECK_HEADERS_ONCE(sys/time.h unistd.h) + AC_CHECK_HEADERS(time.h) + AC_REQUIRE([jm_AC_TYPE_UINTMAX_T]) + AC_CHECK_FUNCS(gettimeofday) +]) diff --git a/modules/mkdtemp b/modules/mkdtemp new file mode 100644 index 0000000000..3f9b8d521f --- /dev/null +++ b/modules/mkdtemp @@ -0,0 +1,26 @@ +Description: +mkdtemp() function: create a private temporary directory. + +Files: +lib/mkdtemp.h +lib/mkdtemp.c +m4/ulonglong.m4 +m4/stdint_h.m4 +m4/inttypes_h.m4 +m4/uintmax_t.m4 +m4/mkdtemp.m4 + +Depends-on: + +configure.ac: +gt_FUNC_MKDTEMP + +Makefile.am: +lib_SOURCES += mkdtemp.h + +Include: +"mkdtemp.h" + +Maintainer: +Bruno Haible +