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