(main): Do not check for volume_label_option unless subcommand_option is CREATE_SUBCO...
[debian/tar] / src / tar.c
1 /* A tar (tape archiver) program.
2
3    Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1999, 2000,
4    2001, 2003 Free Software Foundation, Inc.
5
6    Written by John Gilmore, starting 1985-08-25.
7
8    This program is free software; you can redistribute it and/or modify it
9    under the terms of the GNU General Public License as published by the
10    Free Software Foundation; either version 2, or (at your option) any later
11    version.
12
13    This program is distributed in the hope that it will be useful, but
14    WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
16    Public License for more details.
17
18    You should have received a copy of the GNU General Public License along
19    with this program; if not, write to the Free Software Foundation, Inc.,
20    59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
21
22 #include "system.h"
23
24 #include <fnmatch.h>
25 #include <getopt.h>
26
27 #include <signal.h>
28 #if ! defined SIGCHLD && defined SIGCLD
29 # define SIGCHLD SIGCLD
30 #endif
31
32 /* The following causes "common.h" to produce definitions of all the global
33    variables, rather than just "extern" declarations of them.  GNU tar does
34    depend on the system loader to preset all GLOBAL variables to neutral (or
35    zero) values; explicit initialization is usually not done.  */
36 #define GLOBAL
37 #include "common.h"
38
39 #include <getdate.h>
40 #include <localedir.h>
41 #include <prepargs.h>
42 #include <quotearg.h>
43 #include <xstrtol.h>
44
45 /* Local declarations.  */
46
47 #ifndef DEFAULT_ARCHIVE_FORMAT
48 # define DEFAULT_ARCHIVE_FORMAT GNU_FORMAT
49 #endif
50
51 #ifndef DEFAULT_ARCHIVE
52 # define DEFAULT_ARCHIVE "tar.out"
53 #endif
54
55 #ifndef DEFAULT_BLOCKING
56 # define DEFAULT_BLOCKING 20
57 #endif
58
59 static void usage (int) __attribute__ ((noreturn));
60 \f
61 /* Miscellaneous.  */
62
63 /* Name of option using stdin.  */
64 static const char *stdin_used_by;
65
66 /* Doesn't return if stdin already requested.  */
67 void
68 request_stdin (const char *option)
69 {
70   if (stdin_used_by)
71     USAGE_ERROR ((0, 0, _("Options `-%s' and `-%s' both want standard input"),
72                   stdin_used_by, option));
73
74   stdin_used_by = option;
75 }
76
77 /* Returns true if and only if the user typed 'y' or 'Y'.  */
78 int
79 confirm (const char *message_action, const char *message_name)
80 {
81   static FILE *confirm_file;
82   static int confirm_file_EOF;
83
84   if (!confirm_file)
85     {
86       if (archive == 0 || stdin_used_by)
87         {
88           confirm_file = fopen (TTY_NAME, "r");
89           if (! confirm_file)
90             open_fatal (TTY_NAME);
91         }
92       else
93         {
94           request_stdin ("-w");
95           confirm_file = stdin;
96         }
97     }
98
99   fprintf (stdlis, "%s %s?", message_action, quote (message_name));
100   fflush (stdlis);
101
102   {
103     int reply = confirm_file_EOF ? EOF : getc (confirm_file);
104     int character;
105
106     for (character = reply;
107          character != '\n';
108          character = getc (confirm_file))
109       if (character == EOF)
110         {
111           confirm_file_EOF = 1;
112           fputc ('\n', stdlis);
113           fflush (stdlis);
114           break;
115         }
116     return reply == 'y' || reply == 'Y';
117   }
118 }
119
120 static struct fmttab {
121   char const *name;
122   enum archive_format fmt;
123 } const fmttab[] = {
124   { "v7",      V7_FORMAT },
125   { "oldgnu",  OLDGNU_FORMAT }, 
126   { "posix",   POSIX_FORMAT },
127 #if 0 /* not fully supported yet */
128   { "star",    STAR_FORMAT },
129 #endif
130   { "gnu",     GNU_FORMAT },
131   { NULL,        0 }
132 };
133
134 static void
135 set_archive_format (char const *name)
136 {
137   struct fmttab const *p;
138
139   for (p = fmttab; strcmp (p->name, name) != 0; )
140     if (! (++p)->name)
141       USAGE_ERROR ((0, 0, _("%s: Invalid archive format"),
142                     quotearg_colon (name)));
143
144   if (archive_format != DEFAULT_FORMAT && archive_format != p->fmt)
145     USAGE_ERROR ((0, 0, _("Conflicting archive format options")));
146   
147   archive_format = p->fmt;
148 }
149
150 static const char *
151 archive_format_string (enum archive_format fmt)
152 {
153   struct fmttab const *p;
154
155   for (p = fmttab; p->name; p++)
156     if (p->fmt == fmt)
157       return p->name;
158   return "unknown?";
159 }
160
161 \f
162 /* Options.  */
163
164 /* For long options that unconditionally set a single flag, we have getopt
165    do it.  For the others, we share the code for the equivalent short
166    named option, the name of which is stored in the otherwise-unused `val'
167    field of the `struct option'; for long options that have no equivalent
168    short option, we use non-characters as pseudo short options,
169    starting at CHAR_MAX + 1 and going upwards.  */
170
171 enum
172 {
173   ANCHORED_OPTION = CHAR_MAX + 1,
174   ATIME_PRESERVE_OPTION,
175   BACKUP_OPTION,
176   CHECKPOINT_OPTION,
177   DELETE_OPTION,
178   EXCLUDE_OPTION,
179   FORCE_LOCAL_OPTION,
180   FORMAT_OPTION,
181   GROUP_OPTION,
182   IGNORE_CASE_OPTION,
183   IGNORE_FAILED_READ_OPTION,
184   INDEX_FILE_OPTION,
185   MODE_OPTION,
186   NEWER_MTIME_OPTION,
187   NO_ANCHORED_OPTION,
188   NO_IGNORE_CASE_OPTION,
189   NO_OVERWRITE_DIR_OPTION,
190   NO_WILDCARDS_OPTION,
191   NO_WILDCARDS_MATCH_SLASH_OPTION,
192   NULL_OPTION,
193   NUMERIC_OWNER_OPTION,
194   OVERWRITE_OPTION,
195   OWNER_OPTION,
196   POSIX_OPTION,
197   PRESERVE_OPTION,
198   RECORD_SIZE_OPTION,
199   RECURSIVE_UNLINK_OPTION,
200   REMOVE_FILES_OPTION,
201   RSH_COMMAND_OPTION,
202   SHOW_OMITTED_DIRS_OPTION,
203   SUFFIX_OPTION,
204   TOTALS_OPTION,
205   USE_COMPRESS_PROGRAM_OPTION,
206   VOLNO_FILE_OPTION,
207   WILDCARDS_OPTION,
208   WILDCARDS_MATCH_SLASH_OPTION,
209 };
210
211 /* If nonzero, display usage information and exit.  */
212 static int show_help;
213
214 /* If nonzero, print the version on standard output and exit.  */
215 static int show_version;
216
217 static struct option long_options[] =
218 {
219   {"absolute-names", no_argument, 0, 'P'},
220   {"after-date", required_argument, 0, 'N'},
221   {"anchored", no_argument, 0, ANCHORED_OPTION},
222   {"append", no_argument, 0, 'r'},
223   {"atime-preserve", no_argument, 0, ATIME_PRESERVE_OPTION},
224   {"backup", optional_argument, 0, BACKUP_OPTION},
225   {"block-number", no_argument, 0, 'R'},
226   {"blocking-factor", required_argument, 0, 'b'},
227   {"bzip2", no_argument, 0, 'j'},
228   {"catenate", no_argument, 0, 'A'},
229   {"checkpoint", no_argument, 0, CHECKPOINT_OPTION},
230   {"check-links", no_argument, &check_links_option, 1},
231   {"compare", no_argument, 0, 'd'},
232   {"compress", no_argument, 0, 'Z'},
233   {"concatenate", no_argument, 0, 'A'},
234   {"confirmation", no_argument, 0, 'w'},
235   /* FIXME: --selective as a synonym for --confirmation?  */
236   {"create", no_argument, 0, 'c'},
237   {"delete", no_argument, 0, DELETE_OPTION},
238   {"dereference", no_argument, 0, 'h'},
239   {"diff", no_argument, 0, 'd'},
240   {"directory", required_argument, 0, 'C'},
241   {"exclude", required_argument, 0, EXCLUDE_OPTION},
242   {"exclude-from", required_argument, 0, 'X'},
243   {"extract", no_argument, 0, 'x'},
244   {"file", required_argument, 0, 'f'},
245   {"files-from", required_argument, 0, 'T'},
246   {"force-local", no_argument, 0, FORCE_LOCAL_OPTION},
247   {"format", required_argument, 0, FORMAT_OPTION},
248   {"get", no_argument, 0, 'x'},
249   {"group", required_argument, 0, GROUP_OPTION},
250   {"gunzip", no_argument, 0, 'z'},
251   {"gzip", no_argument, 0, 'z'},
252   {"help", no_argument, &show_help, 1},
253   {"ignore-case", no_argument, 0, IGNORE_CASE_OPTION},
254   {"ignore-failed-read", no_argument, 0, IGNORE_FAILED_READ_OPTION},
255   {"ignore-zeros", no_argument, 0, 'i'},
256   /* FIXME: --ignore-end as a new name for --ignore-zeros?  */
257   {"incremental", no_argument, 0, 'G'},
258   {"index-file", required_argument, 0, INDEX_FILE_OPTION},
259   {"info-script", required_argument, 0, 'F'},
260   {"interactive", no_argument, 0, 'w'},
261   {"keep-old-files", no_argument, 0, 'k'},
262   {"label", required_argument, 0, 'V'},
263   {"list", no_argument, 0, 't'},
264   {"listed-incremental", required_argument, 0, 'g'},
265   {"mode", required_argument, 0, MODE_OPTION},
266   {"multi-volume", no_argument, 0, 'M'},
267   {"new-volume-script", required_argument, 0, 'F'},
268   {"newer", required_argument, 0, 'N'},
269   {"newer-mtime", required_argument, 0, NEWER_MTIME_OPTION},
270   {"null", no_argument, 0, NULL_OPTION},
271   {"no-anchored", no_argument, 0, NO_ANCHORED_OPTION},
272   {"no-ignore-case", no_argument, 0, NO_IGNORE_CASE_OPTION},
273   {"no-overwrite-dir", no_argument, 0, NO_OVERWRITE_DIR_OPTION},
274   {"no-wildcards", no_argument, 0, NO_WILDCARDS_OPTION},
275   {"no-wildcards-match-slash", no_argument, 0, NO_WILDCARDS_MATCH_SLASH_OPTION},
276   {"no-recursion", no_argument, &recursion_option, 0},
277   {"no-same-owner", no_argument, &same_owner_option, -1},
278   {"no-same-permissions", no_argument, &same_permissions_option, -1},
279   {"numeric-owner", no_argument, 0, NUMERIC_OWNER_OPTION},
280   {"old-archive", no_argument, 0, 'o'},
281   {"one-file-system", no_argument, 0, 'l'},
282   {"overwrite", no_argument, 0, OVERWRITE_OPTION},
283   {"owner", required_argument, 0, OWNER_OPTION},
284   {"portability", no_argument, 0, 'o'},
285   {"posix", no_argument, 0, POSIX_OPTION},
286   {"preserve", no_argument, 0, PRESERVE_OPTION},
287   {"preserve-order", no_argument, 0, 's'},
288   {"preserve-permissions", no_argument, 0, 'p'},
289   {"recursion", no_argument, &recursion_option, FNM_LEADING_DIR},
290   {"recursive-unlink", no_argument, 0, RECURSIVE_UNLINK_OPTION},
291   {"read-full-records", no_argument, 0, 'B'},
292   /* FIXME: --partial-blocks might be a synonym for --read-full-records?  */
293   {"record-size", required_argument, 0, RECORD_SIZE_OPTION},
294   {"remove-files", no_argument, 0, REMOVE_FILES_OPTION},
295   {"rsh-command", required_argument, 0, RSH_COMMAND_OPTION},
296   {"same-order", no_argument, 0, 's'},
297   {"same-owner", no_argument, &same_owner_option, 1},
298   {"same-permissions", no_argument, 0, 'p'},
299   {"show-omitted-dirs", no_argument, 0, SHOW_OMITTED_DIRS_OPTION},
300   {"sparse", no_argument, 0, 'S'},
301   {"starting-file", required_argument, 0, 'K'},
302   {"suffix", required_argument, 0, SUFFIX_OPTION},
303   {"tape-length", required_argument, 0, 'L'},
304   {"to-stdout", no_argument, 0, 'O'},
305   {"totals", no_argument, 0, TOTALS_OPTION},
306   {"touch", no_argument, 0, 'm'},
307   {"uncompress", no_argument, 0, 'Z'},
308   {"ungzip", no_argument, 0, 'z'},
309   {"unlink-first", no_argument, 0, 'U'},
310   {"update", no_argument, 0, 'u'},
311   {"use-compress-program", required_argument, 0, USE_COMPRESS_PROGRAM_OPTION},
312   {"verbose", no_argument, 0, 'v'},
313   {"verify", no_argument, 0, 'W'},
314   {"version", no_argument, &show_version, 1},
315   {"volno-file", required_argument, 0, VOLNO_FILE_OPTION},
316   {"wildcards", no_argument, 0, WILDCARDS_OPTION},
317   {"wildcards-match-slash", no_argument, 0, WILDCARDS_MATCH_SLASH_OPTION},
318   
319   {0, 0, 0, 0}
320 };
321
322 /* Print a usage message and exit with STATUS.  */
323 static void
324 usage (int status)
325 {
326   if (status != TAREXIT_SUCCESS)
327     fprintf (stderr, _("Try `%s --help' for more information.\n"),
328              program_name);
329   else
330     {
331       fputs (_("\
332 GNU `tar' saves many files together into a single tape or disk archive, and\n\
333 can restore individual files from the archive.\n"),
334              stdout);
335       printf (_("\nUsage: %s [OPTION]... [FILE]...\n\
336 \n\
337 Examples:\n\
338   %s -cf archive.tar foo bar  # Create archive.tar from files foo and bar.\n\
339   %s -tvf archive.tar         # List all files in archive.tar verbosely.\n\
340   %s -xf archive.tar          # Extract all files from archive.tar.\n"),
341              program_name, program_name, program_name, program_name);
342       fputs (_("\
343 \n\
344 If a long option shows an argument as mandatory, then it is mandatory\n\
345 for the equivalent short option also.  Similarly for optional arguments.\n"),
346              stdout);
347       fputs(_("\
348 \n\
349 Main operation mode:\n\
350   -t, --list              list the contents of an archive\n\
351   -x, --extract, --get    extract files from an archive\n\
352   -c, --create            create a new archive\n\
353   -d, --diff, --compare   find differences between archive and file system\n\
354   -r, --append            append files to the end of an archive\n\
355   -u, --update            only append files newer than copy in archive\n\
356   -A, --catenate          append tar files to an archive\n\
357       --concatenate       same as -A\n\
358       --delete            delete from the archive (not on mag tapes!)\n"),
359             stdout);
360       fputs (_("\
361 \n\
362 Operation modifiers:\n\
363   -W, --verify               attempt to verify the archive after writing it\n\
364       --remove-files         remove files after adding them to the archive\n\
365   -k, --keep-old-files       don't replace existing files when extracting\n\
366       --overwrite            overwrite existing files when extracting\n\
367       --no-overwrite-dir     preserve metadata of existing directories\n\
368   -U, --unlink-first         remove each file prior to extracting over it\n\
369       --recursive-unlink     empty hierarchies prior to extracting directory\n\
370   -S, --sparse               handle sparse files efficiently\n\
371   -O, --to-stdout            extract files to standard output\n\
372   -G, --incremental          handle old GNU-format incremental backup\n\
373   -g, --listed-incremental=FILE\n\
374                              handle new GNU-format incremental backup\n\
375       --ignore-failed-read   do not exit with nonzero on unreadable files\n"),
376              stdout);
377       fputs (_("\
378 \n\
379 Handling of file attributes:\n\
380       --owner=NAME             force NAME as owner for added files\n\
381       --group=NAME             force NAME as group for added files\n\
382       --mode=CHANGES           force (symbolic) mode CHANGES for added files\n\
383       --atime-preserve         don't change access times on dumped files\n\
384   -m, --modification-time      don't extract file modified time\n\
385       --same-owner             try extracting files with the same ownership\n\
386       --no-same-owner          extract files as yourself\n\
387       --numeric-owner          always use numbers for user/group names\n\
388   -p, --same-permissions       extract permissions information\n\
389       --no-same-permissions    do not extract permissions information\n\
390       --preserve-permissions   same as -p\n\
391   -s, --same-order             sort names to extract to match archive\n\
392       --preserve-order         same as -s\n\
393       --preserve               same as both -p and -s\n"),
394              stdout);
395       fputs (_("\
396 \n\
397 Device selection and switching:\n\
398   -f, --file=ARCHIVE             use archive file or device ARCHIVE\n\
399       --force-local              archive file is local even if has a colon\n\
400       --rsh-command=COMMAND      use remote COMMAND instead of rsh\n\
401   -[0-7][lmh]                    specify drive and density\n\
402   -M, --multi-volume             create/list/extract multi-volume archive\n\
403   -L, --tape-length=NUM          change tape after writing NUM x 1024 bytes\n\
404   -F, --info-script=FILE         run script at end of each tape (implies -M)\n\
405       --new-volume-script=FILE   same as -F FILE\n\
406       --volno-file=FILE          use/update the volume number in FILE\n"),
407              stdout);
408       fputs (_("\
409 \n\
410 Device blocking:\n\
411   -b, --blocking-factor=BLOCKS   BLOCKS x 512 bytes per record\n\
412       --record-size=SIZE         SIZE bytes per record, multiple of 512\n\
413   -i, --ignore-zeros             ignore zeroed blocks in archive (means EOF)\n\
414   -B, --read-full-records        reblock as we read (for 4.2BSD pipes)\n"),
415              stdout);
416       fputs (_("\
417 \n\
418 Archive format selection:\n\
419       --format=FMTNAME               create archive of the given format.\n\
420                                      FMTNAME is one of the following:\n\
421                                      v7        old V7 tar format\n\
422                                      oldgnu    GNU format as per tar <= 1.12\n\
423                                      posix     POSIX 1003.1-2001 tar format\n\
424                                      gnu       GNU format\n\
425       --old-archive, --portability   same as --format=v7\n\
426       --posix                        same as --format=posix\n\
427   -V, --label=NAME                   create archive with volume name NAME\n\
428               PATTERN                at list/extract time, a globbing PATTERN\n\
429   -j, --bzip2                        filter the archive through bzip2\n\
430   -z, --gzip, --ungzip               filter the archive through gzip\n\
431   -Z, --compress, --uncompress       filter the archive through compress\n\
432       --use-compress-program=PROG    filter through PROG (must accept -d)\n"),
433              stdout);
434       fputs (_("\
435 \n\
436 Local file selection:\n\
437   -C, --directory=DIR          change to directory DIR\n\
438   -T, --files-from=NAME        get names to extract or create from file NAME\n\
439       --null                   -T reads null-terminated names, disable -C\n\
440       --exclude=PATTERN        exclude files, given as a PATTERN\n\
441   -X, --exclude-from=FILE      exclude patterns listed in FILE\n\
442       --anchored               exclude patterns match file name start (default)\n\
443       --no-anchored            exclude patterns match after any /\n\
444       --ignore-case            exclusion ignores case\n\
445       --no-ignore-case         exclusion is case sensitive (default)\n\
446       --wildcards              exclude patterns use wildcards (default)\n\
447       --no-wildcards           exclude patterns are plain strings\n\
448       --wildcards-match-slash  exclude pattern wildcards match '/' (default)\n\
449       --no-wildcards-match-slash exclude pattern wildcards do not match '/'\n\
450   -P, --absolute-names         don't strip leading `/'s from file names\n\
451   -h, --dereference            dump instead the files symlinks point to\n\
452       --no-recursion           avoid descending automatically in directories\n\
453   -l, --one-file-system        stay in local file system when creating archive\n\
454   -K, --starting-file=NAME     begin at file NAME in the archive\n"),
455              stdout);
456 #if !MSDOS
457       fputs (_("\
458   -N, --newer=DATE             only store files newer than DATE\n\
459       --newer-mtime=DATE       compare date and time when data changed only\n\
460       --after-date=DATE        same as -N\n"),
461              stdout);
462 #endif
463       fputs (_("\
464       --backup[=CONTROL]       backup before removal, choose version control\n\
465       --suffix=SUFFIX          backup before removal, override usual suffix\n"),
466              stdout);
467       fputs (_("\
468 \n\
469 Informative output:\n\
470       --help            print this help, then exit\n\
471       --version         print tar program version number, then exit\n\
472   -v, --verbose         verbosely list files processed\n\
473       --checkpoint      print directory names while reading the archive\n\
474       --check-links     print a message if not all links are dumped\n\
475       --totals          print total bytes written while creating archive\n\
476       --index-file=FILE send verbose output to FILE\n\
477   -R, --block-number    show block number within archive with each message\n\
478   -w, --interactive     ask for confirmation for every action\n\
479       --confirmation    same as -w\n"),
480              stdout);
481       fputs (_("\
482 \n\
483 Compatibility options:\n\
484   -o                                 when creating, same as --old-archive\n\
485                                      when extracting, same as --no-same-owner\n"),
486              stdout);
487       
488       fputs (_("\
489 \n\
490 The backup suffix is `~', unless set with --suffix or SIMPLE_BACKUP_SUFFIX.\n\
491 The version control may be set with --backup or VERSION_CONTROL, values are:\n\
492 \n\
493   t, numbered     make numbered backups\n\
494   nil, existing   numbered if numbered backups exist, simple otherwise\n\
495   never, simple   always make simple backups\n"),
496              stdout);
497       printf (_("\
498 \n\
499 ARCHIVE may be FILE, HOST:FILE or USER@HOST:FILE; DATE may be a textual date\n\
500 or a file name starting with `/' or `.', in which case the file's date is used.\n\
501 *This* `tar' defaults to `--format=%s -f%s -b%d'.\n"),
502               archive_format_string (DEFAULT_ARCHIVE_FORMAT),
503               DEFAULT_ARCHIVE, DEFAULT_BLOCKING);
504       printf (_("\nReport bugs to <%s>.\n"), PACKAGE_BUGREPORT);
505     }
506   exit (status);
507 }
508
509 /* Parse the options for tar.  */
510
511 /* Available option letters are DEHIJQY and aenqy.  Some are reserved:
512
513    e  exit immediately with a nonzero exit status if unexpected errors occur
514    E  use extended headers (draft POSIX headers, that is)
515    I  same as T (for compatibility with Solaris tar)
516    n  the archive is quickly seekable, so don't worry about random seeks
517    q  stop after extracting the first occurrence of the named file
518    y  per-file gzip compression
519    Y  per-block gzip compression */
520
521 #define OPTION_STRING \
522   "-01234567ABC:F:GIK:L:MN:OPRST:UV:WX:Zb:cdf:g:hijklmoprstuvwxyz"
523
524 static void
525 set_subcommand_option (enum subcommand subcommand)
526 {
527   if (subcommand_option != UNKNOWN_SUBCOMMAND
528       && subcommand_option != subcommand)
529     USAGE_ERROR ((0, 0,
530                   _("You may not specify more than one `-Acdtrux' option")));
531
532   subcommand_option = subcommand;
533 }
534
535 static void
536 set_use_compress_program_option (const char *string)
537 {
538   if (use_compress_program_option && strcmp (use_compress_program_option, string) != 0)
539     USAGE_ERROR ((0, 0, _("Conflicting compression options")));
540
541   use_compress_program_option = string;
542 }
543
544 static void
545 decode_options (int argc, char **argv)
546 {
547   int optchar;                  /* option letter */
548   int input_files;              /* number of input files */
549   char const *textual_date_option = 0;
550   char const *backup_suffix_string;
551   char const *version_control_string = 0;
552   int exclude_options = EXCLUDE_WILDCARDS;
553   int o_option = 0;
554   
555   /* Set some default option values.  */
556
557   subcommand_option = UNKNOWN_SUBCOMMAND;
558   archive_format = DEFAULT_FORMAT;
559   blocking_factor = DEFAULT_BLOCKING;
560   record_size = DEFAULT_BLOCKING * BLOCKSIZE;
561   excluded = new_exclude ();
562   newer_mtime_option = TYPE_MINIMUM (time_t);
563   recursion_option = FNM_LEADING_DIR;
564
565   owner_option = -1;
566   group_option = -1;
567
568   backup_suffix_string = getenv ("SIMPLE_BACKUP_SUFFIX");
569
570   /* Convert old-style tar call by exploding option element and rearranging
571      options accordingly.  */
572
573   if (argc > 1 && argv[1][0] != '-')
574     {
575       int new_argc;             /* argc value for rearranged arguments */
576       char **new_argv;          /* argv value for rearranged arguments */
577       char *const *in;          /* cursor into original argv */
578       char **out;               /* cursor into rearranged argv */
579       const char *letter;       /* cursor into old option letters */
580       char buffer[3];           /* constructed option buffer */
581       const char *cursor;       /* cursor in OPTION_STRING */
582
583       /* Initialize a constructed option.  */
584
585       buffer[0] = '-';
586       buffer[2] = '\0';
587
588       /* Allocate a new argument array, and copy program name in it.  */
589
590       new_argc = argc - 1 + strlen (argv[1]);
591       new_argv = xmalloc ((new_argc + 1) * sizeof (char *));
592       in = argv;
593       out = new_argv;
594       *out++ = *in++;
595
596       /* Copy each old letter option as a separate option, and have the
597          corresponding argument moved next to it.  */
598
599       for (letter = *in++; *letter; letter++)
600         {
601           buffer[1] = *letter;
602           *out++ = xstrdup (buffer);
603           cursor = strchr (OPTION_STRING, *letter);
604           if (cursor && cursor[1] == ':')
605             {
606               if (in < argv + argc)
607                 *out++ = *in++;
608               else
609                 USAGE_ERROR ((0, 0, _("Old option `%c' requires an argument."),
610                               *letter));
611             }
612         }
613
614       /* Copy all remaining options.  */
615
616       while (in < argv + argc)
617         *out++ = *in++;
618       *out = 0;
619
620       /* Replace the old option list by the new one.  */
621
622       argc = new_argc;
623       argv = new_argv;
624     }
625
626   /* Parse all options and non-options as they appear.  */
627
628   input_files = 0;
629
630   prepend_default_options (getenv ("TAR_OPTIONS"), &argc, &argv);
631
632   while (optchar = getopt_long (argc, argv, OPTION_STRING, long_options, 0),
633          optchar != -1)
634     switch (optchar)
635       {
636       case '?':
637         usage (TAREXIT_FAILURE);
638
639       case 0:
640         break;
641
642       case 1:
643         /* File name or non-parsed option, because of RETURN_IN_ORDER
644            ordering triggered by the leading dash in OPTION_STRING.  */
645
646         name_add (optarg);
647         input_files++;
648         break;
649
650       case 'A':
651         set_subcommand_option (CAT_SUBCOMMAND);
652         break;
653
654       case 'b':
655         {
656           uintmax_t u;
657           if (! (xstrtoumax (optarg, 0, 10, &u, "") == LONGINT_OK
658                  && u == (blocking_factor = u)
659                  && 0 < blocking_factor
660                  && u == (record_size = u * BLOCKSIZE) / BLOCKSIZE))
661             USAGE_ERROR ((0, 0, "%s: %s", quotearg_colon (optarg),
662                           _("Invalid blocking factor")));
663         }
664         break;
665
666       case 'B':
667         /* Try to reblock input records.  For reading 4.2BSD pipes.  */
668
669         /* It would surely make sense to exchange -B and -R, but it seems
670            that -B has been used for a long while in Sun tar ans most
671            BSD-derived systems.  This is a consequence of the block/record
672            terminology confusion.  */
673
674         read_full_records_option = 1;
675         break;
676
677       case 'c':
678         set_subcommand_option (CREATE_SUBCOMMAND);
679         break;
680
681       case 'C':
682         name_add ("-C");
683         name_add (optarg);
684         break;
685
686       case 'd':
687         set_subcommand_option (DIFF_SUBCOMMAND);
688         break;
689
690       case 'f':
691         if (archive_names == allocated_archive_names)
692           {
693             allocated_archive_names *= 2;
694             archive_name_array =
695               xrealloc (archive_name_array,
696                         sizeof (const char *) * allocated_archive_names);
697           }
698         archive_name_array[archive_names++] = optarg;
699         break;
700
701       case 'F':
702         /* Since -F is only useful with -M, make it implied.  Run this
703            script at the end of each tape.  */
704
705         info_script_option = optarg;
706         multi_volume_option = 1;
707         break;
708
709       case 'g':
710         listed_incremental_option = optarg;
711         after_date_option = 1;
712         /* Fall through.  */
713
714       case 'G':
715         /* We are making an incremental dump (FIXME: are we?); save
716            directories at the beginning of the archive, and include in each
717            directory its contents.  */
718
719         incremental_option = 1;
720         break;
721
722       case 'h':
723         /* Follow symbolic links.  */
724
725         dereference_option = 1;
726         break;
727
728       case 'i':
729         /* Ignore zero blocks (eofs).  This can't be the default,
730            because Unix tar writes two blocks of zeros, then pads out
731            the record with garbage.  */
732
733         ignore_zeros_option = 1;
734         break;
735
736       case 'I':
737         USAGE_ERROR ((0, 0,
738                       _("Warning: the -I option is not supported;"
739                         " perhaps you meant -j or -T?")));
740         break;
741
742       case 'j':
743         set_use_compress_program_option ("bzip2");
744         break;
745
746       case 'k':
747         /* Don't replace existing files.  */
748         old_files_option = KEEP_OLD_FILES;
749         break;
750
751       case 'K':
752         starting_file_option = 1;
753         addname (optarg, 0);
754         break;
755
756       case 'l':
757         /* When dumping directories, don't dump files/subdirectories
758            that are on other filesystems.  */
759
760         one_file_system_option = 1;
761         break;
762
763       case 'L':
764         {
765           uintmax_t u;
766           if (xstrtoumax (optarg, 0, 10, &u, "") != LONGINT_OK)
767             USAGE_ERROR ((0, 0, "%s: %s", quotearg_colon (optarg),
768                           _("Invalid tape length")));
769           tape_length_option = 1024 * (tarlong) u;
770           multi_volume_option = 1;
771         }
772         break;
773
774       case 'm':
775         touch_option = 1;
776         break;
777
778       case 'M':
779         /* Make multivolume archive: when we can't write any more into
780            the archive, re-open it, and continue writing.  */
781
782         multi_volume_option = 1;
783         break;
784
785 #if !MSDOS
786       case 'N':
787         after_date_option = 1;
788         /* Fall through.  */
789
790       case NEWER_MTIME_OPTION:
791         if (newer_mtime_option != TYPE_MINIMUM (time_t))
792           USAGE_ERROR ((0, 0, _("More than one threshold date")));
793
794         if (FILESYSTEM_PREFIX_LEN (optarg) != 0
795             || ISSLASH (*optarg)
796             || *optarg == '.')
797           {
798             struct stat st;
799             if (deref_stat (dereference_option, optarg, &st) != 0)
800               {
801                 stat_error (optarg);
802                 USAGE_ERROR ((0, 0, _("Date file not found")));
803               }
804             newer_mtime_option = st.st_mtime;
805           }
806         else
807           {
808             newer_mtime_option = get_date (optarg, 0);
809             if (newer_mtime_option == (time_t) -1)
810               WARN ((0, 0, _("Substituting %s for unknown date format %s"),
811                      tartime (newer_mtime_option), quote (optarg)));
812             else
813               textual_date_option = optarg;
814           }
815
816         break;
817 #endif /* not MSDOS */
818
819       case 'o':
820         o_option = 1;
821         break;
822
823       case 'O':
824         to_stdout_option = 1;
825         break;
826
827       case 'p':
828         same_permissions_option = 1;
829         break;
830
831       case 'P':
832         absolute_names_option = 1;
833         break;
834
835       case 'r':
836         set_subcommand_option (APPEND_SUBCOMMAND);
837         break;
838
839       case 'R':
840         /* Print block numbers for debugging bad tar archives.  */
841
842         /* It would surely make sense to exchange -B and -R, but it seems
843            that -B has been used for a long while in Sun tar ans most
844            BSD-derived systems.  This is a consequence of the block/record
845            terminology confusion.  */
846
847         block_number_option = 1;
848         break;
849
850       case 's':
851         /* Names to extr are sorted.  */
852
853         same_order_option = 1;
854         break;
855
856       case 'S':
857         sparse_option = 1;
858         break;
859
860       case 't':
861         set_subcommand_option (LIST_SUBCOMMAND);
862         verbose_option++;
863         break;
864
865       case 'T':
866         files_from_option = optarg;
867         break;
868
869       case 'u':
870         set_subcommand_option (UPDATE_SUBCOMMAND);
871         break;
872
873       case 'U':
874         old_files_option = UNLINK_FIRST_OLD_FILES;
875         break;
876
877       case 'v':
878         verbose_option++;
879         break;
880
881       case 'V':
882         volume_label_option = optarg;
883         break;
884
885       case 'w':
886         interactive_option = 1;
887         break;
888
889       case 'W':
890         verify_option = 1;
891         break;
892
893       case 'x':
894         set_subcommand_option (EXTRACT_SUBCOMMAND);
895         break;
896
897       case 'X':
898         if (add_exclude_file (add_exclude, excluded, optarg,
899                               exclude_options | recursion_option, '\n')
900             != 0)
901           {
902             int e = errno;
903             FATAL_ERROR ((0, e, "%s", quotearg_colon (optarg)));
904           }
905         break;
906
907       case 'y':
908         USAGE_ERROR ((0, 0,
909                       _("Warning: the -y option is not supported;"
910                         " perhaps you meant -j?")));
911         break;
912
913       case 'z':
914         set_use_compress_program_option ("gzip");
915         break;
916
917       case 'Z':
918         set_use_compress_program_option ("compress");
919         break;
920
921       case ANCHORED_OPTION:
922         exclude_options |= EXCLUDE_ANCHORED;
923         break;
924
925       case ATIME_PRESERVE_OPTION:
926         atime_preserve_option = 1;
927         break;
928
929       case CHECKPOINT_OPTION:
930         checkpoint_option = 1;
931         break;
932
933       case BACKUP_OPTION:
934         backup_option = 1;
935         if (optarg)
936           version_control_string = optarg;
937         break;
938
939       case DELETE_OPTION:
940         set_subcommand_option (DELETE_SUBCOMMAND);
941         break;
942
943       case EXCLUDE_OPTION:
944         add_exclude (excluded, optarg, exclude_options | recursion_option);
945         break;
946
947       case FORCE_LOCAL_OPTION:
948         force_local_option = 1;
949         break;
950
951       case FORMAT_OPTION:
952         set_archive_format (optarg);
953         break;
954         
955       case INDEX_FILE_OPTION:
956         index_file_name = optarg;
957         break;
958
959       case IGNORE_CASE_OPTION:
960         exclude_options |= FNM_CASEFOLD;
961         break;
962
963       case IGNORE_FAILED_READ_OPTION:
964         ignore_failed_read_option = 1;
965         break;
966
967       case GROUP_OPTION:
968         if (! (strlen (optarg) < GNAME_FIELD_SIZE
969                && gname_to_gid (optarg, &group_option)))
970           {
971             uintmax_t g;
972             if (xstrtoumax (optarg, 0, 10, &g, "") == LONGINT_OK
973                 && g == (gid_t) g)
974               group_option = g;
975             else
976               FATAL_ERROR ((0, 0, "%s: %s", quotearg_colon (optarg),
977                             _("%s: Invalid group")));
978           }
979         break;
980
981       case MODE_OPTION:
982         mode_option
983           = mode_compile (optarg,
984                           MODE_MASK_EQUALS | MODE_MASK_PLUS | MODE_MASK_MINUS);
985         if (mode_option == MODE_INVALID)
986           FATAL_ERROR ((0, 0, _("Invalid mode given on option")));
987         if (mode_option == MODE_MEMORY_EXHAUSTED)
988           xalloc_die ();
989         break;
990
991       case NO_ANCHORED_OPTION:
992         exclude_options &= ~ EXCLUDE_ANCHORED;
993         break;
994
995       case NO_IGNORE_CASE_OPTION:
996         exclude_options &= ~ FNM_CASEFOLD;
997         break;
998
999       case NO_OVERWRITE_DIR_OPTION:
1000         old_files_option = NO_OVERWRITE_DIR_OLD_FILES;
1001         break;
1002
1003       case NO_WILDCARDS_OPTION:
1004         exclude_options &= ~ EXCLUDE_WILDCARDS;
1005         break;
1006
1007       case NO_WILDCARDS_MATCH_SLASH_OPTION:
1008         exclude_options |= FNM_FILE_NAME;
1009         break;
1010
1011       case NULL_OPTION:
1012         filename_terminator = '\0';
1013         break;
1014
1015       case NUMERIC_OWNER_OPTION:
1016         numeric_owner_option = 1;
1017         break;
1018
1019       case OVERWRITE_OPTION:
1020         old_files_option = OVERWRITE_OLD_FILES;
1021         break;
1022
1023       case OWNER_OPTION:
1024         if (! (strlen (optarg) < UNAME_FIELD_SIZE
1025                && uname_to_uid (optarg, &owner_option)))
1026           {
1027             uintmax_t u;
1028             if (xstrtoumax (optarg, 0, 10, &u, "") == LONGINT_OK
1029                 && u == (uid_t) u)
1030               owner_option = u;
1031             else
1032               FATAL_ERROR ((0, 0, "%s: %s", quotearg_colon (optarg),
1033                             _("Invalid owner")));
1034           }
1035         break;
1036
1037       case POSIX_OPTION:
1038         set_archive_format ("posix");
1039         break;
1040
1041       case PRESERVE_OPTION:
1042         same_permissions_option = 1;
1043         same_order_option = 1;
1044         break;
1045
1046       case RECORD_SIZE_OPTION:
1047         {
1048           uintmax_t u;
1049           if (! (xstrtoumax (optarg, 0, 10, &u, "") == LONGINT_OK
1050                  && u == (size_t) u))
1051             USAGE_ERROR ((0, 0, "%s: %s", quotearg_colon (optarg),
1052                           _("Invalid record size")));
1053           record_size = u;
1054           if (record_size % BLOCKSIZE != 0)
1055             USAGE_ERROR ((0, 0, _("Record size must be a multiple of %d."),
1056                           BLOCKSIZE));
1057           blocking_factor = record_size / BLOCKSIZE;
1058         }
1059         break;
1060
1061       case RECURSIVE_UNLINK_OPTION:
1062         recursive_unlink_option = 1;
1063         break;
1064
1065       case REMOVE_FILES_OPTION:
1066         remove_files_option = 1;
1067         break;
1068
1069       case RSH_COMMAND_OPTION:
1070         rsh_command_option = optarg;
1071         break;
1072
1073       case SUFFIX_OPTION:
1074         backup_option = 1;
1075         backup_suffix_string = optarg;
1076         break;
1077
1078       case USE_COMPRESS_PROGRAM_OPTION:
1079         set_use_compress_program_option (optarg);
1080         break;
1081
1082       case VOLNO_FILE_OPTION:
1083         volno_file_option = optarg;
1084         break;
1085
1086       case WILDCARDS_OPTION:
1087         exclude_options |= EXCLUDE_WILDCARDS;
1088         break;
1089
1090       case WILDCARDS_MATCH_SLASH_OPTION:
1091         exclude_options &= ~ FNM_FILE_NAME;
1092         break;
1093
1094       case '0':
1095       case '1':
1096       case '2':
1097       case '3':
1098       case '4':
1099       case '5':
1100       case '6':
1101       case '7':
1102
1103 #ifdef DEVICE_PREFIX
1104         {
1105           int device = optchar - '0';
1106           int density;
1107           static char buf[sizeof DEVICE_PREFIX + 10];
1108           char *cursor;
1109
1110           density = getopt_long (argc, argv, "lmh", 0, 0);
1111           strcpy (buf, DEVICE_PREFIX);
1112           cursor = buf + strlen (buf);
1113
1114 #ifdef DENSITY_LETTER
1115
1116           sprintf (cursor, "%d%c", device, density);
1117
1118 #else /* not DENSITY_LETTER */
1119
1120           switch (density)
1121             {
1122             case 'l':
1123 #ifdef LOW_NUM
1124               device += LOW_NUM;
1125 #endif
1126               break;
1127
1128             case 'm':
1129 #ifdef MID_NUM
1130               device += MID_NUM;
1131 #else
1132               device += 8;
1133 #endif
1134               break;
1135
1136             case 'h':
1137 #ifdef HGH_NUM
1138               device += HGH_NUM;
1139 #else
1140               device += 16;
1141 #endif
1142               break;
1143
1144             default:
1145               usage (TAREXIT_FAILURE);
1146             }
1147           sprintf (cursor, "%d", device);
1148
1149 #endif /* not DENSITY_LETTER */
1150
1151           if (archive_names == allocated_archive_names)
1152             {
1153               allocated_archive_names *= 2;
1154               archive_name_array =
1155                 xrealloc (archive_name_array,
1156                           sizeof (const char *) * allocated_archive_names);
1157             }
1158           archive_name_array[archive_names++] = strdup (buf);
1159         }
1160         break;
1161
1162 #else /* not DEVICE_PREFIX */
1163
1164         USAGE_ERROR ((0, 0,
1165                       _("Options `-[0-7][lmh]' not supported by *this* tar")));
1166
1167 #endif /* not DEVICE_PREFIX */
1168       }
1169
1170   /* Special handling for 'o' option:
1171
1172      GNU tar used to say "output old format".
1173      UNIX98 tar says don't chown files after extracting (we use
1174      "--no-same-owner" for this).
1175
1176      The old GNU tar semantics is retained when used with --create
1177      option, otherwise UNIX98 semantics is assumed */
1178
1179   if (o_option)
1180     {
1181       if (subcommand_option == CREATE_SUBCOMMAND)
1182         {
1183           /* GNU Tar <= 1.13 compatibility */
1184           set_archive_format ("v7");
1185         }
1186       else
1187         {
1188           /* UNIX98 compatibility */
1189           same_owner_option = 1;
1190         }
1191     }
1192
1193   /* Handle operands after any "--" argument.  */
1194   for (; optind < argc; optind++)
1195     {
1196       name_add (argv[optind]);
1197       input_files++;
1198     }
1199
1200   /* Process trivial options.  */
1201
1202   if (show_version)
1203     {
1204       printf ("tar (%s) %s\n", PACKAGE_NAME, PACKAGE_VERSION);
1205       printf (_("Copyright (C) %d Free Software Foundation, Inc.\n"), 2003);
1206       puts (_("\
1207 This program comes with NO WARRANTY, to the extent permitted by law.\n\
1208 You may redistribute it under the terms of the GNU General Public License;\n\
1209 see the file named COPYING for details."));
1210
1211       puts (_("Written by John Gilmore and Jay Fenlason."));
1212
1213       exit (TAREXIT_SUCCESS);
1214     }
1215
1216   if (show_help)
1217     usage (TAREXIT_SUCCESS);
1218
1219   /* Derive option values and check option consistency.  */
1220
1221   if (archive_format == DEFAULT_FORMAT)
1222     archive_format = DEFAULT_ARCHIVE_FORMAT;
1223
1224   if (archive_format == GNU_FORMAT && getenv ("POSIXLY_CORRECT"))
1225     archive_format = POSIX_FORMAT;
1226
1227   if (((volume_label_option && subcommand_option == CREATE_SUBCOMMAND)
1228        || incremental_option || multi_volume_option || sparse_option)
1229       && archive_format != OLDGNU_FORMAT && archive_format != GNU_FORMAT)
1230     USAGE_ERROR ((0, 0,
1231                   _("GNU features wanted on incompatible archive format")));
1232
1233   if (archive_names == 0)
1234     {
1235       /* If no archive file name given, try TAPE from the environment, or
1236          else, DEFAULT_ARCHIVE from the configuration process.  */
1237
1238       archive_names = 1;
1239       archive_name_array[0] = getenv ("TAPE");
1240       if (! archive_name_array[0])
1241         archive_name_array[0] = DEFAULT_ARCHIVE;
1242     }
1243
1244   /* Allow multiple archives only with `-M'.  */
1245
1246   if (archive_names > 1 && !multi_volume_option)
1247     USAGE_ERROR ((0, 0,
1248                   _("Multiple archive files requires `-M' option")));
1249
1250   if (listed_incremental_option
1251       && newer_mtime_option != TYPE_MINIMUM (time_t))
1252     USAGE_ERROR ((0, 0,
1253                   _("Cannot combine --listed-incremental with --newer")));
1254
1255   if (volume_label_option)
1256     {
1257       size_t volume_label_max_len =
1258         (sizeof current_header->header.name
1259          - 1 /* for trailing '\0' */
1260          - (multi_volume_option
1261             ? (sizeof " Volume "
1262                - 1 /* for null at end of " Volume " */
1263                + INT_STRLEN_BOUND (int) /* for volume number */
1264                - 1 /* for sign, as 0 <= volno */)
1265             : 0));
1266       if (volume_label_max_len < strlen (volume_label_option))
1267         USAGE_ERROR ((0, 0,
1268                       _("%s: Volume label is too long (limit is %lu bytes)"),
1269                       quotearg_colon (volume_label_option),
1270                       (unsigned long) volume_label_max_len));
1271     }
1272
1273   /* If ready to unlink hierarchies, so we are for simpler files.  */
1274   if (recursive_unlink_option)
1275     old_files_option = UNLINK_FIRST_OLD_FILES;
1276
1277   /* Forbid using -c with no input files whatsoever.  Check that `-f -',
1278      explicit or implied, is used correctly.  */
1279
1280   switch (subcommand_option)
1281     {
1282     case CREATE_SUBCOMMAND:
1283       if (input_files == 0 && !files_from_option)
1284         USAGE_ERROR ((0, 0,
1285                       _("Cowardly refusing to create an empty archive")));
1286       break;
1287
1288     case EXTRACT_SUBCOMMAND:
1289     case LIST_SUBCOMMAND:
1290     case DIFF_SUBCOMMAND:
1291       for (archive_name_cursor = archive_name_array;
1292            archive_name_cursor < archive_name_array + archive_names;
1293            archive_name_cursor++)
1294         if (!strcmp (*archive_name_cursor, "-"))
1295           request_stdin ("-f");
1296       break;
1297
1298     case CAT_SUBCOMMAND:
1299     case UPDATE_SUBCOMMAND:
1300     case APPEND_SUBCOMMAND:
1301       for (archive_name_cursor = archive_name_array;
1302            archive_name_cursor < archive_name_array + archive_names;
1303            archive_name_cursor++)
1304         if (!strcmp (*archive_name_cursor, "-"))
1305           USAGE_ERROR ((0, 0,
1306                         _("Options `-Aru' are incompatible with `-f -'")));
1307
1308     default:
1309       break;
1310     }
1311
1312   archive_name_cursor = archive_name_array;
1313
1314   /* Prepare for generating backup names.  */
1315
1316   if (backup_suffix_string)
1317     simple_backup_suffix = xstrdup (backup_suffix_string);
1318
1319   if (backup_option)
1320     backup_type = xget_version ("--backup", version_control_string);
1321
1322   if (verbose_option && textual_date_option)
1323     {
1324       char const *treated_as = tartime (newer_mtime_option);
1325       if (strcmp (textual_date_option, treated_as) != 0)
1326         WARN ((0, 0, _("Treating date `%s' as %s"),
1327                textual_date_option, treated_as));
1328     }
1329 }
1330 \f
1331 /* Tar proper.  */
1332
1333 /* Main routine for tar.  */
1334 int
1335 main (int argc, char **argv)
1336 {
1337 #if HAVE_CLOCK_GETTIME
1338   if (clock_gettime (CLOCK_REALTIME, &start_timespec) != 0)
1339 #endif
1340     start_time = time (0);
1341   program_name = argv[0];
1342   setlocale (LC_ALL, "");
1343   bindtextdomain (PACKAGE, LOCALEDIR);
1344   textdomain (PACKAGE);
1345
1346   exit_status = TAREXIT_SUCCESS;
1347   filename_terminator = '\n';
1348   set_quoting_style (0, escape_quoting_style);
1349
1350   /* Pre-allocate a few structures.  */
1351
1352   allocated_archive_names = 10;
1353   archive_name_array =
1354     xmalloc (sizeof (const char *) * allocated_archive_names);
1355   archive_names = 0;
1356
1357 #ifdef SIGCHLD
1358   /* System V fork+wait does not work if SIGCHLD is ignored.  */
1359   signal (SIGCHLD, SIG_DFL);
1360 #endif
1361
1362   init_names ();
1363
1364   /* Decode options.  */
1365
1366   decode_options (argc, argv);
1367   name_init (argc, argv);
1368
1369   /* Main command execution.  */
1370
1371   if (volno_file_option)
1372     init_volume_number ();
1373
1374   switch (subcommand_option)
1375     {
1376     case UNKNOWN_SUBCOMMAND:
1377       USAGE_ERROR ((0, 0,
1378                     _("You must specify one of the `-Acdtrux' options")));
1379
1380     case CAT_SUBCOMMAND:
1381     case UPDATE_SUBCOMMAND:
1382     case APPEND_SUBCOMMAND:
1383       update_archive ();
1384       break;
1385
1386     case DELETE_SUBCOMMAND:
1387       delete_archive_members ();
1388       break;
1389
1390     case CREATE_SUBCOMMAND:
1391       create_archive ();
1392       name_close ();
1393
1394       if (totals_option)
1395         print_total_written ();
1396       break;
1397
1398     case EXTRACT_SUBCOMMAND:
1399       extr_init ();
1400       read_and (extract_archive);
1401
1402       /* FIXME: should extract_finish () even if an ordinary signal is
1403          received.  */
1404       extract_finish ();
1405
1406       break;
1407
1408     case LIST_SUBCOMMAND:
1409       read_and (list_archive);
1410       break;
1411
1412     case DIFF_SUBCOMMAND:
1413       diff_init ();
1414       read_and (diff_archive);
1415       break;
1416     }
1417
1418   if (check_links_option)
1419       check_links ();
1420
1421   if (volno_file_option)
1422     closeout_volume_number ();
1423
1424   /* Dispose of allocated memory, and return.  */
1425
1426   free (archive_name_array);
1427   name_term ();
1428
1429   if (stdlis != stderr && (ferror (stdlis) || fclose (stdlis) != 0))
1430     FATAL_ERROR ((0, 0, _("Error in writing to standard output")));
1431   if (exit_status == TAREXIT_FAILURE)
1432     error (0, 0, _("Error exit delayed from previous errors"));
1433   if (ferror (stderr) || fclose (stderr) != 0)
1434     exit_status = TAREXIT_FAILURE;
1435   exit (exit_status);
1436 }
1437
1438 void
1439 destroy_stat (struct tar_stat_info *st)
1440 {
1441   free (st->orig_file_name);
1442   free (st->file_name);
1443   free (st->link_name);
1444   free (st->uname);
1445   free (st->gname);
1446   memset (st, 0, sizeof (*st));
1447 }
1448