]>
Dogcows Code - chaz/tar/blob - src/names.c
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 chdir_from_initial_wd (name_buffer
);
378 else if (change_dirs
&& strcmp (name_buffer
, "-C") == 0)
382 unquote_string (name_buffer
);
387 /* No more names in file. */
389 if (name_file
&& chdir_flag
)
390 FATAL_ERROR ((0, 0, _("Missing file name after -C")));
395 /*------------------------------.
396 | Close the name file, if any. |
397 `------------------------------*/
402 if (name_file
&& name_file
!= stdin
)
403 if (fclose (name_file
) == EOF
)
404 ERROR ((0, errno
, "%s", name_buffer
));
407 /*-------------------------------------------------------------------------.
408 | Gather names in a list for scanning. Could hash them later if we really |
411 | If the names are already sorted to match the archive, we just read them |
412 | one by one. name_gather reads the first one, and it is called by |
413 | name_match as appropriate to read the next ones. At EOF, the last name |
414 | read is just left in the buffer. This option lets users of small |
415 | machines extract an arbitrary number of files by doing "tar t" and |
416 | editing down the list of files. |
417 `-------------------------------------------------------------------------*/
422 /* Buffer able to hold a single name. */
423 static struct name
*buffer
;
424 static size_t allocated_length
;
428 if (same_order_option
)
430 char *change_dir
= 0;
432 if (allocated_length
== 0)
434 allocated_length
= sizeof (struct name
) + NAME_FIELD_SIZE
;
435 buffer
= xmalloc (allocated_length
);
436 /* FIXME: This memset is overkill, and ugly... */
437 memset (buffer
, 0, allocated_length
);
440 while ((name
= name_next (0)) && strcmp (name
, "-C") == 0)
442 char const *dir
= name_next (0);
444 FATAL_ERROR ((0, 0, _("Missing file name after -C")));
447 change_dir
= 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... */
474 /* Non sorted names -- read them all in. */
478 char *change_dir
= 0;
479 while ((name
= name_next (0)) && strcmp (name
, "-C") == 0)
481 char const *dir
= name_next (0);
483 FATAL_ERROR ((0, 0, _("Missing file name after -C")));
486 change_dir
= xstrdup (dir
);
489 addname (name
, change_dir
);
493 addname (0, change_dir
);
499 /*-----------------------------.
500 | Add a name to the namelist. |
501 `-----------------------------*/
504 addname (char const *string
, char const *change_dir
)
509 length
= string
? strlen (string
) : 0;
510 name
= xmalloc (sizeof (struct name
) + length
);
511 memset (name
, 0, sizeof (struct name
) + length
);
517 name
->length
= length
;
518 memcpy (name
->name
, string
, length
+ 1);
524 name
->regexp
= 0; /* assume not a regular expression */
525 name
->firstch
= 1; /* assume first char is literal */
526 name
->change_dir
= change_dir
;
527 name
->dir_contents
= 0;
529 if (string
&& is_pattern (string
))
532 if (string
[0] == '*' || string
[0] == '[' || string
[0] == '?')
537 namelast
->next
= name
;
543 /*------------------------------------------------------------------------.
544 | Return true if and only if name PATH (from an archive) matches any name |
545 | from the namelist. |
546 `------------------------------------------------------------------------*/
549 name_match (const char *path
)
551 size_t length
= strlen (path
);
552 char const *change_dir
= 0;
556 struct name
*cursor
= namelist
;
559 return ! files_from_option
;
563 chdir_from_initial_wd (cursor
->change_dir
);
565 return ! files_from_option
;
568 for (; cursor
; cursor
= cursor
->next
)
570 if (cursor
->change_dir
)
571 change_dir
= cursor
->change_dir
;
573 /* If first chars don't match, quick skip. */
575 if (cursor
->firstch
&& cursor
->name
[0] != path
[0])
579 ? fnmatch (cursor
->name
, path
, FNM_LEADING_DIR
) == 0
580 : (cursor
->length
<= length
581 && (path
[cursor
->length
] == '\0'
582 || path
[cursor
->length
] == '/')
583 && memcmp (path
, cursor
->name
, cursor
->length
) == 0))
585 cursor
->found
= 1; /* remember it matched */
586 if (starting_file_option
)
591 chdir_from_initial_wd (change_dir
);
593 /* We got a match. */
598 /* Filename from archive not found in namelist. If we have the whole
599 namelist here, just return 0. Otherwise, read the next name in and
600 compare it. If this was the last name, namelist->found will remain
601 on. If not, we loop to compare the newly read name. */
603 if (same_order_option
&& namelist
->found
)
605 name_gather (); /* read one more */
614 /*------------------------------------------------------------------.
615 | Print the names of things in the namelist that were not matched. |
616 `------------------------------------------------------------------*/
619 names_notfound (void)
624 for (cursor
= namelist
; cursor
; cursor
= next
)
627 if (!cursor
->found
&& !cursor
->fake
)
628 ERROR ((0, 0, _("%s: Not found in archive"), cursor
->name
));
630 /* We could free the list, but the process is about to die anyway, so
631 save some CPU time. Amigas and other similarly broken software
632 will need to waste the time, though. */
635 if (!same_order_option
)
642 if (same_order_option
)
646 while (name
= name_next (1), name
)
647 ERROR ((0, 0, _("%s: Not found in archive"), name
));
660 /*-------------------------------------------------------------------------.
661 | This is like name_match, except that it returns a pointer to the name it |
662 | matched, and doesn't set FOUND in structure. The caller will have to do |
663 | that if it wants to. Oh, and if the namelist is empty, it returns null, |
664 | unlike name_match, which returns TRUE. |
665 `-------------------------------------------------------------------------*/
668 name_scan (const char *path
)
670 size_t length
= strlen (path
);
674 struct name
*cursor
= namelist
;
679 for (; cursor
; cursor
= cursor
->next
)
681 /* If first chars don't match, quick skip. */
683 if (cursor
->firstch
&& cursor
->name
[0] != path
[0])
687 ? fnmatch (cursor
->name
, path
, FNM_LEADING_DIR
) == 0
688 : (cursor
->length
<= length
689 && (path
[cursor
->length
] == '\0'
690 || path
[cursor
->length
] == '/')
691 && memcmp (path
, cursor
->name
, cursor
->length
) == 0))
692 return cursor
; /* we got a match */
695 /* Filename from archive not found in namelist. If we have the whole
696 namelist here, just return 0. Otherwise, read the next name in and
697 compare it. If this was the last name, namelist->found will remain
698 on. If not, we loop to compare the newly read name. */
700 if (same_order_option
&& namelist
->found
)
702 name_gather (); /* read one more */
711 /*-----------------------------------------------------------------------.
712 | This returns a name from the namelist which doesn't have ->found set. |
713 | It sets ->found before returning, so successive calls will find and |
714 | return all the non-found names in the namelist |
715 `-----------------------------------------------------------------------*/
717 struct name
*gnu_list_name
;
720 name_from_list (void)
723 gnu_list_name
= namelist
;
724 while (gnu_list_name
&& gnu_list_name
->found
)
725 gnu_list_name
= gnu_list_name
->next
;
728 gnu_list_name
->found
= 1;
729 chdir_from_initial_wd (gnu_list_name
->change_dir
);
730 return gnu_list_name
->name
;
740 blank_name_list (void)
745 for (name
= namelist
; name
; name
= name
->next
)
754 new_name (const char *path
, const char *name
)
756 char *buffer
= xmalloc (strlen (path
) + strlen (name
) + 2);
758 sprintf (buffer
, "%s/%s", path
, name
);
762 /* Return nonzero if file NAME is excluded. Exclude a name if its
763 prefix matches a pattern that contains slashes, or if one of its
764 components matches a pattern that contains no slashes. */
766 excluded_name (char const *name
)
769 name
+= FILESYSTEM_PREFIX_LEN (name
);
771 if (excluded_filename (excluded_with_slash
, name
,
772 FNM_FILE_NAME
| FNM_LEADING_DIR
))
775 for (p
= name
; *p
; p
++)
776 if ((p
== name
|| (ISSLASH (p
[-1]) && !ISSLASH (p
[0])))
777 && excluded_filename (excluded_without_slash
, p
,
778 FNM_FILE_NAME
| FNM_LEADING_DIR
))
This page took 0.06806 seconds and 5 git commands to generate.