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