1 /* $Id: mkstemp.c 5329 2002-03-17 07:39:14Z rra $
3 ** Replacement for a missing mkstemp.
5 ** Written by Russ Allbery <rra@stanford.edu>
6 ** This work is hereby placed in the public domain by its author.
8 ** Provides the same functionality as the library function mkstemp for those
9 ** systems that don't have it.
14 #include "portable/time.h"
18 /* If we're running the test suite, rename mkstemp to avoid conflicts with the
19 system version. #undef it first because some systems may define it to
23 # define mkstemp test_mkstemp
24 int test_mkstemp(char *);
27 /* Pick the longest available integer type. */
29 typedef unsigned long long long_int_type;
31 typedef unsigned long long_int_type;
35 mkstemp(char *template)
37 static const char letters[] =
38 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
42 long_int_type randnum, working;
45 /* Make sure we have a valid template and initialize p to point at the
46 beginning of the template portion of the string. */
47 length = strlen(template);
52 XXXXXX = template + length - 6;
53 if (strcmp(XXXXXX, "XXXXXX") != 0) {
58 /* Get some more-or-less random information. */
59 gettimeofday(&tv, NULL);
60 randnum = ((long_int_type) tv.tv_usec << 16) ^ tv.tv_sec ^ getpid();
62 /* Now, try to find a working file name. We try no more than TMP_MAX file
64 for (tries = 0; tries < TMP_MAX; tries++) {
65 for (working = randnum, i = 0; i < 6; i++) {
66 XXXXXX[i] = letters[working % 62];
69 fd = open(template, O_RDWR | O_CREAT | O_EXCL, 0600);
70 if (fd >= 0 || errno != EEXIST)
73 /* This is a relatively random increment. Cut off the tail end of
74 tv_usec since it's often predictable. */
75 randnum += (tv.tv_usec >> 10) & 0xfff;