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