]> Dogcows Code - chaz/tar/blob - src/names.c
(name_next): If file names are given both in the
[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_index == names)
348 {
349 if (! name_file)
350 break;
351 if (! read_name_from_file ())
352 break;
353 }
354 else
355 {
356 source = name_array[name_index++];
357 if (strlen (source) > name_buffer_length)
358 {
359 free (name_buffer);
360 name_buffer_length = strlen (source);
361 name_buffer = xmalloc (name_buffer_length + 2);
362 }
363 strcpy (name_buffer, source);
364 }
365
366 /* Zap trailing slashes. */
367
368 cursor = name_buffer + strlen (name_buffer) - 1;
369 while (cursor > name_buffer && *cursor == '/')
370 *cursor-- = '\0';
371
372 if (chdir_flag)
373 {
374 if (chdir (name_buffer) < 0)
375 FATAL_ERROR ((0, errno, _("Cannot change to directory %s"),
376 name_buffer));
377 chdir_flag = 0;
378 }
379 else if (change_dirs && strcmp (name_buffer, "-C") == 0)
380 chdir_flag = 1;
381 else
382 {
383 unquote_string (name_buffer);
384 return name_buffer;
385 }
386 }
387
388 /* No more names in file. */
389
390 if (name_file && chdir_flag)
391 FATAL_ERROR ((0, 0, _("Missing file name after -C")));
392
393 return 0;
394 }
395
396 /*------------------------------.
397 | Close the name file, if any. |
398 `------------------------------*/
399
400 void
401 name_close (void)
402 {
403 if (name_file && name_file != stdin)
404 if (fclose (name_file) == EOF)
405 ERROR ((0, errno, "%s", name_buffer));
406 }
407
408 /*-------------------------------------------------------------------------.
409 | Gather names in a list for scanning. Could hash them later if we really |
410 | care. |
411 | |
412 | If the names are already sorted to match the archive, we just read them |
413 | one by one. name_gather reads the first one, and it is called by |
414 | name_match as appropriate to read the next ones. At EOF, the last name |
415 | read is just left in the buffer. This option lets users of small |
416 | machines extract an arbitrary number of files by doing "tar t" and |
417 | editing down the list of files. |
418 `-------------------------------------------------------------------------*/
419
420 void
421 name_gather (void)
422 {
423 /* Buffer able to hold a single name. */
424 static struct name *buffer;
425 static size_t allocated_length;
426
427 char const *name;
428
429 if (same_order_option)
430 {
431 static int change_dir;
432
433 if (allocated_length == 0)
434 {
435 allocated_length = sizeof (struct name) + NAME_FIELD_SIZE;
436 buffer = xmalloc (allocated_length);
437 /* FIXME: This memset is overkill, and ugly... */
438 memset (buffer, 0, allocated_length);
439 }
440
441 while ((name = name_next (0)) && strcmp (name, "-C") == 0)
442 {
443 char const *dir = name_next (0);
444 if (! dir)
445 FATAL_ERROR ((0, 0, _("Missing file name after -C")));
446 change_dir = chdir_arg (xstrdup (dir));
447 }
448
449 if (name)
450 {
451 buffer->length = strlen (name);
452 if (sizeof (struct name) + buffer->length >= allocated_length)
453 {
454 allocated_length = sizeof (struct name) + buffer->length;
455 buffer = xrealloc (buffer, allocated_length);
456 }
457 buffer->change_dir = change_dir;
458 strncpy (buffer->name, name, buffer->length);
459 buffer->name[buffer->length] = 0;
460 buffer->next = 0;
461 buffer->found = 0;
462
463 /* FIXME: Poorly named globals, indeed... */
464 namelist = buffer;
465 namelast = namelist;
466 }
467 }
468 else
469 {
470 /* Non sorted names -- read them all in. */
471 int change_dir = 0;
472
473 for (;;)
474 {
475 int change_dir0 = change_dir;
476 while ((name = name_next (0)) && strcmp (name, "-C") == 0)
477 {
478 char const *dir = name_next (0);
479 if (! dir)
480 FATAL_ERROR ((0, 0, _("Missing file name after -C")));
481 change_dir = chdir_arg (xstrdup (dir));
482 }
483 if (name)
484 addname (name, change_dir);
485 else
486 {
487 if (change_dir != change_dir0)
488 addname (0, change_dir);
489 break;
490 }
491 }
492 }
493 }
494
495 /*-----------------------------.
496 | Add a name to the namelist. |
497 `-----------------------------*/
498
499 void
500 addname (char const *string, int change_dir)
501 {
502 struct name *name;
503 size_t length;
504
505 length = string ? strlen (string) : 0;
506 name = xmalloc (sizeof (struct name) + length);
507 memset (name, 0, sizeof (struct name) + length);
508 name->next = 0;
509
510 if (string)
511 {
512 name->fake = 0;
513 name->length = length;
514 memcpy (name->name, string, length + 1);
515 }
516 else
517 name->fake = 1;
518
519 name->found = 0;
520 name->regexp = 0; /* assume not a regular expression */
521 name->firstch = 1; /* assume first char is literal */
522 name->change_dir = change_dir;
523 name->dir_contents = 0;
524
525 if (string && is_pattern (string))
526 {
527 name->regexp = 1;
528 if (string[0] == '*' || string[0] == '[' || string[0] == '?')
529 name->firstch = 0;
530 }
531
532 if (namelast)
533 namelast->next = name;
534 namelast = name;
535 if (!namelist)
536 namelist = name;
537 }
538
539 /*------------------------------------------------------------------------.
540 | Return true if and only if name PATH (from an archive) matches any name |
541 | from the namelist. |
542 `------------------------------------------------------------------------*/
543
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 return ! files_from_option;
561 }
562
563 for (; cursor; cursor = cursor->next)
564 {
565 /* If first chars don't match, quick skip. */
566
567 if (cursor->firstch && cursor->name[0] != path[0])
568 continue;
569
570 if (cursor->regexp
571 ? fnmatch (cursor->name, path, FNM_LEADING_DIR) == 0
572 : (cursor->length <= length
573 && (path[cursor->length] == '\0'
574 || path[cursor->length] == '/')
575 && memcmp (path, cursor->name, cursor->length) == 0))
576 {
577 cursor->found = 1; /* remember it matched */
578 if (starting_file_option)
579 {
580 free (namelist);
581 namelist = 0;
582 }
583 chdir_do (cursor->change_dir);
584
585 /* We got a match. */
586 return 1;
587 }
588 }
589
590 /* Filename from archive not found in namelist. If we have the whole
591 namelist here, just return 0. Otherwise, read the next name in and
592 compare it. If this was the last name, namelist->found will remain
593 on. If not, we loop to compare the newly read name. */
594
595 if (same_order_option && namelist->found)
596 {
597 name_gather (); /* read one more */
598 if (namelist->found)
599 return 0;
600 }
601 else
602 return 0;
603 }
604 }
605
606 /*------------------------------------------------------------------.
607 | Print the names of things in the namelist that were not matched. |
608 `------------------------------------------------------------------*/
609
610 void
611 names_notfound (void)
612 {
613 struct name *cursor;
614 struct name *next;
615
616 for (cursor = namelist; cursor; cursor = next)
617 {
618 next = cursor->next;
619 if (!cursor->found && !cursor->fake)
620 ERROR ((0, 0, _("%s: Not found in archive"), cursor->name));
621
622 /* We could free the list, but the process is about to die anyway, so
623 save some CPU time. Amigas and other similarly broken software
624 will need to waste the time, though. */
625
626 #ifdef amiga
627 if (!same_order_option)
628 free (cursor);
629 #endif
630 }
631 namelist = 0;
632 namelast = 0;
633
634 if (same_order_option)
635 {
636 char *name;
637
638 while (name = name_next (1), name)
639 ERROR ((0, 0, _("%s: Not found in archive"), name));
640 }
641 }
642 \f
643 /* Sorting name lists. */
644
645 /* Sort linked LIST of names, of given LENGTH, using COMPARE to order
646 names. Return the sorted list. Apart from the type `struct name'
647 and the definition of SUCCESSOR, this is a generic list-sorting
648 function, but it's too painful to make it both generic and portable
649 in C. */
650
651 static struct name *
652 merge_sort (struct name *list, int length,
653 int (*compare) (struct name const*, struct name const*))
654 {
655 struct name *first_list;
656 struct name *second_list;
657 int first_length;
658 int second_length;
659 struct name *result;
660 struct name **merge_point;
661 struct name *cursor;
662 int counter;
663
664 # define SUCCESSOR(name) ((name)->next)
665
666 if (length == 1)
667 return list;
668
669 if (length == 2)
670 {
671 if ((*compare) (list, SUCCESSOR (list)) > 0)
672 {
673 result = SUCCESSOR (list);
674 SUCCESSOR (result) = list;
675 SUCCESSOR (list) = 0;
676 return result;
677 }
678 return list;
679 }
680
681 first_list = list;
682 first_length = (length + 1) / 2;
683 second_length = length / 2;
684 for (cursor = list, counter = first_length - 1;
685 counter;
686 cursor = SUCCESSOR (cursor), counter--)
687 continue;
688 second_list = SUCCESSOR (cursor);
689 SUCCESSOR (cursor) = 0;
690
691 first_list = merge_sort (first_list, first_length, compare);
692 second_list = merge_sort (second_list, second_length, compare);
693
694 merge_point = &result;
695 while (first_list && second_list)
696 if ((*compare) (first_list, second_list) < 0)
697 {
698 cursor = SUCCESSOR (first_list);
699 *merge_point = first_list;
700 merge_point = &SUCCESSOR (first_list);
701 first_list = cursor;
702 }
703 else
704 {
705 cursor = SUCCESSOR (second_list);
706 *merge_point = second_list;
707 merge_point = &SUCCESSOR (second_list);
708 second_list = cursor;
709 }
710 if (first_list)
711 *merge_point = first_list;
712 else
713 *merge_point = second_list;
714
715 return result;
716
717 #undef SUCCESSOR
718 }
719
720 /* A comparison function for sorting names. Put found names last;
721 break ties by string comparison. */
722
723 static int
724 compare_names (struct name const *n1, struct name const *n2)
725 {
726 int found_diff = n2->found - n1->found;
727 return found_diff ? found_diff : strcmp (n1->name, n2->name);
728 }
729 \f
730 /* Add all the dirs in PATH, which is a directory, to the namelist.
731 If any of the files is a directory, recurse on the subdirectory.
732 CHANGE_DIR is the number of the directory that PATH is relative to.
733 DEVICE is the device not to leave, if the -l option is specified. */
734
735 static void
736 add_hierarchy_to_namelist (char *path, int change_dir, dev_t device)
737 {
738 char *buffer = get_directory_contents (path, device);
739
740 {
741 struct name *name;
742
743 for (name = namelist; name; name = name->next)
744 if (strcmp (name->name, path) == 0)
745 break;
746 if (name)
747 name->dir_contents = buffer ? buffer : "\0\0\0\0";
748 }
749
750 if (buffer)
751 {
752 size_t name_length = strlen (path);
753 size_t allocated_length = (name_length >= NAME_FIELD_SIZE
754 ? name_length + NAME_FIELD_SIZE
755 : NAME_FIELD_SIZE);
756 char *name_buffer = xmalloc (allocated_length + 1);
757 /* FIXME: + 2 above? */
758 char *string;
759 size_t string_length;
760
761 strcpy (name_buffer, path);
762 if (name_buffer[name_length - 1] != '/')
763 {
764 name_buffer[name_length++] = '/';
765 name_buffer[name_length] = '\0';
766 }
767
768 for (string = buffer; *string; string += string_length + 1)
769 {
770 string_length = strlen (string);
771 if (*string == 'D')
772 {
773 if (name_length + string_length >= allocated_length)
774 {
775 while (name_length + string_length >= allocated_length)
776 allocated_length += NAME_FIELD_SIZE;
777 name_buffer = xrealloc (name_buffer, allocated_length + 1);
778 }
779 strcpy (name_buffer + name_length, string + 1);
780 addname (name_buffer, change_dir);
781 if (*string == 'D')
782 add_hierarchy_to_namelist (name_buffer, change_dir, device);
783 }
784 }
785
786 free (name_buffer);
787 }
788 }
789 \f
790 /* Collect all the names from argv[] (or whatever), expand them into a
791 directory tree, and sort them. This gets only subdirectories, not
792 all files. */
793
794 void
795 collect_and_sort_names (void)
796 {
797 struct name *name;
798 struct name *next_name;
799 int num_names;
800 struct stat statbuf;
801
802 name_gather ();
803
804 if (listed_incremental_option)
805 read_directory_file ();
806
807 if (!namelist)
808 addname (".", 0);
809
810 for (name = namelist; name; name = next_name)
811 {
812 next_name = name->next;
813 if (name->found || name->dir_contents)
814 continue;
815 if (name->regexp) /* FIXME: just skip regexps for now */
816 continue;
817 chdir_do (name->change_dir);
818 if (name->fake)
819 continue;
820
821 if (deref_stat (dereference_option, name->name, &statbuf) != 0)
822 {
823 ERROR ((0, errno, _("Cannot stat %s"), name->name));
824 continue;
825 }
826 if (S_ISDIR (statbuf.st_mode))
827 {
828 name->found = 1;
829 add_hierarchy_to_namelist (name->name, name->change_dir,
830 statbuf.st_dev);
831 }
832 }
833
834 num_names = 0;
835 for (name = namelist; name; name = name->next)
836 num_names++;
837 namelist = merge_sort (namelist, num_names, compare_names);
838
839 for (name = namelist; name; name = name->next)
840 name->found = 0;
841 }
842
843 /*-------------------------------------------------------------------------.
844 | This is like name_match, except that it returns a pointer to the name it |
845 | matched, and doesn't set FOUND in structure. The caller will have to do |
846 | that if it wants to. Oh, and if the namelist is empty, it returns null, |
847 | unlike name_match, which returns TRUE. |
848 `-------------------------------------------------------------------------*/
849
850 struct name *
851 name_scan (const char *path)
852 {
853 size_t length = strlen (path);
854
855 while (1)
856 {
857 struct name *cursor = namelist;
858
859 if (!cursor)
860 return 0;
861
862 for (; cursor; cursor = cursor->next)
863 {
864 /* If first chars don't match, quick skip. */
865
866 if (cursor->firstch && cursor->name[0] != path[0])
867 continue;
868
869 if (cursor->regexp
870 ? fnmatch (cursor->name, path, FNM_LEADING_DIR) == 0
871 : (cursor->length <= length
872 && (path[cursor->length] == '\0'
873 || path[cursor->length] == '/')
874 && memcmp (path, cursor->name, cursor->length) == 0))
875 return cursor; /* we got a match */
876 }
877
878 /* Filename from archive not found in namelist. If we have the whole
879 namelist here, just return 0. Otherwise, read the next name in and
880 compare it. If this was the last name, namelist->found will remain
881 on. If not, we loop to compare the newly read name. */
882
883 if (same_order_option && namelist->found)
884 {
885 name_gather (); /* read one more */
886 if (namelist->found)
887 return 0;
888 }
889 else
890 return 0;
891 }
892 }
893
894 /*-----------------------------------------------------------------------.
895 | This returns a name from the namelist which doesn't have ->found set. |
896 | It sets ->found before returning, so successive calls will find and |
897 | return all the non-found names in the namelist |
898 `-----------------------------------------------------------------------*/
899
900 struct name *gnu_list_name;
901
902 char *
903 name_from_list (void)
904 {
905 if (!gnu_list_name)
906 gnu_list_name = namelist;
907 while (gnu_list_name && (gnu_list_name->found | gnu_list_name->fake))
908 gnu_list_name = gnu_list_name->next;
909 if (gnu_list_name)
910 {
911 gnu_list_name->found = 1;
912 chdir_do (gnu_list_name->change_dir);
913 return gnu_list_name->name;
914 }
915 return 0;
916 }
917
918 /*---.
919 | ? |
920 `---*/
921
922 void
923 blank_name_list (void)
924 {
925 struct name *name;
926
927 gnu_list_name = 0;
928 for (name = namelist; name; name = name->next)
929 name->found = 0;
930 }
931
932 /*---.
933 | ? |
934 `---*/
935
936 char *
937 new_name (const char *path, const char *name)
938 {
939 char *buffer = xmalloc (strlen (path) + strlen (name) + 2);
940
941 sprintf (buffer, "%s/%s", path, name);
942 return buffer;
943 }
944
945 /* Return nonzero if file NAME is excluded. Exclude a name if its
946 prefix matches a pattern that contains slashes, or if one of its
947 components matches a pattern that contains no slashes. */
948 int
949 excluded_name (char const *name)
950 {
951 char const *p;
952 name += FILESYSTEM_PREFIX_LEN (name);
953
954 if (excluded_filename (excluded_with_slash, name,
955 FNM_FILE_NAME | FNM_LEADING_DIR))
956 return 1;
957
958 for (p = name; *p; p++)
959 if ((p == name || (ISSLASH (p[-1]) && !ISSLASH (p[0])))
960 && excluded_filename (excluded_without_slash, p,
961 FNM_FILE_NAME | FNM_LEADING_DIR))
962 return 1;
963
964 return 0;
965 }
966 \f
967 /* Names to avoid dumping. */
968
969 struct avoided_name
970 {
971 struct avoided_name const *next;
972 char name[1];
973 };
974
975 static struct avoided_name *avoided_names;
976
977 /* Remember to not archive NAME. */
978 void
979 add_avoided_name (char const *name)
980 {
981 struct avoided_name *p = xmalloc (sizeof *p + strlen (name));
982 p->next = avoided_names;
983 avoided_names = p;
984 strcpy (p->name, name);
985 }
986
987 /* Should NAME be avoided when archiving? */
988 int
989 is_avoided_name (char const *name)
990 {
991 struct avoided_name const *p;
992 for (p = avoided_names; p; p = p->next)
993 if (strcmp (p->name, name) == 0)
994 return 1;
995 return 0;
996 }
This page took 0.08328 seconds and 5 git commands to generate.