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
FDECL2(add_one_file,char *,addpath,char *,path)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
FDECL3(add_file_list,int,argc,char **,argv,int,ind)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
FDECL1(add_file,char *,filename)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 *
FDECL3(look_up_addition,char **,newpath,char *,path,struct dirent **,de)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
FDECL2(nuke_duplicates,char *,path,struct dirent **,de)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 *
FDECL3(readdir_add_files,char **,pathp,char *,path,DIR *,dir)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 *
FDECL3(readdir_add_files,char **,pathp,char *,path,DIR *,dir)359 FDECL3(readdir_add_files, char **, pathp, char *,path, DIR *, dir){
360 return (readdir (dir));
361 }
362 #endif
363