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