1 /* Various processing of names.
2 Copyright (C) 1988, 92, 94, 96, 97, 98, 1999 Free Software Foundation, Inc.
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
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.
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. */
18 /* Enable GNU extensions in fnmatch.h. */
20 # define _GNU_SOURCE 1
31 /* User and group names. */
33 extern struct group
*getgrnam ();
34 extern struct passwd
*getpwnam ();
36 extern struct passwd
*getpwuid ();
39 extern struct group
*getgrgid ();
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
47 static char cached_uname
[UNAME_FIELD_SIZE
];
48 static char cached_gname
[GNAME_FIELD_SIZE
];
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 */
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
];
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
;
62 /*------------------------------------------.
63 | Given UID, find the corresponding UNAME. |
64 `------------------------------------------*/
67 uid_to_uname (uid_t uid
, char uname
[UNAME_FIELD_SIZE
])
69 struct passwd
*passwd
;
71 if (uid
!= 0 && uid
== cached_no_such_uid
)
77 if (!cached_uname
[0] || uid
!= cached_uid
)
79 passwd
= getpwuid (uid
);
83 strncpy (cached_uname
, passwd
->pw_name
, UNAME_FIELD_SIZE
);
87 cached_no_such_uid
= uid
;
92 strncpy (uname
, cached_uname
, UNAME_FIELD_SIZE
);
95 /*------------------------------------------.
96 | Given GID, find the corresponding GNAME. |
97 `------------------------------------------*/
100 gid_to_gname (gid_t gid
, char gname
[GNAME_FIELD_SIZE
])
104 if (gid
!= 0 && gid
== cached_no_such_gid
)
110 if (!cached_gname
[0] || gid
!= cached_gid
)
112 setgrent (); /* FIXME: why?! */
113 group
= getgrgid (gid
);
117 strncpy (cached_gname
, group
->gr_name
, GNAME_FIELD_SIZE
);
121 cached_no_such_gid
= gid
;
126 strncpy (gname
, cached_gname
, GNAME_FIELD_SIZE
);
129 /*-------------------------------------------------------------------------.
130 | Given UNAME, set the corresponding UID and return 1, or else, return 0. |
131 `-------------------------------------------------------------------------*/
134 uname_to_uid (char uname
[UNAME_FIELD_SIZE
], uid_t
*uidp
)
136 struct passwd
*passwd
;
138 if (cached_no_such_uname
[0]
139 && strncmp (uname
, cached_no_such_uname
, UNAME_FIELD_SIZE
) == 0)
143 || uname
[0] != cached_uname
[0]
144 || strncmp (uname
, cached_uname
, UNAME_FIELD_SIZE
) != 0)
146 passwd
= getpwnam (uname
);
149 cached_uid
= passwd
->pw_uid
;
150 strncpy (cached_uname
, uname
, UNAME_FIELD_SIZE
);
154 strncpy (cached_no_such_uname
, uname
, UNAME_FIELD_SIZE
);
162 /*-------------------------------------------------------------------------.
163 | Given GNAME, set the corresponding GID and return 1, or else, return 0. |
164 `-------------------------------------------------------------------------*/
167 gname_to_gid (char gname
[GNAME_FIELD_SIZE
], gid_t
*gidp
)
171 if (cached_no_such_gname
[0]
172 && strncmp (gname
, cached_no_such_gname
, GNAME_FIELD_SIZE
) == 0)
176 || gname
[0] != cached_gname
[0]
177 || strncmp (gname
, cached_gname
, GNAME_FIELD_SIZE
) != 0)
179 group
= getgrnam (gname
);
182 cached_gid
= group
->gr_gid
;
183 strncpy (cached_gname
, gname
, GNAME_FIELD_SIZE
);
187 strncpy (cached_no_such_gname
, gname
, GNAME_FIELD_SIZE
);
195 /* Names from the command call. */
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? */
202 /*------------------------.
203 | Initialize structures. |
204 `------------------------*/
209 allocated_names
= 10;
210 name_array
= xmalloc (sizeof (const char *) * allocated_names
);
214 /*--------------------------------------------------------------.
215 | Add NAME at end of name_array, reallocating it as necessary. |
216 `--------------------------------------------------------------*/
219 name_add (const char *name
)
221 if (names
== allocated_names
)
223 allocated_names
*= 2;
225 xrealloc (name_array
, sizeof (const char *) * allocated_names
);
227 name_array
[names
++] = name
;
230 /* Names from external name file. */
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 */
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. */
245 is_pattern (const char *string
)
247 return strchr (string
, '*') || strchr (string
, '[') || strchr (string
, '?');
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 `-----------------------------------------------------------------------*/
256 name_init (int argc
, char *const *argv
)
258 name_buffer
= xmalloc (NAME_FIELD_SIZE
+ 2);
259 name_buffer_length
= NAME_FIELD_SIZE
;
261 if (files_from_option
)
263 if (!strcmp (files_from_option
, "-"))
265 request_stdin ("-T");
268 else if (name_file
= fopen (files_from_option
, "r"), !name_file
)
269 FATAL_ERROR ((0, errno
, _("Cannot open file %s"), files_from_option
));
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 `---------------------------------------------------------------------*/
291 read_name_from_file (void)
296 /* FIXME: getc may be called even if character was EOF the last time here. */
298 /* FIXME: This + 2 allocation might serve no purpose. */
300 while (character
= getc (name_file
),
301 character
!= EOF
&& character
!= filename_terminator
)
303 if (counter
== name_buffer_length
)
305 name_buffer_length
+= NAME_FIELD_SIZE
;
306 name_buffer
= xrealloc (name_buffer
, name_buffer_length
+ 2);
308 name_buffer
[counter
++] = character
;
311 if (counter
== 0 && character
== EOF
)
314 if (counter
== name_buffer_length
)
316 name_buffer_length
+= NAME_FIELD_SIZE
;
317 name_buffer
= xrealloc (name_buffer
, name_buffer_length
+ 2);
319 name_buffer
[counter
] = '\0';
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. |
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 `------------------------------------------------------------------------*/
334 name_next (int change_dirs
)
340 if (filename_terminator
== '\0')
345 /* Get a name, either from file or from saved arguments. */
349 if (!read_name_from_file ())
354 if (name_index
== names
)
357 source
= name_array
[name_index
++];
358 if (strlen (source
) > name_buffer_length
)
361 name_buffer_length
= strlen (source
);
362 name_buffer
= xmalloc (name_buffer_length
+ 2);
364 strcpy (name_buffer
, source
);
367 /* Zap trailing slashes. */
369 cursor
= name_buffer
+ strlen (name_buffer
) - 1;
370 while (cursor
> name_buffer
&& *cursor
== '/')
375 if (chdir (name_buffer
) < 0)
376 FATAL_ERROR ((0, errno
, _("Cannot change to directory %s"),
380 else if (change_dirs
&& strcmp (name_buffer
, "-C") == 0)
384 unquote_string (name_buffer
);
389 /* No more names in file. */
391 if (name_file
&& chdir_flag
)
392 FATAL_ERROR ((0, 0, _("Missing file name after -C")));
397 /*------------------------------.
398 | Close the name file, if any. |
399 `------------------------------*/
404 if (name_file
&& name_file
!= stdin
)
405 if (fclose (name_file
) == EOF
)
406 ERROR ((0, errno
, "%s", name_buffer
));
409 /*-------------------------------------------------------------------------.
410 | Gather names in a list for scanning. Could hash them later if we really |
413 | If the names are already sorted to match the archive, we just read them |
414 | one by one. name_gather reads the first one, and it is called by |
415 | name_match as appropriate to read the next ones. At EOF, the last name |
416 | read is just left in the buffer. This option lets users of small |
417 | machines extract an arbitrary number of files by doing "tar t" and |
418 | editing down the list of files. |
419 `-------------------------------------------------------------------------*/
424 /* Buffer able to hold a single name. */
425 static struct name
*buffer
;
426 static size_t allocated_length
;
430 if (same_order_option
)
432 static int change_dir
;
434 if (allocated_length
== 0)
436 allocated_length
= sizeof (struct name
) + NAME_FIELD_SIZE
;
437 buffer
= xmalloc (allocated_length
);
438 /* FIXME: This memset is overkill, and ugly... */
439 memset (buffer
, 0, allocated_length
);
442 while ((name
= name_next (0)) && strcmp (name
, "-C") == 0)
444 char const *dir
= name_next (0);
446 FATAL_ERROR ((0, 0, _("Missing file name after -C")));
447 change_dir
= chdir_arg (xstrdup (dir
));
452 buffer
->length
= strlen (name
);
453 if (sizeof (struct name
) + buffer
->length
>= allocated_length
)
455 allocated_length
= sizeof (struct name
) + buffer
->length
;
456 buffer
= xrealloc (buffer
, allocated_length
);
458 buffer
->change_dir
= change_dir
;
459 strncpy (buffer
->name
, name
, buffer
->length
);
460 buffer
->name
[buffer
->length
] = 0;
464 /* FIXME: Poorly named globals, indeed... */
471 /* Non sorted names -- read them all in. */
476 int change_dir0
= change_dir
;
477 while ((name
= name_next (0)) && strcmp (name
, "-C") == 0)
479 char const *dir
= name_next (0);
481 FATAL_ERROR ((0, 0, _("Missing file name after -C")));
482 change_dir
= chdir_arg (xstrdup (dir
));
485 addname (name
, change_dir
);
488 if (change_dir
!= change_dir0
)
489 addname (0, change_dir
);
496 /*-----------------------------.
497 | Add a name to the namelist. |
498 `-----------------------------*/
501 addname (char const *string
, int change_dir
)
506 length
= string
? strlen (string
) : 0;
507 name
= xmalloc (sizeof (struct name
) + length
);
508 memset (name
, 0, sizeof (struct name
) + length
);
514 name
->length
= length
;
515 memcpy (name
->name
, string
, length
+ 1);
521 name
->regexp
= 0; /* assume not a regular expression */
522 name
->firstch
= 1; /* assume first char is literal */
523 name
->change_dir
= change_dir
;
524 name
->dir_contents
= 0;
526 if (string
&& is_pattern (string
))
529 if (string
[0] == '*' || string
[0] == '[' || string
[0] == '?')
534 namelast
->next
= name
;
540 /*------------------------------------------------------------------------.
541 | Return true if and only if name PATH (from an archive) matches any name |
542 | from the namelist. |
543 `------------------------------------------------------------------------*/
546 name_match (const char *path
)
548 size_t length
= strlen (path
);
552 struct name
*cursor
= namelist
;
555 return ! files_from_option
;
559 chdir_do (cursor
->change_dir
);
561 return ! files_from_option
;
564 for (; cursor
; cursor
= cursor
->next
)
566 /* If first chars don't match, quick skip. */
568 if (cursor
->firstch
&& cursor
->name
[0] != path
[0])
572 ? fnmatch (cursor
->name
, path
, FNM_LEADING_DIR
) == 0
573 : (cursor
->length
<= length
574 && (path
[cursor
->length
] == '\0'
575 || path
[cursor
->length
] == '/')
576 && memcmp (path
, cursor
->name
, cursor
->length
) == 0))
578 cursor
->found
= 1; /* remember it matched */
579 if (starting_file_option
)
584 chdir_do (cursor
->change_dir
);
586 /* We got a match. */
591 /* Filename from archive not found in namelist. If we have the whole
592 namelist here, just return 0. Otherwise, read the next name in and
593 compare it. If this was the last name, namelist->found will remain
594 on. If not, we loop to compare the newly read name. */
596 if (same_order_option
&& namelist
->found
)
598 name_gather (); /* read one more */
607 /*------------------------------------------------------------------.
608 | Print the names of things in the namelist that were not matched. |
609 `------------------------------------------------------------------*/
612 names_notfound (void)
617 for (cursor
= namelist
; cursor
; cursor
= next
)
620 if (!cursor
->found
&& !cursor
->fake
)
621 ERROR ((0, 0, _("%s: Not found in archive"), cursor
->name
));
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. */
628 if (!same_order_option
)
635 if (same_order_option
)
639 while (name
= name_next (1), name
)
640 ERROR ((0, 0, _("%s: Not found in archive"), name
));
644 /* Sorting name lists. */
646 /* Sort linked LIST of names, of given LENGTH, using COMPARE to order
647 names. Return the sorted list. Apart from the type `struct name'
648 and the definition of SUCCESSOR, this is a generic list-sorting
649 function, but it's too painful to make it both generic and portable
653 merge_sort (struct name
*list
, int length
,
654 int (*compare
) (struct name
const*, struct name
const*))
656 struct name
*first_list
;
657 struct name
*second_list
;
661 struct name
**merge_point
;
665 # define SUCCESSOR(name) ((name)->next)
672 if ((*compare
) (list
, SUCCESSOR (list
)) > 0)
674 result
= SUCCESSOR (list
);
675 SUCCESSOR (result
) = list
;
676 SUCCESSOR (list
) = 0;
683 first_length
= (length
+ 1) / 2;
684 second_length
= length
/ 2;
685 for (cursor
= list
, counter
= first_length
- 1;
687 cursor
= SUCCESSOR (cursor
), counter
--)
689 second_list
= SUCCESSOR (cursor
);
690 SUCCESSOR (cursor
) = 0;
692 first_list
= merge_sort (first_list
, first_length
, compare
);
693 second_list
= merge_sort (second_list
, second_length
, compare
);
695 merge_point
= &result
;
696 while (first_list
&& second_list
)
697 if ((*compare
) (first_list
, second_list
) < 0)
699 cursor
= SUCCESSOR (first_list
);
700 *merge_point
= first_list
;
701 merge_point
= &SUCCESSOR (first_list
);
706 cursor
= SUCCESSOR (second_list
);
707 *merge_point
= second_list
;
708 merge_point
= &SUCCESSOR (second_list
);
709 second_list
= cursor
;
712 *merge_point
= first_list
;
714 *merge_point
= second_list
;
721 /* A comparison function for sorting names. Put found names last;
722 break ties by string comparison. */
725 compare_names (struct name
const *n1
, struct name
const *n2
)
727 int found_diff
= n2
->found
- n1
->found
;
728 return found_diff
? found_diff
: strcmp (n1
->name
, n2
->name
);
731 /* Add all the dirs in PATH, which is a directory, to the namelist.
732 If any of the files is a directory, recurse on the subdirectory.
733 CHANGE_DIR is the number of the directory that PATH is relative to.
734 DEVICE is the device not to leave, if the -l option is specified. */
737 add_hierarchy_to_namelist (char *path
, int change_dir
, dev_t device
)
739 char *buffer
= get_directory_contents (path
, device
);
744 for (name
= namelist
; name
; name
= name
->next
)
745 if (strcmp (name
->name
, path
) == 0)
748 name
->dir_contents
= buffer
? buffer
: "\0\0\0\0";
753 size_t name_length
= strlen (path
);
754 size_t allocated_length
= (name_length
>= NAME_FIELD_SIZE
755 ? name_length
+ NAME_FIELD_SIZE
757 char *name_buffer
= xmalloc (allocated_length
+ 1);
758 /* FIXME: + 2 above? */
760 size_t string_length
;
762 strcpy (name_buffer
, path
);
763 if (name_buffer
[name_length
- 1] != '/')
765 name_buffer
[name_length
++] = '/';
766 name_buffer
[name_length
] = '\0';
769 for (string
= buffer
; *string
; string
+= string_length
+ 1)
771 string_length
= strlen (string
);
774 if (name_length
+ string_length
>= allocated_length
)
776 while (name_length
+ string_length
>= allocated_length
)
777 allocated_length
+= NAME_FIELD_SIZE
;
778 name_buffer
= xrealloc (name_buffer
, allocated_length
+ 1);
780 strcpy (name_buffer
+ name_length
, string
+ 1);
781 addname (name_buffer
, change_dir
);
783 add_hierarchy_to_namelist (name_buffer
, change_dir
, device
);
791 /* Collect all the names from argv[] (or whatever), expand them into a
792 directory tree, and sort them. This gets only subdirectories, not
796 collect_and_sort_names (void)
799 struct name
*next_name
;
805 if (listed_incremental_option
)
806 read_directory_file ();
811 for (name
= namelist
; name
; name
= next_name
)
813 next_name
= name
->next
;
814 if (name
->found
|| name
->dir_contents
)
816 if (name
->regexp
) /* FIXME: just skip regexps for now */
818 chdir_do (name
->change_dir
);
822 if (deref_stat (dereference_option
, name
->name
, &statbuf
) != 0)
824 ERROR ((0, errno
, _("Cannot stat %s"), name
->name
));
827 if (S_ISDIR (statbuf
.st_mode
))
830 add_hierarchy_to_namelist (name
->name
, name
->change_dir
,
836 for (name
= namelist
; name
; name
= name
->next
)
838 namelist
= merge_sort (namelist
, num_names
, compare_names
);
840 for (name
= namelist
; name
; name
= name
->next
)
844 /*-------------------------------------------------------------------------.
845 | This is like name_match, except that it returns a pointer to the name it |
846 | matched, and doesn't set FOUND in structure. The caller will have to do |
847 | that if it wants to. Oh, and if the namelist is empty, it returns null, |
848 | unlike name_match, which returns TRUE. |
849 `-------------------------------------------------------------------------*/
852 name_scan (const char *path
)
854 size_t length
= strlen (path
);
858 struct name
*cursor
= namelist
;
863 for (; cursor
; cursor
= cursor
->next
)
865 /* If first chars don't match, quick skip. */
867 if (cursor
->firstch
&& cursor
->name
[0] != path
[0])
871 ? fnmatch (cursor
->name
, path
, FNM_LEADING_DIR
) == 0
872 : (cursor
->length
<= length
873 && (path
[cursor
->length
] == '\0'
874 || path
[cursor
->length
] == '/')
875 && memcmp (path
, cursor
->name
, cursor
->length
) == 0))
876 return cursor
; /* we got a match */
879 /* Filename from archive not found in namelist. If we have the whole
880 namelist here, just return 0. Otherwise, read the next name in and
881 compare it. If this was the last name, namelist->found will remain
882 on. If not, we loop to compare the newly read name. */
884 if (same_order_option
&& namelist
->found
)
886 name_gather (); /* read one more */
895 /*-----------------------------------------------------------------------.
896 | This returns a name from the namelist which doesn't have ->found set. |
897 | It sets ->found before returning, so successive calls will find and |
898 | return all the non-found names in the namelist |
899 `-----------------------------------------------------------------------*/
901 struct name
*gnu_list_name
;
904 name_from_list (void)
907 gnu_list_name
= namelist
;
908 while (gnu_list_name
&& (gnu_list_name
->found
| gnu_list_name
->fake
))
909 gnu_list_name
= gnu_list_name
->next
;
912 gnu_list_name
->found
= 1;
913 chdir_do (gnu_list_name
->change_dir
);
914 return gnu_list_name
->name
;
924 blank_name_list (void)
929 for (name
= namelist
; name
; name
= name
->next
)
938 new_name (const char *path
, const char *name
)
940 char *buffer
= xmalloc (strlen (path
) + strlen (name
) + 2);
942 sprintf (buffer
, "%s/%s", path
, name
);
946 /* Return nonzero if file NAME is excluded. Exclude a name if its
947 prefix matches a pattern that contains slashes, or if one of its
948 components matches a pattern that contains no slashes. */
950 excluded_name (char const *name
)
953 name
+= FILESYSTEM_PREFIX_LEN (name
);
955 if (excluded_filename (excluded_with_slash
, name
,
956 FNM_FILE_NAME
| FNM_LEADING_DIR
))
959 for (p
= name
; *p
; p
++)
960 if ((p
== name
|| (ISSLASH (p
[-1]) && !ISSLASH (p
[0])))
961 && excluded_filename (excluded_without_slash
, p
,
962 FNM_FILE_NAME
| FNM_LEADING_DIR
))
968 /* Names to avoid dumping. */
972 struct avoided_name
const *next
;
976 static struct avoided_name
*avoided_names
;
978 /* Remember to not archive NAME. */
980 add_avoided_name (char const *name
)
982 struct avoided_name
*p
= xmalloc (sizeof *p
+ strlen (name
));
983 p
->next
= avoided_names
;
985 strcpy (p
->name
, name
);
988 /* Should NAME be avoided when archiving? */
990 is_avoided_name (char const *name
)
992 struct avoided_name
const *p
;
993 for (p
= avoided_names
; p
; p
= p
->next
)
994 if (strcmp (p
->name
, name
) == 0)