]>
Commit | Line | Data |
---|---|---|
0620b39b DA |
1 | #include "../git-compat-util.h" |
2 | ||
3 | /* Adapted from libiberty's mkstemp.c. */ | |
4 | ||
5 | #undef TMP_MAX | |
6 | #define TMP_MAX 16384 | |
7 | ||
8 | int gitmkstemps(char *pattern, int suffix_len) | |
9 | { | |
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; | |
20 | ||
21 | len = strlen(pattern); | |
22 | ||
23 | if (len < 6 + suffix_len) { | |
24 | errno = EINVAL; | |
25 | return -1; | |
26 | } | |
27 | ||
28 | if (strncmp(&pattern[len - 6 - suffix_len], "XXXXXX", 6)) { | |
29 | errno = EINVAL; | |
30 | return -1; | |
31 | } | |
32 | ||
33 | /* | |
34 | * Replace pattern's XXXXXX characters with randomness. | |
35 | * Try TMP_MAX different filenames. | |
36 | */ | |
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; | |
49 | ||
50 | fd = open(pattern, O_CREAT | O_EXCL | O_RDWR, 0600); | |
51 | if (fd > 0) | |
52 | return fd; | |
53 | /* | |
54 | * Fatal error (EPERM, ENOSPC etc). | |
55 | * It doesn't make sense to loop. | |
56 | */ | |
57 | if (errno != EEXIST) | |
58 | break; | |
59 | /* | |
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). | |
63 | */ | |
64 | value += 7777; | |
65 | } | |
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; | |
70 | } |