X-Git-Url: http://erislabs.net/gitweb/?a=blobdiff_plain;f=lib%2Ftempname.c;h=e30872a708c8a7f919edd35bd22a980c13af6574;hb=609f9cb77296a39e8776d420091a66f2ea5acb72;hp=5ead95ea3cc087634ab5b6907e1372de02ee61a6;hpb=9b10f7706c41cdad4cecbc0b17b7eab499b74c49;p=gnulib.git diff --git a/lib/tempname.c b/lib/tempname.c index 5ead95ea3..e30872a70 100644 --- a/lib/tempname.c +++ b/lib/tempname.c @@ -1,20 +1,21 @@ -/* Copyright (C) 1991-1999, 2000 Free Software Foundation, Inc. - This file is part of the GNU C Library. +/* tempname.c - generate the name of a temporary file. - 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. + Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, + 2000, 2001, 2002 Free Software Foundation, Inc. - The GNU C Library is distributed in the hope that it will be useful, + 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 - Library General Public License for more details. + 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 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. */ + 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_CONFIG_H # include @@ -44,10 +45,11 @@ #if STDC_HEADERS || _LIBC # include -# include # include #endif +#include + #if HAVE_FCNTL_H || _LIBC # include #endif @@ -59,6 +61,9 @@ #if HAVE_STDINT_H || _LIBC # include #endif +#if HAVE_INTTYPES_H +# include +#endif #if HAVE_UNISTD_H || _LIBC # include @@ -107,6 +112,25 @@ # define __secure_getenv getenv #endif +#ifdef _LIBC +# include +# if HP_TIMING_AVAIL +# define RANDOM_BITS(Var) \ + if (__builtin_expect (value == UINT64_C (0), 0)) \ + { \ + /* If this is the first time this function is used initialize \ + the variable we accumulate the value in to some somewhat \ + random value. If we'd not do this programs at startup time \ + might have a reduced set of possible names, at least on slow \ + machines. */ \ + struct timeval tv; \ + __gettimeofday (&tv, NULL); \ + value = ((uint64_t) tv.tv_usec << 16) ^ tv.tv_sec; \ + } \ + HP_TIMING_NOW (Var) +# endif +#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 @@ -212,10 +236,23 @@ __gen_tempname (char *tmpl, int kind) char *XXXXXX; static uint64_t value; uint64_t random_time_bits; - int count, fd = -1; + unsigned int count; + int fd = -1; int save_errno = errno; struct_stat64 st; + /* A lower bound on the number of temporary files to attempt to + generate. The maximum total number of temporary file names that + can exist for a given template is 62**6. It should never be + necessary to try all these combinations. Instead if a reasonable + number of names is tried (we define reasonable as 62**3) fail to + give the system administrator the chance to remove the problems. */ + unsigned int attempts_min = 62 * 62 * 62; + + /* The number of times to attempt to generate a temporary file. To + conform to POSIX, this must be no smaller than TMP_MAX. */ + unsigned int attempts = attempts_min < TMP_MAX ? TMP_MAX : attempts_min; + len = strlen (tmpl); if (len < 6 || strcmp (&tmpl[len - 6], "XXXXXX")) { @@ -227,18 +264,22 @@ __gen_tempname (char *tmpl, int kind) XXXXXX = &tmpl[len - 6]; /* Get some more or less random data. */ -#if HAVE_GETTIMEOFDAY || _LIBC +#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 +# else random_time_bits = time (NULL); +# endif #endif value += random_time_bits ^ __getpid (); - for (count = 0; count < TMP_MAX; value += 7777, ++count) + for (count = 0; count < attempts; value += 7777, ++count) { uint64_t v = value;