diff options
Diffstat (limited to 'funtools/util/mkrtemp.c')
-rw-r--r-- | funtools/util/mkrtemp.c | 113 |
1 files changed, 113 insertions, 0 deletions
diff --git a/funtools/util/mkrtemp.c b/funtools/util/mkrtemp.c new file mode 100644 index 0000000..51e1130 --- /dev/null +++ b/funtools/util/mkrtemp.c @@ -0,0 +1,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; + } +} |