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