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

# Content
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