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