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