]> Dogcows Code - chaz/tar/blob - src/names.c
e3e145aef3e4394741e070c2f2a8f1910cf827e2
[chaz/tar] / src / names.c
1 /* Various processing of names.
2
3 Copyright 1988, 1992, 1994, 1996-2001, 2003-2007, 2009, 2013-2014
4 Free Software Foundation, Inc.
5
6 This program is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 3, or (at your option) any later
9 version.
10
11 This program is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
14 Public License for more details.
15
16 You should have received a copy of the GNU General Public License along
17 with this program. If not, see <http://www.gnu.org/licenses/>. */
18
19 #include <system.h>
20
21 #include <fnmatch.h>
22 #include <hash.h>
23 #include <quotearg.h>
24 #include <wordsplit.h>
25 #include <argp.h>
26
27 #include "common.h"
28 \f
29 /* User and group names. */
30
31 /* Make sure you link with the proper libraries if you are running the
32 Yellow Peril (thanks for the good laugh, Ian J.!), or, euh... NIS.
33 This code should also be modified for non-UNIX systems to do something
34 reasonable. */
35
36 static char *cached_uname;
37 static char *cached_gname;
38
39 static uid_t cached_uid; /* valid only if cached_uname is not empty */
40 static gid_t cached_gid; /* valid only if cached_gname is not empty */
41
42 /* These variables are valid only if nonempty. */
43 static char *cached_no_such_uname;
44 static char *cached_no_such_gname;
45
46 /* These variables are valid only if nonzero. It's not worth optimizing
47 the case for weird systems where 0 is not a valid uid or gid. */
48 static uid_t cached_no_such_uid;
49 static gid_t cached_no_such_gid;
50
51 /* Given UID, find the corresponding UNAME. */
52 void
53 uid_to_uname (uid_t uid, char **uname)
54 {
55 struct passwd *passwd;
56
57 if (uid != 0 && uid == cached_no_such_uid)
58 {
59 *uname = xstrdup ("");
60 return;
61 }
62
63 if (!cached_uname || uid != cached_uid)
64 {
65 passwd = getpwuid (uid);
66 if (passwd)
67 {
68 cached_uid = uid;
69 assign_string (&cached_uname, passwd->pw_name);
70 }
71 else
72 {
73 cached_no_such_uid = uid;
74 *uname = xstrdup ("");
75 return;
76 }
77 }
78 *uname = xstrdup (cached_uname);
79 }
80
81 /* Given GID, find the corresponding GNAME. */
82 void
83 gid_to_gname (gid_t gid, char **gname)
84 {
85 struct group *group;
86
87 if (gid != 0 && gid == cached_no_such_gid)
88 {
89 *gname = xstrdup ("");
90 return;
91 }
92
93 if (!cached_gname || gid != cached_gid)
94 {
95 group = getgrgid (gid);
96 if (group)
97 {
98 cached_gid = gid;
99 assign_string (&cached_gname, group->gr_name);
100 }
101 else
102 {
103 cached_no_such_gid = gid;
104 *gname = xstrdup ("");
105 return;
106 }
107 }
108 *gname = xstrdup (cached_gname);
109 }
110
111 /* Given UNAME, set the corresponding UID and return 1, or else, return 0. */
112 int
113 uname_to_uid (char const *uname, uid_t *uidp)
114 {
115 struct passwd *passwd;
116
117 if (cached_no_such_uname
118 && strcmp (uname, cached_no_such_uname) == 0)
119 return 0;
120
121 if (!cached_uname
122 || uname[0] != cached_uname[0]
123 || strcmp (uname, cached_uname) != 0)
124 {
125 passwd = getpwnam (uname);
126 if (passwd)
127 {
128 cached_uid = passwd->pw_uid;
129 assign_string (&cached_uname, passwd->pw_name);
130 }
131 else
132 {
133 assign_string (&cached_no_such_uname, uname);
134 return 0;
135 }
136 }
137 *uidp = cached_uid;
138 return 1;
139 }
140
141 /* Given GNAME, set the corresponding GID and return 1, or else, return 0. */
142 int
143 gname_to_gid (char const *gname, gid_t *gidp)
144 {
145 struct group *group;
146
147 if (cached_no_such_gname
148 && strcmp (gname, cached_no_such_gname) == 0)
149 return 0;
150
151 if (!cached_gname
152 || gname[0] != cached_gname[0]
153 || strcmp (gname, cached_gname) != 0)
154 {
155 group = getgrnam (gname);
156 if (group)
157 {
158 cached_gid = group->gr_gid;
159 assign_string (&cached_gname, gname);
160 }
161 else
162 {
163 assign_string (&cached_no_such_gname, gname);
164 return 0;
165 }
166 }
167 *gidp = cached_gid;
168 return 1;
169 }
170
171 \f
172 static struct name *
173 make_name (const char *file_name)
174 {
175 struct name *p = xzalloc (sizeof (*p));
176 if (!file_name)
177 file_name = "";
178 p->name = xstrdup (file_name);
179 p->length = strlen (p->name);
180 return p;
181 }
182
183 static void
184 free_name (struct name *p)
185 {
186 if (p)
187 {
188 free (p->name);
189 free (p->caname);
190 free (p);
191 }
192 }
193
194 \f
195 /* Names from the command call. */
196
197 static struct name *namelist; /* first name in list, if any */
198 static struct name *nametail; /* end of name list */
199
200 /* File name arguments are processed in two stages: first a
201 name element list (see below) is filled, then the names from it
202 are moved into the namelist.
203
204 This awkward process is needed only to implement --same-order option,
205 which is meant to help process large archives on machines with
206 limited memory. With this option on, namelist contains at most one
207 entry, which diminishes the memory consumption.
208
209 However, I very much doubt if we still need this -- Sergey */
210
211 /* A name_list element contains entries of three types: */
212
213 #define NELT_NAME 0 /* File name */
214 #define NELT_CHDIR 1 /* Change directory request */
215 #define NELT_FMASK 2 /* Change fnmatch options request */
216 #define NELT_FILE 3 /* Read file names from that file */
217 #define NELT_NOOP 4 /* No operation */
218
219 struct name_elt /* A name_array element. */
220 {
221 struct name_elt *next, *prev;
222 char type; /* Element type, see NELT_* constants above */
223 union
224 {
225 const char *name; /* File or directory name */
226 int matching_flags;/* fnmatch options if type == NELT_FMASK */
227 struct /* File, if type == NELT_FILE */
228 {
229 const char *name;/* File name */
230 int term; /* File name terminator in the list */
231 FILE *fp;
232 } file;
233 } v;
234 };
235
236 static struct name_elt *name_head; /* store a list of names */
237 size_t name_count; /* how many of the entries are names? */
238
239 static struct name_elt *
240 name_elt_alloc (void)
241 {
242 struct name_elt *elt;
243
244 elt = xmalloc (sizeof (*elt));
245 if (!name_head)
246 {
247 name_head = elt;
248 name_head->prev = name_head->next = NULL;
249 name_head->type = NELT_NOOP;
250 elt = xmalloc (sizeof (*elt));
251 }
252
253 elt->prev = name_head->prev;
254 if (name_head->prev)
255 name_head->prev->next = elt;
256 elt->next = name_head;
257 name_head->prev = elt;
258 return elt;
259 }
260
261 static struct name_elt *
262 name_elt_alloc_matflags (int matflags)
263 {
264 static int prev_flags = 0; /* FIXME: Or EXCLUDE_ANCHORED? */
265 struct name_elt *ep = name_elt_alloc ();
266 if (prev_flags != matflags)
267 {
268 ep->type = NELT_FMASK;
269 ep->v.matching_flags = matflags;
270 prev_flags = matflags;
271 ep = name_elt_alloc ();
272 }
273 return ep;
274 }
275
276 static void
277 name_list_adjust (void)
278 {
279 if (name_head)
280 while (name_head->prev)
281 name_head = name_head->prev;
282 }
283
284 static void
285 name_list_advance (void)
286 {
287 struct name_elt *elt = name_head;
288 name_head = elt->next;
289 if (name_head)
290 name_head->prev = NULL;
291 free (elt);
292 }
293
294
295 /* Add to name_array the file NAME with fnmatch options MATFLAGS */
296 void
297 name_add_name (const char *name, int matflags)
298 {
299 struct name_elt *ep = name_elt_alloc_matflags (matflags);
300
301 ep->type = NELT_NAME;
302 ep->v.name = name;
303 name_count++;
304 }
305
306 /* Add to name_array a chdir request for the directory NAME */
307 void
308 name_add_dir (const char *name)
309 {
310 struct name_elt *ep = name_elt_alloc ();
311 ep->type = NELT_CHDIR;
312 ep->v.name = name;
313 }
314
315 void
316 name_add_file (const char *name, int term, int matflags)
317 {
318 struct name_elt *ep = name_elt_alloc_matflags (matflags);
319
320 ep->type = NELT_FILE;
321 ep->v.file.name = name;
322 ep->v.file.term = term;
323 ep->v.file.fp = NULL;
324 }
325 \f
326 /* Names from external name file. */
327
328 static char *name_buffer; /* buffer to hold the current file name */
329 static size_t name_buffer_length; /* allocated length of name_buffer */
330
331 /* Set up to gather file names for tar. They can either come from a
332 file or were saved from decoding arguments. */
333 void
334 name_init (void)
335 {
336 name_buffer = xmalloc (NAME_FIELD_SIZE + 2);
337 name_buffer_length = NAME_FIELD_SIZE;
338 name_list_adjust ();
339 }
340
341 void
342 name_term (void)
343 {
344 free (name_buffer);
345 }
346 \f
347 /* Prevent recursive inclusion of the same file */
348 struct file_id_list
349 {
350 struct file_id_list *next;
351 ino_t ino;
352 dev_t dev;
353 const char *from_file;
354 };
355
356 static struct file_id_list *file_id_list;
357
358 /* Return the name of the file from which the file names and options
359 are being read.
360 */
361 static const char *
362 file_list_name (void)
363 {
364 struct name_elt *elt;
365
366 for (elt = name_head; elt; elt = elt->next)
367 if (elt->type == NELT_FILE && elt->v.file.fp)
368 return elt->v.file.name;
369 return _("command line");
370 }
371
372 static int
373 add_file_id (const char *filename)
374 {
375 struct file_id_list *p;
376 struct stat st;
377 const char *reading_from;
378
379 if (stat (filename, &st))
380 stat_fatal (filename);
381 reading_from = file_list_name ();
382 for (p = file_id_list; p; p = p->next)
383 if (p->ino == st.st_ino && p->dev == st.st_dev)
384 {
385 int oldc = set_char_quoting (NULL, ':', 1);
386 ERROR ((0, 0,
387 _("%s: file list requested from %s already read from %s"),
388 quotearg_n (0, filename),
389 reading_from, p->from_file));
390 set_char_quoting (NULL, ':', oldc);
391 return 1;
392 }
393 p = xmalloc (sizeof *p);
394 p->next = file_id_list;
395 p->ino = st.st_ino;
396 p->dev = st.st_dev;
397 p->from_file = reading_from;
398 file_id_list = p;
399 return 0;
400 }
401
402 /* Chop trailing slashes. */
403 static void
404 chopslash (char *str)
405 {
406 char *p = str + strlen (str) - 1;
407 while (p > str && ISSLASH (*p))
408 *p-- = '\0';
409 }
410 \f
411 enum read_file_list_state /* Result of reading file name from the list file */
412 {
413 file_list_success, /* OK, name read successfully */
414 file_list_end, /* End of list file */
415 file_list_zero, /* Zero separator encountered where it should not */
416 file_list_skip /* Empty (zero-length) entry encountered, skip it */
417 };
418
419 /* Read from FP a sequence of characters up to TERM and put them
420 into STK.
421 */
422 static enum read_file_list_state
423 read_name_from_file (struct name_elt *ent)
424 {
425 int c;
426 size_t counter = 0;
427 FILE *fp = ent->v.file.fp;
428 int term = ent->v.file.term;
429
430 for (c = getc (fp); c != EOF && c != term; c = getc (fp))
431 {
432 if (counter == name_buffer_length)
433 name_buffer = x2realloc (name_buffer, &name_buffer_length);
434 name_buffer[counter++] = c;
435 if (c == 0)
436 {
437 /* We have read a zero separator. The file possibly is
438 zero-separated */
439 return file_list_zero;
440 }
441 }
442
443 if (counter == 0 && c != EOF)
444 return file_list_skip;
445
446 if (counter == name_buffer_length)
447 name_buffer = x2realloc (name_buffer, &name_buffer_length);
448 name_buffer[counter] = 0;
449 chopslash (name_buffer);
450 return (counter == 0 && c == EOF) ? file_list_end : file_list_success;
451 }
452
453 static int
454 handle_option (const char *str)
455 {
456 struct wordsplit ws;
457 int i;
458
459 while (*str && isspace (*str))
460 ++str;
461 if (*str != '-')
462 return 1;
463
464 ws.ws_offs = 1;
465 if (wordsplit (str, &ws, WRDSF_DEFFLAGS|WRDSF_DOOFFS))
466 FATAL_ERROR ((0, 0, _("cannot split string '%s': %s"),
467 str, wordsplit_strerror (&ws)));
468 ws.ws_wordv[0] = program_invocation_short_name;
469 more_options (ws.ws_wordc+ws.ws_offs, ws.ws_wordv);
470 for (i = 0; i < ws.ws_wordc+ws.ws_offs; i++)
471 ws.ws_wordv[i] = NULL;
472
473 wordsplit_free (&ws);
474 return 0;
475 }
476
477 static int
478 read_next_name (struct name_elt *ent, struct name_elt *ret)
479 {
480 if (!ent->v.file.fp)
481 {
482 if (!strcmp (ent->v.file.name, "-"))
483 {
484 request_stdin ("-T");
485 ent->v.file.fp = stdin;
486 }
487 else
488 {
489 if (add_file_id (ent->v.file.name))
490 {
491 name_list_advance ();
492 return 1;
493 }
494 if ((ent->v.file.fp = fopen (ent->v.file.name, "r")) == NULL)
495 open_fatal (ent->v.file.name);
496 }
497 }
498
499 while (1)
500 {
501 switch (read_name_from_file (ent))
502 {
503 case file_list_skip:
504 continue;
505
506 case file_list_zero:
507 WARNOPT (WARN_FILENAME_WITH_NULS,
508 (0, 0, N_("%s: file name read contains nul character"),
509 quotearg_colon (ent->v.file.name)));
510 ent->v.file.term = 0;
511 /* fall through */
512 case file_list_success:
513 if (unquote_option)
514 unquote_string (name_buffer);
515 if (handle_option (name_buffer) == 0)
516 {
517 name_list_adjust ();
518 return 1;
519 }
520 ret->type = NELT_NAME;
521 ret->v.name = name_buffer;
522 return 0;
523
524 case file_list_end:
525 if (strcmp (ent->v.file.name, "-"))
526 fclose (ent->v.file.fp);
527 ent->v.file.fp = NULL;
528 name_list_advance ();
529 return 1;
530 }
531 }
532 }
533 \f
534 static void
535 copy_name (struct name_elt *ep)
536 {
537 const char *source;
538 size_t source_len;
539
540 source = ep->v.name;
541 source_len = strlen (source);
542 if (name_buffer_length < source_len)
543 {
544 do
545 {
546 name_buffer_length *= 2;
547 if (! name_buffer_length)
548 xalloc_die ();
549 }
550 while (name_buffer_length < source_len);
551
552 free (name_buffer);
553 name_buffer = xmalloc(name_buffer_length + 2);
554 }
555 strcpy (name_buffer, source);
556 chopslash (name_buffer);
557 }
558
559 \f
560 static int matching_flags; /* exclude_fnmatch options */
561
562 /* Get the next NELT_NAME element from name_array. Result is in
563 static storage and can't be relied upon across two calls.
564
565 If CHANGE_DIRS is true, treat any entries of type NELT_CHDIR as
566 the request to change to the given directory.
567
568 Entries of type NELT_FMASK cause updates of the matching_flags
569 value.
570 */
571 static struct name_elt *
572 name_next_elt (int change_dirs)
573 {
574 static struct name_elt entry;
575 struct name_elt *ep;
576
577 while ((ep = name_head) != NULL)
578 {
579 switch (ep->type)
580 {
581 case NELT_NOOP:
582 name_list_advance ();
583 break;
584
585 case NELT_FMASK:
586 matching_flags = ep->v.matching_flags;
587 recursion_option = matching_flags & FNM_LEADING_DIR;
588 name_list_advance ();
589 continue;
590
591 case NELT_FILE:
592 if (read_next_name (ep, &entry) == 0)
593 return &entry;
594 continue;
595
596 case NELT_CHDIR:
597 if (change_dirs)
598 {
599 chdir_do (chdir_arg (xstrdup (ep->v.name)));
600 name_list_advance ();
601 break;
602 }
603 /* fall through */
604 case NELT_NAME:
605 copy_name (ep);
606 if (unquote_option)
607 unquote_string (name_buffer);
608 entry.type = ep->type;
609 entry.v.name = name_buffer;
610 name_list_advance ();
611 return &entry;
612 }
613 }
614
615 return NULL;
616 }
617
618 const char *
619 name_next (int change_dirs)
620 {
621 struct name_elt *nelt = name_next_elt (change_dirs);
622 return nelt ? nelt->v.name : NULL;
623 }
624
625 /* Gather names in a list for scanning. Could hash them later if we
626 really care.
627
628 If the names are already sorted to match the archive, we just read
629 them one by one. name_gather reads the first one, and it is called
630 by name_match as appropriate to read the next ones. At EOF, the
631 last name read is just left in the buffer. This option lets users
632 of small machines extract an arbitrary number of files by doing
633 "tar t" and editing down the list of files. */
634
635 void
636 name_gather (void)
637 {
638 /* Buffer able to hold a single name. */
639 static struct name *buffer = NULL;
640
641 struct name_elt *ep;
642
643 if (same_order_option)
644 {
645 static int change_dir;
646
647 while ((ep = name_next_elt (0)) && ep->type == NELT_CHDIR)
648 change_dir = chdir_arg (xstrdup (ep->v.name));
649
650 if (ep)
651 {
652 free_name (buffer);
653 buffer = make_name (ep->v.name);
654 buffer->change_dir = change_dir;
655 buffer->next = 0;
656 buffer->found_count = 0;
657 buffer->matching_flags = matching_flags;
658 buffer->directory = NULL;
659 buffer->parent = NULL;
660 buffer->cmdline = true;
661
662 namelist = nametail = buffer;
663 }
664 else if (change_dir)
665 addname (0, change_dir, false, NULL);
666 }
667 else
668 {
669 /* Non sorted names -- read them all in. */
670 int change_dir = 0;
671
672 for (;;)
673 {
674 int change_dir0 = change_dir;
675 while ((ep = name_next_elt (0)) && ep->type == NELT_CHDIR)
676 change_dir = chdir_arg (xstrdup (ep->v.name));
677
678 if (ep)
679 addname (ep->v.name, change_dir, true, NULL);
680 else
681 {
682 if (change_dir != change_dir0)
683 addname (NULL, change_dir, false, NULL);
684 break;
685 }
686 }
687 }
688 }
689
690 /* Add a name to the namelist. */
691 struct name *
692 addname (char const *string, int change_dir, bool cmdline, struct name *parent)
693 {
694 struct name *name = make_name (string);
695
696 name->prev = nametail;
697 name->next = NULL;
698 name->found_count = 0;
699 name->matching_flags = matching_flags;
700 name->change_dir = change_dir;
701 name->directory = NULL;
702 name->parent = parent;
703 name->cmdline = cmdline;
704
705 if (nametail)
706 nametail->next = name;
707 else
708 namelist = name;
709 nametail = name;
710 return name;
711 }
712
713 /* Find a match for FILE_NAME (whose string length is LENGTH) in the name
714 list. */
715 static struct name *
716 namelist_match (char const *file_name, size_t length)
717 {
718 struct name *p;
719
720 for (p = namelist; p; p = p->next)
721 {
722 if (p->name[0]
723 && exclude_fnmatch (p->name, file_name, p->matching_flags))
724 return p;
725 }
726
727 return NULL;
728 }
729
730 void
731 remname (struct name *name)
732 {
733 struct name *p;
734
735 if ((p = name->prev) != NULL)
736 p->next = name->next;
737 else
738 namelist = name->next;
739
740 if ((p = name->next) != NULL)
741 p->prev = name->prev;
742 else
743 nametail = name->prev;
744 }
745
746 /* Return true if and only if name FILE_NAME (from an archive) matches any
747 name from the namelist. */
748 bool
749 name_match (const char *file_name)
750 {
751 size_t length = strlen (file_name);
752
753 while (1)
754 {
755 struct name *cursor = namelist;
756
757 if (!cursor)
758 return true;
759
760 if (cursor->name[0] == 0)
761 {
762 chdir_do (cursor->change_dir);
763 namelist = NULL;
764 nametail = NULL;
765 return true;
766 }
767
768 cursor = namelist_match (file_name, length);
769 if (cursor)
770 {
771 if (!(ISSLASH (file_name[cursor->length]) && recursion_option)
772 || cursor->found_count == 0)
773 cursor->found_count++; /* remember it matched */
774 if (starting_file_option)
775 {
776 free (namelist);
777 namelist = NULL;
778 nametail = NULL;
779 }
780 chdir_do (cursor->change_dir);
781
782 /* We got a match. */
783 return ISFOUND (cursor);
784 }
785
786 /* Filename from archive not found in namelist. If we have the whole
787 namelist here, just return 0. Otherwise, read the next name in and
788 compare it. If this was the last name, namelist->found_count will
789 remain on. If not, we loop to compare the newly read name. */
790
791 if (same_order_option && namelist->found_count)
792 {
793 name_gather (); /* read one more */
794 if (namelist->found_count)
795 return false;
796 }
797 else
798 return false;
799 }
800 }
801
802 /* Returns true if all names from the namelist were processed.
803 P is the stat_info of the most recently processed entry.
804 The decision is postponed until the next entry is read if:
805
806 1) P ended with a slash (i.e. it was a directory)
807 2) P matches any entry from the namelist *and* represents a subdirectory
808 or a file lying under this entry (in the terms of directory structure).
809
810 This is necessary to handle contents of directories. */
811 bool
812 all_names_found (struct tar_stat_info *p)
813 {
814 struct name const *cursor;
815 size_t len;
816
817 if (!p->file_name || occurrence_option == 0 || p->had_trailing_slash)
818 return false;
819 len = strlen (p->file_name);
820 for (cursor = namelist; cursor; cursor = cursor->next)
821 {
822 if ((cursor->name[0] && !WASFOUND (cursor))
823 || (len >= cursor->length && ISSLASH (p->file_name[cursor->length])))
824 return false;
825 }
826 return true;
827 }
828
829 static int
830 regex_usage_warning (const char *name)
831 {
832 static int warned_once = 0;
833
834 if (warn_regex_usage && fnmatch_pattern_has_wildcards (name, 0))
835 {
836 warned_once = 1;
837 WARN ((0, 0,
838 _("Pattern matching characters used in file names")));
839 WARN ((0, 0,
840 _("Use --wildcards to enable pattern matching,"
841 " or --no-wildcards to suppress this warning")));
842 }
843 return warned_once;
844 }
845
846 /* Print the names of things in the namelist that were not matched. */
847 void
848 names_notfound (void)
849 {
850 struct name const *cursor;
851
852 for (cursor = namelist; cursor; cursor = cursor->next)
853 if (!WASFOUND (cursor) && cursor->name[0])
854 {
855 regex_usage_warning (cursor->name);
856 ERROR ((0, 0,
857 (cursor->found_count == 0) ?
858 _("%s: Not found in archive") :
859 _("%s: Required occurrence not found in archive"),
860 quotearg_colon (cursor->name)));
861 }
862
863 /* Don't bother freeing the name list; we're about to exit. */
864 namelist = NULL;
865 nametail = NULL;
866
867 if (same_order_option)
868 {
869 const char *name;
870
871 while ((name = name_next (1)) != NULL)
872 {
873 regex_usage_warning (name);
874 ERROR ((0, 0, _("%s: Not found in archive"),
875 quotearg_colon (name)));
876 }
877 }
878 }
879
880 void
881 label_notfound (void)
882 {
883 struct name const *cursor;
884
885 if (!namelist)
886 return;
887
888 for (cursor = namelist; cursor; cursor = cursor->next)
889 if (WASFOUND (cursor))
890 return;
891
892 if (verbose_option)
893 error (0, 0, _("Archive label mismatch"));
894 set_exit_status (TAREXIT_DIFFERS);
895
896 for (cursor = namelist; cursor; cursor = cursor->next)
897 {
898 if (regex_usage_warning (cursor->name))
899 break;
900 }
901
902 /* Don't bother freeing the name list; we're about to exit. */
903 namelist = NULL;
904 nametail = NULL;
905
906 if (same_order_option)
907 {
908 const char *name;
909
910 while ((name = name_next (1)) != NULL
911 && regex_usage_warning (name) == 0)
912 ;
913 }
914 }
915 \f
916 /* Sorting name lists. */
917
918 /* Sort *singly* linked LIST of names, of given LENGTH, using COMPARE
919 to order names. Return the sorted list. Note that after calling
920 this function, the 'prev' links in list elements are messed up.
921
922 Apart from the type 'struct name' and the definition of SUCCESSOR,
923 this is a generic list-sorting function, but it's too painful to
924 make it both generic and portable
925 in C. */
926
927 static struct name *
928 merge_sort_sll (struct name *list, int length,
929 int (*compare) (struct name const*, struct name const*))
930 {
931 struct name *first_list;
932 struct name *second_list;
933 int first_length;
934 int second_length;
935 struct name *result;
936 struct name **merge_point;
937 struct name *cursor;
938 int counter;
939
940 # define SUCCESSOR(name) ((name)->next)
941
942 if (length == 1)
943 return list;
944
945 if (length == 2)
946 {
947 if ((*compare) (list, SUCCESSOR (list)) > 0)
948 {
949 result = SUCCESSOR (list);
950 SUCCESSOR (result) = list;
951 SUCCESSOR (list) = 0;
952 return result;
953 }
954 return list;
955 }
956
957 first_list = list;
958 first_length = (length + 1) / 2;
959 second_length = length / 2;
960 for (cursor = list, counter = first_length - 1;
961 counter;
962 cursor = SUCCESSOR (cursor), counter--)
963 continue;
964 second_list = SUCCESSOR (cursor);
965 SUCCESSOR (cursor) = 0;
966
967 first_list = merge_sort_sll (first_list, first_length, compare);
968 second_list = merge_sort_sll (second_list, second_length, compare);
969
970 merge_point = &result;
971 while (first_list && second_list)
972 if ((*compare) (first_list, second_list) < 0)
973 {
974 cursor = SUCCESSOR (first_list);
975 *merge_point = first_list;
976 merge_point = &SUCCESSOR (first_list);
977 first_list = cursor;
978 }
979 else
980 {
981 cursor = SUCCESSOR (second_list);
982 *merge_point = second_list;
983 merge_point = &SUCCESSOR (second_list);
984 second_list = cursor;
985 }
986 if (first_list)
987 *merge_point = first_list;
988 else
989 *merge_point = second_list;
990
991 return result;
992
993 #undef SUCCESSOR
994 }
995
996 /* Sort doubly linked LIST of names, of given LENGTH, using COMPARE
997 to order names. Return the sorted list. */
998 static struct name *
999 merge_sort (struct name *list, int length,
1000 int (*compare) (struct name const*, struct name const*))
1001 {
1002 struct name *head, *p, *prev;
1003 head = merge_sort_sll (list, length, compare);
1004 /* Fixup prev pointers */
1005 for (prev = NULL, p = head; p; prev = p, p = p->next)
1006 p->prev = prev;
1007 return head;
1008 }
1009
1010 /* A comparison function for sorting names. Put found names last;
1011 break ties by string comparison. */
1012
1013 static int
1014 compare_names_found (struct name const *n1, struct name const *n2)
1015 {
1016 int found_diff = WASFOUND (n2) - WASFOUND (n1);
1017 return found_diff ? found_diff : strcmp (n1->name, n2->name);
1018 }
1019
1020 /* Simple comparison by names. */
1021 static int
1022 compare_names (struct name const *n1, struct name const *n2)
1023 {
1024 return strcmp (n1->name, n2->name);
1025 }
1026
1027 \f
1028 /* Add all the dirs under ST to the namelist NAME, descending the
1029 directory hierarchy recursively. */
1030
1031 static void
1032 add_hierarchy_to_namelist (struct tar_stat_info *st, struct name *name)
1033 {
1034 const char *buffer;
1035
1036 name->directory = scan_directory (st);
1037 buffer = directory_contents (name->directory);
1038 if (buffer)
1039 {
1040 struct name *child_head = NULL, *child_tail = NULL;
1041 size_t name_length = name->length;
1042 size_t allocated_length = (name_length >= NAME_FIELD_SIZE
1043 ? name_length + NAME_FIELD_SIZE
1044 : NAME_FIELD_SIZE);
1045 char *namebuf = xmalloc (allocated_length + 1);
1046 /* FIXME: + 2 above? */
1047 const char *string;
1048 size_t string_length;
1049 int change_dir = name->change_dir;
1050
1051 strcpy (namebuf, name->name);
1052 if (! ISSLASH (namebuf[name_length - 1]))
1053 {
1054 namebuf[name_length++] = '/';
1055 namebuf[name_length] = '\0';
1056 }
1057
1058 for (string = buffer; *string; string += string_length + 1)
1059 {
1060 string_length = strlen (string);
1061 if (*string == 'D')
1062 {
1063 struct name *np;
1064 struct tar_stat_info subdir;
1065 int subfd;
1066
1067 if (allocated_length <= name_length + string_length)
1068 {
1069 do
1070 {
1071 allocated_length *= 2;
1072 if (! allocated_length)
1073 xalloc_die ();
1074 }
1075 while (allocated_length <= name_length + string_length);
1076
1077 namebuf = xrealloc (namebuf, allocated_length + 1);
1078 }
1079 strcpy (namebuf + name_length, string + 1);
1080 np = addname (namebuf, change_dir, false, name);
1081 if (!child_head)
1082 child_head = np;
1083 else
1084 child_tail->sibling = np;
1085 child_tail = np;
1086
1087 tar_stat_init (&subdir);
1088 subdir.parent = st;
1089 if (st->fd < 0)
1090 {
1091 subfd = -1;
1092 errno = - st->fd;
1093 }
1094 else
1095 subfd = subfile_open (st, string + 1,
1096 open_read_flags | O_DIRECTORY);
1097 if (subfd < 0)
1098 open_diag (namebuf);
1099 else
1100 {
1101 subdir.fd = subfd;
1102 if (fstat (subfd, &subdir.stat) != 0)
1103 stat_diag (namebuf);
1104 else if (! (O_DIRECTORY || S_ISDIR (subdir.stat.st_mode)))
1105 {
1106 errno = ENOTDIR;
1107 open_diag (namebuf);
1108 }
1109 else
1110 {
1111 subdir.orig_file_name = xstrdup (namebuf);
1112 add_hierarchy_to_namelist (&subdir, np);
1113 restore_parent_fd (&subdir);
1114 }
1115 }
1116
1117 tar_stat_destroy (&subdir);
1118 }
1119 }
1120
1121 free (namebuf);
1122 name->child = child_head;
1123 }
1124 }
1125 \f
1126 /* Auxiliary functions for hashed table of struct name's. */
1127
1128 static size_t
1129 name_hash (void const *entry, size_t n_buckets)
1130 {
1131 struct name const *name = entry;
1132 return hash_string (name->caname, n_buckets);
1133 }
1134
1135 /* Compare two directories for equality of their names. */
1136 static bool
1137 name_compare (void const *entry1, void const *entry2)
1138 {
1139 struct name const *name1 = entry1;
1140 struct name const *name2 = entry2;
1141 return strcmp (name1->caname, name2->caname) == 0;
1142 }
1143
1144 \f
1145 /* Rebase 'name' member of CHILD and all its siblings to
1146 the new PARENT. */
1147 static void
1148 rebase_child_list (struct name *child, struct name *parent)
1149 {
1150 size_t old_prefix_len = child->parent->length;
1151 size_t new_prefix_len = parent->length;
1152 char *new_prefix = parent->name;
1153
1154 for (; child; child = child->sibling)
1155 {
1156 size_t size = child->length - old_prefix_len + new_prefix_len;
1157 char *newp = xmalloc (size + 1);
1158 strcpy (newp, new_prefix);
1159 strcat (newp, child->name + old_prefix_len);
1160 free (child->name);
1161 child->name = newp;
1162 child->length = size;
1163
1164 rebase_directory (child->directory,
1165 child->parent->name, old_prefix_len,
1166 new_prefix, new_prefix_len);
1167 }
1168 }
1169
1170 /* Collect all the names from argv[] (or whatever), expand them into a
1171 directory tree, and sort them. This gets only subdirectories, not
1172 all files. */
1173
1174 void
1175 collect_and_sort_names (void)
1176 {
1177 struct name *name;
1178 struct name *next_name, *prev_name = NULL;
1179 int num_names;
1180 Hash_table *nametab;
1181
1182 name_gather ();
1183
1184 if (!namelist)
1185 addname (".", 0, false, NULL);
1186
1187 if (listed_incremental_option)
1188 {
1189 switch (chdir_count ())
1190 {
1191 case 0:
1192 break;
1193
1194 case 1:
1195 if (namelist->change_dir == 0)
1196 USAGE_ERROR ((0, 0,
1197 _("Using -C option inside file list is not "
1198 "allowed with --listed-incremental")));
1199 break;
1200
1201 default:
1202 USAGE_ERROR ((0, 0,
1203 _("Only one -C option is allowed with "
1204 "--listed-incremental")));
1205 }
1206
1207 read_directory_file ();
1208 }
1209
1210 num_names = 0;
1211 for (name = namelist; name; name = name->next, num_names++)
1212 {
1213 struct tar_stat_info st;
1214
1215 if (name->found_count || name->directory)
1216 continue;
1217 if (name->matching_flags & EXCLUDE_WILDCARDS)
1218 /* NOTE: EXCLUDE_ANCHORED is not relevant here */
1219 /* FIXME: just skip regexps for now */
1220 continue;
1221 chdir_do (name->change_dir);
1222
1223 if (name->name[0] == 0)
1224 continue;
1225
1226 tar_stat_init (&st);
1227
1228 if (deref_stat (name->name, &st.stat) != 0)
1229 {
1230 stat_diag (name->name);
1231 continue;
1232 }
1233 if (S_ISDIR (st.stat.st_mode))
1234 {
1235 int dir_fd = openat (chdir_fd, name->name,
1236 open_read_flags | O_DIRECTORY);
1237 if (dir_fd < 0)
1238 open_diag (name->name);
1239 else
1240 {
1241 st.fd = dir_fd;
1242 if (fstat (dir_fd, &st.stat) != 0)
1243 stat_diag (name->name);
1244 else if (O_DIRECTORY || S_ISDIR (st.stat.st_mode))
1245 {
1246 st.orig_file_name = xstrdup (name->name);
1247 name->found_count++;
1248 add_hierarchy_to_namelist (&st, name);
1249 }
1250 }
1251 }
1252
1253 tar_stat_destroy (&st);
1254 }
1255
1256 namelist = merge_sort (namelist, num_names, compare_names);
1257
1258 num_names = 0;
1259 nametab = hash_initialize (0, 0, name_hash, name_compare, NULL);
1260 for (name = namelist; name; name = next_name)
1261 {
1262 next_name = name->next;
1263 name->caname = normalize_filename (name->change_dir, name->name);
1264 if (prev_name)
1265 {
1266 struct name *p = hash_lookup (nametab, name);
1267 if (p)
1268 {
1269 /* Keep the one listed in the command line */
1270 if (!name->parent)
1271 {
1272 if (p->child)
1273 rebase_child_list (p->child, name);
1274 hash_delete (nametab, name);
1275 /* FIXME: remove_directory (p->caname); ? */
1276 remname (p);
1277 free_name (p);
1278 num_names--;
1279 }
1280 else
1281 {
1282 if (name->child)
1283 rebase_child_list (name->child, p);
1284 /* FIXME: remove_directory (name->caname); ? */
1285 remname (name);
1286 free_name (name);
1287 continue;
1288 }
1289 }
1290 }
1291 name->found_count = 0;
1292 if (!hash_insert (nametab, name))
1293 xalloc_die ();
1294 prev_name = name;
1295 num_names++;
1296 }
1297 nametail = prev_name;
1298 hash_free (nametab);
1299
1300 namelist = merge_sort (namelist, num_names, compare_names_found);
1301
1302 if (listed_incremental_option)
1303 {
1304 for (name = namelist; name && name->name[0] == 0; name++)
1305 ;
1306 if (name)
1307 append_incremental_renames (name->directory);
1308 }
1309 }
1310
1311 /* This is like name_match, except that
1312 1. It returns a pointer to the name it matched, and doesn't set FOUND
1313 in structure. The caller will have to do that if it wants to.
1314 2. If the namelist is empty, it returns null, unlike name_match, which
1315 returns TRUE. */
1316 struct name *
1317 name_scan (const char *file_name)
1318 {
1319 size_t length = strlen (file_name);
1320
1321 while (1)
1322 {
1323 struct name *cursor = namelist_match (file_name, length);
1324 if (cursor)
1325 return cursor;
1326
1327 /* Filename from archive not found in namelist. If we have the whole
1328 namelist here, just return 0. Otherwise, read the next name in and
1329 compare it. If this was the last name, namelist->found_count will
1330 remain on. If not, we loop to compare the newly read name. */
1331
1332 if (same_order_option && namelist && namelist->found_count)
1333 {
1334 name_gather (); /* read one more */
1335 if (namelist->found_count)
1336 return 0;
1337 }
1338 else
1339 return 0;
1340 }
1341 }
1342
1343 /* This returns a name from the namelist which doesn't have ->found
1344 set. It sets ->found before returning, so successive calls will
1345 find and return all the non-found names in the namelist. */
1346 struct name *gnu_list_name;
1347
1348 struct name const *
1349 name_from_list (void)
1350 {
1351 if (!gnu_list_name)
1352 gnu_list_name = namelist;
1353 while (gnu_list_name
1354 && (gnu_list_name->found_count || gnu_list_name->name[0] == 0))
1355 gnu_list_name = gnu_list_name->next;
1356 if (gnu_list_name)
1357 {
1358 gnu_list_name->found_count++;
1359 chdir_do (gnu_list_name->change_dir);
1360 return gnu_list_name;
1361 }
1362 return NULL;
1363 }
1364
1365 void
1366 blank_name_list (void)
1367 {
1368 struct name *name;
1369
1370 gnu_list_name = 0;
1371 for (name = namelist; name; name = name->next)
1372 name->found_count = 0;
1373 }
1374
1375 /* Yield a newly allocated file name consisting of FILE_NAME concatenated to
1376 NAME, with an intervening slash if FILE_NAME does not already end in one. */
1377 char *
1378 new_name (const char *file_name, const char *name)
1379 {
1380 size_t file_name_len = strlen (file_name);
1381 size_t namesize = strlen (name) + 1;
1382 int slash = file_name_len && ! ISSLASH (file_name[file_name_len - 1]);
1383 char *buffer = xmalloc (file_name_len + slash + namesize);
1384 memcpy (buffer, file_name, file_name_len);
1385 buffer[file_name_len] = '/';
1386 memcpy (buffer + file_name_len + slash, name, namesize);
1387 return buffer;
1388 }
1389
1390 \f
1391
1392 /* Return the size of the prefix of FILE_NAME that is removed after
1393 stripping NUM leading file name components. NUM must be
1394 positive. */
1395
1396 size_t
1397 stripped_prefix_len (char const *file_name, size_t num)
1398 {
1399 char const *p = file_name + FILE_SYSTEM_PREFIX_LEN (file_name);
1400 while (ISSLASH (*p))
1401 p++;
1402 while (*p)
1403 {
1404 bool slash = ISSLASH (*p);
1405 p++;
1406 if (slash)
1407 {
1408 if (--num == 0)
1409 return p - file_name;
1410 while (ISSLASH (*p))
1411 p++;
1412 }
1413 }
1414 return -1;
1415 }
1416 \f
1417 /* Return nonzero if NAME contains ".." as a file name component. */
1418 bool
1419 contains_dot_dot (char const *name)
1420 {
1421 char const *p = name + FILE_SYSTEM_PREFIX_LEN (name);
1422
1423 for (;; p++)
1424 {
1425 if (p[0] == '.' && p[1] == '.' && (ISSLASH (p[2]) || !p[2]))
1426 return 1;
1427
1428 while (! ISSLASH (*p))
1429 {
1430 if (! *p++)
1431 return 0;
1432 }
1433 }
1434 }
This page took 0.08225 seconds and 3 git commands to generate.