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