]> Dogcows Code - chaz/tar/blob - src/tar.c
Use argp for command line parsing.
[chaz/tar] / src / tar.c
1 /* A tar (tape archiver) program.
2
3 Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1999, 2000,
4 2001, 2003, 2004 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 <argp.h>
26
27 #include <signal.h>
28 #if ! defined SIGCHLD && defined SIGCLD
29 # define SIGCHLD SIGCLD
30 #endif
31
32 /* The following causes "common.h" to produce definitions of all the global
33 variables, rather than just "extern" declarations of them. GNU tar does
34 depend on the system loader to preset all GLOBAL variables to neutral (or
35 zero) values; explicit initialization is usually not done. */
36 #define GLOBAL
37 #include "common.h"
38
39 #include <getdate.h>
40 #include <localedir.h>
41 #include <prepargs.h>
42 #include <quotearg.h>
43 #include <xstrtol.h>
44
45 /* Local declarations. */
46
47 #ifndef DEFAULT_ARCHIVE_FORMAT
48 # define DEFAULT_ARCHIVE_FORMAT GNU_FORMAT
49 #endif
50
51 #ifndef DEFAULT_ARCHIVE
52 # define DEFAULT_ARCHIVE "tar.out"
53 #endif
54
55 #ifndef DEFAULT_BLOCKING
56 # define DEFAULT_BLOCKING 20
57 #endif
58
59 \f
60 /* Miscellaneous. */
61
62 /* Name of option using stdin. */
63 static const char *stdin_used_by;
64
65 /* Doesn't return if stdin already requested. */
66 void
67 request_stdin (const char *option)
68 {
69 if (stdin_used_by)
70 USAGE_ERROR ((0, 0, _("Options `-%s' and `-%s' both want standard input"),
71 stdin_used_by, option));
72
73 stdin_used_by = option;
74 }
75
76 /* Returns true if and only if the user typed 'y' or 'Y'. */
77 int
78 confirm (const char *message_action, const char *message_name)
79 {
80 static FILE *confirm_file;
81 static int confirm_file_EOF;
82
83 if (!confirm_file)
84 {
85 if (archive == 0 || stdin_used_by)
86 {
87 confirm_file = fopen (TTY_NAME, "r");
88 if (! confirm_file)
89 open_fatal (TTY_NAME);
90 }
91 else
92 {
93 request_stdin ("-w");
94 confirm_file = stdin;
95 }
96 }
97
98 fprintf (stdlis, "%s %s?", message_action, quote (message_name));
99 fflush (stdlis);
100
101 {
102 int reply = confirm_file_EOF ? EOF : getc (confirm_file);
103 int character;
104
105 for (character = reply;
106 character != '\n';
107 character = getc (confirm_file))
108 if (character == EOF)
109 {
110 confirm_file_EOF = 1;
111 fputc ('\n', stdlis);
112 fflush (stdlis);
113 break;
114 }
115 return reply == 'y' || reply == 'Y';
116 }
117 }
118
119 static struct fmttab {
120 char const *name;
121 enum archive_format fmt;
122 } const fmttab[] = {
123 { "v7", V7_FORMAT },
124 { "oldgnu", OLDGNU_FORMAT },
125 { "ustar", USTAR_FORMAT },
126 { "posix", POSIX_FORMAT },
127 #if 0 /* not fully supported yet */
128 { "star", STAR_FORMAT },
129 #endif
130 { "gnu", GNU_FORMAT },
131 { NULL, 0 }
132 };
133
134 static void
135 set_archive_format (char const *name)
136 {
137 struct fmttab const *p;
138
139 for (p = fmttab; strcmp (p->name, name) != 0; )
140 if (! (++p)->name)
141 USAGE_ERROR ((0, 0, _("%s: Invalid archive format"),
142 quotearg_colon (name)));
143
144 archive_format = p->fmt;
145 }
146
147 static const char *
148 archive_format_string (enum archive_format fmt)
149 {
150 struct fmttab const *p;
151
152 for (p = fmttab; p->name; p++)
153 if (p->fmt == fmt)
154 return p->name;
155 return "unknown?";
156 }
157
158 #define FORMAT_MASK(n) (1<<(n))
159
160 static void
161 assert_format(unsigned fmt_mask)
162 {
163 if ((FORMAT_MASK(archive_format) & fmt_mask) == 0)
164 USAGE_ERROR ((0, 0,
165 _("GNU features wanted on incompatible archive format")));
166 }
167
168
169 \f
170 /* Options. */
171
172 /* For long options that unconditionally set a single flag, we have getopt
173 do it. For the others, we share the code for the equivalent short
174 named option, the name of which is stored in the otherwise-unused `val'
175 field of the `struct option'; for long options that have no equivalent
176 short option, we use non-characters as pseudo short options,
177 starting at CHAR_MAX + 1 and going upwards. */
178
179 enum
180 {
181 ANCHORED_OPTION = CHAR_MAX + 1,
182 ATIME_PRESERVE_OPTION,
183 BACKUP_OPTION,
184 CHECKPOINT_OPTION,
185 CHECK_LINKS_OPTION,
186 DELETE_OPTION,
187 EXCLUDE_OPTION,
188 FORCE_LOCAL_OPTION,
189 FORMAT_OPTION,
190 GROUP_OPTION,
191 IGNORE_CASE_OPTION,
192 IGNORE_FAILED_READ_OPTION,
193 INDEX_FILE_OPTION,
194 KEEP_NEWER_FILES_OPTION,
195 LICENSE_OPTION,
196 MODE_OPTION,
197 NEWER_MTIME_OPTION,
198 NO_ANCHORED_OPTION,
199 NO_IGNORE_CASE_OPTION,
200 NO_OVERWRITE_DIR_OPTION,
201 NO_RECURSION_OPTION,
202 NO_SAME_OWNER_OPTION,
203 NO_SAME_PERMISSIONS_OPTION,
204 NO_WILDCARDS_OPTION,
205 NO_WILDCARDS_MATCH_SLASH_OPTION,
206 NULL_OPTION,
207 NUMERIC_OWNER_OPTION,
208 OCCURRENCE_OPTION,
209 OLD_ARCHIVE_OPTION,
210 OVERWRITE_OPTION,
211 OWNER_OPTION,
212 PAX_OPTION,
213 POSIX_OPTION,
214 PRESERVE_OPTION,
215 RECORD_SIZE_OPTION,
216 RECURSION_OPTION,
217 RECURSIVE_UNLINK_OPTION,
218 REMOVE_FILES_OPTION,
219 RMT_COMMAND_OPTION,
220 RSH_COMMAND_OPTION,
221 SAME_OWNER_OPTION,
222 SHOW_DEFAULTS_OPTION,
223 SHOW_OMITTED_DIRS_OPTION,
224 STRIP_COMPONENTS_OPTION,
225 SUFFIX_OPTION,
226 TOTALS_OPTION,
227 USAGE_OPTION,
228 USE_COMPRESS_PROGRAM_OPTION,
229 UTC_OPTION,
230 VERSION_OPTION,
231 VOLNO_FILE_OPTION,
232 WILDCARDS_OPTION,
233 WILDCARDS_MATCH_SLASH_OPTION
234 };
235
236 const char *argp_program_version = "tar (" PACKAGE ") " VERSION;
237 const char *argp_program_bug_address = "<" PACKAGE_BUGREPORT ">";
238 static char doc[] = N_("GNU `tar' saves many files together into a single tape or disk archive, and can restore individual files from the archive.\n\
239 \n\
240 Examples:\n\
241 tar -cf archive.tar foo bar # Create archive.tar from files foo and bar.\n\
242 tar -tvf archive.tar # List all files in archive.tar verbosely.\n\
243 tar -xf archive.tar # Extract all files from archive.tar.\n\
244 \vThe backup suffix is `~', unless set with --suffix or SIMPLE_BACKUP_SUFFIX.\n\
245 The version control may be set with --backup or VERSION_CONTROL, values are:\n\n\
246 t, numbered make numbered backups\n\
247 nil, existing numbered if numbered backups exist, simple otherwise\n\
248 never, simple always make simple backups\n");
249
250
251 static struct argp_option options[] = {
252 {NULL, 0, NULL, 0,
253 N_("Main operation mode:"), 0},
254
255 {"list", 't', 0, 0,
256 N_("list the contents of an archive"), 10 },
257 {"extract", 'x', 0, 0,
258 N_("extract files from an archive"), 10 },
259 {"get", 0, 0, OPTION_ALIAS, NULL},
260 {"create", 'c', 0, 0,
261 N_("create a new archive"), 10 },
262 {"diff", 'd', 0, 0,
263 N_("find differences between archive and file system"), 10 },
264 {"compare", 0, 0, OPTION_ALIAS, NULL, 10},
265 {"append", 'r', 0, 0,
266 N_("append files to the end of an archive"), 10 },
267 {"update", 'u', 0, 0,
268 N_("only append files newer than copy in archive"), 10 },
269 {"catenate", 'A', 0, 0,
270 N_("append tar files to an archive"), 10 },
271 {"concatenate", 0, 0, OPTION_ALIAS, NULL, 10},
272 {"delete", DELETE_OPTION, 0, 0,
273 N_("delete from the archive (not on mag tapes!)"), 10 },
274
275 {NULL, 0, NULL, 0,
276 N_("Operation modifiers:"), 20},
277
278 {"verify", 'W', 0, 0,
279 N_("attempt to verify the archive after writing it"), 21 },
280 {"remove-files", REMOVE_FILES_OPTION, 0, 0,
281 N_("remove files after adding them to the archive"), 21 },
282 {"keep-old-files", 'k', 0, 0,
283 N_("don't replace existing files when extracting"), 21 },
284 {"keep-newer-files", KEEP_NEWER_FILES_OPTION, 0, 0,
285 N_("don't replace existing files that are newer than their archive copies"), 21 },
286 {"no-overwrite-dir", NO_OVERWRITE_DIR_OPTION, 0, 0,
287 N_("preserve metadata of existing directories"), 21 },
288 {"overwrite", OVERWRITE_OPTION, 0, 0,
289 N_("overwrite existing files when extracting"), 21 },
290 {"unlink-first", 'U', 0, 0,
291 N_("remove each file prior to extracting over it"), 21 },
292 {"recursive-unlink", RECURSIVE_UNLINK_OPTION, 0, 0,
293 N_("empty hierarchies prior to extracting directory"), 21 },
294 {"sparse", 'S', 0, 0,
295 N_("handle sparse files efficiently"), 21 },
296 {"to-stdout", 'O', 0, 0,
297 N_("extract files to standard output"), 21 },
298 {"incremental", 'G', 0, 0,
299 N_("handle old GNU-format incremental backup"), 21 },
300 {"listed-incremental", 'g', N_("FILE"), 0,
301 N_("handle new GNU-format incremental backup"), 21 },
302 {"ignore-failed-read", IGNORE_FAILED_READ_OPTION, 0, 0,
303 N_("do not exit with nonzero on unreadable files"), 21 },
304 {"occurrence", OCCURRENCE_OPTION, N_("NUMBER"), OPTION_ARG_OPTIONAL,
305 N_("process only the NUMth occurrence of each file in the archive. This option is valid only in conjunction with one of the subcommands --delete, --diff, --extract or --list and when a list of files is given either on the command line or via -T option. NUMBER defaults to 1."), 21 },
306
307 {NULL, 0, NULL, 0,
308 N_("Handling of file attributes:"), 30 },
309
310 {"owner", OWNER_OPTION, N_("NAME"), 0,
311 N_("force NAME as owner for added files"), 31 },
312 {"group", GROUP_OPTION, N_("NAME"), 0,
313 N_("force NAME as group for added files"), 31 },
314 {"mode", MODE_OPTION, N_("CHANGES"), 0,
315 N_("force (symbolic) mode CHANGES for added files"), 31 },
316 {"atime-preserve", ATIME_PRESERVE_OPTION, 0, 0,
317 N_("don't change access times on dumped files"), 31 },
318 {"touch", 'm', 0, 0,
319 N_("don't extract file modified time"), 31 },
320 {"same-owner", SAME_OWNER_OPTION, 0, 0,
321 N_("try extracting files with the same ownership"), 31 },
322 {"no-same-owner", NO_SAME_OWNER_OPTION, 0, 0,
323 N_("extract files as yourself"), 31 },
324 {"numeric-owner", NUMERIC_OWNER_OPTION, 0, 0,
325 N_("always use numbers for user/group names"), 31 },
326 {"preserve-permissions", 'p', 0, 0,
327 N_("extract permissions information"), 31 },
328 {"same-permissions", 0, 0, OPTION_ALIAS, NULL, 31 },
329 {"no-same-permissions", NO_SAME_PERMISSIONS_OPTION, 0, 0,
330 N_("do not extract permissions information"), 31 },
331 {"preserve-order", 's', 0, 0,
332 N_("sort names to extract to match archive"), 31 },
333 {"same-order", 0, 0, OPTION_ALIAS, NULL, 31 },
334 {"preserve", PRESERVE_OPTION, 0, 0,
335 N_("same as both -p and -s"), 31 },
336
337 {NULL, 0, NULL, 0,
338 N_("Device selection and switching:"), 40 },
339
340 {"file", 'f', N_("ARCHIVE"), 0,
341 N_("use archive file or device ARCHIVE"), 41 },
342 {"force-local", FORCE_LOCAL_OPTION, 0, 0,
343 N_("archive file is local even if has a colon"), 41 },
344 {"rmt-command", RMT_COMMAND_OPTION, N_("COMMAND"), 0,
345 N_("use given rmt COMMAND instead of rmt"), 41 },
346 {"rsh-command", RSH_COMMAND_OPTION, N_("COMMAND"), 0,
347 N_("use remote COMMAND instead of rsh"), 41 },
348 #ifdef DEVICE_PREFIX
349 {"-[0-7][lmh]", 0, NULL, OPTION_DOC,
350 N_("specify drive and density"), 41 },
351 #endif
352 {NULL, '0', NULL, OPTION_HIDDEN, NULL, 41 },
353 {NULL, '1', NULL, OPTION_HIDDEN, NULL, 41 },
354 {NULL, '2', NULL, OPTION_HIDDEN, NULL, 41 },
355 {NULL, '3', NULL, OPTION_HIDDEN, NULL, 41 },
356 {NULL, '4', NULL, OPTION_HIDDEN, NULL, 41 },
357 {NULL, '5', NULL, OPTION_HIDDEN, NULL, 41 },
358 {NULL, '6', NULL, OPTION_HIDDEN, NULL, 41 },
359 {NULL, '7', NULL, OPTION_HIDDEN, NULL, 41 },
360 {NULL, '8', NULL, OPTION_HIDDEN, NULL, 41 },
361 {NULL, '9', NULL, OPTION_HIDDEN, NULL, 41 },
362
363 {"multi-volume", 'M', 0, 0,
364 N_("create/list/extract multi-volume archive"), 41 },
365 {"tape-length", 'L', N_("NUMBER"), 0,
366 N_("change tape after writing NUMBER x 1024 bytes"), 41 },
367 {"info-script", 'F', N_("NAME"), 0,
368 N_("run script at end of each tape (implies -M)"), 41 },
369 {"new-volume-script", 0, 0, OPTION_ALIAS, NULL, 41 },
370 {"volno-file", VOLNO_FILE_OPTION, N_("FILE"), 0,
371 N_("use/update the volume number in FILE"), 41 },
372
373 {NULL, 0, NULL, 0,
374 N_("Device blocking:"), 50 },
375
376 {"blocking-factor", 'b', N_("BLOCKS"), 0,
377 N_("BLOCKS x 512 bytes per record"), 51 },
378 {"record-size", RECORD_SIZE_OPTION, N_("NUMBER"), 0,
379 N_("SIZE bytes per record, multiple of 512"), 51 },
380 {"ignore-zeros", 'i', 0, 0,
381 N_("ignore zeroed blocks in archive (means EOF)"), 51 },
382 {"read-full-records", 'B', 0, 0,
383 N_("reblock as we read (for 4.2BSD pipes)"), 51 },
384
385 {NULL, 0, NULL, 0,
386 N_("Archive format selection:"), 60 },
387
388 {"format", FORMAT_OPTION, N_("FORMAT"), 0,
389 N_("create archive of the given format."), 61 },
390
391 {"", 0, NULL, OPTION_DOC, N_("FORMAT is one of the following:"), 62},
392 {"", 0, NULL, OPTION_DOC, N_("v7 old V7 tar format"), 63},
393 {"", 0, NULL, OPTION_DOC, N_("oldgnu GNU format as per tar <= 1.12"), 63},
394 {"", 0, NULL, OPTION_DOC, N_("gnu GNU tar 1.13.x format"), 63},
395 {"", 0, NULL, OPTION_DOC, N_("ustar POSIX 1003.1-1988 (ustar) format"), 63 },
396 {"", 0, NULL, OPTION_DOC, N_("posix POSIX 1003.1-2001 (pax) format"), 63 },
397
398 {"old-archive", OLD_ARCHIVE_OPTION, 0, 0, /* FIXME */
399 N_("same as --format=v7"), 68 },
400 {"portability", 0, 0, OPTION_ALIAS, NULL, 68 },
401 {"posix", POSIX_OPTION, 0, 0,
402 N_("same as --format=posix"), 68 },
403 {"pax-option", PAX_OPTION, N_("keyword[[:]=value][,keyword[[:]=value], ...]"), 0,
404 N_("control pax keywords"), 68 },
405 {"label", 'V', N_("TEXT"), 0,
406 N_("create archive with volume name NAME. At list/extract time, use TEXT as a globbing pattern"), 68 },
407 {"bzip2", 'j', 0, 0,
408 N_("filter the archive through bzip2"), 68 },
409 {"gzip", 'z', 0, 0,
410 N_("filter the archive through gzip"), 68 },
411 {"gunzip", 0, 0, OPTION_ALIAS, NULL, 68 },
412 {"ungzip", 0, 0, OPTION_ALIAS, NULL, 68 },
413 {"compress", 'Z', 0, 0,
414 N_("filter the archive through compress"), 68 },
415 {"uncompress", 0, 0, OPTION_ALIAS, NULL, 68 },
416 {"use-compress-program", USE_COMPRESS_PROGRAM_OPTION, N_("PROG"), 0,
417 N_("filter through PROG (must accept -d)"), 68 },
418
419 {NULL, 0, NULL, 0,
420 N_("Local file selection:"), 70 },
421
422 {"directory", 'C', N_("DIR"), 0,
423 N_("change to directory DIR"), 71 },
424 {"files-from", 'T', N_("FILE-OF-NAMES"), 0,
425 N_("get names to extract or create from file NAME"), 71 },
426 {"null", NULL_OPTION, 0, 0,
427 N_("-T reads null-terminated names, disable -C"), 71 },
428 {"exclude", EXCLUDE_OPTION, N_("PATTERN"), 0,
429 N_("exclude files, given as a PATTERN"), 71 },
430 {"exclude-from", 'X', N_("FILE"), 0,
431 N_("exclude patterns listed in FILE"), 71 },
432 {"ignore-case", IGNORE_CASE_OPTION, 0, 0,
433 N_("exclusion ignores case"), 71 },
434 {"anchored", ANCHORED_OPTION, 0, 0,
435 N_("exclude patterns match file name start (default)"), 71 },
436 {"no-anchored", NO_ANCHORED_OPTION, 0, 0,
437 N_("exclude patterns match after any /"), 71 },
438 {"no-ignore-case", NO_IGNORE_CASE_OPTION, 0, 0,
439 N_("exclusion is case sensitive (default)"), 71 },
440 {"no-wildcards", NO_WILDCARDS_OPTION, 0, 0,
441 N_("exclude patterns are plain strings"), 71 },
442 {"no-wildcards-match-slash", NO_WILDCARDS_MATCH_SLASH_OPTION, 0, 0,
443 N_("exclude pattern wildcards do not match '/'"), 71 },
444 {"no-recursion", NO_RECURSION_OPTION, 0, 0,
445 N_("avoid descending automatically in directories"), 71 },
446 {"one-file-system", 'l', 0, 0, /* FIXME: emit warning */
447 N_("stay in local file system when creating archive"), 71 },
448 {"recursion", RECURSION_OPTION, 0, 0,
449 N_("recurse into directories (default)"), 71 },
450 {"absolute-names", 'P', 0, 0,
451 N_("don't strip leading `/'s from file names"), 71 },
452 {"dereference", 'h', 0, 0,
453 N_("dump instead the files symlinks point to"), 71 },
454 {"starting-file", 'K', N_("MEMBER-NAME"), 0,
455 N_("begin at member MEMBER-NAME in the archive"), 71 },
456 {"strip-components", STRIP_COMPONENTS_OPTION, N_("NUMBER"), 0,
457 N_("strip NUMBER leading components from file names"), 71 },
458 {"newer", 'N', N_("DATE-OR-FILE"), 0,
459 N_("only store files newer than DATE-OR-FILE"), 71 },
460 {"newer-mtime", NEWER_MTIME_OPTION, N_("DATE"), 0,
461 N_("compare date and time when data changed only"), 71 },
462 {"after-date", 'N', N_("DATE"), 0,
463 N_("same as -N"), 71 },
464 {"backup", BACKUP_OPTION, N_("CONTROL"), OPTION_ARG_OPTIONAL,
465 N_("backup before removal, choose version CONTROL"), 71 },
466 {"suffix", SUFFIX_OPTION, N_("STRING"), 0,
467 N_("backup before removal, override usual suffix ('~' unless overridden by environment variable SIMPLE_BACKUP_SUFFIX"), 71 },
468 {"wildcards", WILDCARDS_OPTION, 0, 0,
469 N_("exclude patterns use wildcards (default)"), 71 },
470 {"wildcards-match-slash", WILDCARDS_MATCH_SLASH_OPTION, 0, 0,
471 N_("exclude pattern wildcards match '/' (default)"), 71 },
472
473 {NULL, 0, NULL, 0,
474 N_("Informative output:"), 80 },
475
476 {"verbose", 'v', 0, 0,
477 N_("verbosely list files processed"), 81 },
478 {"checkpoint", CHECKPOINT_OPTION, 0, 0,
479 N_("print directory names while reading the archive"), 81 },
480 {"check-links", CHECK_LINKS_OPTION, 0, 0,
481 N_("print a message if not all links are dumped"), 82 },
482 {"totals", TOTALS_OPTION, 0, 0,
483 N_("print total bytes written while creating archive"), 82 },
484 {"utc", UTC_OPTION, 0, 0,
485 N_("print file modification dates in UTC"), 82 },
486 {"index-file", INDEX_FILE_OPTION, N_("FILE"), 0,
487 N_("send verbose output to FILE"), 82 },
488 {"block-number", 'R', 0, 0,
489 N_("show block number within archive with each message"), 82 },
490 {"interactive", 'w', 0, 0,
491 N_("ask for confirmation for every action"), 82 },
492 {"confirmation", 0, 0, OPTION_ALIAS, NULL, 82 },
493 {"show-defaults", SHOW_DEFAULTS_OPTION, 0, 0,
494 N_("Show tar defaults"), 82 },
495 {"show-omitted-dirs", SHOW_OMITTED_DIRS_OPTION, 0, 0,
496 N_("When listing or extracting, list each directory that does not match search criteria"), 82 },
497
498 {NULL, 0, NULL, 0,
499 N_("Compatibility options:"), 90 },
500
501 {NULL, 'o', 0, 0,
502 N_("when creating, same as --old-archive. When extracting, same as --no-same-owner"), 91 },
503
504 {NULL, 0, NULL, 0,
505 N_("Other options:"), 100 },
506
507 {"help", '?', 0, 0, N_("Give this help list"), -1},
508 {"usage", USAGE_OPTION, 0, 0, N_("Give a short usage message"), -1},
509 {"license", LICENSE_OPTION, 0, 0, N_("Print license and exit"), -1},
510 {"version", VERSION_OPTION, 0, 0, N_("Print program version"), -1},
511 /* FIXME -V (--label) conflicts with the default short option for
512 --version */
513
514 {0, 0, 0, 0}
515 };
516
517 struct tar_args {
518 char const *textual_date_option;
519 int exclude_options;
520 bool o_option;
521 int pax_option;
522 char const *backup_suffix_string;
523 char const *version_control_string;
524 int input_files;
525 };
526
527 static void
528 show_default_settings (FILE *stream)
529 {
530 fprintf (stream,
531 "--format=%s -f%s -b%d --rmt-command=%s --rsh-command=%s\n",
532 archive_format_string (DEFAULT_ARCHIVE_FORMAT),
533 DEFAULT_ARCHIVE, DEFAULT_BLOCKING,
534 DEFAULT_RMT_COMMAND, REMOTE_SHELL);
535 }
536
537 static void
538 set_subcommand_option (enum subcommand subcommand)
539 {
540 if (subcommand_option != UNKNOWN_SUBCOMMAND
541 && subcommand_option != subcommand)
542 USAGE_ERROR ((0, 0,
543 _("You may not specify more than one `-Acdtrux' option")));
544
545 subcommand_option = subcommand;
546 }
547
548 static void
549 set_use_compress_program_option (const char *string)
550 {
551 if (use_compress_program_option && strcmp (use_compress_program_option, string) != 0)
552 USAGE_ERROR ((0, 0, _("Conflicting compression options")));
553
554 use_compress_program_option = string;
555 }
556
557 void
558 license ()
559 {
560 printf ("tar (%s) %s\n%s\n", PACKAGE_NAME, PACKAGE_VERSION,
561 "Copyright (C) 2004 Free Software Foundation, Inc.\n");
562 puts (_("Based on the work of John Gilmore and Jay Fenlason. See AUTHORS\n\
563 for complete list of authors.\n"));
564 printf (_(" GNU tar is free software; you can redistribute it and/or modify\n"
565 " it under the terms of the GNU General Public License as published by\n"
566 " the Free Software Foundation; either version 2 of the License, or\n"
567 " (at your option) any later version.\n"
568 "\n"
569 " GNU Mailutils is distributed in the hope that it will be useful,\n"
570 " but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
571 " MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
572 " GNU General Public License for more details.\n"
573 "\n"
574 " You should have received a copy of the GNU General Public License\n"
575 " along with GNU Mailutils; if not, write to the Free Software\n"
576 " Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\n\n"));
577 exit (0);
578 }
579
580 static error_t
581 parse_opt(int key, char *arg, struct argp_state *state)
582 {
583 struct tar_args *args = state->input;
584
585 switch (key)
586 {
587 case 1:
588 /* File name or non-parsed option, because of ARGP_IN_ORDER */
589 name_add (optarg);
590 args->input_files++;
591 break;
592
593 case 'A':
594 set_subcommand_option (CAT_SUBCOMMAND);
595 break;
596
597 case 'b':
598 {
599 uintmax_t u;
600 if (! (xstrtoumax (arg, 0, 10, &u, "") == LONGINT_OK
601 && u == (blocking_factor = u)
602 && 0 < blocking_factor
603 && u == (record_size = u * BLOCKSIZE) / BLOCKSIZE))
604 USAGE_ERROR ((0, 0, "%s: %s", quotearg_colon (arg),
605 _("Invalid blocking factor")));
606 }
607 break;
608
609 case 'B':
610 /* Try to reblock input records. For reading 4.2BSD pipes. */
611
612 /* It would surely make sense to exchange -B and -R, but it seems
613 that -B has been used for a long while in Sun tar and most
614 BSD-derived systems. This is a consequence of the block/record
615 terminology confusion. */
616
617 read_full_records_option = true;
618 break;
619
620 case 'c':
621 set_subcommand_option (CREATE_SUBCOMMAND);
622 break;
623
624 case 'C':
625 name_add ("-C");
626 name_add (arg);
627 break;
628
629 case 'd':
630 set_subcommand_option (DIFF_SUBCOMMAND);
631 break;
632
633 case 'f':
634 if (archive_names == allocated_archive_names)
635 {
636 allocated_archive_names *= 2;
637 archive_name_array =
638 xrealloc (archive_name_array,
639 sizeof (const char *) * allocated_archive_names);
640 }
641 archive_name_array[archive_names++] = arg;
642 break;
643
644 case 'F':
645 /* Since -F is only useful with -M, make it implied. Run this
646 script at the end of each tape. */
647
648 info_script_option = arg;
649 multi_volume_option = true;
650 break;
651
652 case 'g':
653 listed_incremental_option = arg;
654 after_date_option = true;
655 /* Fall through. */
656
657 case 'G':
658 /* We are making an incremental dump (FIXME: are we?); save
659 directories at the beginning of the archive, and include in each
660 directory its contents. */
661
662 incremental_option = true;
663 break;
664
665 case 'h':
666 /* Follow symbolic links. */
667 dereference_option = true;
668 break;
669
670 case 'i':
671 /* Ignore zero blocks (eofs). This can't be the default,
672 because Unix tar writes two blocks of zeros, then pads out
673 the record with garbage. */
674
675 ignore_zeros_option = true;
676 break;
677
678 case 'I':
679 USAGE_ERROR ((0, 0,
680 _("Warning: the -I option is not supported;"
681 " perhaps you meant -j or -T?")));
682 break;
683
684 case 'j':
685 set_use_compress_program_option ("bzip2");
686 break;
687
688 case 'k':
689 /* Don't replace existing files. */
690 old_files_option = KEEP_OLD_FILES;
691 break;
692
693 case 'K':
694 starting_file_option = true;
695 addname (arg, 0);
696 break;
697
698 case 'l':
699 /* When dumping directories, don't dump files/subdirectories
700 that are on other filesystems. */
701
702 one_file_system_option = true;
703 break;
704
705 case 'L':
706 {
707 uintmax_t u;
708 if (xstrtoumax (arg, 0, 10, &u, "") != LONGINT_OK)
709 USAGE_ERROR ((0, 0, "%s: %s", quotearg_colon (arg),
710 _("Invalid tape length")));
711 tape_length_option = 1024 * (tarlong) u;
712 multi_volume_option = true;
713 }
714 break;
715
716 case 'm':
717 touch_option = true;
718 break;
719
720 case 'M':
721 /* Make multivolume archive: when we can't write any more into
722 the archive, re-open it, and continue writing. */
723
724 multi_volume_option = true;
725 break;
726
727 #if !MSDOS
728 case 'N':
729 after_date_option = true;
730 /* Fall through. */
731
732 case NEWER_MTIME_OPTION:
733 if (NEWER_OPTION_INITIALIZED (newer_mtime_option))
734 USAGE_ERROR ((0, 0, _("More than one threshold date")));
735
736 if (FILESYSTEM_PREFIX_LEN (arg) != 0
737 || ISSLASH (*arg)
738 || *arg == '.')
739 {
740 struct stat st;
741 if (deref_stat (dereference_option, arg, &st) != 0)
742 {
743 stat_error (arg);
744 USAGE_ERROR ((0, 0, _("Date file not found")));
745 }
746 newer_mtime_option.tv_sec = st.st_mtime;
747 newer_mtime_option.tv_nsec = TIMESPEC_NS (st.st_mtim);
748 }
749 else
750 {
751 if (! get_date (&newer_mtime_option, arg, NULL))
752 {
753 WARN ((0, 0, _("Substituting %s for unknown date format %s"),
754 tartime (newer_mtime_option.tv_sec), quote (arg)));
755 newer_mtime_option.tv_nsec = 0;
756 }
757 else
758 args->textual_date_option = arg;
759 }
760
761 break;
762 #endif /* not MSDOS */
763
764 case 'o':
765 args->o_option = true;
766 break;
767
768 case 'O':
769 to_stdout_option = true;
770 break;
771
772 case 'p':
773 same_permissions_option = true;
774 break;
775
776 case 'P':
777 absolute_names_option = true;
778 break;
779
780 case 'r':
781 set_subcommand_option (APPEND_SUBCOMMAND);
782 break;
783
784 case 'R':
785 /* Print block numbers for debugging bad tar archives. */
786
787 /* It would surely make sense to exchange -B and -R, but it seems
788 that -B has been used for a long while in Sun tar ans most
789 BSD-derived systems. This is a consequence of the block/record
790 terminology confusion. */
791
792 block_number_option = true;
793 break;
794
795 case 's':
796 /* Names to extr are sorted. */
797
798 same_order_option = true;
799 break;
800
801 case 'S':
802 sparse_option = true;
803 break;
804
805 case 't':
806 set_subcommand_option (LIST_SUBCOMMAND);
807 verbose_option++;
808 break;
809
810 case 'T':
811 files_from_option = arg;
812 break;
813
814 case 'u':
815 set_subcommand_option (UPDATE_SUBCOMMAND);
816 break;
817
818 case 'U':
819 old_files_option = UNLINK_FIRST_OLD_FILES;
820 break;
821
822 case UTC_OPTION:
823 utc_option = true;
824 break;
825
826 case 'v':
827 verbose_option++;
828 break;
829
830 case 'V':
831 volume_label_option = arg;
832 break;
833
834 case 'w':
835 interactive_option = true;
836 break;
837
838 case 'W':
839 verify_option = true;
840 break;
841
842 case 'x':
843 set_subcommand_option (EXTRACT_SUBCOMMAND);
844 break;
845
846 case 'X':
847 if (add_exclude_file (add_exclude, excluded, arg,
848 args->exclude_options | recursion_option, '\n')
849 != 0)
850 {
851 int e = errno;
852 FATAL_ERROR ((0, e, "%s", quotearg_colon (arg)));
853 }
854 break;
855
856 case 'y':
857 USAGE_ERROR ((0, 0,
858 _("Warning: the -y option is not supported;"
859 " perhaps you meant -j?")));
860 break;
861
862 case 'z':
863 set_use_compress_program_option ("gzip");
864 break;
865
866 case 'Z':
867 set_use_compress_program_option ("compress");
868 break;
869
870 case ANCHORED_OPTION:
871 args->exclude_options |= EXCLUDE_ANCHORED;
872 break;
873
874 case ATIME_PRESERVE_OPTION:
875 atime_preserve_option = true;
876 break;
877
878 case CHECKPOINT_OPTION:
879 checkpoint_option = true;
880 break;
881
882 case BACKUP_OPTION:
883 backup_option = true;
884 if (arg)
885 args->version_control_string = arg;
886 break;
887
888 case DELETE_OPTION:
889 set_subcommand_option (DELETE_SUBCOMMAND);
890 break;
891
892 case EXCLUDE_OPTION:
893 add_exclude (excluded, arg, args->exclude_options | recursion_option);
894 break;
895
896 case FORCE_LOCAL_OPTION:
897 force_local_option = true;
898 break;
899
900 case FORMAT_OPTION:
901 set_archive_format (arg);
902 break;
903
904 case INDEX_FILE_OPTION:
905 index_file_name = arg;
906 break;
907
908 case IGNORE_CASE_OPTION:
909 args->exclude_options |= FNM_CASEFOLD;
910 break;
911
912 case IGNORE_FAILED_READ_OPTION:
913 ignore_failed_read_option = true;
914 break;
915
916 case KEEP_NEWER_FILES_OPTION:
917 old_files_option = KEEP_NEWER_FILES;
918 break;
919
920 case GROUP_OPTION:
921 if (! (strlen (arg) < GNAME_FIELD_SIZE
922 && gname_to_gid (arg, &group_option)))
923 {
924 uintmax_t g;
925 if (xstrtoumax (arg, 0, 10, &g, "") == LONGINT_OK
926 && g == (gid_t) g)
927 group_option = g;
928 else
929 FATAL_ERROR ((0, 0, "%s: %s", quotearg_colon (arg),
930 _("%s: Invalid group")));
931 }
932 break;
933
934 case MODE_OPTION:
935 mode_option
936 = mode_compile (arg,
937 MODE_MASK_EQUALS | MODE_MASK_PLUS | MODE_MASK_MINUS);
938 if (mode_option == MODE_INVALID)
939 FATAL_ERROR ((0, 0, _("Invalid mode given on option")));
940 if (mode_option == MODE_MEMORY_EXHAUSTED)
941 xalloc_die ();
942 break;
943
944 case NO_ANCHORED_OPTION:
945 args->exclude_options &= ~ EXCLUDE_ANCHORED;
946 break;
947
948 case NO_IGNORE_CASE_OPTION:
949 args->exclude_options &= ~ FNM_CASEFOLD;
950 break;
951
952 case NO_OVERWRITE_DIR_OPTION:
953 old_files_option = NO_OVERWRITE_DIR_OLD_FILES;
954 break;
955
956 case NO_WILDCARDS_OPTION:
957 args->exclude_options &= ~ EXCLUDE_WILDCARDS;
958 break;
959
960 case NO_WILDCARDS_MATCH_SLASH_OPTION:
961 args->exclude_options |= FNM_FILE_NAME;
962 break;
963
964 case NULL_OPTION:
965 filename_terminator = '\0';
966 break;
967
968 case NUMERIC_OWNER_OPTION:
969 numeric_owner_option = true;
970 break;
971
972 case OCCURRENCE_OPTION:
973 if (!arg)
974 occurrence_option = 1;
975 else
976 {
977 uintmax_t u;
978 if (xstrtoumax (arg, 0, 10, &u, "") == LONGINT_OK)
979 occurrence_option = u;
980 else
981 FATAL_ERROR ((0, 0, "%s: %s", quotearg_colon (arg),
982 _("Invalid number")));
983 }
984 break;
985
986 case OVERWRITE_OPTION:
987 old_files_option = OVERWRITE_OLD_FILES;
988 break;
989
990 case OWNER_OPTION:
991 if (! (strlen (arg) < UNAME_FIELD_SIZE
992 && uname_to_uid (arg, &owner_option)))
993 {
994 uintmax_t u;
995 if (xstrtoumax (arg, 0, 10, &u, "") == LONGINT_OK
996 && u == (uid_t) u)
997 owner_option = u;
998 else
999 FATAL_ERROR ((0, 0, "%s: %s", quotearg_colon (arg),
1000 _("Invalid owner")));
1001 }
1002 break;
1003
1004 case PAX_OPTION:
1005 args->pax_option++;
1006 xheader_set_option (arg);
1007 break;
1008
1009 case POSIX_OPTION:
1010 set_archive_format ("posix");
1011 break;
1012
1013 case PRESERVE_OPTION:
1014 same_permissions_option = true;
1015 same_order_option = true;
1016 break;
1017
1018 case RECORD_SIZE_OPTION:
1019 {
1020 uintmax_t u;
1021 if (! (xstrtoumax (arg, 0, 10, &u, "") == LONGINT_OK
1022 && u == (size_t) u))
1023 USAGE_ERROR ((0, 0, "%s: %s", quotearg_colon (arg),
1024 _("Invalid record size")));
1025 record_size = u;
1026 if (record_size % BLOCKSIZE != 0)
1027 USAGE_ERROR ((0, 0, _("Record size must be a multiple of %d."),
1028 BLOCKSIZE));
1029 blocking_factor = record_size / BLOCKSIZE;
1030 }
1031 break;
1032
1033 case RECURSIVE_UNLINK_OPTION:
1034 recursive_unlink_option = true;
1035 break;
1036
1037 case REMOVE_FILES_OPTION:
1038 remove_files_option = true;
1039 break;
1040
1041 case RMT_COMMAND_OPTION:
1042 rmt_command_option = arg;
1043 break;
1044
1045 case RSH_COMMAND_OPTION:
1046 rsh_command_option = arg;
1047 break;
1048
1049 case SHOW_DEFAULTS_OPTION:
1050 show_default_settings (stdout);
1051 exit(0);
1052
1053 case STRIP_COMPONENTS_OPTION:
1054 {
1055 uintmax_t u;
1056 if (! (xstrtoumax (arg, 0, 10, &u, "") == LONGINT_OK
1057 && u == (size_t) u))
1058 USAGE_ERROR ((0, 0, "%s: %s", quotearg_colon (arg),
1059 _("Invalid number of elements")));
1060 strip_name_components = u;
1061 }
1062 break;
1063
1064 case SHOW_OMITTED_DIRS_OPTION:
1065 show_omitted_dirs_option = true;
1066 break;
1067
1068 case SUFFIX_OPTION:
1069 backup_option = true;
1070 args->backup_suffix_string = arg;
1071 break;
1072
1073 case TOTALS_OPTION:
1074 totals_option = true;
1075 break;
1076
1077 case USE_COMPRESS_PROGRAM_OPTION:
1078 set_use_compress_program_option (arg);
1079 break;
1080
1081 case VOLNO_FILE_OPTION:
1082 volno_file_option = arg;
1083 break;
1084
1085 case WILDCARDS_OPTION:
1086 args->exclude_options |= EXCLUDE_WILDCARDS;
1087 break;
1088
1089 case WILDCARDS_MATCH_SLASH_OPTION:
1090 args->exclude_options &= ~ FNM_FILE_NAME;
1091 break;
1092
1093 case CHECK_LINKS_OPTION:
1094 check_links_option = 1;
1095 break;
1096
1097 case NO_RECURSION_OPTION:
1098 recursion_option = 0;
1099 break;
1100
1101 case NO_SAME_OWNER_OPTION:
1102 same_owner_option = -1;
1103 break;
1104
1105 case NO_SAME_PERMISSIONS_OPTION:
1106 same_permissions_option = -1;
1107 break;
1108
1109 case RECURSION_OPTION:
1110 recursion_option = FNM_LEADING_DIR;
1111 break;
1112
1113 case SAME_OWNER_OPTION:
1114 same_owner_option = 1;
1115 break;
1116
1117 case '0':
1118 case '1':
1119 case '2':
1120 case '3':
1121 case '4':
1122 case '5':
1123 case '6':
1124 case '7':
1125
1126 #ifdef DEVICE_PREFIX
1127 {
1128 int device = key - '0';
1129 int density;
1130 static char buf[sizeof DEVICE_PREFIX + 10];
1131 char *cursor;
1132
1133 if (arg[1])
1134 argp_error (state, _("Malformed density argument: '%s'"), arg);
1135
1136 strcpy (buf, DEVICE_PREFIX);
1137 cursor = buf + strlen (buf);
1138
1139 #ifdef DENSITY_LETTER
1140
1141 sprintf (cursor, "%d%c", device, arg[0]);
1142
1143 #else /* not DENSITY_LETTER */
1144
1145 switch (arg[0])
1146 {
1147 case 'l':
1148 #ifdef LOW_NUM
1149 device += LOW_NUM;
1150 #endif
1151 break;
1152
1153 case 'm':
1154 #ifdef MID_NUM
1155 device += MID_NUM;
1156 #else
1157 device += 8;
1158 #endif
1159 break;
1160
1161 case 'h':
1162 #ifdef HGH_NUM
1163 device += HGH_NUM;
1164 #else
1165 device += 16;
1166 #endif
1167 break;
1168
1169 default:
1170 argp_error (state, _("Unknown density: '%c'"), arg[0]);
1171 }
1172 sprintf (cursor, "%d", device);
1173
1174 #endif /* not DENSITY_LETTER */
1175
1176 if (archive_names == allocated_archive_names)
1177 {
1178 allocated_archive_names *= 2;
1179 archive_name_array =
1180 xrealloc (archive_name_array,
1181 sizeof (const char *) * allocated_archive_names);
1182 }
1183 archive_name_array[archive_names++] = strdup (buf);
1184 }
1185 break;
1186
1187 #else /* not DEVICE_PREFIX */
1188
1189 argp_error (state,
1190 _("Options `-[0-7][lmh]' not supported by *this* tar"));
1191
1192 #endif /* not DEVICE_PREFIX */
1193
1194 case '?':
1195 state->flags |= ARGP_NO_EXIT;
1196 argp_state_help (state, state->out_stream,
1197 ARGP_HELP_STD_HELP & ~ARGP_HELP_BUG_ADDR);
1198 fprintf (state->out_stream, _("\n*This* tar defaults to:\n"));
1199 show_default_settings (state->out_stream);
1200 fprintf (state->out_stream, "\n");
1201 fprintf (state->out_stream, _("Report bugs to %s.\n"),
1202 argp_program_bug_address);
1203 exit (0);
1204
1205 case USAGE_OPTION:
1206 argp_state_help (state, state->out_stream,
1207 ARGP_HELP_USAGE | ARGP_HELP_EXIT_OK);
1208 break;
1209
1210 case VERSION_OPTION:
1211 fprintf (state->out_stream, "%s\n", argp_program_version);
1212 exit (0);
1213
1214 case LICENSE_OPTION:
1215 license ();
1216 break;
1217
1218 default:
1219 return ARGP_ERR_UNKNOWN;
1220 }
1221 return 0;
1222 }
1223
1224 static struct argp argp = {
1225 options,
1226 parse_opt,
1227 N_("[FILE]..."),
1228 doc,
1229 NULL,
1230 NULL,
1231 NULL
1232 };
1233
1234 void
1235 usage (int status)
1236 {
1237 argp_help (&argp, stderr, ARGP_HELP_SEE, program_name);
1238 exit (status);
1239 }
1240
1241 /* Parse the options for tar. */
1242
1243 static struct argp_option *
1244 find_argp_option (struct argp_option *options, int letter)
1245 {
1246 for (;
1247 !(options->name == NULL
1248 && options->key == 0
1249 && options->arg == 0
1250 && options->flags
1251 && options->doc == NULL); options++)
1252 if (options->key == letter)
1253 return options;
1254 return NULL;
1255 }
1256
1257 /* FIXME:
1258
1259 Available option letters are DEHIJQY and aenqy. Some are reserved:
1260
1261 e exit immediately with a nonzero exit status if unexpected errors occur
1262 E use extended headers (draft POSIX headers, that is)
1263 I same as T (for compatibility with Solaris tar)
1264 n the archive is quickly seekable, so don't worry about random seeks
1265 q stop after extracting the first occurrence of the named file
1266 y per-file gzip compression
1267 Y per-block gzip compression */
1268
1269 static void
1270 decode_options (int argc, char **argv)
1271 {
1272 int optchar; /* option letter */
1273 int index;
1274 struct tar_args args;
1275
1276 /* Set some default option values. */
1277 args.textual_date_option = NULL;
1278 args.exclude_options = EXCLUDE_WILDCARDS;
1279 args.o_option = 0;
1280 args.pax_option = 0;
1281 args.backup_suffix_string = getenv ("SIMPLE_BACKUP_SUFFIX");
1282 args.version_control_string = 0;
1283 args.input_files = 0;
1284
1285
1286 subcommand_option = UNKNOWN_SUBCOMMAND;
1287 archive_format = DEFAULT_FORMAT;
1288 blocking_factor = DEFAULT_BLOCKING;
1289 record_size = DEFAULT_BLOCKING * BLOCKSIZE;
1290 excluded = new_exclude ();
1291 newer_mtime_option.tv_sec = TYPE_MINIMUM (time_t);
1292 newer_mtime_option.tv_nsec = -1;
1293 recursion_option = FNM_LEADING_DIR;
1294
1295 owner_option = -1;
1296 group_option = -1;
1297
1298 /* Convert old-style tar call by exploding option element and rearranging
1299 options accordingly. */
1300
1301 if (argc > 1 && argv[1][0] != '-')
1302 {
1303 int new_argc; /* argc value for rearranged arguments */
1304 char **new_argv; /* argv value for rearranged arguments */
1305 char *const *in; /* cursor into original argv */
1306 char **out; /* cursor into rearranged argv */
1307 const char *letter; /* cursor into old option letters */
1308 char buffer[3]; /* constructed option buffer */
1309
1310 /* Initialize a constructed option. */
1311
1312 buffer[0] = '-';
1313 buffer[2] = '\0';
1314
1315 /* Allocate a new argument array, and copy program name in it. */
1316
1317 new_argc = argc - 1 + strlen (argv[1]);
1318 new_argv = xmalloc ((new_argc + 1) * sizeof (char *));
1319 in = argv;
1320 out = new_argv;
1321 *out++ = *in++;
1322
1323 /* Copy each old letter option as a separate option, and have the
1324 corresponding argument moved next to it. */
1325
1326 for (letter = *in++; *letter; letter++)
1327 {
1328 struct argp_option *opt;
1329
1330 buffer[1] = *letter;
1331 *out++ = xstrdup (buffer);
1332 opt = find_argp_option (options, *letter);
1333 if (opt && opt->arg)
1334 {
1335 if (in < argv + argc)
1336 *out++ = *in++;
1337 else
1338 USAGE_ERROR ((0, 0, _("Old option `%c' requires an argument."),
1339 *letter));
1340 }
1341 }
1342
1343 /* Copy all remaining options. */
1344
1345 while (in < argv + argc)
1346 *out++ = *in++;
1347 *out = 0;
1348
1349 /* Replace the old option list by the new one. */
1350
1351 argc = new_argc;
1352 argv = new_argv;
1353 }
1354
1355 /* Parse all options and non-options as they appear. */
1356
1357 prepend_default_options (getenv ("TAR_OPTIONS"), &argc, &argv);
1358
1359 if (argp_parse (&argp, argc, argv, ARGP_IN_ORDER|ARGP_NO_HELP,
1360 &index, &args))
1361 exit (1); /* FIXME */
1362
1363
1364 /* Special handling for 'o' option:
1365
1366 GNU tar used to say "output old format".
1367 UNIX98 tar says don't chown files after extracting (we use
1368 "--no-same-owner" for this).
1369
1370 The old GNU tar semantics is retained when used with --create
1371 option, otherwise UNIX98 semantics is assumed */
1372
1373 if (args.o_option)
1374 {
1375 if (subcommand_option == CREATE_SUBCOMMAND)
1376 {
1377 /* GNU Tar <= 1.13 compatibility */
1378 set_archive_format ("v7");
1379 }
1380 else
1381 {
1382 /* UNIX98 compatibility */
1383 same_owner_option = 1;
1384 }
1385 }
1386
1387 /* Handle operands after any "--" argument. */
1388 for (; index < argc; index++)
1389 {
1390 name_add (argv[index]);
1391 args.input_files++;
1392 }
1393
1394 /* Derive option values and check option consistency. */
1395
1396 if (archive_format == DEFAULT_FORMAT)
1397 {
1398 if (args.pax_option)
1399 archive_format = POSIX_FORMAT;
1400 else
1401 archive_format = DEFAULT_ARCHIVE_FORMAT;
1402 }
1403
1404 if (volume_label_option && subcommand_option == CREATE_SUBCOMMAND)
1405 assert_format (FORMAT_MASK (OLDGNU_FORMAT)
1406 | FORMAT_MASK (GNU_FORMAT));
1407
1408
1409 if (incremental_option || multi_volume_option)
1410 assert_format (FORMAT_MASK (OLDGNU_FORMAT) | FORMAT_MASK (GNU_FORMAT));
1411
1412 if (sparse_option)
1413 assert_format (FORMAT_MASK (OLDGNU_FORMAT)
1414 | FORMAT_MASK (GNU_FORMAT)
1415 | FORMAT_MASK (POSIX_FORMAT));
1416
1417 if (occurrence_option)
1418 {
1419 if (!args.input_files && !files_from_option)
1420 USAGE_ERROR ((0, 0,
1421 _("--occurrence is meaningless without a file list")));
1422 if (subcommand_option != DELETE_SUBCOMMAND
1423 && subcommand_option != DIFF_SUBCOMMAND
1424 && subcommand_option != EXTRACT_SUBCOMMAND
1425 && subcommand_option != LIST_SUBCOMMAND)
1426 USAGE_ERROR ((0, 0,
1427 _("--occurrence cannot be used in the requested operation mode")));
1428 }
1429
1430 if (archive_names == 0)
1431 {
1432 /* If no archive file name given, try TAPE from the environment, or
1433 else, DEFAULT_ARCHIVE from the configuration process. */
1434
1435 archive_names = 1;
1436 archive_name_array[0] = getenv ("TAPE");
1437 if (! archive_name_array[0])
1438 archive_name_array[0] = DEFAULT_ARCHIVE;
1439 }
1440
1441 /* Allow multiple archives only with `-M'. */
1442
1443 if (archive_names > 1 && !multi_volume_option)
1444 USAGE_ERROR ((0, 0,
1445 _("Multiple archive files require `-M' option")));
1446
1447 if (listed_incremental_option
1448 && NEWER_OPTION_INITIALIZED (newer_mtime_option))
1449 USAGE_ERROR ((0, 0,
1450 _("Cannot combine --listed-incremental with --newer")));
1451
1452 if (volume_label_option)
1453 {
1454 size_t volume_label_max_len =
1455 (sizeof current_header->header.name
1456 - 1 /* for trailing '\0' */
1457 - (multi_volume_option
1458 ? (sizeof " Volume "
1459 - 1 /* for null at end of " Volume " */
1460 + INT_STRLEN_BOUND (int) /* for volume number */
1461 - 1 /* for sign, as 0 <= volno */)
1462 : 0));
1463 if (volume_label_max_len < strlen (volume_label_option))
1464 USAGE_ERROR ((0, 0,
1465 ngettext ("%s: Volume label is too long (limit is %lu byte)",
1466 "%s: Volume label is too long (limit is %lu bytes)",
1467 volume_label_max_len),
1468 quotearg_colon (volume_label_option),
1469 (unsigned long) volume_label_max_len));
1470 }
1471
1472 if (verify_option)
1473 {
1474 if (multi_volume_option)
1475 USAGE_ERROR ((0, 0, _("Cannot verify multi-volume archives")));
1476 if (use_compress_program_option)
1477 USAGE_ERROR ((0, 0, _("Cannot verify compressed archives")));
1478 }
1479
1480 if (use_compress_program_option)
1481 {
1482 if (multi_volume_option)
1483 USAGE_ERROR ((0, 0, _("Cannot use multi-volume compressed archives")));
1484 if (subcommand_option == UPDATE_SUBCOMMAND)
1485 USAGE_ERROR ((0, 0, _("Cannot update compressed archives")));
1486 }
1487
1488 /* It is no harm to use --pax-option on non-pax archives in archive
1489 reading mode. It may even be useful, since it allows to override
1490 file attributes from tar headers. Therefore I allow such usage.
1491 --gray */
1492 if (args.pax_option
1493 && archive_format != POSIX_FORMAT
1494 && (subcommand_option != EXTRACT_SUBCOMMAND
1495 || subcommand_option != DIFF_SUBCOMMAND
1496 || subcommand_option != LIST_SUBCOMMAND))
1497 USAGE_ERROR ((0, 0, _("--pax-option can be used only on POSIX archives")));
1498
1499 /* If ready to unlink hierarchies, so we are for simpler files. */
1500 if (recursive_unlink_option)
1501 old_files_option = UNLINK_FIRST_OLD_FILES;
1502
1503 if (utc_option)
1504 verbose_option = 2;
1505
1506 if (!rmt_command_option)
1507 rmt_command_option = DEFAULT_RMT_COMMAND;
1508
1509 /* Forbid using -c with no input files whatsoever. Check that `-f -',
1510 explicit or implied, is used correctly. */
1511
1512 switch (subcommand_option)
1513 {
1514 case CREATE_SUBCOMMAND:
1515 if (args.input_files == 0 && !files_from_option)
1516 USAGE_ERROR ((0, 0,
1517 _("Cowardly refusing to create an empty archive")));
1518 break;
1519
1520 case EXTRACT_SUBCOMMAND:
1521 case LIST_SUBCOMMAND:
1522 case DIFF_SUBCOMMAND:
1523 for (archive_name_cursor = archive_name_array;
1524 archive_name_cursor < archive_name_array + archive_names;
1525 archive_name_cursor++)
1526 if (!strcmp (*archive_name_cursor, "-"))
1527 request_stdin ("-f");
1528 break;
1529
1530 case CAT_SUBCOMMAND:
1531 case UPDATE_SUBCOMMAND:
1532 case APPEND_SUBCOMMAND:
1533 for (archive_name_cursor = archive_name_array;
1534 archive_name_cursor < archive_name_array + archive_names;
1535 archive_name_cursor++)
1536 if (!strcmp (*archive_name_cursor, "-"))
1537 USAGE_ERROR ((0, 0,
1538 _("Options `-Aru' are incompatible with `-f -'")));
1539
1540 default:
1541 break;
1542 }
1543
1544 archive_name_cursor = archive_name_array;
1545
1546 /* Prepare for generating backup names. */
1547
1548 if (args.backup_suffix_string)
1549 simple_backup_suffix = xstrdup (args.backup_suffix_string);
1550
1551 if (backup_option)
1552 backup_type = xget_version ("--backup", args.version_control_string);
1553
1554 if (verbose_option && args.textual_date_option)
1555 {
1556 /* FIXME: tartime should support nanoseconds, too, so that this
1557 comparison doesn't complain about lost nanoseconds. */
1558 char const *treated_as = tartime (newer_mtime_option.tv_sec);
1559 if (strcmp (args.textual_date_option, treated_as) != 0)
1560 WARN ((0, 0,
1561 ngettext ("Treating date `%s' as %s + %ld nanosecond",
1562 "Treating date `%s' as %s + %ld nanoseconds",
1563 newer_mtime_option.tv_nsec),
1564 args.textual_date_option, treated_as,
1565 newer_mtime_option.tv_nsec));
1566 }
1567 }
1568
1569 \f
1570 /* Tar proper. */
1571
1572 /* Main routine for tar. */
1573 int
1574 main (int argc, char **argv)
1575 {
1576 #if HAVE_CLOCK_GETTIME
1577 if (clock_gettime (CLOCK_REALTIME, &start_timespec) != 0)
1578 #endif
1579 start_time = time (0);
1580 program_name = argv[0];
1581 setlocale (LC_ALL, "");
1582 bindtextdomain (PACKAGE, LOCALEDIR);
1583 textdomain (PACKAGE);
1584
1585 exit_status = TAREXIT_SUCCESS;
1586 filename_terminator = '\n';
1587 set_quoting_style (0, escape_quoting_style);
1588
1589 /* Pre-allocate a few structures. */
1590
1591 allocated_archive_names = 10;
1592 archive_name_array =
1593 xmalloc (sizeof (const char *) * allocated_archive_names);
1594 archive_names = 0;
1595
1596 #ifdef SIGCHLD
1597 /* System V fork+wait does not work if SIGCHLD is ignored. */
1598 signal (SIGCHLD, SIG_DFL);
1599 #endif
1600
1601 init_names ();
1602
1603 /* Decode options. */
1604
1605 decode_options (argc, argv);
1606 name_init ();
1607
1608 /* Main command execution. */
1609
1610 if (volno_file_option)
1611 init_volume_number ();
1612
1613 switch (subcommand_option)
1614 {
1615 case UNKNOWN_SUBCOMMAND:
1616 USAGE_ERROR ((0, 0,
1617 _("You must specify one of the `-Acdtrux' options")));
1618
1619 case CAT_SUBCOMMAND:
1620 case UPDATE_SUBCOMMAND:
1621 case APPEND_SUBCOMMAND:
1622 update_archive ();
1623 break;
1624
1625 case DELETE_SUBCOMMAND:
1626 delete_archive_members ();
1627 break;
1628
1629 case CREATE_SUBCOMMAND:
1630 create_archive ();
1631 name_close ();
1632
1633 if (totals_option)
1634 print_total_written ();
1635 break;
1636
1637 case EXTRACT_SUBCOMMAND:
1638 extr_init ();
1639 read_and (extract_archive);
1640
1641 /* FIXME: should extract_finish () even if an ordinary signal is
1642 received. */
1643 extract_finish ();
1644
1645 break;
1646
1647 case LIST_SUBCOMMAND:
1648 read_and (list_archive);
1649 break;
1650
1651 case DIFF_SUBCOMMAND:
1652 diff_init ();
1653 read_and (diff_archive);
1654 break;
1655 }
1656
1657 if (check_links_option)
1658 check_links ();
1659
1660 if (volno_file_option)
1661 closeout_volume_number ();
1662
1663 /* Dispose of allocated memory, and return. */
1664
1665 free (archive_name_array);
1666 name_term ();
1667
1668 if (stdlis != stderr && (ferror (stdlis) || fclose (stdlis) != 0))
1669 FATAL_ERROR ((0, 0, _("Error in writing to standard output")));
1670 if (exit_status == TAREXIT_FAILURE)
1671 error (0, 0, _("Error exit delayed from previous errors"));
1672 if (ferror (stderr) || fclose (stderr) != 0)
1673 exit_status = TAREXIT_FAILURE;
1674 return exit_status;
1675 }
1676
1677 void
1678 tar_stat_init (struct tar_stat_info *st)
1679 {
1680 memset (st, 0, sizeof (*st));
1681 }
1682
1683 void
1684 tar_stat_destroy (struct tar_stat_info *st)
1685 {
1686 free (st->orig_file_name);
1687 free (st->file_name);
1688 free (st->link_name);
1689 free (st->uname);
1690 free (st->gname);
1691 free (st->sparse_map);
1692 memset (st, 0, sizeof (*st));
1693 }
This page took 0.123075 seconds and 5 git commands to generate.