Back to index

radiance  4R0+20100331
paths.c
Go to the documentation of this file.
00001 #ifndef lint
00002 static const char RCSid[] = "$Id: paths.c,v 2.4 2003/07/01 21:21:40 greg Exp $";
00003 #endif
00004 /*
00005  * Find a writeable tempfile directory.
00006  * Create unique filenames therein, and possibly open the file.
00007  *
00008  */
00009 
00010 #include "copyright.h"
00011 
00012 #include "paths.h"
00013 
00014 
00015 #define TEMPFILE_TEMPLATE "rtXXXXXX"
00016 static const char *defaultpaths[] = DEFAULT_TEMPDIRS;
00017 
00018 
00019 /* Return a writeable directory for temporary files */
00020 /* If s is NULL, we return a static string */
00021 char *
00022 temp_directory(char *s, size_t len)
00023 {
00024        static char td[PATH_MAX]; /* remember */
00025        char * ts = NULL;
00026        int i = 0;
00027        
00028        if (td[0] != '\0') { /* we already have one */
00029               if (s == NULL) { return td; }
00030               strncpy(s, td, len);
00031               s[len-1] = '\0';
00032               return s;
00033        }
00034        /* check where TMP and TEMP point to */
00035        ts = getenv("TMP");
00036        if (ts != NULL && access(ts, W_OK) == 0) {
00037               strncpy(td, ts, sizeof(td));
00038               td[sizeof(td)-1] = '\0';
00039        }
00040        if (ts == NULL) {
00041               ts = getenv("TEMP");
00042               if (ts != NULL && access(ts, W_OK) == 0) {
00043                      strncpy(td, ts, sizeof(td));
00044                      td[sizeof(td)-1] = '\0';
00045               }
00046        }
00047        /* check the platform specific default paths in order */
00048        while (ts == NULL) {
00049               if (defaultpaths[i] == NULL) {
00050                      break;
00051               }
00052               if (access(defaultpaths[i], W_OK) == 0) {
00053                      ts = strncpy(td, defaultpaths[i], sizeof(td));
00054                      td[sizeof(td)-1] = '\0';
00055                      break;
00056               }
00057               i++;
00058        }
00059        /* we found something */
00060        if (ts != NULL) {
00061               if (s == NULL) { return td; }
00062               strncpy(s, ts, len);
00063               s[len-1] = '\0';
00064               return s;
00065        }
00066        return NULL;
00067 }
00068 
00069 
00070 /* Concatenate two strings, leaving exactly one DIRSEP in between */
00071 char *
00072 append_filepath(char *s1, char *s2, size_t len)
00073 {
00074        size_t siz;
00075        char *s;
00076 
00077        siz = strlen(s1);
00078        if (siz > 0) {
00079               /* XXX siz > len is an error */
00080               while (siz > 1 && ISDIRSEP(s1[siz-1])) {
00081                      s1[siz-1] = '\0';
00082                      siz--;
00083               }
00084               if (siz+1 <= len) {
00085                      s1[siz] = DIRSEP;
00086                      siz++;
00087               }
00088        } else if (len >= 2) { /* first path empty */
00089               s1[0] = CURDIR;
00090               s1[1] = DIRSEP;
00091               siz = 2;
00092        } else {
00093               return NULL;
00094        }
00095        while (ISDIRSEP(s2[0])) {
00096               s2++;
00097        }
00098        s = strncat(s1, s2, len-siz);
00099        return s;
00100 }
00101 
00102 
00103 /* Do the actual work for tempfiles, except for the uniquification */
00104 static char *
00105 prepare_tmpname(char *s, size_t len, char *templ)
00106 {
00107        static char lp[PATH_MAX] = "\0";
00108        char *ts = NULL;
00109 
00110        if (s == NULL) { /* return our static string */
00111               s = lp;
00112               len = sizeof(lp);
00113        }
00114 
00115        ts = temp_directory(s, len);
00116        if (ts == NULL) { return NULL; }
00117        ts = append_filepath(ts, templ != NULL ? templ : TEMPFILE_TEMPLATE, len);
00118        return ts;
00119 }
00120 
00121 
00122 /* Compose a *currently* unique name within a temporary directory */
00123 /* If s is NULL, we return a static string */
00124 /* If templ is NULL, we take our default template */
00125 /* WARNING: On Windows, there's a maximum of 27 unique names within
00126             one process for the same template. */
00127 char *
00128 temp_filename(char *s, size_t len, char *templ)
00129 {
00130        char *ts = NULL;
00131 
00132        ts = prepare_tmpname(s, len, templ);
00133        if (ts == NULL) { return NULL; }
00134        return mktemp(ts);
00135 }
00136 
00137 
00138 /* Open a unique temp file in a safe way (not safe on Windows) */
00139 /* If s is NULL, we use a static string the caller won't learn about */
00140 /* If templ is NULL, we take our default template */
00141 /* This one is supposed to protect against race conditions on unix */
00142 /* WARNING: On Windows, there's no protection against race conditions */
00143 /* WARNING: On Windows, there's a maximum of 27 unique names within
00144             one process for the same template. */
00145 int
00146 temp_fd(char *s, size_t len, char *templ)
00147 {
00148        char *ts = NULL;
00149 
00150        ts = prepare_tmpname(s, len, templ);
00151        if (ts == NULL) return -1;
00152 #ifdef _WIN32
00153        ts = mktemp(ts);
00154        if (ts == NULL) return -1;
00155        return open(ts, O_CREAT|O_EXCL, S_IRUSR|S_IWUSR);
00156 #else
00157        return mkstemp(ts);
00158 #endif
00159 }
00160 
00161 /* As above, but returns a file pointer instead of a descriptor */
00162 FILE *
00163 temp_fp(char *s, size_t len, char *templ)
00164 {
00165        int fd = temp_fd(s, len, templ);
00166        if (fd < 0) return NULL;
00167        return fdopen(fd, "w+");
00168 }
00169 
00170 
00171 #ifdef TEST_MODULE
00172 int main()
00173 {
00174        static char p[PATH_MAX] = "\0";
00175        char * pp, *qq = NULL;
00176        pp = temp_directory(p, sizeof(p));
00177        printf("%s\n", pp);
00178 
00179        qq = temp_filename(pp, sizeof(p), "//something/else_XXXXXX");
00180        printf("%s\n", qq);
00181 
00182        qq = temp_filename(pp, sizeof(p), NULL);
00183        printf("%s\n", qq);
00184 }
00185 #endif
00186