1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26
27 #include <stdlib.h>
28 #include <string.h>
29
30 #include <vroot/vroot.h>
31 #include <vroot/args.h>
32
33 #include <string.h>
34 #include <sys/param.h>
35 #include <sys/file.h>
36
37 typedef struct {
38 short init;
39 pathpt vector;
40 const char *env_var;
41 } vroot_patht;
42
43 typedef struct {
44 vroot_patht vroot;
45 vroot_patht path;
46 char full_path[MAXPATHLEN+1];
47 char *vroot_start;
48 char *path_start;
49 char *filename_start;
50 int scan_vroot_first;
51 int cpp_style_path;
52 } vroot_datat, *vroot_datapt;
53
54 static vroot_datat vroot_data= {
55 { 0, NULL, "VIRTUAL_ROOT"},
56 { 0, NULL, "PATH"},
57 "", NULL, NULL, NULL, 0, 1};
58
59 void
add_dir_to_path(const char * path,register pathpt * pointer,register int position)60 add_dir_to_path(const char *path, register pathpt *pointer, register int position)
61 {
62 register int size= 0;
63 register int length;
64 register char *name;
65 register pathcellpt p;
66 pathpt new_path;
67
68 if (*pointer != NULL) {
69 for (p= &((*pointer)[0]); p->path != NULL; p++, size++);
70 if (position < 0)
71 position= size;}
72 else
73 if (position < 0)
74 position= 0;
75 if (position >= size) {
76 new_path= (pathpt)calloc((unsigned)(position+2), sizeof(pathcellt));
77 if (*pointer != NULL) {
78 memcpy((char *)new_path,(char *)(*pointer), size*sizeof(pathcellt));
79 free((char *)(*pointer));};
80 *pointer= new_path;};
81 length= strlen(path);
82 name= (char *)malloc((unsigned)(length+1));
83 (void)strcpy(name, path);
84 if ((*pointer)[position].path != NULL)
85 free((*pointer)[position].path);
86 (*pointer)[position].path= name;
87 (*pointer)[position].length= length;
88 }
89
90 pathpt
parse_path_string(register char * string,register int remove_slash)91 parse_path_string(register char *string, register int remove_slash)
92 {
93 register char *p;
94 pathpt result= NULL;
95
96 if (string != NULL)
97 for (; 1; string= p+1) {
98 if (p= strchr(string, ':')) *p= 0;
99 if ((remove_slash == 1) && !strcmp(string, "/"))
100 add_dir_to_path("", &result, -1);
101 else
102 add_dir_to_path(string, &result, -1);
103 if (p) *p= ':';
104 else return(result);};
105 return((pathpt)NULL);
106 }
107
108 const char *
get_vroot_name(void)109 get_vroot_name(void)
110 {
111 return(vroot_data.vroot.env_var);
112 }
113
114 const char *
get_path_name(void)115 get_path_name(void)
116 {
117 return(vroot_data.path.env_var);
118 }
119
120 void
flush_path_cache(void)121 flush_path_cache(void)
122 {
123 vroot_data.path.init= 0;
124 }
125
126 void
flush_vroot_cache(void)127 flush_vroot_cache(void)
128 {
129 vroot_data.vroot.init= 0;
130 }
131
132 void
scan_path_first(void)133 scan_path_first(void)
134 {
135 vroot_data.scan_vroot_first= 0;
136 }
137
138 void
scan_vroot_first(void)139 scan_vroot_first(void)
140 {
141 vroot_data.scan_vroot_first= 1;
142 }
143
144 void
set_path_style(int style)145 set_path_style(int style)
146 {
147 vroot_data.cpp_style_path= style;
148 }
149
150 char *
get_vroot_path(register char ** vroot,register char ** path,register char ** filename)151 get_vroot_path(register char **vroot, register char **path, register char **filename)
152 {
153 if (vroot != NULL) {
154 if ((*vroot= vroot_data.vroot_start) == NULL)
155 if ((*vroot= vroot_data.path_start) == NULL)
156 *vroot= vroot_data.filename_start;};
157 if (path != NULL) {
158 if ((*path= vroot_data.path_start) == NULL)
159 *path= vroot_data.filename_start;};
160 if (filename != NULL)
161 *filename= vroot_data.filename_start;
162 return(vroot_data.full_path);
163 }
164
165 void
translate_with_thunk(register char * filename,int (* thunk)(char *),pathpt path_vector,pathpt vroot_vector,rwt rw)166 translate_with_thunk(register char *filename, int (*thunk) (char *), pathpt path_vector, pathpt vroot_vector, rwt rw)
167 {
168 register pathcellt *vp;
169 pathcellt *pp;
170 register pathcellt *pp1;
171 register char *p;
172 int flags[256];
173
174 /* Setup path to use */
175 if (rw == rw_write)
176 pp1= NULL; /* Do not use path when writing */
177 else {
178 if (path_vector == VROOT_DEFAULT) {
179 if (!vroot_data.path.init) {
180 vroot_data.path.init= 1;
181 vroot_data.path.vector= parse_path_string(getenv(vroot_data.path.env_var), 0);};
182 path_vector= vroot_data.path.vector;};
183 pp1= path_vector == NULL ? NULL : &(path_vector)[0];};
184
185 /* Setup vroot to use */
186 if (vroot_vector == VROOT_DEFAULT) {
187 if (!vroot_data.vroot.init) {
188 vroot_data.vroot.init= 1;
189 vroot_data.vroot.vector= parse_path_string(getenv(vroot_data.vroot.env_var), 1);};
190 vroot_vector= vroot_data.vroot.vector;};
191 vp= vroot_vector == NULL ? NULL : &(vroot_vector)[0];
192
193 /* Setup to remember pieces */
194 vroot_data.vroot_start= NULL;
195 vroot_data.path_start= NULL;
196 vroot_data.filename_start= NULL;
197
198 int flen = strlen(filename);
199 if(flen >= MAXPATHLEN) {
200 errno = ENAMETOOLONG;
201 return;
202 }
203
204 switch ((vp ?1:0) + (pp1 ? 2:0)) {
205 case 0: /* No path. No vroot. */
206 use_name:
207 (void)strcpy(vroot_data.full_path, filename);
208 vroot_data.filename_start= vroot_data.full_path;
209 (void)(*thunk)(vroot_data.full_path);
210 return;
211 case 1: /* No path. Vroot */
212 if (filename[0] != '/') goto use_name;
213 for (; vp->path != NULL; vp++) {
214 if((1 + flen + vp->length) >= MAXPATHLEN) {
215 errno = ENAMETOOLONG;
216 continue;
217 }
218 p= vroot_data.full_path;
219 (void)strcpy(vroot_data.vroot_start= p, vp->path);
220 p+= vp->length;
221 (void)strcpy(vroot_data.filename_start= p, filename);
222 if ((*thunk)(vroot_data.full_path)) return;};
223 (void)strcpy(vroot_data.full_path, filename);
224 return;
225 case 2: /* Path. No vroot. */
226 if (vroot_data.cpp_style_path) {
227 if (filename[0] == '/') goto use_name;
228 } else {
229 if (strchr(filename, '/') != NULL) goto use_name;
230 };
231 for (; pp1->path != NULL; pp1++) {
232 p= vroot_data.full_path;
233 if((1 + flen + pp1->length) >= MAXPATHLEN) {
234 errno = ENAMETOOLONG;
235 continue;
236 }
237 if (vroot_data.cpp_style_path) {
238 (void)strcpy(vroot_data.path_start= p, pp1->path);
239 p+= pp1->length;
240 *p++= '/';
241 } else {
242 if (pp1->length != 0) {
243 (void)strcpy(vroot_data.path_start= p,
244 pp1->path);
245 p+= pp1->length;
246 *p++= '/';
247 };
248 };
249 (void)strcpy(vroot_data.filename_start= p, filename);
250 if ((*thunk)(vroot_data.full_path)) return;};
251 (void)strcpy(vroot_data.full_path, filename);
252 return;
253 case 3: { /* Path. Vroot. */
254 int *rel_path, path_len= 1;
255 if (vroot_data.scan_vroot_first == 0) {
256 for (pp= pp1; pp->path != NULL; pp++) path_len++;
257 rel_path= flags;
258 for (path_len-= 2; path_len >= 0; path_len--) rel_path[path_len]= 0;
259 for (; vp->path != NULL; vp++)
260 for (pp= pp1, path_len= 0; pp->path != NULL; pp++, path_len++) {
261 int len = 0;
262 if (rel_path[path_len] == 1) continue;
263 if (pp->path[0] != '/') rel_path[path_len]= 1;
264 p= vroot_data.full_path;
265 if ((filename[0] == '/') || (pp->path[0] == '/')) {
266 if(vp->length >= MAXPATHLEN) {
267 errno = ENAMETOOLONG;
268 continue;
269 }
270 (void)strcpy(vroot_data.vroot_start= p, vp->path); p+= vp->length;
271 len += vp->length;
272 };
273 if (vroot_data.cpp_style_path) {
274 if (filename[0] != '/') {
275 if(1 + len + pp->length >= MAXPATHLEN) {
276 errno = ENAMETOOLONG;
277 continue;
278 }
279 (void)strcpy(vroot_data.path_start= p, pp->path); p+= pp->length;
280 *p++= '/';
281 len += 1 + pp->length;
282 };
283 } else {
284 if (strchr(filename, '/') == NULL) {
285 if (pp->length != 0) {
286 if(1 + len + pp->length >= MAXPATHLEN) {
287 errno = ENAMETOOLONG;
288 continue;
289 }
290 (void)strcpy(vroot_data.path_start= p,
291 pp->path);
292 p+= pp->length;
293 *p++= '/';
294 len += 1 + pp->length;
295 }
296 }
297 };
298 (void)strcpy(vroot_data.filename_start= p, filename);
299 if ((*thunk)(vroot_data.full_path)) return;};}
300 else { pathcellt *vp1= vp;
301 for (pp= pp1, path_len= 0; pp->path != NULL; pp++, path_len++)
302 for (vp= vp1; vp->path != NULL; vp++) {
303 int len = 0;
304 p= vroot_data.full_path;
305 if ((filename[0] == '/') || (pp->path[0] == '/')) {
306 if(vp->length >= MAXPATHLEN) {
307 errno = ENAMETOOLONG;
308 continue;
309 }
310 (void)strcpy(vroot_data.vroot_start= p, vp->path); p+= vp->length;
311 len += vp->length;
312 }
313 if (vroot_data.cpp_style_path) {
314 if (filename[0] != '/') {
315 if(1 + len + pp->length >= MAXPATHLEN) {
316 errno = ENAMETOOLONG;
317 continue;
318 }
319 (void)strcpy(vroot_data.path_start= p, pp->path); p+= pp->length;
320 *p++= '/';
321 len += 1 + pp->length;
322 }
323 } else {
324 if (strchr(filename, '/') == NULL) {
325 if(1 + len + pp->length >= MAXPATHLEN) {
326 errno = ENAMETOOLONG;
327 continue;
328 }
329 (void)strcpy(vroot_data.path_start= p, pp->path); p+= pp->length;
330 *p++= '/';
331 len += 1 + pp->length;
332 }
333 }
334 (void)strcpy(vroot_data.filename_start= p, filename);
335 if ((*thunk)(vroot_data.full_path)) return;};};
336 (void)strcpy(vroot_data.full_path, filename);
337 return;};};
338 }
339