(to_chars): Fix base-256 output.
[debian/tar] / src / names.c
1 /* Various processing of names.
2    Copyright (C) 1988, 92, 94, 96, 97, 98, 1999 Free Software Foundation, Inc.
3
4    This program is free software; you can redistribute it and/or modify it
5    under the terms of the GNU General Public License as published by the
6    Free Software Foundation; either version 2, or (at your option) any later
7    version.
8
9    This program is distributed in the hope that it will be useful, but
10    WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
12    Public License for more details.
13
14    You should have received a copy of the GNU General Public License along
15    with this program; if not, write to the Free Software Foundation, Inc.,
16    59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
17
18 /* Enable GNU extensions in fnmatch.h.  */
19 #ifndef _GNU_SOURCE
20 # define _GNU_SOURCE 1
21 #endif
22
23 #include "system.h"
24
25 #include <pwd.h>
26 #include <grp.h>
27 #include <fnmatch.h>
28
29 #include "common.h"
30 \f
31 /* User and group names.  */
32
33 extern struct group *getgrnam ();
34 extern struct passwd *getpwnam ();
35 #if !HAVE_GETPWUID
36 extern struct passwd *getpwuid ();
37 #endif
38 #if !HAVE_GETGRGID
39 extern struct group *getgrgid ();
40 #endif
41
42 /* Make sure you link with the proper libraries if you are running the
43    Yellow Peril (thanks for the good laugh, Ian J.!), or, euh... NIS.
44    This code should also be modified for non-UNIX systems to do something
45    reasonable.  */
46
47 static char cached_uname[UNAME_FIELD_SIZE];
48 static char cached_gname[GNAME_FIELD_SIZE];
49
50 static uid_t cached_uid;        /* valid only if cached_uname is not empty */
51 static gid_t cached_gid;        /* valid only if cached_gname is not empty */
52
53 /* These variables are valid only if nonempty.  */
54 static char cached_no_such_uname[UNAME_FIELD_SIZE];
55 static char cached_no_such_gname[GNAME_FIELD_SIZE];
56
57 /* These variables are valid only if nonzero.  It's not worth optimizing
58    the case for weird systems where 0 is not a valid uid or gid.  */
59 static uid_t cached_no_such_uid;
60 static gid_t cached_no_such_gid;
61
62 /*------------------------------------------.
63 | Given UID, find the corresponding UNAME.  |
64 `------------------------------------------*/
65
66 void
67 uid_to_uname (uid_t uid, char uname[UNAME_FIELD_SIZE])
68 {
69   struct passwd *passwd;
70
71   if (uid != 0 && uid == cached_no_such_uid)
72     {
73       *uname = '\0';
74       return;
75     }
76
77   if (!cached_uname[0] || uid != cached_uid)
78     {
79       passwd = getpwuid (uid);
80       if (passwd)
81         {
82           cached_uid = uid;
83           strncpy (cached_uname, passwd->pw_name, UNAME_FIELD_SIZE);
84         }
85       else
86         {
87           cached_no_such_uid = uid;
88           *uname = '\0';
89           return;
90         }
91     }
92   strncpy (uname, cached_uname, UNAME_FIELD_SIZE);
93 }
94
95 /*------------------------------------------.
96 | Given GID, find the corresponding GNAME.  |
97 `------------------------------------------*/
98
99 void
100 gid_to_gname (gid_t gid, char gname[GNAME_FIELD_SIZE])
101 {
102   struct group *group;
103
104   if (gid != 0 && gid == cached_no_such_gid)
105     {
106       *gname = '\0';
107       return;
108     }
109
110   if (!cached_gname[0] || gid != cached_gid)
111     {
112       setgrent ();              /* FIXME: why?! */
113       group = getgrgid (gid);
114       if (group)
115         {
116           cached_gid = gid;
117           strncpy (cached_gname, group->gr_name, GNAME_FIELD_SIZE);
118         }
119       else
120         {
121           cached_no_such_gid = gid;
122           *gname = '\0';
123           return;
124         }
125     }
126   strncpy (gname, cached_gname, GNAME_FIELD_SIZE);
127 }
128
129 /*-------------------------------------------------------------------------.
130 | Given UNAME, set the corresponding UID and return 1, or else, return 0.  |
131 `-------------------------------------------------------------------------*/
132
133 int
134 uname_to_uid (char uname[UNAME_FIELD_SIZE], uid_t *uidp)
135 {
136   struct passwd *passwd;
137
138   if (cached_no_such_uname[0]
139       && strncmp (uname, cached_no_such_uname, UNAME_FIELD_SIZE) == 0)
140     return 0;
141
142   if (!cached_uname[0]
143       || uname[0] != cached_uname[0]
144       || strncmp (uname, cached_uname, UNAME_FIELD_SIZE) != 0)
145     {
146       passwd = getpwnam (uname);
147       if (passwd)
148         {
149           cached_uid = passwd->pw_uid;
150           strncpy (cached_uname, uname, UNAME_FIELD_SIZE);
151         }
152       else
153         {
154           strncpy (cached_no_such_uname, uname, UNAME_FIELD_SIZE);
155           return 0;
156         }
157     }
158   *uidp = cached_uid;
159   return 1;
160 }
161
162 /*-------------------------------------------------------------------------.
163 | Given GNAME, set the corresponding GID and return 1, or else, return 0.  |
164 `-------------------------------------------------------------------------*/
165
166 int
167 gname_to_gid (char gname[GNAME_FIELD_SIZE], gid_t *gidp)
168 {
169   struct group *group;
170
171   if (cached_no_such_gname[0]
172       && strncmp (gname, cached_no_such_gname, GNAME_FIELD_SIZE) == 0)
173     return 0;
174
175   if (!cached_gname[0]
176       || gname[0] != cached_gname[0]
177       || strncmp (gname, cached_gname, GNAME_FIELD_SIZE) != 0)
178     {
179       group = getgrnam (gname);
180       if (group)
181         {
182           cached_gid = group->gr_gid;
183           strncpy (cached_gname, gname, GNAME_FIELD_SIZE);
184         }
185       else
186         {
187           strncpy (cached_no_such_gname, gname, GNAME_FIELD_SIZE);
188           return 0;
189         }
190     }
191   *gidp = cached_gid;
192   return 1;
193 }
194 \f
195 /* Names from the command call.  */
196
197 static const char **name_array; /* store an array of names */
198 static int allocated_names;     /* how big is the array? */
199 static int names;               /* how many entries does it have? */
200 static int name_index;          /* how many of the entries have we scanned? */
201
202 /*------------------------.
203 | Initialize structures.  |
204 `------------------------*/
205
206 void
207 init_names (void)
208 {
209   allocated_names = 10;
210   name_array = xmalloc (sizeof (const char *) * allocated_names);
211   names = 0;
212 }
213
214 /*--------------------------------------------------------------.
215 | Add NAME at end of name_array, reallocating it as necessary.  |
216 `--------------------------------------------------------------*/
217
218 void
219 name_add (const char *name)
220 {
221   if (names == allocated_names)
222     {
223       allocated_names *= 2;
224       name_array =
225         xrealloc (name_array, sizeof (const char *) * allocated_names);
226     }
227   name_array[names++] = name;
228 }
229 \f
230 /* Names from external name file.  */
231
232 static FILE *name_file;         /* file to read names from */
233 static char *name_buffer;       /* buffer to hold the current file name */
234 static size_t name_buffer_length; /* allocated length of name_buffer */
235
236 /*---.
237 | ?  |
238 `---*/
239
240 /* FIXME: I should better check more closely.  It seems at first glance that
241    is_pattern is only used when reading a file, and ignored for all
242    command line arguments.  */
243
244 static inline int
245 is_pattern (const char *string)
246 {
247   return strchr (string, '*') || strchr (string, '[') || strchr (string, '?');
248 }
249
250 /*-----------------------------------------------------------------------.
251 | Set up to gather file names for tar.  They can either come from a file |
252 | or were saved from decoding arguments.                                 |
253 `-----------------------------------------------------------------------*/
254
255 void
256 name_init (int argc, char *const *argv)
257 {
258   name_buffer = xmalloc (NAME_FIELD_SIZE + 2);
259   name_buffer_length = NAME_FIELD_SIZE;
260
261   if (files_from_option)
262     {
263       if (!strcmp (files_from_option, "-"))
264         {
265           request_stdin ("-T");
266           name_file = stdin;
267         }
268       else if (name_file = fopen (files_from_option, "r"), !name_file)
269         FATAL_ERROR ((0, errno, _("Cannot open file %s"), files_from_option));
270     }
271 }
272
273 /*---.
274 | ?  |
275 `---*/
276
277 void
278 name_term (void)
279 {
280   free (name_buffer);
281   free (name_array);
282 }
283
284 /*---------------------------------------------------------------------.
285 | Read the next filename from name_file and null-terminate it.  Put it |
286 | into name_buffer, reallocating and adjusting name_buffer_length if   |
287 | necessary.  Return 0 at end of file, 1 otherwise.                    |
288 `---------------------------------------------------------------------*/
289
290 static int
291 read_name_from_file (void)
292 {
293   int character;
294   size_t counter = 0;
295
296   /* FIXME: getc may be called even if character was EOF the last time here.  */
297
298   /* FIXME: This + 2 allocation might serve no purpose.  */
299
300   while (character = getc (name_file),
301          character != EOF && character != filename_terminator)
302     {
303       if (counter == name_buffer_length)
304         {
305           name_buffer_length += NAME_FIELD_SIZE;
306           name_buffer = xrealloc (name_buffer, name_buffer_length + 2);
307         }
308       name_buffer[counter++] = character;
309     }
310
311   if (counter == 0 && character == EOF)
312     return 0;
313
314   if (counter == name_buffer_length)
315     {
316       name_buffer_length += NAME_FIELD_SIZE;
317       name_buffer = xrealloc (name_buffer, name_buffer_length + 2);
318     }
319   name_buffer[counter] = '\0';
320
321   return 1;
322 }
323
324 /*------------------------------------------------------------------------.
325 | Get the next name from ARGV or the file of names.  Result is in static  |
326 | storage and can't be relied upon across two calls.                      |
327 |                                                                         |
328 | If CHANGE_DIRS is true, treat a filename of the form "-C" as meaning    |
329 | that the next filename is the name of a directory to change to.  If     |
330 | `filename_terminator' is NUL, CHANGE_DIRS is effectively always false.  |
331 `------------------------------------------------------------------------*/
332
333 char *
334 name_next (int change_dirs)
335 {
336   const char *source;
337   char *cursor;
338   int chdir_flag = 0;
339
340   if (filename_terminator == '\0')
341     change_dirs = 0;
342
343   while (1)
344     {
345       /* Get a name, either from file or from saved arguments.  */
346
347       if (name_file)
348         {
349           if (!read_name_from_file ())
350             break;
351         }
352       else
353         {
354           if (name_index == names)
355             break;
356
357           source = name_array[name_index++];
358           if (strlen (source) > name_buffer_length)
359             {
360               free (name_buffer);
361               name_buffer_length = strlen (source);
362               name_buffer = xmalloc (name_buffer_length + 2);
363             }
364           strcpy (name_buffer, source);
365         }
366
367       /* Zap trailing slashes.  */
368
369       cursor = name_buffer + strlen (name_buffer) - 1;
370       while (cursor > name_buffer && *cursor == '/')
371         *cursor-- = '\0';
372
373       if (chdir_flag)
374         {
375           if (chdir (name_buffer) < 0)
376             FATAL_ERROR ((0, errno, _("Cannot change to directory %s"),
377                           name_buffer));
378           chdir_flag = 0;
379         }
380       else if (change_dirs && strcmp (name_buffer, "-C") == 0)
381         chdir_flag = 1;
382       else
383         {
384           unquote_string (name_buffer);
385           return name_buffer;
386         }
387     }
388
389   /* No more names in file.  */
390
391   if (name_file && chdir_flag)
392     FATAL_ERROR ((0, 0, _("Missing file name after -C")));
393
394   return 0;
395 }
396
397 /*------------------------------.
398 | Close the name file, if any.  |
399 `------------------------------*/
400
401 void
402 name_close (void)
403 {
404   if (name_file && name_file != stdin)
405     if (fclose (name_file) == EOF)
406       ERROR ((0, errno, "%s", name_buffer));
407 }
408
409 /*-------------------------------------------------------------------------.
410 | Gather names in a list for scanning.  Could hash them later if we really |
411 | care.                                                                    |
412 |                                                                          |
413 | If the names are already sorted to match the archive, we just read them  |
414 | one by one.  name_gather reads the first one, and it is called by        |
415 | name_match as appropriate to read the next ones.  At EOF, the last name  |
416 | read is just left in the buffer.  This option lets users of small        |
417 | machines extract an arbitrary number of files by doing "tar t" and       |
418 | editing down the list of files.                                          |
419 `-------------------------------------------------------------------------*/
420
421 void
422 name_gather (void)
423 {
424   /* Buffer able to hold a single name.  */
425   static struct name *buffer;
426   static size_t allocated_length;
427
428   char const *name;
429
430   if (same_order_option)
431     {
432       static int change_dir;
433
434       if (allocated_length == 0)
435         {
436           allocated_length = sizeof (struct name) + NAME_FIELD_SIZE;
437           buffer = xmalloc (allocated_length);
438           /* FIXME: This memset is overkill, and ugly...  */
439           memset (buffer, 0, allocated_length);
440         }
441
442       while ((name = name_next (0)) && strcmp (name, "-C") == 0)
443         {
444           char const *dir = name_next (0);
445           if (! dir)
446             FATAL_ERROR ((0, 0, _("Missing file name after -C")));
447           change_dir = chdir_arg (xstrdup (dir));
448         }
449
450       if (name)
451         {
452           buffer->length = strlen (name);
453           if (sizeof (struct name) + buffer->length >= allocated_length)
454             {
455               allocated_length = sizeof (struct name) + buffer->length;
456               buffer = xrealloc (buffer, allocated_length);
457             }
458           buffer->change_dir = change_dir;
459           strncpy (buffer->name, name, buffer->length);
460           buffer->name[buffer->length] = 0;
461           buffer->next = 0;
462           buffer->found = 0;
463
464           /* FIXME: Poorly named globals, indeed...  */
465           namelist = buffer;
466           namelast = namelist;
467         }
468     }
469   else
470     {
471       /* Non sorted names -- read them all in.  */
472       int change_dir = 0;
473
474       for (;;)
475         {
476           int change_dir0 = change_dir;
477           while ((name = name_next (0)) && strcmp (name, "-C") == 0)
478             {
479               char const *dir = name_next (0);
480               if (! dir)
481                 FATAL_ERROR ((0, 0, _("Missing file name after -C")));
482               change_dir = chdir_arg (xstrdup (dir));
483             }
484           if (name)
485             addname (name, change_dir);
486           else
487             {
488               if (change_dir != change_dir0)
489                 addname (0, change_dir);
490               break;
491             }
492         }
493     }
494 }
495
496 /*-----------------------------.
497 | Add a name to the namelist.  |
498 `-----------------------------*/
499
500 void
501 addname (char const *string, int change_dir)
502 {
503   struct name *name;
504   size_t length;
505
506   length = string ? strlen (string) : 0;
507   name = xmalloc (sizeof (struct name) + length);
508   memset (name, 0, sizeof (struct name) + length);
509   name->next = 0;
510
511   if (string)
512     {
513       name->fake = 0;
514       name->length = length;
515       memcpy (name->name, string, length + 1);
516     }
517   else
518     name->fake = 1;
519
520   name->found = 0;
521   name->regexp = 0;             /* assume not a regular expression */
522   name->firstch = 1;            /* assume first char is literal */
523   name->change_dir = change_dir;
524   name->dir_contents = 0;
525
526   if (string && is_pattern (string))
527     {
528       name->regexp = 1;
529       if (string[0] == '*' || string[0] == '[' || string[0] == '?')
530         name->firstch = 0;
531     }
532
533   if (namelast)
534     namelast->next = name;
535   namelast = name;
536   if (!namelist)
537     namelist = name;
538 }
539
540 /*------------------------------------------------------------------------.
541 | Return true if and only if name PATH (from an archive) matches any name |
542 | from the namelist.                                                      |
543 `------------------------------------------------------------------------*/
544
545 int
546 name_match (const char *path)
547 {
548   size_t length = strlen (path);
549
550   while (1)
551     {
552       struct name *cursor = namelist;
553
554       if (!cursor)
555         return ! files_from_option;
556
557       if (cursor->fake)
558         {
559           chdir_do (cursor->change_dir);
560           namelist = 0;
561           return ! files_from_option;
562         }
563
564       for (; cursor; cursor = cursor->next)
565         {
566           /* If first chars don't match, quick skip.  */
567
568           if (cursor->firstch && cursor->name[0] != path[0])
569             continue;
570
571           if (cursor->regexp
572               ? fnmatch (cursor->name, path, FNM_LEADING_DIR) == 0
573               : (cursor->length <= length
574                  && (path[cursor->length] == '\0'
575                      || path[cursor->length] == '/')
576                  && memcmp (path, cursor->name, cursor->length) == 0))
577             {
578               cursor->found = 1; /* remember it matched */
579               if (starting_file_option)
580                 {
581                   free (namelist);
582                   namelist = 0;
583                 }
584               chdir_do (cursor->change_dir);
585   
586               /* We got a match.  */
587               return 1;
588             }
589         }
590
591       /* Filename from archive not found in namelist.  If we have the whole
592          namelist here, just return 0.  Otherwise, read the next name in and
593          compare it.  If this was the last name, namelist->found will remain
594          on.  If not, we loop to compare the newly read name.  */
595
596       if (same_order_option && namelist->found)
597         {
598           name_gather ();       /* read one more */
599           if (namelist->found)
600             return 0;
601         }
602       else
603         return 0;
604     }
605 }
606
607 /*------------------------------------------------------------------.
608 | Print the names of things in the namelist that were not matched.  |
609 `------------------------------------------------------------------*/
610
611 void
612 names_notfound (void)
613 {
614   struct name *cursor;
615   struct name *next;
616
617   for (cursor = namelist; cursor; cursor = next)
618     {
619       next = cursor->next;
620       if (!cursor->found && !cursor->fake)
621         ERROR ((0, 0, _("%s: Not found in archive"), cursor->name));
622
623       /* We could free the list, but the process is about to die anyway, so
624          save some CPU time.  Amigas and other similarly broken software
625          will need to waste the time, though.  */
626
627 #ifdef amiga
628       if (!same_order_option)
629         free (cursor);
630 #endif
631     }
632   namelist = 0;
633   namelast = 0;
634
635   if (same_order_option)
636     {
637       char *name;
638
639       while (name = name_next (1), name)
640         ERROR ((0, 0, _("%s: Not found in archive"), name));
641     }
642 }
643 \f
644 /* Sorting name lists.  */
645
646 /* Sort linked LIST of names, of given LENGTH, using COMPARE to order
647    names.  Return the sorted list.  Apart from the type `struct name'
648    and the definition of SUCCESSOR, this is a generic list-sorting
649    function, but it's too painful to make it both generic and portable
650    in C.  */
651
652 static struct name *
653 merge_sort (struct name *list, int length,
654             int (*compare) (struct name const*, struct name const*))
655 {
656   struct name *first_list;
657   struct name *second_list;
658   int first_length;
659   int second_length;
660   struct name *result;
661   struct name **merge_point;
662   struct name *cursor;
663   int counter;
664
665 # define SUCCESSOR(name) ((name)->next)
666
667   if (length == 1)
668     return list;
669
670   if (length == 2)
671     {
672       if ((*compare) (list, SUCCESSOR (list)) > 0)
673         {
674           result = SUCCESSOR (list);
675           SUCCESSOR (result) = list;
676           SUCCESSOR (list) = 0;
677           return result;
678         }
679       return list;
680     }
681
682   first_list = list;
683   first_length = (length + 1) / 2;
684   second_length = length / 2;
685   for (cursor = list, counter = first_length - 1;
686        counter;
687        cursor = SUCCESSOR (cursor), counter--)
688     continue;
689   second_list = SUCCESSOR (cursor);
690   SUCCESSOR (cursor) = 0;
691
692   first_list = merge_sort (first_list, first_length, compare);
693   second_list = merge_sort (second_list, second_length, compare);
694
695   merge_point = &result;
696   while (first_list && second_list)
697     if ((*compare) (first_list, second_list) < 0)
698       {
699         cursor = SUCCESSOR (first_list);
700         *merge_point = first_list;
701         merge_point = &SUCCESSOR (first_list);
702         first_list = cursor;
703       }
704     else
705       {
706         cursor = SUCCESSOR (second_list);
707         *merge_point = second_list;
708         merge_point = &SUCCESSOR (second_list);
709         second_list = cursor;
710       }
711   if (first_list)
712     *merge_point = first_list;
713   else
714     *merge_point = second_list;
715
716   return result;
717
718 #undef SUCCESSOR
719 }
720
721 /* A comparison function for sorting names.  Put found names last;
722    break ties by string comparison.  */
723
724 static int
725 compare_names (struct name const *n1, struct name const *n2)
726 {
727   int found_diff = n2->found - n1->found;
728   return found_diff ? found_diff : strcmp (n1->name, n2->name);
729 }
730 \f
731 /* Add all the dirs in PATH, which is a directory, to the namelist.
732    If any of the files is a directory, recurse on the subdirectory.
733    CHANGE_DIR is the number of the directory that PATH is relative to.
734    DEVICE is the device not to leave, if the -l option is specified.  */
735
736 static void
737 add_hierarchy_to_namelist (char *path, int change_dir, dev_t device)
738 {
739   char *buffer = get_directory_contents (path, device);
740
741   {
742     struct name *name;
743
744     for (name = namelist; name; name = name->next)
745       if (strcmp (name->name, path) == 0)
746         break;
747     if (name)
748       name->dir_contents = buffer ? buffer : "\0\0\0\0";
749   }
750
751   if (buffer)
752     {
753       size_t name_length = strlen (path);
754       size_t allocated_length = (name_length >= NAME_FIELD_SIZE
755                                  ? name_length + NAME_FIELD_SIZE
756                                  : NAME_FIELD_SIZE);
757       char *name_buffer = xmalloc (allocated_length + 1);
758                                 /* FIXME: + 2 above?  */
759       char *string;
760       size_t string_length;
761
762       strcpy (name_buffer, path);
763       if (name_buffer[name_length - 1] != '/')
764         {
765           name_buffer[name_length++] = '/';
766           name_buffer[name_length] = '\0';
767         }
768
769       for (string = buffer; *string; string += string_length + 1)
770         {
771           string_length = strlen (string);
772           if (*string == 'D')
773             {
774               if (name_length + string_length >= allocated_length)
775                 {
776                   while (name_length + string_length >= allocated_length)
777                     allocated_length += NAME_FIELD_SIZE;
778                   name_buffer = xrealloc (name_buffer, allocated_length + 1);
779                 }
780               strcpy (name_buffer + name_length, string + 1);
781               addname (name_buffer, change_dir);
782               if (*string == 'D')
783                 add_hierarchy_to_namelist (name_buffer, change_dir, device);
784             }
785         }
786
787       free (name_buffer);
788     }
789 }
790 \f
791 /* Collect all the names from argv[] (or whatever), expand them into a
792    directory tree, and sort them.  This gets only subdirectories, not
793    all files.  */
794
795 void
796 collect_and_sort_names (void)
797 {
798   struct name *name;
799   struct name *next_name;
800   int num_names;
801   struct stat statbuf;
802
803   name_gather ();
804
805   if (listed_incremental_option)
806     read_directory_file ();
807
808   if (!namelist)
809     addname (".", 0);
810
811   for (name = namelist; name; name = next_name)
812     {
813       next_name = name->next;
814       if (name->found || name->dir_contents)
815         continue;
816       if (name->regexp)         /* FIXME: just skip regexps for now */
817         continue;
818       chdir_do (name->change_dir);
819       if (name->fake)
820         continue;
821
822       if (deref_stat (dereference_option, name->name, &statbuf) != 0)
823         {
824           ERROR ((0, errno, _("Cannot stat %s"), name->name));
825           continue;
826         }
827       if (S_ISDIR (statbuf.st_mode))
828         {
829           name->found = 1;
830           add_hierarchy_to_namelist (name->name, name->change_dir,
831                                      statbuf.st_dev);
832         }
833     }
834
835   num_names = 0;
836   for (name = namelist; name; name = name->next)
837     num_names++;
838   namelist = merge_sort (namelist, num_names, compare_names);
839
840   for (name = namelist; name; name = name->next)
841     name->found = 0;
842 }
843
844 /*-------------------------------------------------------------------------.
845 | This is like name_match, except that it returns a pointer to the name it |
846 | matched, and doesn't set FOUND in structure.  The caller will have to do |
847 | that if it wants to.  Oh, and if the namelist is empty, it returns null, |
848 | unlike name_match, which returns TRUE.                                   |
849 `-------------------------------------------------------------------------*/
850
851 struct name *
852 name_scan (const char *path)
853 {
854   size_t length = strlen (path);
855
856   while (1)
857     {
858       struct name *cursor = namelist;
859
860       if (!cursor)
861         return 0;
862
863       for (; cursor; cursor = cursor->next)
864         {
865           /* If first chars don't match, quick skip.  */
866
867           if (cursor->firstch && cursor->name[0] != path[0])
868             continue;
869
870           if (cursor->regexp
871               ? fnmatch (cursor->name, path, FNM_LEADING_DIR) == 0
872               : (cursor->length <= length
873                  && (path[cursor->length] == '\0'
874                      || path[cursor->length] == '/')
875                  && memcmp (path, cursor->name, cursor->length) == 0))
876             return cursor;      /* we got a match */
877         }
878
879       /* Filename from archive not found in namelist.  If we have the whole
880          namelist here, just return 0.  Otherwise, read the next name in and
881          compare it.  If this was the last name, namelist->found will remain
882          on.  If not, we loop to compare the newly read name.  */
883
884       if (same_order_option && namelist->found)
885         {
886           name_gather ();       /* read one more */
887           if (namelist->found)
888             return 0;
889         }
890       else
891         return 0;
892     }
893 }
894
895 /*-----------------------------------------------------------------------.
896 | This returns a name from the namelist which doesn't have ->found set.  |
897 | It sets ->found before returning, so successive calls will find and    |
898 | return all the non-found names in the namelist                         |
899 `-----------------------------------------------------------------------*/
900
901 struct name *gnu_list_name;
902
903 char *
904 name_from_list (void)
905 {
906   if (!gnu_list_name)
907     gnu_list_name = namelist;
908   while (gnu_list_name && (gnu_list_name->found | gnu_list_name->fake))
909     gnu_list_name = gnu_list_name->next;
910   if (gnu_list_name)
911     {
912       gnu_list_name->found = 1;
913       chdir_do (gnu_list_name->change_dir);
914       return gnu_list_name->name;
915     }
916   return 0;
917 }
918
919 /*---.
920 | ?  |
921 `---*/
922
923 void
924 blank_name_list (void)
925 {
926   struct name *name;
927
928   gnu_list_name = 0;
929   for (name = namelist; name; name = name->next)
930     name->found = 0;
931 }
932
933 /*---.
934 | ?  |
935 `---*/
936
937 char *
938 new_name (const char *path, const char *name)
939 {
940   char *buffer = xmalloc (strlen (path) + strlen (name) + 2);
941
942   sprintf (buffer, "%s/%s", path, name);
943   return buffer;
944 }
945
946 /* Return nonzero if file NAME is excluded.  Exclude a name if its
947    prefix matches a pattern that contains slashes, or if one of its
948    components matches a pattern that contains no slashes.  */
949 int
950 excluded_name (char const *name)
951 {
952   char const *p;
953   name += FILESYSTEM_PREFIX_LEN (name);
954
955   if (excluded_filename (excluded_with_slash, name,
956                          FNM_FILE_NAME | FNM_LEADING_DIR))
957     return 1;
958
959   for (p = name; *p; p++)
960     if ((p == name || (ISSLASH (p[-1]) && !ISSLASH (p[0])))
961         && excluded_filename (excluded_without_slash, p,
962                               FNM_FILE_NAME | FNM_LEADING_DIR))
963       return 1;
964
965   return 0;
966 }
967 \f
968 /* Names to avoid dumping.  */
969
970 struct avoided_name
971 {
972   struct avoided_name const *next;
973   char name[1];
974 };
975
976 static struct avoided_name *avoided_names;
977
978 /* Remember to not archive NAME.  */
979 void
980 add_avoided_name (char const *name)
981 {
982   struct avoided_name *p = xmalloc (sizeof *p + strlen (name));
983   p->next = avoided_names;
984   avoided_names = p;
985   strcpy (p->name, name);
986 }
987
988 /* Should NAME be avoided when archiving?  */
989 int
990 is_avoided_name (char const *name)
991 {
992   struct avoided_name const *p;
993   for (p = avoided_names; p; p = p->next)
994     if (strcmp (p->name, name) == 0)
995       return 1;
996   return 0;
997 }