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 }