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