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. */
347 if (name_index
== names
)
351 if (! read_name_from_file ())
356 source
= name_array
[name_index
++];
357 if (strlen (source
) > name_buffer_length
)
360 name_buffer_length
= strlen (source
);
361 name_buffer
= xmalloc (name_buffer_length
+ 2);
363 strcpy (name_buffer
, source
);
366 /* Zap trailing slashes. */
368 cursor
= name_buffer
+ strlen (name_buffer
) - 1;
369 while (cursor
> name_buffer
&& *cursor
== '/')
374 if (chdir (name_buffer
) < 0)
375 FATAL_ERROR ((0, errno
, _("Cannot change to directory %s"),
379 else if (change_dirs
&& strcmp (name_buffer
, "-C") == 0)
383 unquote_string (name_buffer
);
388 /* No more names in file. */
390 if (name_file
&& chdir_flag
)
391 FATAL_ERROR ((0, 0, _("Missing file name after -C")));
396 /*------------------------------.
397 | Close the name file, if any. |
398 `------------------------------*/
403 if (name_file
&& name_file
!= stdin
)
404 if (fclose (name_file
) == EOF
)
405 ERROR ((0, errno
, "%s", name_buffer
));
408 /*-------------------------------------------------------------------------.
409 | Gather names in a list for scanning. Could hash them later if we really |
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 `-------------------------------------------------------------------------*/
423 /* Buffer able to hold a single name. */
424 static struct name
*buffer
;
425 static size_t allocated_length
;
429 if (same_order_option
)
431 static int change_dir
;
433 if (allocated_length
== 0)
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
);
441 while ((name
= name_next (0)) && strcmp (name
, "-C") == 0)
443 char const *dir
= name_next (0);
445 FATAL_ERROR ((0, 0, _("Missing file name after -C")));
446 change_dir
= chdir_arg (xstrdup (dir
));
451 buffer
->length
= strlen (name
);
452 if (sizeof (struct name
) + buffer
->length
>= allocated_length
)
454 allocated_length
= sizeof (struct name
) + buffer
->length
;
455 buffer
= xrealloc (buffer
, allocated_length
);
457 buffer
->change_dir
= change_dir
;
458 strncpy (buffer
->name
, name
, buffer
->length
);
459 buffer
->name
[buffer
->length
] = 0;
463 /* FIXME: Poorly named globals, indeed... */
470 /* Non sorted names -- read them all in. */
475 int change_dir0
= change_dir
;
476 while ((name
= name_next (0)) && strcmp (name
, "-C") == 0)
478 char const *dir
= name_next (0);
480 FATAL_ERROR ((0, 0, _("Missing file name after -C")));
481 change_dir
= chdir_arg (xstrdup (dir
));
484 addname (name
, change_dir
);
487 if (change_dir
!= change_dir0
)
488 addname (0, change_dir
);
495 /*-----------------------------.
496 | Add a name to the namelist. |
497 `-----------------------------*/
500 addname (char const *string
, int change_dir
)
505 length
= string
? strlen (string
) : 0;
506 name
= xmalloc (sizeof (struct name
) + length
);
507 memset (name
, 0, sizeof (struct name
) + length
);
513 name
->length
= length
;
514 memcpy (name
->name
, string
, length
+ 1);
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;
525 if (string
&& is_pattern (string
))
528 if (string
[0] == '*' || string
[0] == '[' || string
[0] == '?')
533 namelast
->next
= name
;
539 /*------------------------------------------------------------------------.
540 | Return true if and only if name PATH (from an archive) matches any name |
541 | from the namelist. |
542 `------------------------------------------------------------------------*/
545 name_match (const char *path
)
547 size_t length
= strlen (path
);
551 struct name
*cursor
= namelist
;
554 return ! files_from_option
;
558 chdir_do (cursor
->change_dir
);
560 return ! files_from_option
;
563 for (; cursor
; cursor
= cursor
->next
)
565 /* If first chars don't match, quick skip. */
567 if (cursor
->firstch
&& cursor
->name
[0] != path
[0])
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))
577 cursor
->found
= 1; /* remember it matched */
578 if (starting_file_option
)
583 chdir_do (cursor
->change_dir
);
585 /* We got a match. */
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. */
595 if (same_order_option
&& namelist
->found
)
597 name_gather (); /* read one more */
606 /*------------------------------------------------------------------.
607 | Print the names of things in the namelist that were not matched. |
608 `------------------------------------------------------------------*/
611 names_notfound (void)
616 for (cursor
= namelist
; cursor
; cursor
= next
)
619 if (!cursor
->found
&& !cursor
->fake
)
620 ERROR ((0, 0, _("%s: Not found in archive"), cursor
->name
));
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. */
627 if (!same_order_option
)
634 if (same_order_option
)
638 while (name
= name_next (1), name
)
639 ERROR ((0, 0, _("%s: Not found in archive"), name
));
643 /* Sorting name lists. */
645 /* Sort linked LIST of names, of given LENGTH, using COMPARE to order
646 names. Return the sorted list. Apart from the type `struct name'
647 and the definition of SUCCESSOR, this is a generic list-sorting
648 function, but it's too painful to make it both generic and portable
652 merge_sort (struct name
*list
, int length
,
653 int (*compare
) (struct name
const*, struct name
const*))
655 struct name
*first_list
;
656 struct name
*second_list
;
660 struct name
**merge_point
;
664 # define SUCCESSOR(name) ((name)->next)
671 if ((*compare
) (list
, SUCCESSOR (list
)) > 0)
673 result
= SUCCESSOR (list
);
674 SUCCESSOR (result
) = list
;
675 SUCCESSOR (list
) = 0;
682 first_length
= (length
+ 1) / 2;
683 second_length
= length
/ 2;
684 for (cursor
= list
, counter
= first_length
- 1;
686 cursor
= SUCCESSOR (cursor
), counter
--)
688 second_list
= SUCCESSOR (cursor
);
689 SUCCESSOR (cursor
) = 0;
691 first_list
= merge_sort (first_list
, first_length
, compare
);
692 second_list
= merge_sort (second_list
, second_length
, compare
);
694 merge_point
= &result
;
695 while (first_list
&& second_list
)
696 if ((*compare
) (first_list
, second_list
) < 0)
698 cursor
= SUCCESSOR (first_list
);
699 *merge_point
= first_list
;
700 merge_point
= &SUCCESSOR (first_list
);
705 cursor
= SUCCESSOR (second_list
);
706 *merge_point
= second_list
;
707 merge_point
= &SUCCESSOR (second_list
);
708 second_list
= cursor
;
711 *merge_point
= first_list
;
713 *merge_point
= second_list
;
720 /* A comparison function for sorting names. Put found names last;
721 break ties by string comparison. */
724 compare_names (struct name
const *n1
, struct name
const *n2
)
726 int found_diff
= n2
->found
- n1
->found
;
727 return found_diff
? found_diff
: strcmp (n1
->name
, n2
->name
);
730 /* Add all the dirs in PATH, which is a directory, to the namelist.
731 If any of the files is a directory, recurse on the subdirectory.
732 CHANGE_DIR is the number of the directory that PATH is relative to.
733 DEVICE is the device not to leave, if the -l option is specified. */
736 add_hierarchy_to_namelist (char *path
, int change_dir
, dev_t device
)
738 char *buffer
= get_directory_contents (path
, device
);
743 for (name
= namelist
; name
; name
= name
->next
)
744 if (strcmp (name
->name
, path
) == 0)
747 name
->dir_contents
= buffer
? buffer
: "\0\0\0\0";
752 size_t name_length
= strlen (path
);
753 size_t allocated_length
= (name_length
>= NAME_FIELD_SIZE
754 ? name_length
+ NAME_FIELD_SIZE
756 char *name_buffer
= xmalloc (allocated_length
+ 1);
757 /* FIXME: + 2 above? */
759 size_t string_length
;
761 strcpy (name_buffer
, path
);
762 if (name_buffer
[name_length
- 1] != '/')
764 name_buffer
[name_length
++] = '/';
765 name_buffer
[name_length
] = '\0';
768 for (string
= buffer
; *string
; string
+= string_length
+ 1)
770 string_length
= strlen (string
);
773 if (name_length
+ string_length
>= allocated_length
)
775 while (name_length
+ string_length
>= allocated_length
)
776 allocated_length
+= NAME_FIELD_SIZE
;
777 name_buffer
= xrealloc (name_buffer
, allocated_length
+ 1);
779 strcpy (name_buffer
+ name_length
, string
+ 1);
780 addname (name_buffer
, change_dir
);
782 add_hierarchy_to_namelist (name_buffer
, change_dir
, device
);
790 /* Collect all the names from argv[] (or whatever), expand them into a
791 directory tree, and sort them. This gets only subdirectories, not
795 collect_and_sort_names (void)
798 struct name
*next_name
;
804 if (listed_incremental_option
)
805 read_directory_file ();
810 for (name
= namelist
; name
; name
= next_name
)
812 next_name
= name
->next
;
813 if (name
->found
|| name
->dir_contents
)
815 if (name
->regexp
) /* FIXME: just skip regexps for now */
817 chdir_do (name
->change_dir
);
821 if (deref_stat (dereference_option
, name
->name
, &statbuf
) != 0)
823 ERROR ((0, errno
, _("Cannot stat %s"), name
->name
));
826 if (S_ISDIR (statbuf
.st_mode
))
829 add_hierarchy_to_namelist (name
->name
, name
->change_dir
,
835 for (name
= namelist
; name
; name
= name
->next
)
837 namelist
= merge_sort (namelist
, num_names
, compare_names
);
839 for (name
= namelist
; name
; name
= name
->next
)
843 /*-------------------------------------------------------------------------.
844 | This is like name_match, except that it returns a pointer to the name it |
845 | matched, and doesn't set FOUND in structure. The caller will have to do |
846 | that if it wants to. Oh, and if the namelist is empty, it returns null, |
847 | unlike name_match, which returns TRUE. |
848 `-------------------------------------------------------------------------*/
851 name_scan (const char *path
)
853 size_t length
= strlen (path
);
857 struct name
*cursor
= namelist
;
862 for (; cursor
; cursor
= cursor
->next
)
864 /* If first chars don't match, quick skip. */
866 if (cursor
->firstch
&& cursor
->name
[0] != path
[0])
870 ? fnmatch (cursor
->name
, path
, FNM_LEADING_DIR
) == 0
871 : (cursor
->length
<= length
872 && (path
[cursor
->length
] == '\0'
873 || path
[cursor
->length
] == '/')
874 && memcmp (path
, cursor
->name
, cursor
->length
) == 0))
875 return cursor
; /* we got a match */
878 /* Filename from archive not found in namelist. If we have the whole
879 namelist here, just return 0. Otherwise, read the next name in and
880 compare it. If this was the last name, namelist->found will remain
881 on. If not, we loop to compare the newly read name. */
883 if (same_order_option
&& namelist
->found
)
885 name_gather (); /* read one more */
894 /*-----------------------------------------------------------------------.
895 | This returns a name from the namelist which doesn't have ->found set. |
896 | It sets ->found before returning, so successive calls will find and |
897 | return all the non-found names in the namelist |
898 `-----------------------------------------------------------------------*/
900 struct name
*gnu_list_name
;
903 name_from_list (void)
906 gnu_list_name
= namelist
;
907 while (gnu_list_name
&& (gnu_list_name
->found
| gnu_list_name
->fake
))
908 gnu_list_name
= gnu_list_name
->next
;
911 gnu_list_name
->found
= 1;
912 chdir_do (gnu_list_name
->change_dir
);
913 return gnu_list_name
->name
;
923 blank_name_list (void)
928 for (name
= namelist
; name
; name
= name
->next
)
937 new_name (const char *path
, const char *name
)
939 char *buffer
= xmalloc (strlen (path
) + strlen (name
) + 2);
941 sprintf (buffer
, "%s/%s", path
, name
);
945 /* Return nonzero if file NAME is excluded. Exclude a name if its
946 prefix matches a pattern that contains slashes, or if one of its
947 components matches a pattern that contains no slashes. */
949 excluded_name (char const *name
)
952 name
+= FILESYSTEM_PREFIX_LEN (name
);
954 if (excluded_filename (excluded_with_slash
, name
,
955 FNM_FILE_NAME
| FNM_LEADING_DIR
))
958 for (p
= name
; *p
; p
++)
959 if ((p
== name
|| (ISSLASH (p
[-1]) && !ISSLASH (p
[0])))
960 && excluded_filename (excluded_without_slash
, p
,
961 FNM_FILE_NAME
| FNM_LEADING_DIR
))
967 /* Names to avoid dumping. */
971 struct avoided_name
const *next
;
975 static struct avoided_name
*avoided_names
;
977 /* Remember to not archive NAME. */
979 add_avoided_name (char const *name
)
981 struct avoided_name
*p
= xmalloc (sizeof *p
+ strlen (name
));
982 p
->next
= avoided_names
;
984 strcpy (p
->name
, name
);
987 /* Should NAME be avoided when archiving? */
989 is_avoided_name (char const *name
)
991 struct avoided_name
const *p
;
992 for (p
= avoided_names
; p
; p
= p
->next
)
993 if (strcmp (p
->name
, name
) == 0)