diff options
author | Bruno Haible <bruno@clisp.org> | 2001-09-13 14:58:50 +0000 |
---|---|---|
committer | Bruno Haible <bruno@clisp.org> | 2001-09-13 14:58:50 +0000 |
commit | b1732b47eb8b2f841f287226e2a06439a9875b36 (patch) | |
tree | 72df0a4f7c1d9fd8e52bd30ffd1e50e27c7a6d38 | |
parent | ac1431e0d99f4dea88bd6b6d27fbcbdebf39052f (diff) | |
download | external_gettext-b1732b47eb8b2f841f287226e2a06439a9875b36.zip external_gettext-b1732b47eb8b2f841f287226e2a06439a9875b36.tar.gz external_gettext-b1732b47eb8b2f841f287226e2a06439a9875b36.tar.bz2 |
Subroutines for creating temporary directories.
-rw-r--r-- | ChangeLog | 4 | ||||
-rw-r--r-- | configure.in | 2 | ||||
-rw-r--r-- | lib/ChangeLog | 10 | ||||
-rw-r--r-- | lib/Makefile.am | 9 | ||||
-rw-r--r-- | lib/mkdtemp.c | 197 | ||||
-rw-r--r-- | lib/mkdtemp.h | 40 | ||||
-rw-r--r-- | lib/tmpdir.c | 157 | ||||
-rw-r--r-- | lib/tmpdir.h | 34 | ||||
-rw-r--r-- | m4/ChangeLog | 6 | ||||
-rw-r--r-- | m4/Makefile.am | 4 | ||||
-rw-r--r-- | m4/mkdtemp.m4 | 11 | ||||
-rw-r--r-- | m4/tmpdir.m4 | 9 |
12 files changed, 477 insertions, 6 deletions
@@ -1,3 +1,7 @@ +2001-09-02 Bruno Haible <haible@clisp.cons.org> + + * configure.in: Call gt_TMPDIR and gt_FUNC_MKDTEMP. + 2001-09-03 Bruno Haible <haible@clisp.cons.org> * configure.in: Call gt_PROG_LEX. diff --git a/configure.in b/configure.in index 9cf2728..56556be 100644 --- a/configure.in +++ b/configure.in @@ -59,6 +59,8 @@ fi jm_PREREQ_MBSWIDTH AC_FUNC_VFORK gt_UNION_WAIT +gt_TMPDIR +gt_FUNC_MKDTEMP AM_FUNC_ERROR_AT_LINE diff --git a/lib/ChangeLog b/lib/ChangeLog index 06f1f52..c9b1f2f 100644 --- a/lib/ChangeLog +++ b/lib/ChangeLog @@ -1,5 +1,15 @@ 2001-09-02 Bruno Haible <haible@clisp.cons.org> + * mkdtemp.h: New file. + * mkdtemp.c: New file, mostly taken from glibc-2.2.4. + * tmpdir.h: New file. + * tmpdir.c: New file, mostly taken from glibc-2.2.4. + * Makefile.am (EXTRA_DIST): Add mkdtemp.c. + (libnlsut_a_SOURCES): Add tmpdir.c. + (noinst_HEADERS): Add mkdtemp.h, tmpdir.h. + +2001-09-02 Bruno Haible <haible@clisp.cons.org> + * execute.h: New file. * execute.c: New file. * Makefile.am (libnlsut_a_SOURCES): Add execute.c. diff --git a/lib/Makefile.am b/lib/Makefile.am index 0ad1557..98ebe19 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -22,7 +22,7 @@ AUTOMAKE_OPTIONS = 1.2 gnits noinst_LIBRARIES = libnlsut.a EXTRA_DIST = alloca.c config.charset error.c getline.c memset.c memmove.c \ -ref-add.sin ref-del.sin stpcpy.c stpncpy.c strcasecmp.c strcspn.c \ +mkdtemp.c ref-add.sin ref-del.sin stpcpy.c stpncpy.c strcasecmp.c strcspn.c \ strncasecmp.c strstr.c strtol.c strtoul.c vasprintf.c \ stdbool.h.in \ gen-lbrkprop.c 3level.h @@ -30,14 +30,15 @@ gen-lbrkprop.c 3level.h libnlsut_a_SOURCES = basename.c c-ctype.c concatpath.c execute.c findprog.c \ fstrcmp.c full-write.c gcd.c getopt.c getopt1.c hash.c linebreak.c \ localcharset.c mbswidth.c obstack.c pipe-bidi.c pipe-in.c pipe-out.c \ -progname.c safe-read.c wait-process.c xerror.c xgetcwd.c xmalloc.c xstrdup.c +progname.c safe-read.c tmpdir.c wait-process.c xerror.c xgetcwd.c xmalloc.c \ +xstrdup.c libnlsut_a_LIBADD = @ALLOCA@ @LIBOBJS@ noinst_HEADERS = c-ctype.h error.h execute.h findprog.h fstrcmp.h \ full-write.h gcd.h getline.h getopt.h hash.h lbrkprop.h linebreak.h mbswidth.h \ -obstack.h pathmax.h pipe.h progname.h safe-read.h system.h utf8-ucs4.h \ -utf16-ucs4.h wait-process.h xerror.h +mkdtemp.h obstack.h pathmax.h pipe.h progname.h safe-read.h system.h tmpdir.h \ +utf8-ucs4.h utf16-ucs4.h wait-process.h xerror.h DEFS = -DLIBDIR=\"$(libdir)\" @DEFS@ INCLUDES = -I. -I$(srcdir) -I.. -I../intl diff --git a/lib/mkdtemp.c b/lib/mkdtemp.c new file mode 100644 index 0000000..b1a8b16 --- /dev/null +++ b/lib/mkdtemp.c @@ -0,0 +1,197 @@ +/* Copyright (C) 1999, 2001 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 <errno.h> +#ifndef __set_errno +# define __set_errno(Val) errno = (Val) +#endif + +#include <stddef.h> +#include <stdlib.h> +#include <string.h> + +#include <stdio.h> +#ifndef TMP_MAX +# define TMP_MAX 238328 +#endif + +#if HAVE_STDINT_H || _LIBC +# include <stdint.h> +#endif + +#if HAVE_UNISTD_H || _LIBC +# include <unistd.h> +#endif + +#if HAVE_GETTIMEOFDAY || _LIBC +# if HAVE_SYS_TIME_H || _LIBC +# include <sys/time.h> +# endif +#else +# if HAVE_TIME_H || _LIBC +# include <time.h> +# endif +#endif + +#include <sys/stat.h> +#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 (tmpl) + 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 (template) + 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 0000000..b56128e --- /dev/null +++ b/lib/mkdtemp.h @@ -0,0 +1,40 @@ +/* Creating a private temporary directory. + Copyright (C) 2001 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. */ + +#ifndef PARAMS +# if defined (__GNUC__) || __STDC__ +# define PARAMS(Args) Args +# else +# define PARAMS(Args) () +# endif +#endif + +#if HAVE_MKDTEMP + +/* Get mkdtemp() declaration. */ +#include <stdlib.h> + +#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 PARAMS ((char *template)); + +#endif diff --git a/lib/tmpdir.c b/lib/tmpdir.c new file mode 100644 index 0000000..159547e --- /dev/null +++ b/lib/tmpdir.c @@ -0,0 +1,157 @@ +/* Copyright (C) 1999, 2001 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 sysdeps/posix/tempname.c. */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +/* Specification. */ +#include "tmpdir.h" + +#include <stdlib.h> + +#include <errno.h> +#ifndef __set_errno +# define __set_errno(Val) errno = (Val) +#endif + +#include <stdio.h> +#ifndef P_tmpdir +# define P_tmpdir "/tmp" +#endif + +#include <sys/stat.h> +#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 struct_stat64 struct stat64 +#else +# define struct_stat64 struct stat +# define __xstat64(version, path, buf) stat (path, buf) +#endif + +#if ! (HAVE___SECURE_GETENV || _LIBC) +# define __secure_getenv getenv +#endif + + +/* Prototypes for local functions. Needed to ensure compiler checking of + function argument counts despite of K&R C function definition syntax. */ +static int direxists PARAMS ((const char *dir)); + + +/* Return nonzero if DIR is an existent directory. */ +static int +direxists (dir) + const char *dir; +{ + struct_stat64 buf; + return __xstat64 (_STAT_VER, dir, &buf) == 0 && S_ISDIR (buf.st_mode); +} + +/* Path search algorithm, for tmpnam, tmpfile, etc. If DIR is + non-null and exists, uses it; otherwise uses the first of $TMPDIR, + P_tmpdir, /tmp that exists. Copies into TMPL a template suitable + for use with mk[s]temp. Will fail (-1) if DIR is non-null and + doesn't exist, none of the searched dirs exists, or there's not + enough space in TMPL. */ +int +path_search (tmpl, tmpl_len, dir, pfx, try_tmpdir) + char *tmpl; + size_t tmpl_len; + const char *dir; + const char *pfx; + int try_tmpdir; +{ + const char *d; + size_t dlen, plen; + + if (!pfx || !pfx[0]) + { + pfx = "file"; + plen = 4; + } + else + { + plen = strlen (pfx); + if (plen > 5) + plen = 5; + } + + if (try_tmpdir) + { + d = __secure_getenv ("TMPDIR"); + if (d != NULL && direxists (d)) + dir = d; + else if (dir != NULL && direxists (dir)) + /* nothing */ ; + else + dir = NULL; + } + if (dir == NULL) + { + if (direxists (P_tmpdir)) + dir = P_tmpdir; + else if (strcmp (P_tmpdir, "/tmp") != 0 && direxists ("/tmp")) + dir = "/tmp"; + else + { + __set_errno (ENOENT); + return -1; + } + } + + dlen = strlen (dir); + while (dlen > 1 && dir[dlen - 1] == '/') + dlen--; /* remove trailing slashes */ + + /* check we have room for "${dir}/${pfx}XXXXXX\0" */ + if (tmpl_len < dlen + 1 + plen + 6 + 1) + { + __set_errno (EINVAL); + return -1; + } + + sprintf (tmpl, "%.*s/%.*sXXXXXX", (int) dlen, dir, (int) plen, pfx); + return 0; +} diff --git a/lib/tmpdir.h b/lib/tmpdir.h new file mode 100644 index 0000000..8fe7c31 --- /dev/null +++ b/lib/tmpdir.h @@ -0,0 +1,34 @@ +/* Determine a temporary directory. + Copyright (C) 2001 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. */ + +#ifndef PARAMS +# if defined (__GNUC__) || __STDC__ +# define PARAMS(Args) Args +# else +# define PARAMS(Args) () +# endif +#endif + +#include <stddef.h> + +/* Path search algorithm, for tmpnam, tmpfile, etc. If DIR is + non-null and exists, uses it; otherwise uses the first of $TMPDIR, + P_tmpdir, /tmp that exists. Copies into TMPL a template suitable + for use with mk[s]temp. Will fail (-1) if DIR is non-null and + doesn't exist, none of the searched dirs exists, or there's not + enough space in TMPL. */ +extern int path_search PARAMS ((char *tmpl, size_t tmpl_len, const char *dir, const char *pfx, int try_tmpdir)); diff --git a/m4/ChangeLog b/m4/ChangeLog index cf3fa14..f89a47a 100644 --- a/m4/ChangeLog +++ b/m4/ChangeLog @@ -1,3 +1,9 @@ +2001-09-02 Bruno Haible <haible@clisp.cons.org> + + * mkdtemp.m4: New file. + * tmpdir.m4: New file. + * Makefile.am (EXTRA_DIST): Add them. + 2001-09-03 Bruno Haible <haible@clisp.cons.org> * flex.m4: New file. diff --git a/m4/Makefile.am b/m4/Makefile.am index 80026d0..ea1fdb3 100644 --- a/m4/Makefile.am +++ b/m4/Makefile.am @@ -9,5 +9,5 @@ aclocal_DATA = codeset.m4 gettext.m4 glibc21.m4 iconv.m4 isc-posix.m4 lcmessage. EXTRA_DIST = README \ c-bs-a.m4 codeset.m4 flex.m4 getline.m4 gettext.m4 glibc21.m4 iconv.m4 \ inttypes_h.m4 isc-posix.m4 lcmessage.m4 libtool.m4 mbrtowc.m4 mbstate_t.m4 \ -mbswidth.m4 progtest.m4 setlocale.m4 signed.m4 ssize_t.m4 stdbool.m4 \ -uintmax_t.m4 ulonglong.m4 unionwait.m4 +mbswidth.m4 mkdtemp.m4 progtest.m4 setlocale.m4 signed.m4 ssize_t.m4 \ +stdbool.m4 tmpdir.m4 uintmax_t.m4 ulonglong.m4 unionwait.m4 diff --git a/m4/mkdtemp.m4 b/m4/mkdtemp.m4 new file mode 100644 index 0000000..73ce4c0 --- /dev/null +++ b/m4/mkdtemp.m4 @@ -0,0 +1,11 @@ +#serial 1 + +# Prerequisites of lib/mkdtemp.c + +AC_DEFUN([gt_FUNC_MKDTEMP], +[ + AC_REPLACE_FUNCS(mkdtemp) + AC_STAT_MACROS_BROKEN + AC_CHECK_HEADERS(fcntl.h stdint.h sys/time.h time.h unistd.h) + AC_CHECK_FUNCS(gettimeofday) +]) diff --git a/m4/tmpdir.m4 b/m4/tmpdir.m4 new file mode 100644 index 0000000..5b09d03 --- /dev/null +++ b/m4/tmpdir.m4 @@ -0,0 +1,9 @@ +#serial 1 + +# Prerequisites for lib/tmpdir.c + +AC_DEFUN([gt_TMPDIR], +[ + AC_STAT_MACROS_BROKEN + AC_CHECK_FUNCS(__secure_getenv) +]) |