blob: 12a0430a5763c41456aa4aa1f789cd62827d8ea8 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
|
/*
* This has been derived from the implementation in the FreeBSD libc.
*
* 2000-12-28 Ha*vard Kva*len <havardk@xmms.org>:
* Stripped down to only mkdtemp() and made more portable
*
*/
#include <sys/stat.h>
#include <sys/time.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
static const unsigned char padchar[] =
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
char * mkdtemp(char *path)
{
register char *start, *trv, *suffp;
char *pad;
struct stat sbuf;
int rval;
for (trv = path; *trv; ++trv)
;
suffp = trv;
--trv;
if (trv < path) {
errno = EINVAL;
return NULL;
}
/* Fill space with random characters */
/*
* I hope this is random enough. The orginal implementation
* uses arc4random(3) which is not available everywhere.
*/
while (*trv == 'X') {
int randv = random() % (sizeof(padchar) - 1);
*trv-- = padchar[randv];
}
start = trv + 1;
/*
* check the target directory.
*/
for (;; --trv) {
if (trv <= path)
break;
if (*trv == '/') {
*trv = '\0';
rval = stat(path, &sbuf);
*trv = '/';
if (rval != 0)
return NULL;
if (!S_ISDIR(sbuf.st_mode)) {
errno = ENOTDIR;
return NULL;
}
break;
}
}
for (;;) {
if (mkdir(path, 0700) == 0)
return path;
if (errno != EEXIST)
return NULL;
/* If we have a collision, cycle through the space of filenames */
for (trv = start;;) {
if (*trv == '\0' || trv == suffp)
return NULL;
pad = strchr(padchar, *trv);
if (pad == NULL || !*++pad)
*trv++ = padchar[0];
else {
*trv++ = *pad;
break;
}
}
}
/*NOTREACHED*/
}
|