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