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