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