Merge branch 'gf/maint-sh-setup-nongit-ok' into maint-1.6.6
[tgit.git] / compat / mkstemps.c
blob14179c8e6d24f4b570c92f203eaf5ca44c8434da
1 #include "../git-compat-util.h"
3 /* Adapted from libiberty's mkstemp.c. */
5 #undef TMP_MAX
6 #define TMP_MAX 16384
8 int gitmkstemps(char *pattern, int suffix_len)
10 static const char letters[] =
11 "abcdefghijklmnopqrstuvwxyz"
12 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
13 "0123456789";
14 static const int num_letters = 62;
15 uint64_t value;
16 struct timeval tv;
17 char *template;
18 size_t len;
19 int fd, count;
21 len = strlen(pattern);
23 if (len < 6 + suffix_len) {
24 errno = EINVAL;
25 return -1;
28 if (strncmp(&pattern[len - 6 - suffix_len], "XXXXXX", 6)) {
29 errno = EINVAL;
30 return -1;
34 * Replace pattern's XXXXXX characters with randomness.
35 * Try TMP_MAX different filenames.
37 gettimeofday(&tv, NULL);
38 value = ((size_t)(tv.tv_usec << 16)) ^ tv.tv_sec ^ getpid();
39 template = &pattern[len - 6 - suffix_len];
40 for (count = 0; count < TMP_MAX; ++count) {
41 uint64_t v = value;
42 /* Fill in the random bits. */
43 template[0] = letters[v % num_letters]; v /= num_letters;
44 template[1] = letters[v % num_letters]; v /= num_letters;
45 template[2] = letters[v % num_letters]; v /= num_letters;
46 template[3] = letters[v % num_letters]; v /= num_letters;
47 template[4] = letters[v % num_letters]; v /= num_letters;
48 template[5] = letters[v % num_letters]; v /= num_letters;
50 fd = open(pattern, O_CREAT | O_EXCL | O_RDWR, 0600);
51 if (fd > 0)
52 return fd;
54 * Fatal error (EPERM, ENOSPC etc).
55 * It doesn't make sense to loop.
57 if (errno != EEXIST)
58 break;
60 * This is a random value. It is only necessary that
61 * the next TMP_MAX values generated by adding 7777 to
62 * VALUE are different with (module 2^32).
64 value += 7777;
66 /* We return the null string if we can't find a unique file name. */
67 pattern[0] = '\0';
68 errno = EINVAL;
69 return -1;