]> Dogcows Code - chaz/tar/blob - src/names.c
(<quotearg.h>): New include.
[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 #include <quotearg.h>
29
30 #include "common.h"
31 \f
32 /* User and group names. */
33
34 extern struct group *getgrnam ();
35 extern struct passwd *getpwnam ();
36 #if !HAVE_GETPWUID
37 extern struct passwd *getpwuid ();
38 #endif
39 #if !HAVE_GETGRGID
40 extern struct group *getgrgid ();
41 #endif
42
43 /* Make sure you link with the proper libraries if you are running the
44 Yellow Peril (thanks for the good laugh, Ian J.!), or, euh... NIS.
45 This code should also be modified for non-UNIX systems to do something
46 reasonable. */
47
48 static char cached_uname[UNAME_FIELD_SIZE];
49 static char cached_gname[GNAME_FIELD_SIZE];
50
51 static uid_t cached_uid; /* valid only if cached_uname is not empty */
52 static gid_t cached_gid; /* valid only if cached_gname is not empty */
53
54 /* These variables are valid only if nonempty. */
55 static char cached_no_such_uname[UNAME_FIELD_SIZE];
56 static char cached_no_such_gname[GNAME_FIELD_SIZE];
57
58 /* These variables are valid only if nonzero. It's not worth optimizing
59 the case for weird systems where 0 is not a valid uid or gid. */
60 static uid_t cached_no_such_uid;
61 static gid_t cached_no_such_gid;
62
63 /*------------------------------------------.
64 | Given UID, find the corresponding UNAME. |
65 `------------------------------------------*/
66
67 void
68 uid_to_uname (uid_t uid, char uname[UNAME_FIELD_SIZE])
69 {
70 struct passwd *passwd;
71
72 if (uid != 0 && uid == cached_no_such_uid)
73 {
74 *uname = '\0';
75 return;
76 }
77
78 if (!cached_uname[0] || uid != cached_uid)
79 {
80 passwd = getpwuid (uid);
81 if (passwd)
82 {
83 cached_uid = uid;
84 strncpy (cached_uname, passwd->pw_name, UNAME_FIELD_SIZE);
85 }
86 else
87 {
88 cached_no_such_uid = uid;
89 *uname = '\0';
90 return;
91 }
92 }
93 strncpy (uname, cached_uname, UNAME_FIELD_SIZE);
94 }
95
96 /*------------------------------------------.
97 | Given GID, find the corresponding GNAME. |
98 `------------------------------------------*/
99
100 void
101 gid_to_gname (gid_t gid, char gname[GNAME_FIELD_SIZE])
102 {
103 struct group *group;
104
105 if (gid != 0 && gid == cached_no_such_gid)
106 {
107 *gname = '\0';
108 return;
109 }
110
111 if (!cached_gname[0] || gid != cached_gid)
112 {
113 setgrent (); /* FIXME: why?! */
114 group = getgrgid (gid);
115 if (group)
116 {
117 cached_gid = gid;
118 strncpy (cached_gname, group->gr_name, GNAME_FIELD_SIZE);
119 }
120 else
121 {
122 cached_no_such_gid = gid;
123 *gname = '\0';
124 return;
125 }
126 }
127 strncpy (gname, cached_gname, GNAME_FIELD_SIZE);
128 }
129
130 /*-------------------------------------------------------------------------.
131 | Given UNAME, set the corresponding UID and return 1, or else, return 0. |
132 `-------------------------------------------------------------------------*/
133
134 int
135 uname_to_uid (char uname[UNAME_FIELD_SIZE], uid_t *uidp)
136 {
137 struct passwd *passwd;
138
139 if (cached_no_such_uname[0]
140 && strncmp (uname, cached_no_such_uname, UNAME_FIELD_SIZE) == 0)
141 return 0;
142
143 if (!cached_uname[0]
144 || uname[0] != cached_uname[0]
145 || strncmp (uname, cached_uname, UNAME_FIELD_SIZE) != 0)
146 {
147 passwd = getpwnam (uname);
148 if (passwd)
149 {
150 cached_uid = passwd->pw_uid;
151 strncpy (cached_uname, uname, UNAME_FIELD_SIZE);
152 }
153 else
154 {
155 strncpy (cached_no_such_uname, uname, UNAME_FIELD_SIZE);
156 return 0;
157 }
158 }
159 *uidp = cached_uid;
160 return 1;
161 }
162
163 /*-------------------------------------------------------------------------.
164 | Given GNAME, set the corresponding GID and return 1, or else, return 0. |
165 `-------------------------------------------------------------------------*/
166
167 int
168 gname_to_gid (char gname[GNAME_FIELD_SIZE], gid_t *gidp)
169 {
170 struct group *group;
171
172 if (cached_no_such_gname[0]
173 && strncmp (gname, cached_no_such_gname, GNAME_FIELD_SIZE) == 0)
174 return 0;
175
176 if (!cached_gname[0]
177 || gname[0] != cached_gname[0]
178 || strncmp (gname, cached_gname, GNAME_FIELD_SIZE) != 0)
179 {
180 group = getgrnam (gname);
181 if (group)
182 {
183 cached_gid = group->gr_gid;
184 strncpy (cached_gname, gname, GNAME_FIELD_SIZE);
185 }
186 else
187 {
188 strncpy (cached_no_such_gname, gname, GNAME_FIELD_SIZE);
189 return 0;
190 }
191 }
192 *gidp = cached_gid;
193 return 1;
194 }
195 \f
196 /* Names from the command call. */
197
198 static const char **name_array; /* store an array of names */
199 static int allocated_names; /* how big is the array? */
200 static int names; /* how many entries does it have? */
201 static int name_index; /* how many of the entries have we scanned? */
202
203 /*------------------------.
204 | Initialize structures. |
205 `------------------------*/
206
207 void
208 init_names (void)
209 {
210 allocated_names = 10;
211 name_array = xmalloc (sizeof (const char *) * allocated_names);
212 names = 0;
213 }
214
215 /*--------------------------------------------------------------.
216 | Add NAME at end of name_array, reallocating it as necessary. |
217 `--------------------------------------------------------------*/
218
219 void
220 name_add (const char *name)
221 {
222 if (names == allocated_names)
223 {
224 allocated_names *= 2;
225 name_array =
226 xrealloc (name_array, sizeof (const char *) * allocated_names);
227 }
228 name_array[names++] = name;
229 }
230 \f
231 /* Names from external name file. */
232
233 static FILE *name_file; /* file to read names from */
234 static char *name_buffer; /* buffer to hold the current file name */
235 static size_t name_buffer_length; /* allocated length of name_buffer */
236
237 /*---.
238 | ? |
239 `---*/
240
241 /* FIXME: I should better check more closely. It seems at first glance that
242 is_pattern is only used when reading a file, and ignored for all
243 command line arguments. */
244
245 static inline int
246 is_pattern (const char *string)
247 {
248 return strchr (string, '*') || strchr (string, '[') || strchr (string, '?');
249 }
250
251 /*-----------------------------------------------------------------------.
252 | Set up to gather file names for tar. They can either come from a file |
253 | or were saved from decoding arguments. |
254 `-----------------------------------------------------------------------*/
255
256 void
257 name_init (int argc, char *const *argv)
258 {
259 name_buffer = xmalloc (NAME_FIELD_SIZE + 2);
260 name_buffer_length = NAME_FIELD_SIZE;
261
262 if (files_from_option)
263 {
264 if (!strcmp (files_from_option, "-"))
265 {
266 request_stdin ("-T");
267 name_file = stdin;
268 }
269 else if (name_file = fopen (files_from_option, "r"), !name_file)
270 open_fatal (files_from_option);
271 }
272 }
273
274 /*---.
275 | ? |
276 `---*/
277
278 void
279 name_term (void)
280 {
281 free (name_buffer);
282 free (name_array);
283 }
284
285 /*---------------------------------------------------------------------.
286 | Read the next filename from name_file and null-terminate it. Put it |
287 | into name_buffer, reallocating and adjusting name_buffer_length if |
288 | necessary. Return 0 at end of file, 1 otherwise. |
289 `---------------------------------------------------------------------*/
290
291 static int
292 read_name_from_file (void)
293 {
294 int character;
295 size_t counter = 0;
296
297 /* FIXME: getc may be called even if character was EOF the last time here. */
298
299 /* FIXME: This + 2 allocation might serve no purpose. */
300
301 while (character = getc (name_file),
302 character != EOF && character != filename_terminator)
303 {
304 if (counter == name_buffer_length)
305 {
306 name_buffer_length += NAME_FIELD_SIZE;
307 name_buffer = xrealloc (name_buffer, name_buffer_length + 2);
308 }
309 name_buffer[counter++] = character;
310 }
311
312 if (counter == 0 && character == EOF)
313 return 0;
314
315 if (counter == name_buffer_length)
316 {
317 name_buffer_length += NAME_FIELD_SIZE;
318 name_buffer = xrealloc (name_buffer, name_buffer_length + 2);
319 }
320 name_buffer[counter] = '\0';
321
322 return 1;
323 }
324
325 /*------------------------------------------------------------------------.
326 | Get the next name from ARGV or the file of names. Result is in static |
327 | storage and can't be relied upon across two calls. |
328 | |
329 | If CHANGE_DIRS is true, treat a filename of the form "-C" as meaning |
330 | that the next filename is the name of a directory to change to. If |
331 | `filename_terminator' is NUL, CHANGE_DIRS is effectively always false. |
332 `------------------------------------------------------------------------*/
333
334 char *
335 name_next (int change_dirs)
336 {
337 const char *source;
338 char *cursor;
339 int chdir_flag = 0;
340
341 if (filename_terminator == '\0')
342 change_dirs = 0;
343
344 while (1)
345 {
346 /* Get a name, either from file or from saved arguments. */
347
348 if (name_index == names)
349 {
350 if (! name_file)
351 break;
352 if (! read_name_from_file ())
353 break;
354 }
355 else
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 chdir_fatal (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) != 0)
405 close_error (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"),
621 quotearg_colon (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"),
641 quotearg_colon (name)));
642 }
643 }
644 \f
645 /* Sorting name lists. */
646
647 /* Sort linked LIST of names, of given LENGTH, using COMPARE to order
648 names. Return the sorted list. Apart from the type `struct name'
649 and the definition of SUCCESSOR, this is a generic list-sorting
650 function, but it's too painful to make it both generic and portable
651 in C. */
652
653 static struct name *
654 merge_sort (struct name *list, int length,
655 int (*compare) (struct name const*, struct name const*))
656 {
657 struct name *first_list;
658 struct name *second_list;
659 int first_length;
660 int second_length;
661 struct name *result;
662 struct name **merge_point;
663 struct name *cursor;
664 int counter;
665
666 # define SUCCESSOR(name) ((name)->next)
667
668 if (length == 1)
669 return list;
670
671 if (length == 2)
672 {
673 if ((*compare) (list, SUCCESSOR (list)) > 0)
674 {
675 result = SUCCESSOR (list);
676 SUCCESSOR (result) = list;
677 SUCCESSOR (list) = 0;
678 return result;
679 }
680 return list;
681 }
682
683 first_list = list;
684 first_length = (length + 1) / 2;
685 second_length = length / 2;
686 for (cursor = list, counter = first_length - 1;
687 counter;
688 cursor = SUCCESSOR (cursor), counter--)
689 continue;
690 second_list = SUCCESSOR (cursor);
691 SUCCESSOR (cursor) = 0;
692
693 first_list = merge_sort (first_list, first_length, compare);
694 second_list = merge_sort (second_list, second_length, compare);
695
696 merge_point = &result;
697 while (first_list && second_list)
698 if ((*compare) (first_list, second_list) < 0)
699 {
700 cursor = SUCCESSOR (first_list);
701 *merge_point = first_list;
702 merge_point = &SUCCESSOR (first_list);
703 first_list = cursor;
704 }
705 else
706 {
707 cursor = SUCCESSOR (second_list);
708 *merge_point = second_list;
709 merge_point = &SUCCESSOR (second_list);
710 second_list = cursor;
711 }
712 if (first_list)
713 *merge_point = first_list;
714 else
715 *merge_point = second_list;
716
717 return result;
718
719 #undef SUCCESSOR
720 }
721
722 /* A comparison function for sorting names. Put found names last;
723 break ties by string comparison. */
724
725 static int
726 compare_names (struct name const *n1, struct name const *n2)
727 {
728 int found_diff = n2->found - n1->found;
729 return found_diff ? found_diff : strcmp (n1->name, n2->name);
730 }
731 \f
732 /* Add all the dirs in PATH, which is a directory, to the namelist.
733 If any of the files is a directory, recurse on the subdirectory.
734 CHANGE_DIR is the number of the directory that PATH is relative to.
735 DEVICE is the device not to leave, if the -l option is specified. */
736
737 static void
738 add_hierarchy_to_namelist (char *path, int change_dir, dev_t device)
739 {
740 char *buffer = get_directory_contents (path, device);
741
742 {
743 struct name *name;
744
745 for (name = namelist; name; name = name->next)
746 if (strcmp (name->name, path) == 0)
747 break;
748 if (name)
749 name->dir_contents = buffer ? buffer : "\0\0\0\0";
750 }
751
752 if (buffer)
753 {
754 size_t name_length = strlen (path);
755 size_t allocated_length = (name_length >= NAME_FIELD_SIZE
756 ? name_length + NAME_FIELD_SIZE
757 : NAME_FIELD_SIZE);
758 char *name_buffer = xmalloc (allocated_length + 1);
759 /* FIXME: + 2 above? */
760 char *string;
761 size_t string_length;
762
763 strcpy (name_buffer, path);
764 if (name_buffer[name_length - 1] != '/')
765 {
766 name_buffer[name_length++] = '/';
767 name_buffer[name_length] = '\0';
768 }
769
770 for (string = buffer; *string; string += string_length + 1)
771 {
772 string_length = strlen (string);
773 if (*string == 'D')
774 {
775 if (name_length + string_length >= allocated_length)
776 {
777 while (name_length + string_length >= allocated_length)
778 allocated_length += NAME_FIELD_SIZE;
779 name_buffer = xrealloc (name_buffer, allocated_length + 1);
780 }
781 strcpy (name_buffer + name_length, string + 1);
782 addname (name_buffer, change_dir);
783 if (*string == 'D')
784 add_hierarchy_to_namelist (name_buffer, change_dir, device);
785 }
786 }
787
788 free (name_buffer);
789 }
790 }
791 \f
792 /* Collect all the names from argv[] (or whatever), expand them into a
793 directory tree, and sort them. This gets only subdirectories, not
794 all files. */
795
796 void
797 collect_and_sort_names (void)
798 {
799 struct name *name;
800 struct name *next_name;
801 int num_names;
802 struct stat statbuf;
803
804 name_gather ();
805
806 if (listed_incremental_option)
807 read_directory_file ();
808
809 if (!namelist)
810 addname (".", 0);
811
812 for (name = namelist; name; name = next_name)
813 {
814 next_name = name->next;
815 if (name->found || name->dir_contents)
816 continue;
817 if (name->regexp) /* FIXME: just skip regexps for now */
818 continue;
819 chdir_do (name->change_dir);
820 if (name->fake)
821 continue;
822
823 if (deref_stat (dereference_option, name->name, &statbuf) != 0)
824 {
825 stat_error (name->name);
826 continue;
827 }
828 if (S_ISDIR (statbuf.st_mode))
829 {
830 name->found = 1;
831 add_hierarchy_to_namelist (name->name, name->change_dir,
832 statbuf.st_dev);
833 }
834 }
835
836 num_names = 0;
837 for (name = namelist; name; name = name->next)
838 num_names++;
839 namelist = merge_sort (namelist, num_names, compare_names);
840
841 for (name = namelist; name; name = name->next)
842 name->found = 0;
843 }
844
845 /*-------------------------------------------------------------------------.
846 | This is like name_match, except that it returns a pointer to the name it |
847 | matched, and doesn't set FOUND in structure. The caller will have to do |
848 | that if it wants to. Oh, and if the namelist is empty, it returns null, |
849 | unlike name_match, which returns TRUE. |
850 `-------------------------------------------------------------------------*/
851
852 struct name *
853 name_scan (const char *path)
854 {
855 size_t length = strlen (path);
856
857 while (1)
858 {
859 struct name *cursor = namelist;
860
861 if (!cursor)
862 return 0;
863
864 for (; cursor; cursor = cursor->next)
865 {
866 /* If first chars don't match, quick skip. */
867
868 if (cursor->firstch && cursor->name[0] != path[0])
869 continue;
870
871 if (cursor->regexp
872 ? fnmatch (cursor->name, path, FNM_LEADING_DIR) == 0
873 : (cursor->length <= length
874 && (path[cursor->length] == '\0'
875 || path[cursor->length] == '/')
876 && memcmp (path, cursor->name, cursor->length) == 0))
877 return cursor; /* we got a match */
878 }
879
880 /* Filename from archive not found in namelist. If we have the whole
881 namelist here, just return 0. Otherwise, read the next name in and
882 compare it. If this was the last name, namelist->found will remain
883 on. If not, we loop to compare the newly read name. */
884
885 if (same_order_option && namelist->found)
886 {
887 name_gather (); /* read one more */
888 if (namelist->found)
889 return 0;
890 }
891 else
892 return 0;
893 }
894 }
895
896 /*-----------------------------------------------------------------------.
897 | This returns a name from the namelist which doesn't have ->found set. |
898 | It sets ->found before returning, so successive calls will find and |
899 | return all the non-found names in the namelist |
900 `-----------------------------------------------------------------------*/
901
902 struct name *gnu_list_name;
903
904 char *
905 name_from_list (void)
906 {
907 if (!gnu_list_name)
908 gnu_list_name = namelist;
909 while (gnu_list_name && (gnu_list_name->found | gnu_list_name->fake))
910 gnu_list_name = gnu_list_name->next;
911 if (gnu_list_name)
912 {
913 gnu_list_name->found = 1;
914 chdir_do (gnu_list_name->change_dir);
915 return gnu_list_name->name;
916 }
917 return 0;
918 }
919
920 /*---.
921 | ? |
922 `---*/
923
924 void
925 blank_name_list (void)
926 {
927 struct name *name;
928
929 gnu_list_name = 0;
930 for (name = namelist; name; name = name->next)
931 name->found = 0;
932 }
933
934 /*---.
935 | ? |
936 `---*/
937
938 char *
939 new_name (const char *path, const char *name)
940 {
941 char *buffer = xmalloc (strlen (path) + strlen (name) + 2);
942
943 sprintf (buffer, "%s/%s", path, name);
944 return buffer;
945 }
946
947 /* Return nonzero if file NAME is excluded. Exclude a name if its
948 prefix matches a pattern that contains slashes, or if one of its
949 components matches a pattern that contains no slashes. */
950 int
951 excluded_name (char const *name)
952 {
953 char const *p;
954 name += FILESYSTEM_PREFIX_LEN (name);
955
956 if (excluded_filename (excluded_with_slash, name,
957 FNM_FILE_NAME | FNM_LEADING_DIR))
958 return 1;
959
960 for (p = name; *p; p++)
961 if (((p == name || ISSLASH (p[-1])) && !ISSLASH (p[0]))
962 && excluded_filename (excluded_without_slash, p,
963 FNM_FILE_NAME | FNM_LEADING_DIR))
964 return 1;
965
966 return 0;
967 }
968 \f
969 /* Names to avoid dumping. */
970
971 struct avoided_name
972 {
973 struct avoided_name const *next;
974 char name[1];
975 };
976
977 static struct avoided_name *avoided_names;
978
979 /* Remember to not archive NAME. */
980 void
981 add_avoided_name (char const *name)
982 {
983 struct avoided_name *p = xmalloc (sizeof *p + strlen (name));
984 p->next = avoided_names;
985 avoided_names = p;
986 strcpy (p->name, name);
987 }
988
989 /* Should NAME be avoided when archiving? */
990 int
991 is_avoided_name (char const *name)
992 {
993 struct avoided_name const *p;
994 for (p = avoided_names; p; p = p->next)
995 if (strcmp (p->name, name) == 0)
996 return 1;
997 return 0;
998 }
This page took 0.074348 seconds and 5 git commands to generate.