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