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