tempname.c 8.9 KB

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