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