1 /* 2 * File files.c - Handle ADD_FILES related stuff. 3 4 Written by Eric Youngdale (1993). 5 6 Copyright 1993 Yggdrasil Computing, Incorporated 7 8 This program is free software; you can redistribute it and/or modify 9 it under the terms of the GNU General Public License as published by 10 the Free Software Foundation; either version 2, or (at your option) 11 any later version. 12 13 This program is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with this program; if not, write to the Free Software 20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ 21 22 /* ADD_FILES changes made by Ross Biro biro@yggdrasil.com 2/23/95 */ 23 24 static char rcsid[] ="$Id: files.c,v 1.1 2000/10/10 20:40:14 beck Exp $"; 25 26 #include "config.h" 27 #include <errno.h> 28 #include "mkisofs.h" 29 30 #include <stdlib.h> 31 #include <ctype.h> 32 33 #ifdef ADD_FILES 34 35 struct file_adds { 36 char *name; 37 struct file_adds *child; 38 struct file_adds *next; 39 int add_count; 40 int used; 41 union diru { 42 /* 43 * XXX Struct dirent is not guaranteed to be any size on a POSIX 44 * XXX compliant system. 45 * XXX We need to allocate enough space here, to allow the hacky 46 * XXX code in tree.c made by Ross Biro biro@yggdrasil.com 47 * XXX to work on operating systems other than Linux :-( 48 * XXX Changes made by Joerg Schilling joerg@schily.isdn.cs.tu-berlin.de 49 * XXX to prevent core dumps on Solaris. 50 * XXX Space allocated: 51 * XXX 1024 bytes == NAME_MAX 52 * XXX + 2 bytes for directory record length 53 * XXX + 2*8 bytes for inode number & offset (64 for future exp) 54 */ 55 struct dirent de; 56 char dspace[NAME_MAX+2+2*8]; 57 } du; 58 struct { 59 char *path; 60 char *name; 61 } *adds; 62 }; 63 extern struct file_adds *root_file_adds; 64 65 /* 66 * FIXME(eric) - the file adding code really doesn't work very well 67 * at all. We should differentiate between adding directories, and adding 68 * single files, as adding a full directory affects how we should be 69 * searching for things. Ideally what we should do is make two passes 70 * through the local filesystem - one to figure out what trees we need 71 * to scan (and merge in any additions at that point), and the second to 72 * actually fill out each structure with the appropriate contents. 73 * 74 * 75 */ 76 77 struct file_adds *root_file_adds = NULL; 78 79 void 80 FDECL2(add_one_file, char *, addpath, char *, path ) 81 { 82 char *cp; 83 char *name; 84 struct file_adds *f; 85 struct file_adds *tmp; 86 87 f = root_file_adds; 88 tmp = NULL; 89 90 name = strrchr (addpath, PATH_SEPARATOR); 91 if (name == NULL) { 92 name = addpath; 93 } else { 94 name++; 95 } 96 97 cp = strtok (addpath, SPATH_SEPARATOR); 98 99 while (cp != NULL && strcmp (name, cp)) { 100 if (f == NULL) { 101 root_file_adds = e_malloc (sizeof *root_file_adds); 102 f=root_file_adds; 103 f->name = NULL; 104 f->child = NULL; 105 f->next = NULL; 106 f->add_count = 0; 107 f->adds = NULL; 108 f->used = 0; 109 } 110 if (f->child) { 111 for (tmp = f->child; tmp->next != NULL; tmp =tmp->next) { 112 if (strcmp (tmp->name, cp) == 0) { 113 f = tmp; 114 goto next; 115 } 116 } 117 if (strcmp (tmp->name, cp) == 0) { 118 f=tmp; 119 goto next; 120 } 121 /* add a new node. */ 122 tmp->next = e_malloc (sizeof (*tmp->next)); 123 f=tmp->next; 124 f->name = strdup (cp); 125 f->child = NULL; 126 f->next = NULL; 127 f->add_count = 0; 128 f->adds = NULL; 129 f->used = 0; 130 } else { 131 /* no children. */ 132 f->child = e_malloc (sizeof (*f->child)); 133 f = f->child; 134 f->name = strdup (cp); 135 f->child = NULL; 136 f->next = NULL; 137 f->add_count = 0; 138 f->adds = NULL; 139 f->used = 0; 140 141 } 142 next: 143 cp = strtok (NULL, SPATH_SEPARATOR); 144 } 145 /* Now f if non-null points to where we should add things */ 146 if (f == NULL) { 147 root_file_adds = e_malloc (sizeof *root_file_adds); 148 f=root_file_adds; 149 f->name = NULL; 150 f->child = NULL; 151 f->next = NULL; 152 f->add_count = 0; 153 f->adds = NULL; 154 } 155 156 /* Now f really points to where we should add this name. */ 157 f->add_count++; 158 f->adds = realloc (f->adds, sizeof (*f->adds)*f->add_count); 159 f->adds[f->add_count-1].path = strdup (path); 160 f->adds[f->add_count-1].name = strdup (name); 161 } 162 163 /* 164 * Function: add_file_list 165 * 166 * Purpose: Register an add-in file. 167 * 168 * Arguments: 169 */ 170 void 171 FDECL3(add_file_list, int, argc, char **,argv, int, ind) 172 { 173 char *ptr; 174 char *dup_arg; 175 176 while (ind < argc) { 177 dup_arg = strdup (argv[ind]); 178 ptr = strchr (dup_arg,'='); 179 if (ptr == NULL) { 180 free (dup_arg); 181 return; 182 } 183 *ptr = 0; 184 ptr++; 185 add_one_file (dup_arg, ptr); 186 free (dup_arg); 187 ind++; 188 } 189 } 190 void 191 FDECL1(add_file, char *, filename) 192 { 193 char buff[1024]; 194 FILE *f; 195 char *ptr; 196 char *p2; 197 int count=0; 198 199 if (strcmp (filename, "-") == 0) { 200 f = stdin; 201 } else { 202 f = fopen (filename, "r"); 203 if (f == NULL) { 204 perror ("fopen"); 205 exit (1); 206 } 207 } 208 while (fgets (buff, 1024, f)) { 209 count++; 210 ptr = buff; 211 while (isspace (*ptr)) ptr++; 212 if (*ptr==0) continue; 213 if (*ptr=='#') continue; 214 215 if (ptr[strlen(ptr)-1]== '\n') ptr[strlen(ptr)-1]=0; 216 p2 = strchr (ptr, '='); 217 if (p2 == NULL) { 218 fprintf (stderr, "Error in line %d: %s\n", count, buff); 219 exit (1); 220 } 221 *p2 = 0; 222 p2++; 223 add_one_file (ptr, p2); 224 } 225 if (f != stdin) fclose (f); 226 } 227 228 /* This function looks up additions. */ 229 char * 230 FDECL3(look_up_addition,char **, newpath, char *,path, struct dirent **,de) 231 { 232 char *dup_path; 233 char *cp; 234 struct file_adds *f; 235 struct file_adds *tmp = NULL; 236 237 f=root_file_adds; 238 if (!f) return NULL; 239 240 /* I don't trust strtok */ 241 dup_path = strdup (path); 242 243 cp = strtok (dup_path, SPATH_SEPARATOR); 244 while (cp != NULL) { 245 for (tmp = f->child; tmp != NULL; tmp=tmp->next) { 246 if (strcmp (tmp->name, cp) == 0) break; 247 } 248 if (tmp == NULL) { 249 /* no match */ 250 free (dup_path); 251 return (NULL); 252 } 253 f = tmp; 254 cp = strtok(NULL, SPATH_SEPARATOR); 255 } 256 free (dup_path); 257 258 /* 259 * If nothing, then return. 260 */ 261 if (tmp == NULL) 262 { 263 /* no match */ 264 return (NULL); 265 } 266 267 /* looks like we found something. */ 268 if (tmp->used >= tmp->add_count) return (NULL); 269 270 *newpath = tmp->adds[tmp->used].path; 271 tmp->used++; 272 *de = &(tmp->du.de); 273 return (tmp->adds[tmp->used-1].name); 274 275 } 276 277 /* This function looks up additions. */ 278 void 279 FDECL2(nuke_duplicates, char *, path, struct dirent **,de) 280 { 281 char *dup_path; 282 char *cp; 283 struct file_adds *f; 284 struct file_adds *tmp; 285 286 f=root_file_adds; 287 if (!f) return; 288 289 /* I don't trust strtok */ 290 dup_path = strdup (path); 291 292 cp = strtok (dup_path, SPATH_SEPARATOR); 293 while (cp != NULL) { 294 for (tmp = f->child; tmp != NULL; tmp=tmp->next) { 295 if (strcmp (tmp->name, cp) == 0) break; 296 } 297 if (tmp == NULL) { 298 /* no match */ 299 free (dup_path); 300 return; 301 } 302 f = tmp; 303 cp = strtok(NULL, SPATH_SEPARATOR); 304 } 305 free (dup_path); 306 307 #if 0 308 /* looks like we found something. */ 309 if (tmp->used >= tmp->add_count) return; 310 311 *newpath = tmp->adds[tmp->used].path; 312 tmp->used++; 313 *de = &(tmp->du.de); 314 return (tmp->adds[tmp->used-1].name); 315 #endif 316 return; 317 } 318 319 /* This function lets us add files from outside the standard file tree. 320 It is useful if we want to duplicate a cd, but add/replace things. 321 We should note that the real path will be used for exclusions. */ 322 323 struct dirent * 324 FDECL3(readdir_add_files, char **, pathp, char *,path, DIR *, dir){ 325 struct dirent *de; 326 327 char *addpath; 328 char *name; 329 330 de = readdir (dir); 331 if (de) { 332 nuke_duplicates(path, &de); 333 return (de); 334 } 335 336 name=look_up_addition (&addpath, path, &de); 337 338 if (!name) { 339 return NULL; 340 } 341 342 *pathp=addpath; 343 344 /* Now we must create the directory entry. */ 345 /* fortuneately only the name seems to matter. */ 346 /* 347 de->d_ino = -1; 348 de->d_off = 0; 349 de->d_reclen = strlen (name); 350 */ 351 strncpy (de->d_name, name, NAME_MAX); 352 de->d_name[NAME_MAX]=0; 353 nuke_duplicates(path, &de); 354 return (de); 355 356 } 357 358 #else 359 struct dirent * 360 FDECL3(readdir_add_files, char **, pathp, char *,path, DIR *, dir){ 361 return (readdir (dir)); 362 } 363 #endif 364