8301a3e2b48e6209ab4545caf408354c820eb969
[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 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    59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
19
20 #include "system.h"
21
22 #include <fnmatch.h>
23 #include <grp.h>
24 #include <hash.h>
25 #include <pwd.h>
26 #include <quotearg.h>
27
28 #include "common.h"
29 \f
30 /* User and group names.  */
31
32 struct group *getgrnam ();
33 struct passwd *getpwnam ();
34 #if ! HAVE_DECL_GETPWUID
35 struct passwd *getpwuid ();
36 #endif
37 #if ! HAVE_DECL_GETGRGID
38 struct group *getgrgid ();
39 #endif
40
41 /* Make sure you link with the proper libraries if you are running the
42    Yellow Peril (thanks for the good laugh, Ian J.!), or, euh... NIS.
43    This code should also be modified for non-UNIX systems to do something
44    reasonable.  */
45
46 static char *cached_uname;
47 static char *cached_gname;
48
49 static uid_t cached_uid;        /* valid only if cached_uname is not empty */
50 static gid_t cached_gid;        /* valid only if cached_gname is not empty */
51
52 /* These variables are valid only if nonempty.  */
53 static char *cached_no_such_uname;
54 static char *cached_no_such_gname;
55
56 /* These variables are valid only if nonzero.  It's not worth optimizing
57    the case for weird systems where 0 is not a valid uid or gid.  */
58 static uid_t cached_no_such_uid;
59 static gid_t cached_no_such_gid;
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 = strdup ("");
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 = strdup ("");
85           return;
86         }
87     }
88   *uname = strdup (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 = strdup ("");
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 = strdup ("");
115           return;
116         }
117     }
118   *gname = strdup (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 *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 *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 \f
213 /* Names from external name file.  */
214
215 static FILE *name_file;         /* file to read names from */
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 (int argc, char *const *argv)
233 {
234   name_buffer = xmalloc (NAME_FIELD_SIZE + 2);
235   name_buffer_length = NAME_FIELD_SIZE;
236
237   if (files_from_option)
238     {
239       if (!strcmp (files_from_option, "-"))
240         {
241           request_stdin ("-T");
242           name_file = stdin;
243         }
244       else if (name_file = fopen (files_from_option, "r"), !name_file)
245         open_fatal (files_from_option);
246     }
247 }
248
249 void
250 name_term (void)
251 {
252   free (name_buffer);
253   free (name_array);
254 }
255
256 /* Read the next filename from name_file and null-terminate it.  Put
257    it into name_buffer, reallocating and adjusting name_buffer_length
258    if necessary.  Return 0 at end of file, 1 otherwise.  */
259 static int
260 read_name_from_file (void)
261 {
262   int character;
263   size_t counter = 0;
264
265   /* FIXME: getc may be called even if character was EOF the last time here.  */
266
267   /* FIXME: This + 2 allocation might serve no purpose.  */
268
269   while (character = getc (name_file),
270          character != EOF && character != filename_terminator)
271     {
272       if (counter == name_buffer_length)
273         {
274           if (name_buffer_length * 2 < name_buffer_length)
275             xalloc_die ();
276           name_buffer_length *= 2;
277           name_buffer = xrealloc (name_buffer, name_buffer_length + 2);
278         }
279       name_buffer[counter++] = character;
280     }
281
282   if (counter == 0 && character == EOF)
283     return 0;
284
285   if (counter == name_buffer_length)
286     {
287       if (name_buffer_length * 2 < name_buffer_length)
288         xalloc_die ();
289       name_buffer_length *= 2;
290       name_buffer = xrealloc (name_buffer, name_buffer_length + 2);
291     }
292   name_buffer[counter] = '\0';
293
294   return 1;
295 }
296
297 /* Get the next name from ARGV or the file of names.  Result is in
298    static storage and can't be relied upon across two calls.
299
300    If CHANGE_DIRS is true, treat a filename of the form "-C" as
301    meaning that the next filename is the name of a directory to change
302    to.  If filename_terminator is NUL, CHANGE_DIRS is effectively
303    always false.  */
304 char *
305 name_next (int change_dirs)
306 {
307   const char *source;
308   char *cursor;
309   int chdir_flag = 0;
310
311   if (filename_terminator == '\0')
312     change_dirs = 0;
313
314   while (1)
315     {
316       /* Get a name, either from file or from saved arguments.  */
317
318       if (name_index == names)
319         {
320           if (! name_file)
321             break;
322           if (! read_name_from_file ())
323             break;
324         }
325       else
326         {
327           size_t source_len;
328           source = name_array[name_index++];
329           source_len = strlen (source);
330           if (name_buffer_length < source_len)
331             {
332               do
333                 {
334                   name_buffer_length *= 2;
335                   if (! name_buffer_length)
336                     xalloc_die ();
337                 }
338               while (name_buffer_length < source_len);
339
340               free (name_buffer);
341               name_buffer = xmalloc (name_buffer_length + 2);
342             }
343           strcpy (name_buffer, source);
344         }
345
346       /* Zap trailing slashes.  */
347
348       cursor = name_buffer + strlen (name_buffer) - 1;
349       while (cursor > name_buffer && ISSLASH (*cursor))
350         *cursor-- = '\0';
351
352       if (chdir_flag)
353         {
354           if (chdir (name_buffer) < 0)
355             chdir_fatal (name_buffer);
356           chdir_flag = 0;
357         }
358       else if (change_dirs && strcmp (name_buffer, "-C") == 0)
359         chdir_flag = 1;
360       else
361         {
362           unquote_string (name_buffer);
363           return name_buffer;
364         }
365     }
366
367   /* No more names in file.  */
368
369   if (name_file && chdir_flag)
370     FATAL_ERROR ((0, 0, _("Missing file name after -C")));
371
372   return 0;
373 }
374
375 /* Close the name file, if any.  */
376 void
377 name_close (void)
378 {
379   if (name_file && name_file != stdin)
380     if (fclose (name_file) != 0)
381       close_error (name_buffer);
382 }
383
384 /* Gather names in a list for scanning.  Could hash them later if we
385    really care.
386
387    If the names are already sorted to match the archive, we just read
388    them one by one.  name_gather reads the first one, and it is called
389    by name_match as appropriate to read the next ones.  At EOF, the
390    last name read is just left in the buffer.  This option lets users
391    of small machines extract an arbitrary number of files by doing
392    "tar t" and editing down the list of files.  */
393
394 void
395 name_gather (void)
396 {
397   /* Buffer able to hold a single name.  */
398   static struct name *buffer;
399   static size_t allocated_size;
400
401   char const *name;
402
403   if (same_order_option)
404     {
405       static int change_dir;
406
407       if (allocated_size == 0)
408         {
409           allocated_size = offsetof (struct name, name) + NAME_FIELD_SIZE + 1;
410           buffer = xmalloc (allocated_size);
411           /* FIXME: This memset is overkill, and ugly...  */
412           memset (buffer, 0, allocated_size);
413         }
414
415       while ((name = name_next (0)) && strcmp (name, "-C") == 0)
416         {
417           char const *dir = name_next (0);
418           if (! dir)
419             FATAL_ERROR ((0, 0, _("Missing file name after -C")));
420           change_dir = chdir_arg (xstrdup (dir));
421         }
422
423       if (name)
424         {
425           size_t needed_size;
426           buffer->length = strlen (name);
427           needed_size = offsetof (struct name, name) + buffer->length + 1;
428           if (allocated_size < needed_size)
429             {
430               do
431                 {
432                   allocated_size *= 2;
433                   if (! allocated_size)
434                     xalloc_die ();
435                 }
436               while (allocated_size < needed_size);
437
438               buffer = xrealloc (buffer, allocated_size);
439             }
440           buffer->change_dir = change_dir;
441           strcpy (buffer->name, name);
442           buffer->next = 0;
443           buffer->found = 0;
444
445           namelist = buffer;
446           nametail = &namelist->next;
447         }
448     }
449   else
450     {
451       /* Non sorted names -- read them all in.  */
452       int change_dir = 0;
453
454       for (;;)
455         {
456           int change_dir0 = change_dir;
457           while ((name = name_next (0)) && strcmp (name, "-C") == 0)
458             {
459               char const *dir = name_next (0);
460               if (! dir)
461                 FATAL_ERROR ((0, 0, _("Missing file name after -C")));
462               change_dir = chdir_arg (xstrdup (dir));
463             }
464           if (name)
465             addname (name, change_dir);
466           else
467             {
468               if (change_dir != change_dir0)
469                 addname (0, change_dir);
470               break;
471             }
472         }
473     }
474 }
475
476 /*  Add a name to the namelist.  */
477 struct name *
478 addname (char const *string, int change_dir)
479 {
480   size_t length = string ? strlen (string) : 0;
481   struct name *name = xmalloc (offsetof (struct name, name) + length + 1);
482
483   if (string)
484     {
485       name->fake = 0;
486       strcpy (name->name, string);
487     }
488   else
489     {
490       name->fake = 1;
491
492       /* FIXME: This initialization (and the byte of memory that it
493          initializes) is probably not needed, but we are currently in
494          bug-fix mode so we'll leave it in for now.  */
495       name->name[0] = 0;
496     }
497
498   name->next = 0;
499   name->length = length;
500   name->found = 0;
501   name->regexp = 0;             /* assume not a regular expression */
502   name->firstch = 1;            /* assume first char is literal */
503   name->change_dir = change_dir;
504   name->dir_contents = 0;
505
506   if (string && is_pattern (string))
507     {
508       name->regexp = 1;
509       if (string[0] == '*' || string[0] == '[' || string[0] == '?')
510         name->firstch = 0;
511     }
512
513   *nametail = name;
514   nametail = &name->next;
515   return name;
516 }
517
518 /* Find a match for PATH (whose string length is LENGTH) in the name
519    list.  */
520 static struct name *
521 namelist_match (char const *path, size_t length)
522 {
523   struct name *p;
524
525   for (p = namelist; p; p = p->next)
526     {
527       /* If first chars don't match, quick skip.  */
528
529       if (p->firstch && p->name[0] != path[0])
530         continue;
531
532       if (p->regexp
533           ? fnmatch (p->name, path, recursion_option) == 0
534           : (p->length <= length
535              && (path[p->length] == '\0'
536                  || (ISSLASH (path[p->length]) && recursion_option))
537              && memcmp (path, p->name, p->length) == 0))
538         return p;
539     }
540
541   return 0;
542 }
543
544 /* Return true if and only if name PATH (from an archive) matches any
545    name from the namelist.  */
546 int
547 name_match (const char *path)
548 {
549   size_t length = strlen (path);
550
551   while (1)
552     {
553       struct name *cursor = namelist;
554
555       if (!cursor)
556         return ! files_from_option;
557
558       if (cursor->fake)
559         {
560           chdir_do (cursor->change_dir);
561           namelist = 0;
562           nametail = &namelist;
563           return ! files_from_option;
564         }
565
566       cursor = namelist_match (path, length);
567       if (cursor)
568         {
569           cursor->found = 1; /* remember it matched */
570           if (starting_file_option)
571             {
572               free (namelist);
573               namelist = 0;
574               nametail = &namelist;
575             }
576           chdir_do (cursor->change_dir);
577
578           /* We got a match.  */
579           return 1;
580         }
581
582       /* Filename from archive not found in namelist.  If we have the whole
583          namelist here, just return 0.  Otherwise, read the next name in and
584          compare it.  If this was the last name, namelist->found will remain
585          on.  If not, we loop to compare the newly read name.  */
586
587       if (same_order_option && namelist->found)
588         {
589           name_gather ();       /* read one more */
590           if (namelist->found)
591             return 0;
592         }
593       else
594         return 0;
595     }
596 }
597
598 /* Print the names of things in the namelist that were not matched.  */
599 void
600 names_notfound (void)
601 {
602   struct name const *cursor;
603
604   for (cursor = namelist; cursor; cursor = cursor->next)
605     if (!cursor->found && !cursor->fake)
606       ERROR ((0, 0, _("%s: Not found in archive"),
607               quotearg_colon (cursor->name)));
608
609   /* Don't bother freeing the name list; we're about to exit.  */
610   namelist = 0;
611   nametail = &namelist;
612
613   if (same_order_option)
614     {
615       char *name;
616
617       while (name = name_next (1), name)
618         ERROR ((0, 0, _("%s: Not found in archive"),
619                 quotearg_colon (name)));
620     }
621 }
622 \f
623 /* Sorting name lists.  */
624
625 /* Sort linked LIST of names, of given LENGTH, using COMPARE to order
626    names.  Return the sorted list.  Apart from the type `struct name'
627    and the definition of SUCCESSOR, this is a generic list-sorting
628    function, but it's too painful to make it both generic and portable
629    in C.  */
630
631 static struct name *
632 merge_sort (struct name *list, int length,
633             int (*compare) (struct name const*, struct name const*))
634 {
635   struct name *first_list;
636   struct name *second_list;
637   int first_length;
638   int second_length;
639   struct name *result;
640   struct name **merge_point;
641   struct name *cursor;
642   int counter;
643
644 # define SUCCESSOR(name) ((name)->next)
645
646   if (length == 1)
647     return list;
648
649   if (length == 2)
650     {
651       if ((*compare) (list, SUCCESSOR (list)) > 0)
652         {
653           result = SUCCESSOR (list);
654           SUCCESSOR (result) = list;
655           SUCCESSOR (list) = 0;
656           return result;
657         }
658       return list;
659     }
660
661   first_list = list;
662   first_length = (length + 1) / 2;
663   second_length = length / 2;
664   for (cursor = list, counter = first_length - 1;
665        counter;
666        cursor = SUCCESSOR (cursor), counter--)
667     continue;
668   second_list = SUCCESSOR (cursor);
669   SUCCESSOR (cursor) = 0;
670
671   first_list = merge_sort (first_list, first_length, compare);
672   second_list = merge_sort (second_list, second_length, compare);
673
674   merge_point = &result;
675   while (first_list && second_list)
676     if ((*compare) (first_list, second_list) < 0)
677       {
678         cursor = SUCCESSOR (first_list);
679         *merge_point = first_list;
680         merge_point = &SUCCESSOR (first_list);
681         first_list = cursor;
682       }
683     else
684       {
685         cursor = SUCCESSOR (second_list);
686         *merge_point = second_list;
687         merge_point = &SUCCESSOR (second_list);
688         second_list = cursor;
689       }
690   if (first_list)
691     *merge_point = first_list;
692   else
693     *merge_point = second_list;
694
695   return result;
696
697 #undef SUCCESSOR
698 }
699
700 /* A comparison function for sorting names.  Put found names last;
701    break ties by string comparison.  */
702
703 static int
704 compare_names (struct name const *n1, struct name const *n2)
705 {
706   int found_diff = n2->found - n1->found;
707   return found_diff ? found_diff : strcmp (n1->name, n2->name);
708 }
709 \f
710 /* Add all the dirs under NAME, which names a directory, to the namelist.
711    If any of the files is a directory, recurse on the subdirectory.
712    DEVICE is the device not to leave, if the -l option is specified.  */
713
714 static void
715 add_hierarchy_to_namelist (struct name *name, dev_t device)
716 {
717   char *path = name->name;
718   char *buffer = get_directory_contents (path, device);
719
720   if (! buffer)
721     name->dir_contents = "\0\0\0\0";
722   else
723     {
724       size_t name_length = name->length;
725       size_t allocated_length = (name_length >= NAME_FIELD_SIZE
726                                  ? name_length + NAME_FIELD_SIZE
727                                  : NAME_FIELD_SIZE);
728       char *name_buffer = xmalloc (allocated_length + 1);
729                                 /* FIXME: + 2 above?  */
730       char *string;
731       size_t string_length;
732       int change_dir = name->change_dir;
733
734       name->dir_contents = buffer;
735       strcpy (name_buffer, path);
736       if (! ISSLASH (name_buffer[name_length - 1]))
737         {
738           name_buffer[name_length++] = '/';
739           name_buffer[name_length] = '\0';
740         }
741
742       for (string = buffer; *string; string += string_length + 1)
743         {
744           string_length = strlen (string);
745           if (*string == 'D')
746             {
747               if (allocated_length <= name_length + string_length)
748                 {
749                   do
750                     {
751                       allocated_length *= 2;
752                       if (! allocated_length)
753                         xalloc_die ();
754                     }
755                   while (allocated_length <= name_length + string_length);
756
757                   name_buffer = xrealloc (name_buffer, allocated_length + 1);
758                 }
759               strcpy (name_buffer + name_length, string + 1);
760               add_hierarchy_to_namelist (addname (name_buffer, change_dir),
761                                          device);
762             }
763         }
764
765       free (name_buffer);
766     }
767 }
768 \f
769 /* Collect all the names from argv[] (or whatever), expand them into a
770    directory tree, and sort them.  This gets only subdirectories, not
771    all files.  */
772
773 void
774 collect_and_sort_names (void)
775 {
776   struct name *name;
777   struct name *next_name;
778   int num_names;
779   struct stat statbuf;
780
781   name_gather ();
782
783   if (listed_incremental_option)
784     read_directory_file ();
785
786   if (!namelist)
787     addname (".", 0);
788
789   for (name = namelist; name; name = next_name)
790     {
791       next_name = name->next;
792       if (name->found || name->dir_contents)
793         continue;
794       if (name->regexp)         /* FIXME: just skip regexps for now */
795         continue;
796       chdir_do (name->change_dir);
797       if (name->fake)
798         continue;
799
800       if (deref_stat (dereference_option, name->name, &statbuf) != 0)
801         {
802           if (ignore_failed_read_option)
803             stat_warn (name->name);
804           else
805             stat_error (name->name);
806           continue;
807         }
808       if (S_ISDIR (statbuf.st_mode))
809         {
810           name->found = 1;
811           add_hierarchy_to_namelist (name, statbuf.st_dev);
812         }
813     }
814
815   num_names = 0;
816   for (name = namelist; name; name = name->next)
817     num_names++;
818   namelist = merge_sort (namelist, num_names, compare_names);
819
820   for (name = namelist; name; name = name->next)
821     name->found = 0;
822 }
823
824 /* This is like name_match, except that it returns a pointer to the
825    name it matched, and doesn't set FOUND in structure.  The caller
826    will have to do that if it wants to.  Oh, and if the namelist is
827    empty, it returns null, unlike name_match, which returns TRUE.  */
828 struct name *
829 name_scan (const char *path)
830 {
831   size_t length = strlen (path);
832
833   while (1)
834     {
835       struct name *cursor = namelist_match (path, length);
836       if (cursor)
837         return cursor;
838
839       /* Filename from archive not found in namelist.  If we have the whole
840          namelist here, just return 0.  Otherwise, read the next name in and
841          compare it.  If this was the last name, namelist->found will remain
842          on.  If not, we loop to compare the newly read name.  */
843
844       if (same_order_option && namelist && namelist->found)
845         {
846           name_gather ();       /* read one more */
847           if (namelist->found)
848             return 0;
849         }
850       else
851         return 0;
852     }
853 }
854
855 /* This returns a name from the namelist which doesn't have ->found
856    set.  It sets ->found before returning, so successive calls will
857    find and return all the non-found names in the namelist.  */
858 struct name *gnu_list_name;
859
860 char *
861 name_from_list (void)
862 {
863   if (!gnu_list_name)
864     gnu_list_name = namelist;
865   while (gnu_list_name && (gnu_list_name->found | gnu_list_name->fake))
866     gnu_list_name = gnu_list_name->next;
867   if (gnu_list_name)
868     {
869       gnu_list_name->found = 1;
870       chdir_do (gnu_list_name->change_dir);
871       return gnu_list_name->name;
872     }
873   return 0;
874 }
875
876 void
877 blank_name_list (void)
878 {
879   struct name *name;
880
881   gnu_list_name = 0;
882   for (name = namelist; name; name = name->next)
883     name->found = 0;
884 }
885
886 /* Yield a newly allocated file name consisting of PATH concatenated to
887    NAME, with an intervening slash if PATH does not already end in one.  */
888 char *
889 new_name (const char *path, const char *name)
890 {
891   size_t pathlen = strlen (path);
892   size_t namesize = strlen (name) + 1;
893   int slash = pathlen && ! ISSLASH (path[pathlen - 1]);
894   char *buffer = xmalloc (pathlen + slash + namesize);
895   memcpy (buffer, path, pathlen);
896   buffer[pathlen] = '/';
897   memcpy (buffer + pathlen + slash, name, namesize);
898   return buffer;
899 }
900
901 /* Return nonzero if file NAME is excluded.  */
902 bool
903 excluded_name (char const *name)
904 {
905   return excluded_filename (excluded, name + FILESYSTEM_PREFIX_LEN (name));
906 }
907 \f
908 /* Hash tables of strings.  */
909
910 /* Calculate the hash of a string.  */
911 static unsigned
912 hash_string_hasher (void const *name, unsigned n_buckets)
913 {
914   return hash_string (name, n_buckets);
915 }
916
917 /* Compare two strings for equality.  */
918 static bool
919 hash_string_compare (void const *name1, void const *name2)
920 {
921   return strcmp (name1, name2) == 0;
922 }
923
924 /* Return zero if TABLE contains a copy of STRING; otherwise, insert a
925    copy of STRING to TABLE and return 1.  */
926 static bool
927 hash_string_insert (Hash_table **table, char const *string)
928 {
929   Hash_table *t = *table;
930   char *s = xstrdup (string);
931   char *e;
932
933   if (! ((t
934           || (*table = t = hash_initialize (0, 0, hash_string_hasher,
935                                             hash_string_compare, 0)))
936          && (e = hash_insert (t, s))))
937     xalloc_die ();
938
939   if (e == s)
940     return 1;
941   else
942     {
943       free (s);
944       return 0;
945     }
946 }
947
948 /* Return 1 if TABLE contains STRING.  */
949 static bool
950 hash_string_lookup (Hash_table const *table, char const *string)
951 {
952   return table && hash_lookup (table, string);
953 }
954 \f
955 /* Names to avoid dumping.  */
956 static Hash_table *avoided_name_table;
957
958 /* Remember to not archive NAME.  */
959 void
960 add_avoided_name (char const *name)
961 {
962   hash_string_insert (&avoided_name_table, name);
963 }
964
965 /* Should NAME be avoided when archiving?  */
966 bool
967 is_avoided_name (char const *name)
968 {
969   return hash_string_lookup (avoided_name_table, name);
970 }
971 \f
972 /* Return a safer suffix of FILE_NAME, or "." if it has no safer
973    suffix.  Check for fully specified file names and other atrocities.
974    Warn the user if we do not return NAME.  If LINK_TARGET is 1,
975    FILE_NAME is the target of a hard link, not a member name.  */
976
977 char *
978 safer_name_suffix (char const *file_name, bool link_target)
979 {
980   char const *p;
981
982   if (absolute_names_option)
983     p = file_name;
984   else
985     {
986       /* Skip file system prefixes, leading pathnames that contain
987          "..", and leading slashes.  */
988
989       size_t prefix_len = FILESYSTEM_PREFIX_LEN (file_name);
990
991       for (p = file_name + prefix_len; *p; )
992         {
993           if (p[0] == '.' && p[1] == '.' && (ISSLASH (p[2]) || !p[2]))
994             prefix_len = p + 2 - file_name;
995
996           do
997             {
998               char c = *p++;
999               if (ISSLASH (c))
1000                 break;
1001             }
1002           while (*p);
1003         }
1004
1005       for (p = file_name + prefix_len; ISSLASH (*p); p++)
1006         continue;
1007       prefix_len = p - file_name;
1008
1009       if (prefix_len)
1010         {
1011           static Hash_table *prefix_table[2];
1012           char *prefix = alloca (prefix_len + 1);
1013           memcpy (prefix, file_name, prefix_len);
1014           prefix[prefix_len] = '\0';
1015
1016           if (hash_string_insert (&prefix_table[link_target], prefix))
1017             {
1018               static char const *const diagnostic[] =
1019               {
1020                 N_("Removing leading `%s' from member names"),
1021                 N_("Removing leading `%s' from hard link targets")
1022               };
1023               WARN ((0, 0, _(diagnostic[link_target]), prefix));
1024             }
1025         }
1026     }
1027
1028   if (! *p)
1029     {
1030       if (p == file_name)
1031         {
1032           static char const *const diagnostic[] =
1033           {
1034             N_("Substituting `.' for empty member name"),
1035             N_("Substituting `.' for empty hard link target")
1036           };
1037           WARN ((0, 0, _(diagnostic[link_target])));
1038         }
1039
1040       p = ".";
1041     }
1042
1043   return (char *) p;
1044 }
1045 \f
1046 /* Return nonzero if NAME contains ".." as a path name component.  */
1047 bool
1048 contains_dot_dot (char const *name)
1049 {
1050   char const *p = name + FILESYSTEM_PREFIX_LEN (name);
1051
1052   for (;; p++)
1053     {
1054       if (p[0] == '.' && p[1] == '.' && (ISSLASH (p[2]) || !p[2]))
1055         return 1;
1056
1057       do
1058         {
1059           if (! *p++)
1060             return 0;
1061         }
1062       while (! ISSLASH (*p));
1063     }
1064 }