1/* tempname.c - generate the name of a temporary file. 2 3 Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 4 2000, 2001, 2002, 2003, 2005, 2006, 2007 Free Software Foundation, 5 Inc. 6 7 This program is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 2, or (at your option) 10 any later version. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License along 18 with this program; if not, write to the Free Software Foundation, 19 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ 20 21/* Extracted from glibc sysdeps/posix/tempname.c. See also tmpdir.c. */ 22 23#if !_LIBC 24# include <config.h> 25# include "tempname.h" 26#endif 27 28#include <sys/types.h> 29#include <assert.h> 30 31#include <errno.h> 32#ifndef __set_errno 33# define __set_errno(Val) errno = (Val) 34#endif 35 36#include <stdio.h> 37#ifndef P_tmpdir 38# define P_tmpdir "/tmp" 39#endif 40#ifndef TMP_MAX 41# define TMP_MAX 238328 42#endif 43#ifndef __GT_FILE 44# define __GT_FILE 0 45# define __GT_BIGFILE 1 46# define __GT_DIR 2 47# define __GT_NOCREATE 3 48#endif 49 50#include <stddef.h> 51#include <stdlib.h> 52#include <string.h> 53 54#include <fcntl.h> 55#include <sys/time.h> 56#include <stdint.h> 57#include <unistd.h> 58 59#include <sys/stat.h> 60 61#if _LIBC 62# define struct_stat64 struct stat64 63# define small_open __open 64# define large_open __open64 65#else 66# define struct_stat64 struct stat 67# define small_open open 68# define large_open open 69# define __gen_tempname gen_tempname 70# define __getpid getpid 71# define __gettimeofday gettimeofday 72# define __mkdir mkdir 73# define __lxstat64(version, file, buf) lstat (file, buf) 74# define __xstat64(version, file, buf) stat (file, buf) 75#endif 76 77#if ! (HAVE___SECURE_GETENV || _LIBC) 78# define __secure_getenv getenv 79#endif 80 81#ifdef _LIBC 82# include <hp-timing.h> 83# if HP_TIMING_AVAIL 84# define RANDOM_BITS(Var) \ 85 if (__builtin_expect (value == UINT64_C (0), 0)) \ 86 { \ 87 /* If this is the first time this function is used initialize \ 88 the variable we accumulate the value in to some somewhat \ 89 random value. If we'd not do this programs at startup time \ 90 might have a reduced set of possible names, at least on slow \ 91 machines. */ \ 92 struct timeval tv; \ 93 __gettimeofday (&tv, NULL); \ 94 value = ((uint64_t) tv.tv_usec << 16) ^ tv.tv_sec; \ 95 } \ 96 HP_TIMING_NOW (Var) 97# endif 98#endif 99 100/* Use the widest available unsigned type if uint64_t is not 101 available. The algorithm below extracts a number less than 62**6 102 (approximately 2**35.725) from uint64_t, so ancient hosts where 103 uintmax_t is only 32 bits lose about 3.725 bits of randomness, 104 which is better than not having mkstemp at all. */ 105#if !defined UINT64_MAX && !defined uint64_t 106# define uint64_t uintmax_t 107#endif 108 109#if _LIBC 110/* Return nonzero if DIR is an existent directory. */ 111static int 112direxists (const char *dir) 113{ 114 struct_stat64 buf; 115 return __xstat64 (_STAT_VER, dir, &buf) == 0 && S_ISDIR (buf.st_mode); 116} 117 118/* Path search algorithm, for tmpnam, tmpfile, etc. If DIR is 119 non-null and exists, uses it; otherwise uses the first of $TMPDIR, 120 P_tmpdir, /tmp that exists. Copies into TMPL a template suitable 121 for use with mk[s]temp. Will fail (-1) if DIR is non-null and 122 doesn't exist, none of the searched dirs exists, or there's not 123 enough space in TMPL. */ 124int 125__path_search (char *tmpl, size_t tmpl_len, const char *dir, const char *pfx, 126 int try_tmpdir) 127{ 128 const char *d; 129 size_t dlen, plen; 130 131 if (!pfx || !pfx[0]) 132 { 133 pfx = "file"; 134 plen = 4; 135 } 136 else 137 { 138 plen = strlen (pfx); 139 if (plen > 5) 140 plen = 5; 141 } 142 143 if (try_tmpdir) 144 { 145 d = __secure_getenv ("TMPDIR"); 146 if (d != NULL && direxists (d)) 147 dir = d; 148 else if (dir != NULL && direxists (dir)) 149 /* nothing */ ; 150 else 151 dir = NULL; 152 } 153 if (dir == NULL) 154 { 155 if (direxists (P_tmpdir)) 156 dir = P_tmpdir; 157 else if (strcmp (P_tmpdir, "/tmp") != 0 && direxists ("/tmp")) 158 dir = "/tmp"; 159 else 160 { 161 __set_errno (ENOENT); 162 return -1; 163 } 164 } 165 166 dlen = strlen (dir); 167 while (dlen > 1 && dir[dlen - 1] == '/') 168 dlen--; /* remove trailing slashes */ 169 170 /* check we have room for "${dir}/${pfx}XXXXXX\0" */ 171 if (tmpl_len < dlen + 1 + plen + 6 + 1) 172 { 173 __set_errno (EINVAL); 174 return -1; 175 } 176 177 sprintf (tmpl, "%.*s/%.*sXXXXXX", (int) dlen, dir, (int) plen, pfx); 178 return 0; 179} 180#endif /* _LIBC */ 181 182/* These are the characters used in temporary file names. */ 183static const char letters[] = 184"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; 185 186/* Generate a temporary file name based on TMPL. TMPL must match the 187 rules for mk[s]temp (i.e. end in "XXXXXX"). The name constructed 188 does not exist at the time of the call to __gen_tempname. TMPL is 189 overwritten with the result. 190 191 KIND may be one of: 192 __GT_NOCREATE: simply verify that the name does not exist 193 at the time of the call. 194 __GT_FILE: create the file using open(O_CREAT|O_EXCL) 195 and return a read-write fd. The file is mode 0600. 196 __GT_BIGFILE: same as __GT_FILE but use open64(). 197 __GT_DIR: create a directory, which will be mode 0700. 198 199 We use a clever algorithm to get hard-to-predict names. */ 200int 201__gen_tempname (char *tmpl, int kind) 202{ 203 int len; 204 char *XXXXXX; 205 static uint64_t value; 206 uint64_t random_time_bits; 207 unsigned int count; 208 int fd = -1; 209 int save_errno = errno; 210 struct_stat64 st; 211 212 /* A lower bound on the number of temporary files to attempt to 213 generate. The maximum total number of temporary file names that 214 can exist for a given template is 62**6. It should never be 215 necessary to try all these combinations. Instead if a reasonable 216 number of names is tried (we define reasonable as 62**3) fail to 217 give the system administrator the chance to remove the problems. */ 218#define ATTEMPTS_MIN (62 * 62 * 62) 219 220 /* The number of times to attempt to generate a temporary file. To 221 conform to POSIX, this must be no smaller than TMP_MAX. */ 222#if ATTEMPTS_MIN < TMP_MAX 223 unsigned int attempts = TMP_MAX; 224#else 225 unsigned int attempts = ATTEMPTS_MIN; 226#endif 227 228 len = strlen (tmpl); 229 if (len < 6 || strcmp (&tmpl[len - 6], "XXXXXX")) 230 { 231 __set_errno (EINVAL); 232 return -1; 233 } 234 235 /* This is where the Xs start. */ 236 XXXXXX = &tmpl[len - 6]; 237 238 /* Get some more or less random data. */ 239#ifdef RANDOM_BITS 240 RANDOM_BITS (random_time_bits); 241#else 242 { 243 struct timeval tv; 244 __gettimeofday (&tv, NULL); 245 random_time_bits = ((uint64_t) tv.tv_usec << 16) ^ tv.tv_sec; 246 } 247#endif 248 value += random_time_bits ^ __getpid (); 249 250 for (count = 0; count < attempts; value += 7777, ++count) 251 { 252 uint64_t v = value; 253 254 /* Fill in the random bits. */ 255 XXXXXX[0] = letters[v % 62]; 256 v /= 62; 257 XXXXXX[1] = letters[v % 62]; 258 v /= 62; 259 XXXXXX[2] = letters[v % 62]; 260 v /= 62; 261 XXXXXX[3] = letters[v % 62]; 262 v /= 62; 263 XXXXXX[4] = letters[v % 62]; 264 v /= 62; 265 XXXXXX[5] = letters[v % 62]; 266 267 switch (kind) 268 { 269 case __GT_FILE: 270 fd = small_open (tmpl, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR); 271 break; 272 273 case __GT_BIGFILE: 274 fd = large_open (tmpl, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR); 275 break; 276 277 case __GT_DIR: 278 fd = __mkdir (tmpl, S_IRUSR | S_IWUSR | S_IXUSR); 279 break; 280 281 case __GT_NOCREATE: 282 /* This case is backward from the other three. __gen_tempname 283 succeeds if __xstat fails because the name does not exist. 284 Note the continue to bypass the common logic at the bottom 285 of the loop. */ 286 if (__lxstat64 (_STAT_VER, tmpl, &st) < 0) 287 { 288 if (errno == ENOENT) 289 { 290 __set_errno (save_errno); 291 return 0; 292 } 293 else 294 /* Give up now. */ 295 return -1; 296 } 297 continue; 298 299 default: 300 assert (! "invalid KIND in __gen_tempname"); 301 } 302 303 if (fd >= 0) 304 { 305 __set_errno (save_errno); 306 return fd; 307 } 308 else if (errno != EEXIST) 309 return -1; 310 } 311 312 /* We got out of the loop because we ran out of combinations to try. */ 313 __set_errno (EEXIST); 314 return -1; 315} 316