summaryrefslogtreecommitdiff
path: root/genisoimage/files.c
diff options
context:
space:
mode:
Diffstat (limited to 'genisoimage/files.c')
-rw-r--r--genisoimage/files.c398
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