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;
}
}
|