xref: /openbsd-src/gnu/usr.sbin/mkhybrid/src/files.c (revision daf88648c0e349d5c02e1504293082072c981640)
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 static char rcsid[] ="$Id: files.c,v 1.1 2000/10/10 20:40:14 beck Exp $";
25 
26 #include "config.h"
27 #include <errno.h>
28 #include "mkisofs.h"
29 
30 #include <stdlib.h>
31 #include <ctype.h>
32 
33 #ifdef ADD_FILES
34 
35 struct file_adds {
36   char *name;
37   struct file_adds *child;
38   struct file_adds *next;
39   int add_count;
40   int used;
41   union diru {
42 	/*
43 	 * XXX Struct dirent is not guaranteed to be any size on a POSIX
44 	 * XXX compliant system.
45 	 * XXX We need to allocate enough space here, to allow the hacky
46 	 * XXX code in tree.c made by Ross Biro biro@yggdrasil.com
47 	 * XXX to work on operating systems other than Linux :-(
48 	 * XXX Changes made by Joerg Schilling joerg@schily.isdn.cs.tu-berlin.de
49 	 * XXX to prevent core dumps on Solaris.
50 	 * XXX Space allocated:
51 	 * XXX		1024 bytes == NAME_MAX
52 	 * XXX	+	2   bytes for directory record length
53 	 * XXX	+	2*8 bytes for inode number & offset (64 for future exp)
54 	 */
55   	struct dirent	de;
56   	char		dspace[NAME_MAX+2+2*8];
57   } du;
58   struct {
59     char *path;
60     char *name;
61   } *adds;
62 };
63 extern struct file_adds *root_file_adds;
64 
65 /*
66  * FIXME(eric) - the file adding code really doesn't work very well
67  * at all.  We should differentiate between adding directories, and adding
68  * single files, as adding a full directory affects how we should be
69  * searching for things.  Ideally what we should do is make two passes
70  * through the local filesystem - one to figure out what trees we need
71  * to scan (and merge in any additions at that point), and the second to
72  * actually fill out each structure with the appropriate contents.
73  *
74  *
75  */
76 
77 struct file_adds *root_file_adds = NULL;
78 
79 void
80 FDECL2(add_one_file, char *, addpath, char *, path )
81 {
82   char *cp;
83   char *name;
84   struct file_adds *f;
85   struct file_adds *tmp;
86 
87   f = root_file_adds;
88   tmp = NULL;
89 
90   name = strrchr (addpath, PATH_SEPARATOR);
91   if (name == NULL) {
92     name = addpath;
93   } else {
94     name++;
95   }
96 
97   cp = strtok (addpath, SPATH_SEPARATOR);
98 
99   while (cp != NULL && strcmp (name, cp)) {
100      if (f == NULL) {
101         root_file_adds = e_malloc (sizeof *root_file_adds);
102         f=root_file_adds;
103         f->name = NULL;
104         f->child = NULL;
105         f->next = NULL;
106         f->add_count = 0;
107         f->adds = NULL;
108 	f->used = 0;
109      }
110     if (f->child) {
111       for (tmp = f->child; tmp->next != NULL; tmp =tmp->next) {
112          if (strcmp (tmp->name, cp) == 0) {
113            f = tmp;
114            goto next;
115          }
116       }
117       if (strcmp (tmp->name, cp) == 0) {
118           f=tmp;
119           goto next;
120       }
121       /* add a new node. */
122       tmp->next = e_malloc (sizeof (*tmp->next));
123       f=tmp->next;
124       f->name = strdup (cp);
125       f->child = NULL;
126       f->next = NULL;
127       f->add_count = 0;
128       f->adds = NULL;
129       f->used = 0;
130     } else {
131       /* no children. */
132       f->child = e_malloc (sizeof (*f->child));
133       f = f->child;
134       f->name = strdup (cp);
135       f->child = NULL;
136       f->next = NULL;
137       f->add_count = 0;
138       f->adds = NULL;
139       f->used = 0;
140 
141     }
142    next:
143      cp = strtok (NULL, SPATH_SEPARATOR);
144    }
145   /* Now f if non-null points to where we should add things */
146   if (f == NULL) {
147      root_file_adds = e_malloc (sizeof *root_file_adds);
148      f=root_file_adds;
149      f->name = NULL;
150      f->child = NULL;
151      f->next = NULL;
152      f->add_count = 0;
153      f->adds = NULL;
154    }
155 
156   /* Now f really points to where we should add this name. */
157   f->add_count++;
158   f->adds = realloc (f->adds, sizeof (*f->adds)*f->add_count);
159   f->adds[f->add_count-1].path = strdup (path);
160   f->adds[f->add_count-1].name = strdup (name);
161 }
162 
163 /*
164  * Function:	add_file_list
165  *
166  * Purpose:	Register an add-in file.
167  *
168  * Arguments:
169  */
170 void
171 FDECL3(add_file_list, int, argc, char **,argv, int, ind)
172 {
173   char *ptr;
174   char *dup_arg;
175 
176   while (ind < argc) {
177      dup_arg = strdup (argv[ind]);
178      ptr = strchr (dup_arg,'=');
179      if (ptr == NULL) {
180         free (dup_arg);
181         return;
182      }
183      *ptr = 0;
184      ptr++;
185      add_one_file (dup_arg, ptr);
186      free (dup_arg);
187      ind++;
188   }
189 }
190 void
191 FDECL1(add_file, char *, filename)
192 {
193   char buff[1024];
194   FILE *f;
195   char *ptr;
196   char *p2;
197   int count=0;
198 
199   if (strcmp (filename, "-") == 0) {
200     f = stdin;
201   } else {
202     f = fopen (filename, "r");
203     if (f == NULL) {
204       perror ("fopen");
205       exit (1);
206     }
207   }
208   while (fgets (buff, 1024, f)) {
209     count++;
210     ptr = buff;
211     while (isspace (*ptr)) ptr++;
212     if (*ptr==0) continue;
213     if (*ptr=='#') continue;
214 
215     if (ptr[strlen(ptr)-1]== '\n') ptr[strlen(ptr)-1]=0;
216     p2 = strchr (ptr, '=');
217     if (p2 == NULL) {
218       fprintf (stderr, "Error in line %d: %s\n", count, buff);
219       exit (1);
220     }
221     *p2 = 0;
222     p2++;
223     add_one_file (ptr, p2);
224   }
225   if (f != stdin) fclose (f);
226 }
227 
228 /* This function looks up additions. */
229 char *
230 FDECL3(look_up_addition,char **, newpath, char *,path, struct dirent **,de)
231 {
232   char *dup_path;
233   char *cp;
234   struct file_adds *f;
235   struct file_adds *tmp = NULL;
236 
237   f=root_file_adds;
238   if (!f) return NULL;
239 
240   /* I don't trust strtok */
241   dup_path = strdup (path);
242 
243   cp = strtok (dup_path, SPATH_SEPARATOR);
244   while (cp != NULL) {
245     for (tmp = f->child; tmp != NULL; tmp=tmp->next) {
246       if (strcmp (tmp->name, cp) == 0) break;
247     }
248     if (tmp == NULL) {
249       /* no match */
250       free (dup_path);
251       return (NULL);
252     }
253     f = tmp;
254     cp = strtok(NULL, SPATH_SEPARATOR);
255   }
256   free (dup_path);
257 
258   /*
259    * If nothing, then return.
260    */
261   if (tmp == NULL)
262     {
263       /* no match */
264       return (NULL);
265     }
266 
267   /* looks like we found something. */
268   if (tmp->used >= tmp->add_count) return (NULL);
269 
270   *newpath = tmp->adds[tmp->used].path;
271   tmp->used++;
272   *de = &(tmp->du.de);
273   return (tmp->adds[tmp->used-1].name);
274 
275 }
276 
277 /* This function looks up additions. */
278 void
279 FDECL2(nuke_duplicates, char *, path, struct dirent **,de)
280 {
281   char *dup_path;
282   char *cp;
283   struct file_adds *f;
284   struct file_adds *tmp;
285 
286   f=root_file_adds;
287   if (!f) return;
288 
289   /* I don't trust strtok */
290   dup_path = strdup (path);
291 
292   cp = strtok (dup_path, SPATH_SEPARATOR);
293   while (cp != NULL) {
294     for (tmp = f->child; tmp != NULL; tmp=tmp->next) {
295       if (strcmp (tmp->name, cp) == 0) break;
296     }
297     if (tmp == NULL) {
298       /* no match */
299       free (dup_path);
300       return;
301     }
302     f = tmp;
303     cp = strtok(NULL, SPATH_SEPARATOR);
304   }
305   free (dup_path);
306 
307 #if 0
308   /* looks like we found something. */
309   if (tmp->used >= tmp->add_count) return;
310 
311   *newpath = tmp->adds[tmp->used].path;
312   tmp->used++;
313   *de = &(tmp->du.de);
314   return (tmp->adds[tmp->used-1].name);
315 #endif
316   return;
317 }
318 
319 /* This function lets us add files from outside the standard file tree.
320    It is useful if we want to duplicate a cd, but add/replace things.
321    We should note that the real path will be used for exclusions. */
322 
323 struct dirent *
324 FDECL3(readdir_add_files, char **, pathp, char *,path, DIR *, dir){
325   struct dirent *de;
326 
327   char *addpath;
328   char *name;
329 
330   de = readdir (dir);
331   if (de) {
332     nuke_duplicates(path, &de);
333     return (de);
334   }
335 
336   name=look_up_addition (&addpath, path, &de);
337 
338   if (!name) {
339     return NULL;
340   }
341 
342   *pathp=addpath;
343 
344   /* Now we must create the directory entry. */
345   /* fortuneately only the name seems to matter. */
346   /*
347   de->d_ino = -1;
348   de->d_off = 0;
349   de->d_reclen = strlen (name);
350   */
351   strncpy (de->d_name, name, NAME_MAX);
352   de->d_name[NAME_MAX]=0;
353   nuke_duplicates(path, &de);
354   return (de);
355 
356 }
357 
358 #else
359 struct dirent *
360 FDECL3(readdir_add_files, char **, pathp, char *,path, DIR *, dir){
361   return (readdir (dir));
362 }
363 #endif
364