/* @(#)files.c 1.19 10/12/19 joerg */ #ifndef lint static char sccsid[] = "@(#)files.c 1.19 10/12/19 joerg"; #endif /* * File files.c - Handle ADD_FILES related stuff. * * Written by Eric Youngdale (1993). * * Copyright 1993 Yggdrasil Computing, Incorporated * Copyright (c) 1999-2010 J. Schilling * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* ADD_FILES changes made by Ross Biro biro@yggdrasil.com 2/23/95 */ #include #include "mkisofs.h" #include #include #include #ifdef ADD_FILES void add_one_file __PR((char *addpath, char *path)); void add_file_list __PR((int argc, char **argv, int ind)); void add_file __PR((char *filename)); char *look_up_addition __PR((char **newpath, char *path, struct dirent **de)); void nuke_duplicates __PR((char *path, struct dirent **de)); struct dirent *readdir_add_files __PR((char **pathp, char *path, DIR *dir)); struct file_adds { char *name; struct file_adds *child; struct file_adds *next; int add_count; int used; union diru { /* * XXX Struct dirent is not guaranteed to be any size on a POSIX * XXX compliant system. * XXX We need to allocate enough space here, to allow the hacky * XXX code in tree.c made by Ross Biro biro@yggdrasil.com * XXX to work on operating systems other than Linux :-( * XXX Changes made by Joerg Schilling * XXX joerg@schily.isdn.cs.tu-berlin.de * XXX to prevent core dumps on Solaris. * XXX Space allocated: * XXX 1024 bytes == NAME_MAX * XXX + 2 bytes for directory record length * XXX + 2*8 bytes for inode number & offset (64 for future exp) */ struct dirent de; char dspace[NAME_MAX + 2 + 2 * 8]; } du; struct { char *path; char *name; } *adds; }; extern struct file_adds *root_file_adds; /* * FIXME(eric) - the file adding code really doesn't work very well * at all. We should differentiate between adding directories, and adding * single files, as adding a full directory affects how we should be * searching for things. Ideally what we should do is make two passes * through the local filesystem - one to figure out what trees we need * to scan (and merge in any additions at that point), and the second to * actually fill out each structure with the appropriate contents. */ struct file_adds *root_file_adds = NULL; void add_one_file(addpath, path) char *addpath; char *path; { char *cp; char *name; struct file_adds *f; struct file_adds *tmp; f = root_file_adds; tmp = NULL; name = strrchr(addpath, PATH_SEPARATOR); if (name == NULL) { name = addpath; } else { name++; } cp = strtok(addpath, SPATH_SEPARATOR); while (cp != NULL && strcmp(name, cp)) { if (f == NULL) { root_file_adds = e_malloc(sizeof (*root_file_adds)); f = root_file_adds; f->name = NULL; f->child = NULL; f->next = NULL; f->add_count = 0; f->adds = NULL; f->used = 0; } if (f->child) { for (tmp = f->child; tmp->next != NULL; tmp = tmp->next) { if (strcmp(tmp->name, cp) == 0) { f = tmp; goto next; } } if (strcmp(tmp->name, cp) == 0) { f = tmp; goto next; } /* add a new node. */ tmp->next = e_malloc(sizeof (*tmp->next)); f = tmp->next; f->name = e_strdup(cp); f->child = NULL; f->next = NULL; f->add_count = 0; f->adds = NULL; f->used = 0; } else { /* no children. */ f->child = e_malloc(sizeof (*f->child)); f = f->child; f->name = e_strdup(cp); f->child = NULL; f->next = NULL; f->add_count = 0; f->adds = NULL; f->used = 0; } next: cp = strtok(NULL, SPATH_SEPARATOR); } /* Now f if non-null points to where we should add things */ if (f == NULL) { root_file_adds = e_malloc(sizeof (*root_file_adds)); f = root_file_adds; f->name = NULL; f->child = NULL; f->next = NULL; f->add_count = 0; f->adds = NULL; } /* Now f really points to where we should add this name. */ f->add_count++; f->adds = realloc(f->adds, sizeof (*f->adds) * f->add_count); f->adds[f->add_count - 1].path = e_strdup(path); f->adds[f->add_count - 1].name = e_strdup(name); } /* * Function: add_file_list * * Purpose: Register an add-in file. * * Arguments: */ void add_file_list(argc, argv, ind) int argc; char **argv; int ind; { char *ptr; char *dup_arg; while (ind < argc) { dup_arg = e_strdup(argv[ind]); ptr = strchr(dup_arg, '='); if (ptr == NULL) { free(dup_arg); return; } *ptr = 0; ptr++; add_one_file(dup_arg, ptr); free(dup_arg); ind++; } } void add_file(filename) char *filename; { char buff[PATH_MAX]; FILE *f; char *ptr; char *p2; int count = 0; if (strcmp(filename, "-") == 0) { f = stdin; } else { f = fopen(filename, "r"); if (f == NULL) { comerr(_("Cannot open '%s'.\n"), filename); } } while (fgets(buff, sizeof (buff), f)) { count++; ptr = buff; while (isspace(*ptr)) ptr++; if (*ptr == 0) continue; if (*ptr == '#') continue; if (ptr[strlen(ptr) - 1] == '\n') ptr[strlen(ptr) - 1] = 0; p2 = strchr(ptr, '='); if (p2 == NULL) { comerrno(EX_BAD, _("Error in file '%s' line %d: %s\n"), filename, count, buff); } *p2 = 0; p2++; add_one_file(ptr, p2); } if (f != stdin) fclose(f); } /* This function looks up additions. */ char * look_up_addition(newpath, path, de) char **newpath; char *path; struct dirent **de; { char *dup_path; char *cp; struct file_adds *f; struct file_adds *tmp = NULL; f = root_file_adds; if (!f) return (NULL); /* I don't trust strtok */ dup_path = e_strdup(path); cp = strtok(dup_path, SPATH_SEPARATOR); while (cp != NULL) { for (tmp = f->child; tmp != NULL; tmp = tmp->next) { if (strcmp(tmp->name, cp) == 0) break; } if (tmp == NULL) { /* no match */ free(dup_path); return (NULL); } f = tmp; cp = strtok(NULL, SPATH_SEPARATOR); } free(dup_path); /* If nothing, then return. */ if (tmp == NULL) { /* no match */ return (NULL); } /* looks like we found something. */ if (tmp->used >= tmp->add_count) return (NULL); *newpath = tmp->adds[tmp->used].path; tmp->used++; *de = &(tmp->du.de); return (tmp->adds[tmp->used - 1].name); } /* This function looks up additions. */ void nuke_duplicates(path, de) char *path; struct dirent **de; { char *dup_path; char *cp; struct file_adds *f; struct file_adds *tmp; f = root_file_adds; if (!f) return; /* I don't trust strtok */ dup_path = e_strdup(path); cp = strtok(dup_path, SPATH_SEPARATOR); while (cp != NULL) { for (tmp = f->child; tmp != NULL; tmp = tmp->next) { if (strcmp(tmp->name, cp) == 0) break; } if (tmp == NULL) { /* no match */ free(dup_path); return; } f = tmp; cp = strtok(NULL, SPATH_SEPARATOR); } free(dup_path); #if 0 /* looks like we found something. */ if (tmp->used >= tmp->add_count) return; *newpath = tmp->adds[tmp->used].path; tmp->used++; *de = &(tmp->du.de); return (tmp->adds[tmp->used - 1].name); #endif } /* * This function lets us add files from outside the standard file tree. * It is useful if we want to duplicate a cd, but add/replace things. * We should note that the real path will be used for exclusions. */ struct dirent * readdir_add_files(pathp, path, dir) char **pathp; char *path; DIR *dir; { struct dirent *de; char *addpath; char *name; de = readdir(dir); if (de) { nuke_duplicates(path, &de); return (de); } name = look_up_addition(&addpath, path, &de); if (!name) { return (NULL); } *pathp = addpath; /* * Now we must create the directory entry. * fortuneately only the name seems to matter. */ /* de->d_ino = -1; de->d_off = 0; de->d_reclen = strlen (name); */ strncpy(de->d_name, name, NAME_MAX); de->d_name[NAME_MAX] = 0; nuke_duplicates(path, &de); return (de); } #else struct dirent * readdir_add_files(pathp, path, dir) char **pathp; char *path; DIR *dir; { return (readdir(dir)); } #endif