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