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