diff options
Diffstat (limited to 'genisoimage/files.c')
-rw-r--r-- | genisoimage/files.c | 398 |
1 files changed, 398 insertions, 0 deletions
diff --git a/genisoimage/files.c b/genisoimage/files.c new file mode 100644 index 0000000..d17a2c7 --- /dev/null +++ b/genisoimage/files.c @@ -0,0 +1,398 @@ +/* + * This file has been modified for the cdrkit suite. + * + * The behaviour and appearence of the program code below can differ to a major + * extent from the version distributed by the original author(s). + * + * For details, see Changelog file distributed with the cdrkit package. If you + * received this file from another source then ask the distributing person for + * a log of modifications. + * + */ + +/* @(#)files.c 1.12 04/03/04 joerg */ +/* + * File files.c - Handle ADD_FILES related stuff. + * + * Written by Eric Youngdale (1993). + * + * Copyright 1993 Yggdrasil Computing, Incorporated + * + * 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 <mconfig.h> +#include "genisoimage.h" +#include <errno.h> +#include <schily.h> +#include <ctype.h> + +#ifdef ADD_FILES + +void add_one_file(char *addpath, char *path); +void add_file_list(int argc, char **argv, int ind); +void add_file(char *filename); +char *look_up_addition(char **newpath, char *path, struct dirent **de); +void nuke_duplicates(char *path, struct dirent **de); +struct dirent *readdir_add_files(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(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 = 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 = 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 = strdup(path); + f->adds[f->add_count - 1].name = strdup(name); +} + +/* + * Function: add_file_list + * + * Purpose: Register an add-in file. + * + * Arguments: + */ +void +add_file_list(int argc, char **argv, int ind) +{ + char *ptr; + char *dup_arg; + + while (ind < argc) { + dup_arg = 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(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) { +#ifdef USE_LIBSCHILY + comerr("Cannot open '%s'.\n", filename); +#else + perror("fopen"); + exit(1); +#endif + } + } + 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) { +#ifdef USE_LIBSCHILY + comerrno(EX_BAD, "Error in file '%s' line %d: %s\n", + filename, count, buff); +#else + fprintf(stderr, "Error in file '%s' line %d: %s\n", + filename, count, buff); + exit(1); +#endif + } + *p2 = 0; + p2++; + add_one_file(ptr, p2); + } + if (f != stdin) + fclose(f); +} + +/* This function looks up additions. */ +char * +look_up_addition(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 = 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(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 = 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(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(char **pathp, char *path, DIR *dir) +{ + return (readdir(dir)); +} + +#endif |