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