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