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 * @(#)vroot.cc 1.11 06/12/12
27 */
28
29 #pragma ident "@(#)vroot.cc 1.11 06/12/12"
30
31 #include <stdlib.h>
32 #include <string.h>
33
34 #include <vroot/vroot.h>
35 #include <vroot/args.h>
36
37 #include <string.h>
38 #include <sys/param.h>
39 #include <sys/file.h>
40
41 #include <avo/intl.h> /* for NOCATGETS */
42
43 typedef struct {
44 short init;
45 pathpt vector;
46 char *env_var;
47 } vroot_patht;
48
49 typedef struct {
50 vroot_patht vroot;
51 vroot_patht path;
52 char full_path[MAXPATHLEN+1];
53 char *vroot_start;
54 char *path_start;
55 char *filename_start;
56 int scan_vroot_first;
57 int cpp_style_path;
58 } vroot_datat, *vroot_datapt;
59
60 static vroot_datat vroot_data= {
61 { 0, NULL, NOCATGETS("VIRTUAL_ROOT")},
62 { 0, NULL, NOCATGETS("PATH")},
63 "", NULL, NULL, NULL, 0, 1};
64
65 void
66 add_dir_to_path(register char *path, register pathpt *pointer, register int position)
67 {
68 register int size= 0;
69 register int length;
70 register char *name;
71 register pathcellpt p;
72 pathpt new_path;
73
74 if (*pointer != NULL) {
75 for (p= &((*pointer)[0]); p->path != NULL; p++, size++);
76 if (position < 0)
77 position= size;}
78 else
79 if (position < 0)
80 position= 0;
81 if (position >= size) {
82 new_path= (pathpt)calloc((unsigned)(position+2), sizeof(pathcellt));
83 if (*pointer != NULL) {
84 memcpy((char *)new_path,(char *)(*pointer), size*sizeof(pathcellt));
85 free((char *)(*pointer));};
86 *pointer= new_path;};
87 length= strlen(path);
88 name= (char *)malloc((unsigned)(length+1));
89 (void)strcpy(name, path);
90 if ((*pointer)[position].path != NULL)
91 free((*pointer)[position].path);
92 (*pointer)[position].path= name;
93 (*pointer)[position].length= length;
94 }
95
96 pathpt
97 parse_path_string(register char *string, register int remove_slash)
98 {
99 register char *p;
100 pathpt result= NULL;
101
102 if (string != NULL)
103 for (; 1; string= p+1) {
104 if (p= strchr(string, ':')) *p= 0;
105 if ((remove_slash == 1) && !strcmp(string, "/"))
106 add_dir_to_path("", &result, -1);
107 else
108 add_dir_to_path(string, &result, -1);
109 if (p) *p= ':';
110 else return(result);};
111 return((pathpt)NULL);
112 }
113
114 char *
115 get_vroot_name(void)
116 {
117 return(vroot_data.vroot.env_var);
118 }
119
120 char *
121 get_path_name(void)
122 {
123 return(vroot_data.path.env_var);
124 }
125
126 void
127 flush_path_cache(void)
128 {
129 vroot_data.path.init= 0;
130 }
131
132 void
133 flush_vroot_cache(void)
134 {
135 vroot_data.vroot.init= 0;
136 }
137
138 void
139 scan_path_first(void)
140 {
141 vroot_data.scan_vroot_first= 0;
142 }
143
144 void
145 scan_vroot_first(void)
146 {
147 vroot_data.scan_vroot_first= 1;
148 }
149
150 void
151 set_path_style(int style)
152 {
153 vroot_data.cpp_style_path= style;
154 }
155
156 char *
157 get_vroot_path(register char **vroot, register char **path, register char **filename)
158 {
159 if (vroot != NULL) {
160 if ((*vroot= vroot_data.vroot_start) == NULL)
161 if ((*vroot= vroot_data.path_start) == NULL)
162 *vroot= vroot_data.filename_start;};
163 if (path != NULL) {
164 if ((*path= vroot_data.path_start) == NULL)
165 *path= vroot_data.filename_start;};
166 if (filename != NULL)
167 *filename= vroot_data.filename_start;
168 return(vroot_data.full_path);
169 }
170
171 void
172 translate_with_thunk(register char *filename, int (*thunk) (char *), pathpt path_vector, pathpt vroot_vector, rwt rw)
173 {
174 register pathcellt *vp;
175 pathcellt *pp;
176 register pathcellt *pp1;
177 register char *p;
178 int flags[256];
179
180 /* Setup path to use */
181 if (rw == rw_write)
182 pp1= NULL; /* Do not use path when writing */
183 else {
184 if (path_vector == VROOT_DEFAULT) {
185 if (!vroot_data.path.init) {
186 vroot_data.path.init= 1;
187 vroot_data.path.vector= parse_path_string(getenv(vroot_data.path.env_var), 0);};
188 path_vector= vroot_data.path.vector;};
189 pp1= path_vector == NULL ? NULL : &(path_vector)[0];};
190
191 /* Setup vroot to use */
192 if (vroot_vector == VROOT_DEFAULT) {
193 if (!vroot_data.vroot.init) {
194 vroot_data.vroot.init= 1;
195 vroot_data.vroot.vector= parse_path_string(getenv(vroot_data.vroot.env_var), 1);};
196 vroot_vector= vroot_data.vroot.vector;};
197 vp= vroot_vector == NULL ? NULL : &(vroot_vector)[0];
198
199 /* Setup to remember pieces */
200 vroot_data.vroot_start= NULL;
201 vroot_data.path_start= NULL;
202 vroot_data.filename_start= NULL;
203
204 int flen = strlen(filename);
205 if(flen >= MAXPATHLEN) {
206 errno = ENAMETOOLONG;
207 return;
208 }
209
210 switch ((vp ?1:0) + (pp1 ? 2:0)) {
211 case 0: /* No path. No vroot. */
212 use_name:
213 (void)strcpy(vroot_data.full_path, filename);
214 vroot_data.filename_start= vroot_data.full_path;
215 (void)(*thunk)(vroot_data.full_path);
216 return;
217 case 1: /* No path. Vroot */
218 if (filename[0] != '/') goto use_name;
219 for (; vp->path != NULL; vp++) {
220 if((1 + flen + vp->length) >= MAXPATHLEN) {
221 errno = ENAMETOOLONG;
222 continue;
223 }
224 p= vroot_data.full_path;
225 (void)strcpy(vroot_data.vroot_start= p, vp->path);
226 p+= vp->length;
227 (void)strcpy(vroot_data.filename_start= p, filename);
228 if ((*thunk)(vroot_data.full_path)) return;};
229 (void)strcpy(vroot_data.full_path, filename);
230 return;
231 case 2: /* Path. No vroot. */
232 if (vroot_data.cpp_style_path) {
233 if (filename[0] == '/') goto use_name;
234 } else {
235 if (strchr(filename, '/') != NULL) goto use_name;
236 };
237 for (; pp1->path != NULL; pp1++) {
238 p= vroot_data.full_path;
239 if((1 + flen + pp1->length) >= MAXPATHLEN) {
240 errno = ENAMETOOLONG;
241 continue;
242 }
243 if (vroot_data.cpp_style_path) {
244 (void)strcpy(vroot_data.path_start= p, pp1->path);
245 p+= pp1->length;
246 *p++= '/';
247 } else {
248 if (pp1->length != 0) {
249 (void)strcpy(vroot_data.path_start= p,
250 pp1->path);
251 p+= pp1->length;
252 *p++= '/';
253 };
254 };
255 (void)strcpy(vroot_data.filename_start= p, filename);
256 if ((*thunk)(vroot_data.full_path)) return;};
257 (void)strcpy(vroot_data.full_path, filename);
258 return;
259 case 3: { /* Path. Vroot. */
260 int *rel_path, path_len= 1;
261 if (vroot_data.scan_vroot_first == 0) {
262 for (pp= pp1; pp->path != NULL; pp++) path_len++;
263 rel_path= flags;
264 for (path_len-= 2; path_len >= 0; path_len--) rel_path[path_len]= 0;
265 for (; vp->path != NULL; vp++)
266 for (pp= pp1, path_len= 0; pp->path != NULL; pp++, path_len++) {
267 int len = 0;
268 if (rel_path[path_len] == 1) continue;
269 if (pp->path[0] != '/') rel_path[path_len]= 1;
270 p= vroot_data.full_path;
271 if ((filename[0] == '/') || (pp->path[0] == '/')) {
272 if(vp->length >= MAXPATHLEN) {
273 errno = ENAMETOOLONG;
274 continue;
275 }
276 (void)strcpy(vroot_data.vroot_start= p, vp->path); p+= vp->length;
277 len += vp->length;
278 };
279 if (vroot_data.cpp_style_path) {
280 if (filename[0] != '/') {
281 if(1 + len + pp->length >= MAXPATHLEN) {
282 errno = ENAMETOOLONG;
283 continue;
284 }
285 (void)strcpy(vroot_data.path_start= p, pp->path); p+= pp->length;
286 *p++= '/';
287 len += 1 + pp->length;
288 };
289 } else {
290 if (strchr(filename, '/') == NULL) {
291 if (pp->length != 0) {
292 if(1 + len + pp->length >= MAXPATHLEN) {
293 errno = ENAMETOOLONG;
294 continue;
295 }
296 (void)strcpy(vroot_data.path_start= p,
297 pp->path);
298 p+= pp->length;
299 *p++= '/';
300 len += 1 + pp->length;
301 }
302 }
303 };
304 (void)strcpy(vroot_data.filename_start= p, filename);
305 if ((*thunk)(vroot_data.full_path)) return;};}
306 else { pathcellt *vp1= vp;
307 for (pp= pp1, path_len= 0; pp->path != NULL; pp++, path_len++)
308 for (vp= vp1; vp->path != NULL; vp++) {
309 int len = 0;
310 p= vroot_data.full_path;
311 if ((filename[0] == '/') || (pp->path[0] == '/')) {
312 if(vp->length >= MAXPATHLEN) {
313 errno = ENAMETOOLONG;
314 continue;
315 }
316 (void)strcpy(vroot_data.vroot_start= p, vp->path); p+= vp->length;
317 len += vp->length;
318 }
319 if (vroot_data.cpp_style_path) {
320 if (filename[0] != '/') {
321 if(1 + len + pp->length >= MAXPATHLEN) {
322 errno = ENAMETOOLONG;
323 continue;
324 }
325 (void)strcpy(vroot_data.path_start= p, pp->path); p+= pp->length;
326 *p++= '/';
327 len += 1 + pp->length;
328 }
329 } else {
330 if (strchr(filename, '/') == NULL) {
331 if(1 + len + pp->length >= MAXPATHLEN) {
332 errno = ENAMETOOLONG;
333 continue;
334 }
335 (void)strcpy(vroot_data.path_start= p, pp->path); p+= pp->length;
336 *p++= '/';
337 len += 1 + pp->length;
338 }
339 }
340 (void)strcpy(vroot_data.filename_start= p, filename);
341 if ((*thunk)(vroot_data.full_path)) return;};};
342 (void)strcpy(vroot_data.full_path, filename);
343 return;};};
344 }