OpenCoverage

tempname.c

Absolute File Name:/home/opencoverage/opencoverage/guest-scripts/coreutils/src/lib/tempname.c
Source codeSwitch to Preprocessed file
LineSourceCount
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. */-
106static int-
107direxists (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. */-
119int-
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-
177static inline bool _GL_ATTRIBUTE_PURE-
178check_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:
  • cp
  • ln
  • mktemp
  • mv
596
181}-
182-
183/* These are the characters used in temporary file names. */-
184static const char letters[] =-
185"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";-
186-
187int-
188try_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
len < x_suffix_len + suffixlenDescription
TRUEnever evaluated
FALSEevaluated 596 times by 4 tests
Evaluated by:
  • cp
  • ln
  • mktemp
  • mv
0-596
217 || ! check_x_suffix (&tmpl[len - x_suffix_len - suffixlen],
! check_x_suff... x_suffix_len)Description
TRUEnever evaluated
FALSEevaluated 596 times by 4 tests
Evaluated by:
  • cp
  • ln
  • mktemp
  • mv
0-596
218 x_suffix_len))
! check_x_suff... x_suffix_len)Description
TRUEnever evaluated
FALSEevaluated 596 times by 4 tests
Evaluated by:
  • cp
  • ln
  • mktemp
  • mv
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)
! rand_srcDescription
TRUEnever evaluated
FALSEevaluated 596 times by 4 tests
Evaluated by:
  • cp
  • ln
  • mktemp
  • mv
0-596
230 return -1;
never executed: return -1;
0
231-
232 for (count = 0; count < attempts; ++count)
count < attemptsDescription
TRUEevaluated 596 times by 4 tests
Evaluated by:
  • cp
  • ln
  • mktemp
  • mv
FALSEnever evaluated
0-596
233 {-
234 size_t i;-
235-
236 for (i = 0; i < x_suffix_len; i++)
i < x_suffix_lenDescription
TRUEevaluated 2470 times by 4 tests
Evaluated by:
  • cp
  • ln
  • mktemp
  • mv
FALSEevaluated 596 times by 4 tests
Evaluated by:
  • cp
  • ln
  • mktemp
  • mv
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:
  • cp
  • ln
  • mktemp
  • mv
2470
238-
239 fd = tryfunc (tmpl, args);-
240 if (fd >= 0)
fd >= 0Description
TRUEevaluated 594 times by 4 tests
Evaluated by:
  • cp
  • ln
  • mktemp
  • mv
FALSEevaluated 2 times by 2 tests
Evaluated by:
  • cp
  • mktemp
2-594
241 {-
242 __set_errno (save_errno);-
243 goto done;
executed 594 times by 4 tests: goto done;
Executed by:
  • cp
  • ln
  • mktemp
  • mv
594
244 }-
245 else if (errno != EEXIST)
(*__errno_location ()) != 17Description
TRUEevaluated 2 times by 2 tests
Evaluated by:
  • cp
  • mktemp
FALSEnever evaluated
0-2
246 {-
247 fd = -1;-
248 goto done;
executed 2 times by 2 tests: goto done;
Executed by:
  • cp
  • mktemp
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:
  • cp
  • ln
  • mktemp
  • mv
596
265}-
266-
267static int-
268try_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:
  • mktemp
13
272 (*openflags & ~O_ACCMODE)
executed 13 times by 1 test: return open (tmpl, (*openflags & ~ 0003 ) | 02 | 0100 | 0200 , 0400 | 0200 );
Executed by:
  • mktemp
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:
  • mktemp
13
274}-
275-
276static int-
277try_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:
  • mktemp
549
280}-
281-
282static int-
283try_nocreate (char *tmpl, void *flags _GL_UNUSED)-
284{-
285 struct_stat64 st;-
286-
287 if (__lxstat64 (_STAT_VER, tmpl, &st) == 0 || errno == EOVERFLOW)
lstat (tmpl, &st) == 0Description
TRUEnever evaluated
FALSEevaluated 4 times by 1 test
Evaluated by:
  • mktemp
(*__errno_location ()) == 75Description
TRUEnever evaluated
FALSEevaluated 4 times by 1 test
Evaluated by:
  • mktemp
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:
  • mktemp
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. */-
306int-
307gen_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:
  • mktemp
13
315 tryfunc = try_file;-
316 break;
executed 13 times by 1 test: break;
Executed by:
  • mktemp
13
317-
318 case __GT_DIR:
executed 549 times by 1 test: case 1:
Executed by:
  • mktemp
549
319 tryfunc = try_dir;-
320 break;
executed 549 times by 1 test: break;
Executed by:
  • mktemp
549
321-
322 case __GT_NOCREATE:
executed 4 times by 1 test: case 2:
Executed by:
  • mktemp
4
323 tryfunc = try_nocreate;-
324 break;
executed 4 times by 1 test: break;
Executed by:
  • mktemp
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:
  • mktemp
566
331}-
332-
333int-
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-
339int-
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 codeSwitch to Preprocessed file

Generated by Squish Coco 4.1.2