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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
|
/*
* Copyright (c) 1999-2003 Smithsonian Astrophysical Observatory
*/
#include <mkrtemp.h>
/*
*
* mkrtemp -- make a unique temportary filename that is hard to guess,
* and, optionally, open it using securely: O_CREAT|O_EXCL|O_RDWR, 0600.
* This should be an improvement over mktmp and mkstmp because of the use
* of usec of gettimeofday() to make up the filename -- harder to guess.
* If you want to use a random number generater instead, set the environment
* variable MTRTEMP_RAND to "true".
*
* The routine also allows for both a prefix and suffix to be specified,
* so that you can create files with extensions. Either of these can be NULL.
*
*/
#ifdef ANSI_FUNC
int mkrtemp(char *prefix, char *suffix, char *path, int len, int doopen)
#else
int mkrtemp(prefix, suffix, path, len, doopen)
char *prefix;
char *suffix;
char *path;
int len;
int doopen;
#endif
{
char *s;
int fd;
long lval;
struct stat sbuf;
struct timeval tv;
static int _method=0;
/* clear the buffer */
*path = '\0';
if( len <=0 )
return -1;
/* check validity of the target directory, if necessary */
if( prefix && *prefix ){
int bad=0;
char *xprefix=xstrdup(prefix);
for(s=xprefix; *s; s++)
;
for(; s>=xprefix ; s--){
if( (*s == '/') || (*s == '\\') ){
*s = '\0';
if( stat(xprefix, &sbuf) ){
bad = -1;
}
else if( !S_ISDIR(sbuf.st_mode) ){
errno = ENOTDIR;
bad = -1;
}
break;
}
}
free(xprefix);
if( bad )
return -1;
}
/* initialize method */
if( !_method ){
/* assume gettimeofday() usecs */
_method = 1;
/* but allow for using RNG */
if( (s=(char *)getenv("MKRTEMP_RAND")) && istrue(s) )
_method = 2;
gettimeofday(&tv, NULL);
switch(_method){
case 1:
break;
case 2:
srand48(tv.tv_sec+tv.tv_usec);
break;
}
}
/* main loop -- make up a new file name and check for non-existence */
lval = 0;
while( 1 ){
switch(_method){
case 1:
gettimeofday(&tv, NULL);
/* avoid repeated checks on same value of lval */
if( lval == tv.tv_usec )
lval /= 2;
else
lval = tv.tv_usec;
break;
case 2:
lval = lrand48();
break;
default:
return -1;
}
snprintf(path, len, "%s%ld%s",
(prefix?prefix:""), lval, (suffix?suffix:""));
if( doopen ){
if( (fd=open(path, O_CREAT|O_EXCL|O_RDWR, 0600)) >= 0)
return fd;
if (errno != EEXIST)
return -1;
}
else if( lstat(path, &sbuf) )
return errno==ENOENT ? 0 : -1;
}
}
|