xref: /illumos-gate/usr/src/cmd/make/lib/vroot/vroot.cc (revision e7afc443cb8c2e0a379fe48b15a0c7fb61a4b2fc)
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,pathpt * pointer,int position)60 add_dir_to_path(const char *path, pathpt *pointer, int position)
61 {
62 	int		size= 0;
63 	int		length;
64 	char		*name;
65 	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(char * string,int remove_slash)91 parse_path_string(char *string, int remove_slash)
92 {
93 	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(char ** vroot,char ** path,char ** filename)151 get_vroot_path(char **vroot, char **path, 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(char * filename,int (* thunk)(char *),pathpt path_vector,pathpt vroot_vector,rwt rw)166 translate_with_thunk(char *filename, int (*thunk) (char *), pathpt path_vector, pathpt vroot_vector, rwt rw)
167 {
168 	pathcellt	*vp;
169 	pathcellt	*pp;
170 	pathcellt	*pp1;
171 	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