1
1
/* tempname.c - generate the name of a temporary file.
3
Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
4
2000, 2001, 2002, 2003, 2005, 2006, 2007 Free Software Foundation,
3
Copyright (C) 1991-2003, 2005-2007, 2009-2010 Free Software Foundation, Inc.
7
5
This program is free software: you can redistribute it and/or modify
8
6
it under the terms of the GNU General Public License as published by
61
62
# define struct_stat64 struct stat64
62
# define small_open __open
63
# define large_open __open64
65
64
# define struct_stat64 struct stat
66
# define small_open open
67
# define large_open open
68
65
# define __gen_tempname gen_tempname
69
66
# define __getpid getpid
70
67
# define __gettimeofday gettimeofday
71
68
# define __mkdir mkdir
70
# define __open64 open
72
71
# define __lxstat64(version, file, buf) lstat (file, buf)
73
72
# define __xstat64(version, file, buf) stat (file, buf)
81
80
# include <hp-timing.h>
82
81
# if HP_TIMING_AVAIL
83
82
# define RANDOM_BITS(Var) \
84
if (__builtin_expect (value == UINT64_C (0), 0)) \
86
/* If this is the first time this function is used initialize \
87
the variable we accumulate the value in to some somewhat \
88
random value. If we'd not do this programs at startup time \
89
might have a reduced set of possible names, at least on slow \
92
__gettimeofday (&tv, NULL); \
93
value = ((uint64_t) tv.tv_usec << 16) ^ tv.tv_sec; \
83
if (__builtin_expect (value == UINT64_C (0), 0)) \
85
/* If this is the first time this function is used initialize \
86
the variable we accumulate the value in to some somewhat \
87
random value. If we'd not do this programs at startup time \
88
might have a reduced set of possible names, at least on slow \
91
__gettimeofday (&tv, NULL); \
92
value = ((uint64_t) tv.tv_usec << 16) ^ tv.tv_sec; \
95
94
HP_TIMING_NOW (Var)
137
136
plen = strlen (pfx);
144
143
d = __secure_getenv ("TMPDIR");
145
144
if (d != NULL && direxists (d))
147
146
else if (dir != NULL && direxists (dir))
154
153
if (direxists (P_tmpdir))
156
155
else if (strcmp (P_tmpdir, "/tmp") != 0 && direxists ("/tmp"))
160
__set_errno (ENOENT);
159
__set_errno (ENOENT);
165
164
dlen = strlen (dir);
166
165
while (dlen > 1 && dir[dlen - 1] == '/')
167
dlen--; /* remove trailing slashes */
166
dlen--; /* remove trailing slashes */
169
168
/* check we have room for "${dir}/${pfx}XXXXXX\0" */
170
169
if (tmpl_len < dlen + 1 + plen + 6 + 1)
183
182
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
185
184
/* Generate a temporary file name based on TMPL. TMPL must match the
186
rules for mk[s]temp (i.e. end in "XXXXXX"). The name constructed
187
does not exist at the time of the call to __gen_tempname. TMPL is
188
overwritten with the result.
185
rules for mk[s]temp (i.e. end in "XXXXXX", possibly with a suffix).
186
The name constructed does not exist at the time of the call to
187
__gen_tempname. TMPL is overwritten with the result.
190
189
KIND may be one of:
191
__GT_NOCREATE: simply verify that the name does not exist
192
at the time of the call.
193
__GT_FILE: create the file using open(O_CREAT|O_EXCL)
194
and return a read-write fd. The file is mode 0600.
195
__GT_BIGFILE: same as __GT_FILE but use open64().
196
__GT_DIR: create a directory, which will be mode 0700.
190
__GT_NOCREATE: simply verify that the name does not exist
191
at the time of the call.
192
__GT_FILE: create the file using open(O_CREAT|O_EXCL)
193
and return a read-write fd. The file is mode 0600.
194
__GT_DIR: create a directory, which will be mode 0700.
198
196
We use a clever algorithm to get hard-to-predict names. */
200
__gen_tempname (char *tmpl, int kind)
198
__gen_tempname (char *tmpl, int suffixlen, int flags, int kind)
227
225
len = strlen (tmpl);
228
if (len < 6 || strcmp (&tmpl[len - 6], "XXXXXX"))
226
if (len < 6 + suffixlen || memcmp (&tmpl[len - 6 - suffixlen], "XXXXXX", 6))
230
228
__set_errno (EINVAL);
234
232
/* This is where the Xs start. */
235
XXXXXX = &tmpl[len - 6];
233
XXXXXX = &tmpl[len - 6 - suffixlen];
237
235
/* Get some more or less random data. */
238
236
#ifdef RANDOM_BITS
264
262
XXXXXX[5] = letters[v % 62];
269
fd = small_open (tmpl, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
273
fd = large_open (tmpl, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
277
fd = __mkdir (tmpl, S_IRUSR | S_IWUSR | S_IXUSR);
281
/* This case is backward from the other three. __gen_tempname
282
succeeds if __xstat fails because the name does not exist.
283
Note the continue to bypass the common logic at the bottom
285
if (__lxstat64 (_STAT_VER, tmpl, &st) < 0)
289
__set_errno (save_errno);
299
assert (! "invalid KIND in __gen_tempname");
269
| O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
273
fd = __mkdir (tmpl, S_IRUSR | S_IWUSR | S_IXUSR);
277
/* This case is backward from the other three. __gen_tempname
278
succeeds if __xstat fails because the name does not exist.
279
Note the continue to bypass the common logic at the bottom
281
if (__lxstat64 (_STAT_VER, tmpl, &st) < 0)
285
__set_errno (save_errno);
295
assert (! "invalid KIND in __gen_tempname");
304
__set_errno (save_errno);
301
__set_errno (save_errno);
307
304
else if (errno != EEXIST)
311
308
/* We got out of the loop because we ran out of combinations to try. */