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