initial import
[vym] / mkdtemp.cpp
1 #include <stdint.h>
2 #include <string.h>
3 #include <errno.h>
4 #include <io.h>
5 #include <sys/time.h>
6
7 extern "C" {
8 pid_t getpid (void);
9 }
10
11 char *
12 mkdtemp(char *tmpl)
13 {
14     // Implementation based on GLIBC implementation.
15
16     static const char letters[] =
17         "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
18
19     static uint64_t value;
20
21     const unsigned int ATTEMPTS_MIN = (62 * 62 * 62);
22
23     int save_errno = errno;
24
25     size_t len = strlen(tmpl);
26     if (len < 6 || strcmp(&tmpl[len - 6], "XXXXXX"))
27     {
28         errno = EINVAL;
29         return NULL;
30     }
31
32     char *XXXXXX = &tmpl[len - 6];
33
34     uint64_t random_time_bits = time(NULL);
35
36     value += (random_time_bits ^ getpid());
37
38     unsigned int count;
39     for (count = 0; count < ATTEMPTS_MIN; value += 7777, ++count)
40     {
41         uint64_t v = value;
42
43         XXXXXX[0] = letters[v % 62];
44         v /= 62;
45         XXXXXX[1] = letters[v % 62];
46         v /= 62;
47         XXXXXX[2] = letters[v % 62];
48         v /= 62;
49         XXXXXX[3] = letters[v % 62];
50         v /= 62;
51         XXXXXX[4] = letters[v % 62];
52         v /= 62;
53         XXXXXX[5] = letters[v % 62];
54
55                 if (mkdir(tmpl) == 0)
56         {
57             errno = save_errno;
58                         return tmpl;
59         }
60
61                 if (errno != EEXIST)
62                         return NULL;
63     }
64
65     errno = EEXIST;
66     return NULL;
67 }