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