ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/paths.c
Revision: 2.1
Committed: Sun Jun 8 12:01:52 2003 UTC (20 years, 10 months ago) by schorsch
Content type: text/plain
Branch: MAIN
Log Message:
Cross-platform functions to find a writeable directory for tempfiles,
create unique filenames therein, and create a file.

File Contents

# User Rev Content
1 schorsch 2.1 #ifndef lint
2     static const char RCSid[] = "$Id$";
3     #endif
4     /*
5     * Find a writeable tempfile directory.
6     * Create unique filenames therein, and possibly open the file.
7     *
8     */
9    
10     #include "copyright.h"
11    
12     #include "paths.h"
13    
14    
15     #define TEMPFILE_TEMPLATE "rtXXXXXX"
16     static const char *defaultpaths[] = DEFAULT_TEMPDIRS;
17    
18    
19     /* Return a writeable directory for temporary files */
20     /* If s is NULL, we return a static string */
21     char *
22     temp_directory(char *s, size_t len)
23     {
24     static char td[PATH_MAX] = "\0"; /* remember */
25     char * ts = NULL;
26     int i = 0;
27    
28     if (td[0] != '\0') { /* we already have one */
29     if (s == NULL) { return td; }
30     strncpy(s, td, len);
31     s[len-1] = '\0';
32     return s;
33     }
34     /* check where TMP and TEMP point to */
35     ts = getenv("TMP");
36     if (ts != NULL && access(ts, W_OK) == 0) {
37     strncpy(td, ts, sizeof(td));
38     td[sizeof(td)-1] = '\0';
39     }
40     if (ts == NULL) {
41     ts = getenv("TEMP");
42     if (ts != NULL && access(ts, W_OK) == 0) {
43     strncpy(td, ts, sizeof(td));
44     td[sizeof(td)-1] = '\0';
45     }
46     }
47     /* check the platform specific default paths in order */
48     while (ts == NULL) {
49     if (defaultpaths[i] == NULL) {
50     break;
51     }
52     if (access(defaultpaths[i], W_OK) == 0) {
53     ts = strncpy(td, defaultpaths[i], sizeof(td));
54     td[sizeof(td)-1] = '\0';
55     break;
56     }
57     i++;
58     }
59     /* we found something */
60     if (ts != NULL) {
61     if (s == NULL) { return td; }
62     strncpy(s, ts, len);
63     s[len-1] = '\0';
64     return s;
65     }
66     return NULL;
67     }
68    
69    
70     /* Concatenate two strings, leaving exactly one DIRSEP in between */
71     char *
72     append_filepath(char *s1, char *s2, size_t len)
73     {
74     size_t siz;
75     char *s;
76    
77     siz = strlen(s1);
78     /* XXX siz > len is an error */
79     while (siz > 1 && ISDIRSEP(s1[siz-1])) {
80     s1[siz-1] = '\0';
81     siz--;
82     }
83     if (siz+1 <= len) {
84     s1[siz] = DIRSEP;
85     siz++;
86     }
87     while (ISDIRSEP(s2[0])) {
88     s2++;
89     }
90     s = strncat(s1, s2, len-siz);
91     return s;
92     }
93    
94    
95     /* Do the actual work for tempfiles, except for the uniquification */
96     static char *
97     prepare_tmpname(char *s, size_t len, char *templ)
98     {
99     static char lp[PATH_MAX] = "\0"; /* remember what we found last time */
100     char *ts = NULL;
101    
102     if (s == NULL) { /* return our static string */
103     s = lp;
104     len = sizeof(lp);
105     }
106    
107     ts = temp_directory(s, len);
108     if (ts == NULL) { return NULL; }
109     ts = append_filepath(ts, templ != NULL ? templ : TEMPFILE_TEMPLATE, len);
110     return ts;
111     }
112    
113    
114     /* Compose a *currently* unique name within a temporary directory */
115     /* If s is NULL, we return a static string */
116     /* If templ is NULL, we take our default template */
117     /* WARNING: On Windows, there's a maximum of 27 unique names within
118     one process for the same template. */
119     char *
120     temp_filename(char *s, size_t len, char *templ)
121     {
122     char *ts = NULL;
123    
124     ts = prepare_tmpname(s, len, templ);
125     if (ts == NULL) { return NULL; }
126     return mktemp(ts);
127     }
128    
129    
130     /* Open a unique temp file in a safe way (not safe on Windows) */
131     /* If s is NULL, we use a static string the caller won't learn about */
132     /* If templ is NULL, we take our default template */
133     /* This one is supposed to protect against race conditions on unix */
134     /* WARNING: On Windows, there's no protection against race conditions */
135     /* WARNING: On Windows, there's a maximum of 27 unique names within
136     one process for the same template. */
137     int
138     temp_file(char *s, size_t len, char *templ)
139     {
140     char *ts = NULL;
141    
142     ts = prepare_tmpname(s, len, templ);
143     if (ts == NULL) return -1;
144     #ifdef _WIN32
145     ts = mktemp(ts);
146     if (ts == NULL) return -1;
147     return fopen(ts, "r+b");
148     #else
149     return mkstemp(ts);
150     #endif
151     }
152    
153    
154     #ifdef MODULE_TEST
155     int main()
156     {
157     static char p[PATH_MAX] = "\0";
158     char * pp, *qq = NULL;
159     pp = temp_directory(p, sizeof(p));
160    
161     printf("%s\n", pp);
162     qq = temp_filename(pp, sizeof(p), "//something/else_XXXXXX");
163     printf("%s\n", qq);
164     qq = temp_filename(pp, sizeof(p), NULL);
165     printf("%s\n", qq);
166     }
167     #endif
168