2 * Replacement for a missing mkstemp.
4 * Provides the same functionality as the library function mkstemp for those
5 * systems that don't have it.
7 * The canonical version of this file is maintained in the rra-c-util package,
8 * which can be found at <https://www.eyrie.org/~eagle/software/rra-c-util/>.
10 * Written by Russ Allbery <eagle@eyrie.org>
12 * The authors hereby relinquish any claim to any copyright that they may have
13 * in this work, whether granted under contract or by operation of law or
14 * international treaty, and hereby commit to the public, at large, that they
15 * shall not, at any time in the future, seek to enforce any copyright in this
16 * work against any person or entity, or prevent any person or entity from
17 * copying, publishing, distributing or creating derivative works of this
22 #include <portable/system.h>
26 #ifdef HAVE_SYS_TIME_H
27 # include <sys/time.h>
32 * If we're running the test suite, rename mkstemp to avoid conflicts with the
33 * system version. #undef it first because some systems may define it to
38 # define mkstemp test_mkstemp
39 int test_mkstemp(char *);
42 /* Pick the longest available integer type. */
43 #if HAVE_LONG_LONG_INT
44 typedef unsigned long long long_int_type;
46 typedef unsigned long long_int_type;
50 mkstemp(char *template)
52 static const char letters[] =
53 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
57 long_int_type randnum, working;
61 * Make sure we have a valid template and initialize p to point at the
62 * beginning of the template portion of the string.
64 length = strlen(template);
69 XXXXXX = template + length - 6;
70 if (strcmp(XXXXXX, "XXXXXX") != 0) {
75 /* Get some more-or-less random information. */
76 gettimeofday(&tv, NULL);
77 randnum = ((long_int_type) tv.tv_usec << 16) ^ tv.tv_sec ^ getpid();
80 * Now, try to find a working file name. We try no more than TMP_MAX file
83 for (tries = 0; tries < TMP_MAX; tries++) {
84 for (working = randnum, i = 0; i < 6; i++) {
85 XXXXXX[i] = letters[working % 62];
88 fd = open(template, O_RDWR | O_CREAT | O_EXCL, 0600);
89 if (fd >= 0 || (errno != EEXIST && errno != EISDIR))
93 * This is a relatively random increment. Cut off the tail end of
94 * tv_usec since it's often predictable.
96 randnum += (tv.tv_usec >> 10) & 0xfff;