xref: /openbsd/gnu/usr.sbin/mkhybrid/src/files.c (revision 404b540a)
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
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
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
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 *
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
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 *
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 *
359 FDECL3(readdir_add_files, char **, pathp, char *,path, DIR *, dir){
360   return (readdir (dir));
361 }
362 #endif
363