]> Dogcows Code - chaz/tar/blob - src/tar.c
*** empty log message ***
[chaz/tar] / src / tar.c
1 /* Tar -- a tape archiver.
2 Copyright (C) 1988, 1992 Free Software Foundation
3
4 This file is part of GNU Tar.
5
6 GNU Tar is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GNU Tar is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU Tar; see the file COPYING. If not, write to
18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
19
20 /*
21 * A tar (tape archiver) program.
22 *
23 * Written by John Gilmore, ihnp4!hoptoad!gnu, starting 25 Aug 85.
24 */
25
26 #include <stdio.h>
27 #include <sys/types.h> /* Needed for typedefs in tar.h */
28 #include "getopt.h"
29 #include "regex.h"
30 #include "fnmatch.h"
31
32 /*
33 * The following causes "tar.h" to produce definitions of all the
34 * global variables, rather than just "extern" declarations of them.
35 */
36 #define TAR_EXTERN /**/
37 #include "tar.h"
38
39 #include "port.h"
40
41 #if defined(_POSIX_VERSION) || defined(DIRENT)
42 #include <dirent.h>
43 #ifdef direct
44 #undef direct
45 #endif /* direct */
46 #define direct dirent
47 #define DP_NAMELEN(x) strlen((x)->d_name)
48 #endif /* _POSIX_VERSION or DIRENT */
49 #if !defined(_POSIX_VERSION) && !defined(DIRENT) && defined(BSD42)
50 #include <sys/dir.h>
51 #define DP_NAMELEN(x) (x)->d_namlen
52 #endif /* not _POSIX_VERSION and BSD42 */
53 #ifdef __MSDOS__
54 #include "msd_dir.h"
55 #define DP_NAMELEN(x) (x)->d_namlen
56 #define direct dirent
57 #endif
58 #if defined(USG) && !defined(_POSIX_VERSION) && !defined(DIRENT)
59 #include <ndir.h>
60 #define DP_NAMELEN(x) strlen((x)->d_name)
61 #endif /* USG and not _POSIX_VERSION and not DIRENT */
62
63 /*
64 * We should use a conversion routine that does reasonable error
65 * checking -- atoi doesn't. For now, punt. FIXME.
66 */
67 #define intconv atoi
68 PTR ck_malloc ();
69 PTR ck_realloc ();
70 extern int getoldopt ();
71 extern void read_and ();
72 extern void list_archive ();
73 extern void extract_archive ();
74 extern void diff_archive ();
75 extern void create_archive ();
76 extern void update_archive ();
77 extern void junk_archive ();
78
79 /* JF */
80 extern time_t get_date ();
81
82 time_t new_time;
83
84 static FILE *namef; /* File to read names from */
85 static char **n_argv; /* Argv used by name routines */
86 static int n_argc; /* Argc used by name routines */
87 static char **n_ind; /* Store an array of names */
88 static int n_indalloc; /* How big is the array? */
89 static int n_indused; /* How many entries does it have? */
90 static int n_indscan; /* How many of the entries have we scanned? */
91
92
93 extern FILE *msg_file;
94
95 int check_exclude ();
96 void add_exclude ();
97 void add_exclude_file ();
98 void addname ();
99 void describe ();
100 void diff_init ();
101 void extr_init ();
102 int is_regex ();
103 void name_add ();
104 void name_init ();
105 void options ();
106 char *un_quote_string ();
107
108 #ifndef S_ISLNK
109 #define lstat stat
110 #endif
111
112 #ifndef DEFBLOCKING
113 #define DEFBLOCKING 20
114 #endif
115
116 #ifndef DEF_AR_FILE
117 #define DEF_AR_FILE "tar.out"
118 #endif
119
120 /* For long options that unconditionally set a single flag, we have getopt
121 do it. For the others, we share the code for the equivalent short
122 named option, the name of which is stored in the otherwise-unused `val'
123 field of the `struct option'; for long options that have no equivalent
124 short option, we use nongraphic characters as pseudo short option
125 characters, starting (for no particular reason) with character 10. */
126
127 struct option long_options[] =
128 {
129 {"create", 0, 0, 'c'},
130 {"append", 0, 0, 'r'},
131 {"extract", 0, 0, 'x'},
132 {"get", 0, 0, 'x'},
133 {"list", 0, 0, 't'},
134 {"update", 0, 0, 'u'},
135 {"catenate", 0, 0, 'A'},
136 {"concatenate", 0, 0, 'A'},
137 {"compare", 0, 0, 'd'},
138 {"diff", 0, 0, 'd'},
139 {"delete", 0, 0, 14},
140 {"help", 0, 0, 12},
141
142 {"null", 0, 0, 16},
143 {"directory", 1, 0, 'C'},
144 {"record-number", 0, &f_sayblock, 1},
145 {"files-from", 1, 0, 'T'},
146 {"label", 1, 0, 'V'},
147 {"exclude-from", 1, 0, 'X'},
148 {"exclude", 1, 0, 15},
149 {"file", 1, 0, 'f'},
150 {"block-size", 1, 0, 'b'},
151 {"version", 0, 0, 11},
152 {"verbose", 0, 0, 'v'},
153 {"totals", 0, &f_totals, 1},
154
155 {"read-full-blocks", 0, &f_reblock, 1},
156 {"starting-file", 1, 0, 'K'},
157 {"to-stdout", 0, &f_exstdout, 1},
158 {"ignore-zeros", 0, &f_ignorez, 1},
159 {"keep-old-files", 0, 0, 'k'},
160 {"uncompress", 0, &f_compress, 1},
161 {"same-permissions", 0, &f_use_protection, 1},
162 {"preserve-permissions", 0, &f_use_protection, 1},
163 {"modification-time", 0, &f_modified, 1},
164 {"preserve", 0, 0, 10},
165 {"same-order", 0, &f_sorted_names, 1},
166 {"same-owner", 0, &f_do_chown, 1},
167 {"preserve-order", 0, &f_sorted_names, 1},
168
169 {"newer", 1, 0, 'N'},
170 {"after-date", 1, 0, 'N'},
171 {"newer-mtime", 1, 0, 13},
172 {"incremental", 0, 0, 'G'},
173 {"listed-incremental", 1, 0, 'g'},
174 {"multi-volume", 0, &f_multivol, 1},
175 {"info-script", 1, 0, 'F'},
176 {"absolute-paths", 0, &f_absolute_paths, 1},
177 {"interactive", 0, &f_confirm, 1},
178 {"confirmation", 0, &f_confirm, 1},
179
180 {"verify", 0, &f_verify, 1},
181 {"dereference", 0, &f_follow_links, 1},
182 {"one-file-system", 0, &f_local_filesys, 1},
183 {"old-archive", 0, 0, 'o'},
184 {"portability", 0, 0, 'o'},
185 {"compress", 0, &f_compress, 1},
186 {"compress-block", 0, &f_compress, 2},
187 {"sparse", 0, &f_sparse_files, 1},
188 {"tape-length", 1, 0, 'L'},
189 {"remove-files", 0, &f_remove_files, 1},
190 {"ignore-failed-read", 0, &f_ignore_failed_read, 1},
191 {"checkpoint", 0, &f_checkpoint, 1},
192 {"show-omitted-dirs", 0, &f_show_omitted_dirs, 1},
193 {"volno-file", 1, 0, 17},
194 {"force-local", 0, &f_force_local, 1},
195 {"atime-preserve", 0, &f_atime_preserve, 1},
196
197 {0, 0, 0, 0}
198 };
199
200 /*
201 * Main routine for tar.
202 */
203 void
204 main (argc, argv)
205 int argc;
206 char **argv;
207 {
208 extern char version_string[];
209
210 tar = argv[0]; /* JF: was "tar" Set program name */
211 filename_terminator = '\n';
212 errors = 0;
213
214 options (argc, argv);
215
216 if (!n_argv)
217 name_init (argc, argv);
218
219 if (f_volno_file)
220 init_volume_number ();
221
222 switch (cmd_mode)
223 {
224 case CMD_CAT:
225 case CMD_UPDATE:
226 case CMD_APPEND:
227 update_archive ();
228 break;
229 case CMD_DELETE:
230 junk_archive ();
231 break;
232 case CMD_CREATE:
233 create_archive ();
234 if (f_totals)
235 fprintf (stderr, "Total bytes written: %d\n", tot_written);
236 break;
237 case CMD_EXTRACT:
238 if (f_volhdr)
239 {
240 const char *err;
241 label_pattern = (struct re_pattern_buffer *)
242 ck_malloc (sizeof *label_pattern);
243 err = re_compile_pattern (f_volhdr, strlen (f_volhdr),
244 label_pattern);
245 if (err)
246 {
247 fprintf (stderr, "Bad regular expression: %s\n",
248 err);
249 errors++;
250 break;
251 }
252
253 }
254 extr_init ();
255 read_and (extract_archive);
256 break;
257 case CMD_LIST:
258 if (f_volhdr)
259 {
260 const char *err;
261 label_pattern = (struct re_pattern_buffer *)
262 ck_malloc (sizeof *label_pattern);
263 err = re_compile_pattern (f_volhdr, strlen (f_volhdr),
264 label_pattern);
265 if (err)
266 {
267 fprintf (stderr, "Bad regular expression: %s\n",
268 err);
269 errors++;
270 break;
271 }
272 }
273 read_and (list_archive);
274 #if 0
275 if (!errors)
276 errors = different;
277 #endif
278 break;
279 case CMD_DIFF:
280 diff_init ();
281 read_and (diff_archive);
282 break;
283 case CMD_VERSION:
284 fprintf (stderr, "%s\n", version_string);
285 break;
286 case CMD_NONE:
287 msg ("you must specify exactly one of the r, c, t, x, or d options\n");
288 fprintf (stderr, "For more information, type ``%s --help''.\n", tar);
289 exit (EX_ARGSBAD);
290 }
291 if (f_volno_file)
292 closeout_volume_number ();
293 exit (errors);
294 /* NOTREACHED */
295 }
296
297
298 /*
299 * Parse the options for tar.
300 */
301 void
302 options (argc, argv)
303 int argc;
304 char **argv;
305 {
306 register int c; /* Option letter */
307 int ind = -1;
308
309 /* Set default option values */
310 blocking = DEFBLOCKING; /* From Makefile */
311 ar_files = (char **) malloc (sizeof (char *) * 10);
312 ar_files_len = 10;
313 n_ar_files = 0;
314 cur_ar_file = 0;
315
316 /* Parse options */
317 while ((c = getoldopt (argc, argv,
318 "-01234567Ab:BcC:df:F:g:GhikK:lL:mMN:oOpPrRsStT:uvV:wWxX:zZ",
319 long_options, &ind)) != EOF)
320 {
321 switch (c)
322 {
323 case 0: /* long options that set a single flag */
324 break;
325 case 1:
326 /* File name or non-parsed option */
327 name_add (optarg);
328 break;
329 case 'C':
330 name_add ("-C");
331 name_add (optarg);
332 break;
333 case 10: /* preserve */
334 f_use_protection = f_sorted_names = 1;
335 break;
336 case 11:
337 if (cmd_mode != CMD_NONE)
338 goto badopt;
339 cmd_mode = CMD_VERSION;
340 break;
341 case 12: /* help */
342 printf ("This is GNU tar, the tape archiving program.\n");
343 describe ();
344 exit (1);
345 case 13:
346 f_new_files++;
347 goto get_newer;
348
349 case 14: /* Delete in the archive */
350 if (cmd_mode != CMD_NONE)
351 goto badopt;
352 cmd_mode = CMD_DELETE;
353 break;
354
355 case 15:
356 f_exclude++;
357 add_exclude (optarg);
358 break;
359
360 case 16: /* -T reads null terminated filenames. */
361 filename_terminator = '\0';
362 break;
363
364 case 17:
365 f_volno_file = optarg;
366 break;
367
368 case 'g': /* We are making a GNU dump; save
369 directories at the beginning of
370 the archive, and include in each
371 directory its contents */
372 if (f_oldarch)
373 goto badopt;
374 f_gnudump++;
375 gnu_dumpfile = optarg;
376 break;
377
378
379 case '0':
380 case '1':
381 case '2':
382 case '3':
383 case '4':
384 case '5':
385 case '6':
386 case '7':
387 {
388 /* JF this'll have to be modified for other
389 systems, of course! */
390 int d, add;
391 static char buf[50];
392
393 d = getoldopt (argc, argv, "lmh");
394 #ifdef MAYBEDEF
395 sprintf (buf, "/dev/rmt/%d%c", c, d);
396 #else
397 #ifndef LOW_NUM
398 #define LOW_NUM 0
399 #define MID_NUM 8
400 #define HGH_NUM 16
401 #endif
402 if (d == 'l')
403 add = LOW_NUM;
404 else if (d == 'm')
405 add = MID_NUM;
406 else if (d == 'h')
407 add = HGH_NUM;
408 else
409 goto badopt;
410
411 sprintf (buf, "/dev/rmt%d", add + c - '0');
412 #endif
413 if (n_ar_files == ar_files_len)
414 ar_files
415 = (char **)
416 ck_malloc (sizeof (char *)
417 * (ar_files_len *= 2));
418 ar_files[n_ar_files++] = buf;
419 }
420 break;
421
422 case 'A': /* Arguments are tar files,
423 just cat them onto the end
424 of the archive. */
425 if (cmd_mode != CMD_NONE)
426 goto badopt;
427 cmd_mode = CMD_CAT;
428 break;
429
430 case 'b': /* Set blocking factor */
431 blocking = intconv (optarg);
432 break;
433
434 case 'B': /* Try to reblock input */
435 f_reblock++; /* For reading 4.2BSD pipes */
436 break;
437
438 case 'c': /* Create an archive */
439 if (cmd_mode != CMD_NONE)
440 goto badopt;
441 cmd_mode = CMD_CREATE;
442 break;
443
444 #if 0
445 case 'C':
446 if (chdir (optarg) < 0)
447 msg_perror ("Can't change directory to %d", optarg);
448 break;
449 #endif
450
451 case 'd': /* Find difference tape/disk */
452 if (cmd_mode != CMD_NONE)
453 goto badopt;
454 cmd_mode = CMD_DIFF;
455 break;
456
457 case 'f': /* Use ar_file for the archive */
458 if (n_ar_files == ar_files_len)
459 ar_files
460 = (char **) ck_malloc (sizeof (char *)
461 * (ar_files_len *= 2));
462
463 ar_files[n_ar_files++] = optarg;
464 break;
465
466 case 'F':
467 /* Since -F is only useful with -M , make it implied */
468 f_run_script_at_end++;/* run this script at the end */
469 info_script = optarg; /* of each tape */
470 f_multivol++;
471 break;
472
473 case 'G': /* We are making a GNU dump; save
474 directories at the beginning of
475 the archive, and include in each
476 directory its contents */
477 if (f_oldarch)
478 goto badopt;
479 f_gnudump++;
480 gnu_dumpfile = 0;
481 break;
482
483 case 'h':
484 f_follow_links++; /* follow symbolic links */
485 break;
486
487 case 'i':
488 f_ignorez++; /* Ignore zero records (eofs) */
489 /*
490 * This can't be the default, because Unix tar
491 * writes two records of zeros, then pads out the
492 * block with garbage.
493 */
494 break;
495
496 case 'k': /* Don't overwrite files */
497 #ifdef NO_OPEN3
498 msg ("can't keep old files on this system");
499 exit (EX_ARGSBAD);
500 #else
501 f_keep++;
502 #endif
503 break;
504
505 case 'K':
506 f_startfile++;
507 addname (optarg);
508 break;
509
510 case 'l': /* When dumping directories, don't
511 dump files/subdirectories that are
512 on other filesystems. */
513 f_local_filesys++;
514 break;
515
516 case 'L':
517 tape_length = intconv (optarg);
518 f_multivol++;
519 break;
520 case 'm':
521 f_modified++;
522 break;
523
524 case 'M': /* Make Multivolume archive:
525 When we can't write any more
526 into the archive, re-open it,
527 and continue writing */
528 f_multivol++;
529 break;
530
531 case 'N': /* Only write files newer than X */
532 get_newer:
533 f_new_files++;
534 new_time = get_date (optarg, (PTR) 0);
535 if (new_time == (time_t) - 1)
536 {
537 msg ("invalid date format `%s'", optarg);
538 exit (EX_ARGSBAD);
539 }
540 break;
541
542 case 'o': /* Generate old archive */
543 if (f_gnudump /* || f_dironly */ )
544 goto badopt;
545 f_oldarch++;
546 break;
547
548 case 'O':
549 f_exstdout++;
550 break;
551
552 case 'p':
553 f_use_protection++;
554 break;
555
556 case 'P':
557 f_absolute_paths++;
558 break;
559
560 case 'r': /* Append files to the archive */
561 if (cmd_mode != CMD_NONE)
562 goto badopt;
563 cmd_mode = CMD_APPEND;
564 break;
565
566 case 'R':
567 f_sayblock++; /* Print block #s for debug */
568 break; /* of bad tar archives */
569
570 case 's':
571 f_sorted_names++; /* Names to extr are sorted */
572 break;
573
574 case 'S': /* deal with sparse files */
575 f_sparse_files++;
576 break;
577 case 't':
578 if (cmd_mode != CMD_NONE)
579 goto badopt;
580 cmd_mode = CMD_LIST;
581 f_verbose++; /* "t" output == "cv" or "xv" */
582 break;
583
584 case 'T':
585 name_file = optarg;
586 f_namefile++;
587 break;
588
589 case 'u': /* Append files to the archive that
590 aren't there, or are newer than the
591 copy in the archive */
592 if (cmd_mode != CMD_NONE)
593 goto badopt;
594 cmd_mode = CMD_UPDATE;
595 break;
596
597 case 'v':
598 f_verbose++;
599 break;
600
601 case 'V':
602 f_volhdr = optarg;
603 break;
604
605 case 'w':
606 f_confirm++;
607 break;
608
609 case 'W':
610 f_verify++;
611 break;
612
613 case 'x': /* Extract files from the archive */
614 if (cmd_mode != CMD_NONE)
615 goto badopt;
616 cmd_mode = CMD_EXTRACT;
617 break;
618
619 case 'X':
620 f_exclude++;
621 add_exclude_file (optarg);
622 break;
623
624 case 'z': /* Easy to type */
625 case 'Z': /* Like the filename extension .Z */
626 f_compress++;
627 break;
628
629 case '?':
630 badopt:
631 msg ("Unknown option. Use '%s --help' for a complete list of options.", tar);
632 exit (EX_ARGSBAD);
633
634 }
635 }
636
637 blocksize = blocking * RECORDSIZE;
638 if (n_ar_files == 0)
639 {
640 n_ar_files = 1;
641 ar_files[0] = getenv ("TAPE"); /* From environment, or */
642 if (ar_files[0] == 0)
643 ar_files[0] = DEF_AR_FILE; /* From Makefile */
644 }
645 if (n_ar_files > 1 && !f_multivol)
646 {
647 msg ("Multiple archive files requires --multi-volume\n");
648 exit (EX_ARGSBAD);
649 }
650 }
651
652
653 /*
654 * Print as much help as the user's gonna get.
655 *
656 * We have to sprinkle in the KLUDGE lines because too many compilers
657 * cannot handle character strings longer than about 512 bytes. Yuk!
658 * In particular, MS-DOS and Xenix MSC and PDP-11 V7 Unix have this
659 * problem.
660 */
661 void
662 describe ()
663 {
664 puts ("choose one of the following:");
665 fputs ("\
666 -A, --catenate,\n\
667 --concatenate append tar files to an archive\n\
668 -c, --create create a new archive\n\
669 -d, --diff,\n\
670 --compare find differences between archive and file system\n\
671 --delete delete from the archive (not for use on mag tapes!)\n\
672 -r, --append append files to the end of an archive\n\
673 -t, --list list the contents of an archive\n\
674 -u, --update only append files that are newer than copy in archive\n\
675 -x, --extract,\n\
676 --get extract files from an archive\n", stdout);
677
678 fprintf (stdout, "\
679 Other options:\n\
680 --atime-preserve don't change access times on dumped files\n\
681 -b, --block-size N block size of Nx512 bytes (default N=%d)\n", DEFBLOCKING);
682 fputs ("\
683 -B, --read-full-blocks reblock as we read (for reading 4.2BSD pipes)\n\
684 -C, --directory DIR change to directory DIR\n\
685 --checkpoint print directory names while reading the archive\n\
686 ", stdout); /* KLUDGE */
687 fprintf (stdout, "\
688 -f, --file [HOSTNAME:]F use archive file or device F (default %s)\n",
689 DEF_AR_FILE);
690 fputs ("\
691 --force-local archive file is local even if has a colon\n\
692 -F, --info-script F run script at end of each tape (implies -M)\n\
693 -G, --incremental create/list/extract old GNU-format incremental backup\n\
694 -g, --listed-incremental F create/list/extract new GNU-format incremental backup\n\
695 -h, --dereference don't dump symlinks; dump the files they point to\n\
696 -i, --ignore-zeros ignore blocks of zeros in archive (normally mean EOF)\n\
697 --ignore-failed-read don't exit with non-zero status on unreadable files\n\
698 -k, --keep-old-files keep existing files; don't overwrite them from archive\n\
699 -K, --starting-file FILE begin at FILE in the archive\n\
700 -l, --one-file-system stay in local file system when creating an archive\n\
701 -L, --tape-length LENGTH change tapes after writing LENGTH\n\
702 ", stdout); /* KLUDGE */
703 fputs ("\
704 -m, --modification-time don't extract file modified time\n\
705 -M, --multi-volume create/list/extract multi-volume archive\n\
706 -N, --after-date DATE,\n\
707 --newer DATE only store files newer than DATE\n\
708 -o, --old-archive,\n\
709 --portability write a V7 format archive, rather than ANSI format\n\
710 -O, --to-stdout extract files to standard output\n\
711 -p, --same-permissions,\n\
712 --preserve-permissions extract all protection information\n\
713 -P, --absolute-paths don't strip leading `/'s from file names\n\
714 --preserve like -p -s\n\
715 ", stdout); /* KLUDGE */
716 fputs ("\
717 -R, --record-number show record number within archive with each message\n\
718 --remove-files remove files after adding them to the archive\n\
719 -s, --same-order,\n\
720 --preserve-order list of names to extract is sorted to match archive\n\
721 --same-owner create extracted files with the same ownership \n\
722 -S, --sparse handle sparse files efficiently\n\
723 -T, --files-from F get names to extract or create from file F\n\
724 --null -T reads null-terminated names, disable -C\n\
725 --totals print total bytes written with --create\n\
726 -v, --verbose verbosely list files processed\n\
727 -V, --label NAME create archive with volume name NAME\n\
728 --version print tar program version number\n\
729 -w, --interactive,\n\
730 --confirmation ask for confirmation for every action\n\
731 ", stdout); /* KLUDGE */
732 fputs ("\
733 -W, --verify attempt to verify the archive after writing it\n\
734 --exclude FILE exclude file FILE\n\
735 -X, --exclude-from FILE exclude files listed in FILE\n\
736 -z, -Z, --compress,\n\
737 --uncompress filter the archive through compress\n\
738 -[0-7][lmh] specify drive and density\n\
739 ", stdout);
740 }
741
742 void
743 name_add (name)
744 char *name;
745 {
746 if (n_indalloc == n_indused)
747 {
748 n_indalloc += 10;
749 n_ind = (char **) (n_indused ? ck_realloc (n_ind, n_indalloc * sizeof (char *)): ck_malloc (n_indalloc * sizeof (char *)));
750 }
751 n_ind[n_indused++] = name;
752 }
753
754 /*
755 * Set up to gather file names for tar.
756 *
757 * They can either come from stdin or from argv.
758 */
759 void
760 name_init (argc, argv)
761 int argc;
762 char **argv;
763 {
764
765 if (f_namefile)
766 {
767 if (optind < argc)
768 {
769 msg ("too many args with -T option");
770 exit (EX_ARGSBAD);
771 }
772 if (!strcmp (name_file, "-"))
773 {
774 namef = stdin;
775 }
776 else
777 {
778 namef = fopen (name_file, "r");
779 if (namef == NULL)
780 {
781 msg_perror ("can't open file %s", name_file);
782 exit (EX_BADFILE);
783 }
784 }
785 }
786 else
787 {
788 /* Get file names from argv, after options. */
789 n_argc = argc;
790 n_argv = argv;
791 }
792 }
793
794 /* Read the next filename read from STREAM and null-terminate it.
795 Put it into BUFFER, reallocating and adjusting *PBUFFER_SIZE if necessary.
796 Return the new value for BUFFER, or NULL at end of file. */
797
798 char *
799 read_name_from_file (buffer, pbuffer_size, stream)
800 char *buffer;
801 size_t *pbuffer_size;
802 FILE *stream;
803 {
804 register int c;
805 register int indx = 0;
806 register size_t buffer_size = *pbuffer_size;
807
808 while ((c = getc (stream)) != EOF && c != filename_terminator)
809 {
810 if (indx == buffer_size)
811 {
812 buffer_size += NAMSIZ;
813 buffer = ck_realloc (buffer, buffer_size + 2);
814 }
815 buffer[indx++] = c;
816 }
817 if (indx == 0 && c == EOF)
818 return NULL;
819 if (indx == buffer_size)
820 {
821 buffer_size += NAMSIZ;
822 buffer = ck_realloc (buffer, buffer_size + 2);
823 }
824 buffer[indx] = '\0';
825 *pbuffer_size = buffer_size;
826 return buffer;
827 }
828
829 /*
830 * Get the next name from argv or the name file.
831 *
832 * Result is in static storage and can't be relied upon across two calls.
833 *
834 * If CHANGE_DIRS is non-zero, treat a filename of the form "-C" as
835 * meaning that the next filename is the name of a directory to change to.
836 * If `filename_terminator' is '\0', CHANGE_DIRS is effectively always 0.
837 */
838
839 char *
840 name_next (change_dirs)
841 int change_dirs;
842 {
843 static char *buffer; /* Holding pattern */
844 static int buffer_siz;
845 register char *p;
846 register char *q = 0;
847 register int next_name_is_dir = 0;
848 extern char *un_quote_string ();
849
850 if (buffer_siz == 0)
851 {
852 buffer = ck_malloc (NAMSIZ + 2);
853 buffer_siz = NAMSIZ;
854 }
855 if (filename_terminator == '\0')
856 change_dirs = 0;
857 tryagain:
858 if (namef == NULL)
859 {
860 if (n_indscan < n_indused)
861 p = n_ind[n_indscan++];
862 else if (optind < n_argc)
863 /* Names come from argv, after options */
864 p = n_argv[optind++];
865 else
866 {
867 if (q)
868 msg ("Missing filename after -C");
869 return NULL;
870 }
871
872 /* JF trivial support for -C option. I don't know if
873 chdir'ing at this point is dangerous or not.
874 It seems to work, which is all I ask. */
875 if (change_dirs && !q && p[0] == '-' && p[1] == 'C' && p[2] == '\0')
876 {
877 q = p;
878 goto tryagain;
879 }
880 if (q)
881 {
882 if (chdir (p) < 0)
883 msg_perror ("Can't chdir to %s", p);
884 q = 0;
885 goto tryagain;
886 }
887 /* End of JF quick -C hack */
888
889 if (f_exclude && check_exclude (p))
890 goto tryagain;
891 return un_quote_string (p);
892 }
893 while (p = read_name_from_file (buffer, &buffer_siz, namef))
894 {
895 buffer = p;
896 if (*p == '\0')
897 continue; /* Ignore empty lines. */
898 q = p + strlen (p) - 1;
899 while (q > p && *q == '/')/* Zap trailing "/"s. */
900 *q-- = '\0';
901 if (change_dirs && next_name_is_dir == 0
902 && p[0] == '-' && p[1] == 'C' && p[2] == '\0')
903 {
904 next_name_is_dir = 1;
905 goto tryagain;
906 }
907 if (next_name_is_dir)
908 {
909 if (chdir (p) < 0)
910 msg_perror ("Can't change to directory %s", p);
911 next_name_is_dir = 0;
912 goto tryagain;
913 }
914 if (f_exclude && check_exclude (p))
915 goto tryagain;
916 return un_quote_string (p);
917 }
918 return NULL;
919 }
920
921
922 /*
923 * Close the name file, if any.
924 */
925 void
926 name_close ()
927 {
928
929 if (namef != NULL && namef != stdin)
930 fclose (namef);
931 }
932
933
934 /*
935 * Gather names in a list for scanning.
936 * Could hash them later if we really care.
937 *
938 * If the names are already sorted to match the archive, we just
939 * read them one by one. name_gather reads the first one, and it
940 * is called by name_match as appropriate to read the next ones.
941 * At EOF, the last name read is just left in the buffer.
942 * This option lets users of small machines extract an arbitrary
943 * number of files by doing "tar t" and editing down the list of files.
944 */
945 void
946 name_gather ()
947 {
948 register char *p;
949 static struct name *namebuf; /* One-name buffer */
950 static namelen;
951 static char *chdir_name;
952
953 if (f_sorted_names)
954 {
955 if (!namelen)
956 {
957 namelen = NAMSIZ;
958 namebuf = (struct name *) ck_malloc (sizeof (struct name) + NAMSIZ);
959 }
960 p = name_next (0);
961 if (p)
962 {
963 if (*p == '-' && p[1] == 'C' && p[2] == '\0')
964 {
965 chdir_name = name_next (0);
966 p = name_next (0);
967 if (!p)
968 {
969 msg ("Missing file name after -C");
970 exit (EX_ARGSBAD);
971 }
972 namebuf->change_dir = chdir_name;
973 }
974 namebuf->length = strlen (p);
975 if (namebuf->length >= namelen)
976 {
977 namebuf = (struct name *) ck_realloc (namebuf, sizeof (struct name) + namebuf->length);
978 namelen = namebuf->length;
979 }
980 strncpy (namebuf->name, p, namebuf->length);
981 namebuf->name[namebuf->length] = 0;
982 namebuf->next = (struct name *) NULL;
983 namebuf->found = 0;
984 namelist = namebuf;
985 namelast = namelist;
986 }
987 return;
988 }
989
990 /* Non sorted names -- read them all in */
991 while (p = name_next (0))
992 addname (p);
993 }
994
995 /*
996 * Add a name to the namelist.
997 */
998 void
999 addname (name)
1000 char *name; /* pointer to name */
1001 {
1002 register int i; /* Length of string */
1003 register struct name *p; /* Current struct pointer */
1004 static char *chdir_name;
1005 char *new_name ();
1006
1007 if (name[0] == '-' && name[1] == 'C' && name[2] == '\0')
1008 {
1009 chdir_name = name_next (0);
1010 name = name_next (0);
1011 if (!chdir_name)
1012 {
1013 msg ("Missing file name after -C");
1014 exit (EX_ARGSBAD);
1015 }
1016 if (chdir_name[0] != '/')
1017 {
1018 char *path = ck_malloc (PATH_MAX);
1019 #if defined(__MSDOS__) || defined(USG) || defined(_POSIX_VERSION)
1020 if (!getcwd (path, PATH_MAX))
1021 {
1022 msg ("Couldn't get current directory.");
1023 exit (EX_SYSTEM);
1024 }
1025 #else
1026 char *getwd ();
1027
1028 if (!getwd (path))
1029 {
1030 msg ("Couldn't get current directory: %s", path);
1031 exit (EX_SYSTEM);
1032 }
1033 #endif
1034 chdir_name = new_name (path, chdir_name);
1035 free (path);
1036 }
1037 }
1038
1039 if (name)
1040 {
1041 i = strlen (name);
1042 /*NOSTRICT*/
1043 p = (struct name *) malloc ((unsigned) (sizeof (struct name) + i));
1044 }
1045 else
1046 p = (struct name *) malloc ((unsigned) (sizeof (struct name)));
1047 if (!p)
1048 {
1049 if (name)
1050 msg ("cannot allocate mem for name '%s'.", name);
1051 else
1052 msg ("cannot allocate mem for chdir record.");
1053 exit (EX_SYSTEM);
1054 }
1055 p->next = (struct name *) NULL;
1056 if (name)
1057 {
1058 p->fake = 0;
1059 p->length = i;
1060 strncpy (p->name, name, i);
1061 p->name[i] = '\0'; /* Null term */
1062 }
1063 else
1064 p->fake = 1;
1065 p->found = 0;
1066 p->regexp = 0; /* Assume not a regular expression */
1067 p->firstch = 1; /* Assume first char is literal */
1068 p->change_dir = chdir_name;
1069 p->dir_contents = 0; /* JF */
1070 if (name)
1071 {
1072 if (index (name, '*') || index (name, '[') || index (name, '?'))
1073 {
1074 p->regexp = 1; /* No, it's a regexp */
1075 if (name[0] == '*' || name[0] == '[' || name[0] == '?')
1076 p->firstch = 0; /* Not even 1st char literal */
1077 }
1078 }
1079
1080 if (namelast)
1081 namelast->next = p;
1082 namelast = p;
1083 if (!namelist)
1084 namelist = p;
1085 }
1086
1087 /*
1088 * Return nonzero if name P (from an archive) matches any name from
1089 * the namelist, zero if not.
1090 */
1091 int
1092 name_match (p)
1093 register char *p;
1094 {
1095 register struct name *nlp;
1096 register int len;
1097
1098 again:
1099 if (0 == (nlp = namelist)) /* Empty namelist is easy */
1100 return 1;
1101 if (nlp->fake)
1102 {
1103 if (nlp->change_dir && chdir (nlp->change_dir))
1104 msg_perror ("Can't change to directory %d", nlp->change_dir);
1105 namelist = 0;
1106 return 1;
1107 }
1108 len = strlen (p);
1109 for (; nlp != 0; nlp = nlp->next)
1110 {
1111 /* If first chars don't match, quick skip */
1112 if (nlp->firstch && nlp->name[0] != p[0])
1113 continue;
1114
1115 /* Regular expressions (shell globbing, actually). */
1116 if (nlp->regexp)
1117 {
1118 if (fnmatch (nlp->name, p, FNM_TARPATH) == 0)
1119 {
1120 nlp->found = 1; /* Remember it matched */
1121 if (f_startfile)
1122 {
1123 free ((void *) namelist);
1124 namelist = 0;
1125 }
1126 if (nlp->change_dir && chdir (nlp->change_dir))
1127 msg_perror ("Can't change to directory %s", nlp->change_dir);
1128 return 1; /* We got a match */
1129 }
1130 continue;
1131 }
1132
1133 /* Plain Old Strings */
1134 if (nlp->length <= len /* Archive len >= specified */
1135 && (p[nlp->length] == '\0' || p[nlp->length] == '/')
1136 /* Full match on file/dirname */
1137 && strncmp (p, nlp->name, nlp->length) == 0) /* Name compare */
1138 {
1139 nlp->found = 1; /* Remember it matched */
1140 if (f_startfile)
1141 {
1142 free ((void *) namelist);
1143 namelist = 0;
1144 }
1145 if (nlp->change_dir && chdir (nlp->change_dir))
1146 msg_perror ("Can't change to directory %s", nlp->change_dir);
1147 return 1; /* We got a match */
1148 }
1149 }
1150
1151 /*
1152 * Filename from archive not found in namelist.
1153 * If we have the whole namelist here, just return 0.
1154 * Otherwise, read the next name in and compare it.
1155 * If this was the last name, namelist->found will remain on.
1156 * If not, we loop to compare the newly read name.
1157 */
1158 if (f_sorted_names && namelist->found)
1159 {
1160 name_gather (); /* Read one more */
1161 if (!namelist->found)
1162 goto again;
1163 }
1164 return 0;
1165 }
1166
1167
1168 /*
1169 * Print the names of things in the namelist that were not matched.
1170 */
1171 void
1172 names_notfound ()
1173 {
1174 register struct name *nlp, *next;
1175 register char *p;
1176
1177 for (nlp = namelist; nlp != 0; nlp = next)
1178 {
1179 next = nlp->next;
1180 if (!nlp->found)
1181 msg ("%s not found in archive", nlp->name);
1182
1183 /*
1184 * We could free() the list, but the process is about
1185 * to die anyway, so save some CPU time. Amigas and
1186 * other similarly broken software will need to waste
1187 * the time, though.
1188 */
1189 #ifdef amiga
1190 if (!f_sorted_names)
1191 free (nlp);
1192 #endif
1193 }
1194 namelist = (struct name *) NULL;
1195 namelast = (struct name *) NULL;
1196
1197 if (f_sorted_names)
1198 {
1199 while (0 != (p = name_next (1)))
1200 msg ("%s not found in archive", p);
1201 }
1202 }
1203
1204 /* These next routines were created by JF */
1205
1206 void
1207 name_expand ()
1208 {
1209 ;
1210 }
1211
1212 /* This is like name_match(), except that it returns a pointer to the name
1213 it matched, and doesn't set ->found The caller will have to do that
1214 if it wants to. Oh, and if the namelist is empty, it returns 0, unlike
1215 name_match(), which returns TRUE */
1216
1217 struct name *
1218 name_scan (p)
1219 register char *p;
1220 {
1221 register struct name *nlp;
1222 register int len;
1223
1224 again:
1225 if (0 == (nlp = namelist)) /* Empty namelist is easy */
1226 return 0;
1227 len = strlen (p);
1228 for (; nlp != 0; nlp = nlp->next)
1229 {
1230 /* If first chars don't match, quick skip */
1231 if (nlp->firstch && nlp->name[0] != p[0])
1232 continue;
1233
1234 /* Regular expressions */
1235 if (nlp->regexp)
1236 {
1237 if (fnmatch (nlp->name, p, FNM_TARPATH) == 0)
1238 return nlp; /* We got a match */
1239 continue;
1240 }
1241
1242 /* Plain Old Strings */
1243 if (nlp->length <= len /* Archive len >= specified */
1244 && (p[nlp->length] == '\0' || p[nlp->length] == '/')
1245 /* Full match on file/dirname */
1246 && strncmp (p, nlp->name, nlp->length) == 0) /* Name compare */
1247 return nlp; /* We got a match */
1248 }
1249
1250 /*
1251 * Filename from archive not found in namelist.
1252 * If we have the whole namelist here, just return 0.
1253 * Otherwise, read the next name in and compare it.
1254 * If this was the last name, namelist->found will remain on.
1255 * If not, we loop to compare the newly read name.
1256 */
1257 if (f_sorted_names && namelist->found)
1258 {
1259 name_gather (); /* Read one more */
1260 if (!namelist->found)
1261 goto again;
1262 }
1263 return (struct name *) 0;
1264 }
1265
1266 /* This returns a name from the namelist which doesn't have ->found set.
1267 It sets ->found before returning, so successive calls will find and return
1268 all the non-found names in the namelist */
1269
1270 struct name *gnu_list_name;
1271
1272 char *
1273 name_from_list ()
1274 {
1275 if (!gnu_list_name)
1276 gnu_list_name = namelist;
1277 while (gnu_list_name && gnu_list_name->found)
1278 gnu_list_name = gnu_list_name->next;
1279 if (gnu_list_name)
1280 {
1281 gnu_list_name->found++;
1282 if (gnu_list_name->change_dir)
1283 if (chdir (gnu_list_name->change_dir) < 0)
1284 msg_perror ("can't chdir to %s", gnu_list_name->change_dir);
1285 return gnu_list_name->name;
1286 }
1287 return (char *) 0;
1288 }
1289
1290 void
1291 blank_name_list ()
1292 {
1293 struct name *n;
1294
1295 gnu_list_name = 0;
1296 for (n = namelist; n; n = n->next)
1297 n->found = 0;
1298 }
1299
1300 char *
1301 new_name (path, name)
1302 char *path, *name;
1303 {
1304 char *path_buf;
1305
1306 path_buf = (char *) malloc (strlen (path) + strlen (name) + 2);
1307 if (path_buf == 0)
1308 {
1309 msg ("Can't allocate memory for name '%s/%s", path, name);
1310 exit (EX_SYSTEM);
1311 }
1312 (void) sprintf (path_buf, "%s/%s", path, name);
1313 return path_buf;
1314 }
1315
1316 /* returns non-zero if the luser typed 'y' or 'Y', zero otherwise. */
1317
1318 int
1319 confirm (action, file)
1320 char *action, *file;
1321 {
1322 int c, nl;
1323 static FILE *confirm_file = 0;
1324 extern FILE *msg_file;
1325 extern char TTY_NAME[];
1326
1327 fprintf (msg_file, "%s %s?", action, file);
1328 fflush (msg_file);
1329 if (!confirm_file)
1330 {
1331 confirm_file = (archive == 0) ? fopen (TTY_NAME, "r") : stdin;
1332 if (!confirm_file)
1333 {
1334 msg ("Can't read confirmation from user");
1335 exit (EX_SYSTEM);
1336 }
1337 }
1338 c = getc (confirm_file);
1339 for (nl = c; nl != '\n' && nl != EOF; nl = getc (confirm_file))
1340 ;
1341 return (c == 'y' || c == 'Y');
1342 }
1343
1344 char *x_buffer = 0;
1345 int size_x_buffer;
1346 int free_x_buffer;
1347
1348 char **exclude = 0;
1349 int size_exclude = 0;
1350 int free_exclude = 0;
1351
1352 char **re_exclude = 0;
1353 int size_re_exclude = 0;
1354 int free_re_exclude = 0;
1355
1356 void
1357 add_exclude (name)
1358 char *name;
1359 {
1360 /* char *rname;*/
1361 /* char **tmp_ptr;*/
1362 int size_buf;
1363
1364 un_quote_string (name);
1365 size_buf = strlen (name);
1366
1367 if (x_buffer == 0)
1368 {
1369 x_buffer = (char *) ck_malloc (size_buf + 1024);
1370 free_x_buffer = 1024;
1371 }
1372 else if (free_x_buffer <= size_buf)
1373 {
1374 char *old_x_buffer;
1375 char **tmp_ptr;
1376
1377 old_x_buffer = x_buffer;
1378 x_buffer = (char *) ck_realloc (x_buffer, size_x_buffer + 1024);
1379 free_x_buffer = 1024;
1380 for (tmp_ptr = exclude; tmp_ptr < exclude + size_exclude; tmp_ptr++)
1381 *tmp_ptr = x_buffer + ((*tmp_ptr) - old_x_buffer);
1382 for (tmp_ptr = re_exclude; tmp_ptr < re_exclude + size_re_exclude; tmp_ptr++)
1383 *tmp_ptr = x_buffer + ((*tmp_ptr) - old_x_buffer);
1384 }
1385
1386 if (is_regex (name))
1387 {
1388 if (free_re_exclude == 0)
1389 {
1390 re_exclude = (char **) (re_exclude ? ck_realloc (re_exclude, (size_re_exclude + 32) * sizeof (char *)): ck_malloc (sizeof (char *) * 32));
1391 free_re_exclude += 32;
1392 }
1393 re_exclude[size_re_exclude] = x_buffer + size_x_buffer;
1394 size_re_exclude++;
1395 free_re_exclude--;
1396 }
1397 else
1398 {
1399 if (free_exclude == 0)
1400 {
1401 exclude = (char **) (exclude ? ck_realloc (exclude, (size_exclude + 32) * sizeof (char *)): ck_malloc (sizeof (char *) * 32));
1402 free_exclude += 32;
1403 }
1404 exclude[size_exclude] = x_buffer + size_x_buffer;
1405 size_exclude++;
1406 free_exclude--;
1407 }
1408 strcpy (x_buffer + size_x_buffer, name);
1409 size_x_buffer += size_buf + 1;
1410 free_x_buffer -= size_buf + 1;
1411 }
1412
1413 void
1414 add_exclude_file (file)
1415 char *file;
1416 {
1417 FILE *fp;
1418 char buf[1024];
1419
1420 if (strcmp (file, "-"))
1421 fp = fopen (file, "r");
1422 else
1423 /* Let's hope the person knows what they're doing. */
1424 /* Using -X - -T - -f - will get you *REALLY* strange
1425 results. . . */
1426 fp = stdin;
1427
1428 if (!fp)
1429 {
1430 msg_perror ("can't open %s", file);
1431 exit (2);
1432 }
1433 while (fgets (buf, 1024, fp))
1434 {
1435 /* int size_buf;*/
1436 char *end_str;
1437
1438 end_str = rindex (buf, '\n');
1439 if (end_str)
1440 *end_str = '\0';
1441 add_exclude (buf);
1442
1443 }
1444 fclose (fp);
1445 }
1446
1447 int
1448 is_regex (str)
1449 char *str;
1450 {
1451 return index (str, '*') || index (str, '[') || index (str, '?');
1452 }
1453
1454 /* Returns non-zero if the file 'name' should not be added/extracted */
1455 int
1456 check_exclude (name)
1457 char *name;
1458 {
1459 int n;
1460 char *str;
1461 extern char *strstr ();
1462
1463 for (n = 0; n < size_re_exclude; n++)
1464 {
1465 if (fnmatch (re_exclude[n], name, FNM_TARPATH) == 0)
1466 return 1;
1467 }
1468 for (n = 0; n < size_exclude; n++)
1469 {
1470 /* Accept the output from strstr only if it is the last
1471 part of the string. There is certainly a faster way to
1472 do this. . . */
1473 if ((str = strstr (name, exclude[n]))
1474 && (str == name || str[-1] == '/')
1475 && str[strlen (exclude[n])] == '\0')
1476 return 1;
1477 }
1478 return 0;
1479 }
This page took 0.103147 seconds and 5 git commands to generate.