400 lines
8.4 KiB
C
400 lines
8.4 KiB
C
|
/* @(#)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 <schily/mconfig.h>
|
||
|
#include "mkisofs.h"
|
||
|
#include <schily/errno.h>
|
||
|
#include <schily/schily.h>
|
||
|
#include <schily/ctype.h>
|
||
|
|
||
|
#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
|