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 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 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 * 109 get_vroot_name(void) 110 { 111 return(vroot_data.vroot.env_var); 112 } 113 114 const char * 115 get_path_name(void) 116 { 117 return(vroot_data.path.env_var); 118 } 119 120 void 121 flush_path_cache(void) 122 { 123 vroot_data.path.init= 0; 124 } 125 126 void 127 flush_vroot_cache(void) 128 { 129 vroot_data.vroot.init= 0; 130 } 131 132 void 133 scan_path_first(void) 134 { 135 vroot_data.scan_vroot_first= 0; 136 } 137 138 void 139 scan_vroot_first(void) 140 { 141 vroot_data.scan_vroot_first= 1; 142 } 143 144 void 145 set_path_style(int style) 146 { 147 vroot_data.cpp_style_path= style; 148 } 149 150 char * 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 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