1 | /* A tar (tape archiver) program.
|
---|
2 |
|
---|
3 | Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1999, 2000,
|
---|
4 | 2001, 2003, 2004, 2005, 2006 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 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
---|
21 |
|
---|
22 | #include <system.h>
|
---|
23 |
|
---|
24 | #include <fnmatch.h>
|
---|
25 | #include <getline.h>
|
---|
26 | #include <argp.h>
|
---|
27 | #include <argp-namefrob.h>
|
---|
28 | #include <argp-fmtstream.h>
|
---|
29 |
|
---|
30 | #include <signal.h>
|
---|
31 | #if ! defined SIGCHLD && defined SIGCLD
|
---|
32 | # define SIGCHLD SIGCLD
|
---|
33 | #endif
|
---|
34 |
|
---|
35 | /* The following causes "common.h" to produce definitions of all the global
|
---|
36 | variables, rather than just "extern" declarations of them. GNU tar does
|
---|
37 | depend on the system loader to preset all GLOBAL variables to neutral (or
|
---|
38 | zero) values; explicit initialization is usually not done. */
|
---|
39 | #define GLOBAL
|
---|
40 | #include "common.h"
|
---|
41 |
|
---|
42 | #include <argmatch.h>
|
---|
43 | #include <closeout.h>
|
---|
44 | #include <configmake.h>
|
---|
45 | #include <exitfail.h>
|
---|
46 | #include <getdate.h>
|
---|
47 | #include <rmt.h>
|
---|
48 | #include <rmt-command.h>
|
---|
49 | #include <prepargs.h>
|
---|
50 | #include <quotearg.h>
|
---|
51 | #include <version-etc.h>
|
---|
52 | #include <xstrtol.h>
|
---|
53 | #include <stdopen.h>
|
---|
54 |
|
---|
55 | /* Local declarations. */
|
---|
56 |
|
---|
57 | #ifndef DEFAULT_ARCHIVE_FORMAT
|
---|
58 | # define DEFAULT_ARCHIVE_FORMAT GNU_FORMAT
|
---|
59 | #endif
|
---|
60 |
|
---|
61 | #ifndef DEFAULT_ARCHIVE
|
---|
62 | # define DEFAULT_ARCHIVE "tar.out"
|
---|
63 | #endif
|
---|
64 |
|
---|
65 | #ifndef DEFAULT_BLOCKING
|
---|
66 | # define DEFAULT_BLOCKING 20
|
---|
67 | #endif
|
---|
68 |
|
---|
69 | |
---|
70 |
|
---|
71 | /* Miscellaneous. */
|
---|
72 |
|
---|
73 | /* Name of option using stdin. */
|
---|
74 | static const char *stdin_used_by;
|
---|
75 |
|
---|
76 | /* Doesn't return if stdin already requested. */
|
---|
77 | void
|
---|
78 | request_stdin (const char *option)
|
---|
79 | {
|
---|
80 | if (stdin_used_by)
|
---|
81 | USAGE_ERROR ((0, 0, _("Options `-%s' and `-%s' both want standard input"),
|
---|
82 | stdin_used_by, option));
|
---|
83 |
|
---|
84 | stdin_used_by = option;
|
---|
85 | }
|
---|
86 |
|
---|
87 | extern int rpmatch (char const *response);
|
---|
88 |
|
---|
89 | /* Returns true if and only if the user typed an affirmative response. */
|
---|
90 | int
|
---|
91 | confirm (const char *message_action, const char *message_name)
|
---|
92 | {
|
---|
93 | static FILE *confirm_file;
|
---|
94 | static int confirm_file_EOF;
|
---|
95 | bool status = false;
|
---|
96 |
|
---|
97 | if (!confirm_file)
|
---|
98 | {
|
---|
99 | if (archive == 0 || stdin_used_by)
|
---|
100 | {
|
---|
101 | confirm_file = fopen (TTY_NAME, "r");
|
---|
102 | if (! confirm_file)
|
---|
103 | open_fatal (TTY_NAME);
|
---|
104 | }
|
---|
105 | else
|
---|
106 | {
|
---|
107 | request_stdin ("-w");
|
---|
108 | confirm_file = stdin;
|
---|
109 | }
|
---|
110 | }
|
---|
111 |
|
---|
112 | fprintf (stdlis, "%s %s?", message_action, quote (message_name));
|
---|
113 | fflush (stdlis);
|
---|
114 |
|
---|
115 | if (!confirm_file_EOF)
|
---|
116 | {
|
---|
117 | char *response = NULL;
|
---|
118 | size_t response_size = 0;
|
---|
119 | if (getline (&response, &response_size, confirm_file) < 0)
|
---|
120 | confirm_file_EOF = 1;
|
---|
121 | else
|
---|
122 | status = rpmatch (response) > 0;
|
---|
123 | free (response);
|
---|
124 | }
|
---|
125 |
|
---|
126 | if (confirm_file_EOF)
|
---|
127 | {
|
---|
128 | fputc ('\n', stdlis);
|
---|
129 | fflush (stdlis);
|
---|
130 | }
|
---|
131 |
|
---|
132 | return status;
|
---|
133 | }
|
---|
134 |
|
---|
135 | static struct fmttab {
|
---|
136 | char const *name;
|
---|
137 | enum archive_format fmt;
|
---|
138 | } const fmttab[] = {
|
---|
139 | { "v7", V7_FORMAT },
|
---|
140 | { "oldgnu", OLDGNU_FORMAT },
|
---|
141 | { "ustar", USTAR_FORMAT },
|
---|
142 | { "posix", POSIX_FORMAT },
|
---|
143 | #if 0 /* not fully supported yet */
|
---|
144 | { "star", STAR_FORMAT },
|
---|
145 | #endif
|
---|
146 | { "gnu", GNU_FORMAT },
|
---|
147 | { "pax", POSIX_FORMAT }, /* An alias for posix */
|
---|
148 | { NULL, 0 }
|
---|
149 | };
|
---|
150 |
|
---|
151 | static void
|
---|
152 | set_archive_format (char const *name)
|
---|
153 | {
|
---|
154 | struct fmttab const *p;
|
---|
155 |
|
---|
156 | for (p = fmttab; strcmp (p->name, name) != 0; )
|
---|
157 | if (! (++p)->name)
|
---|
158 | USAGE_ERROR ((0, 0, _("%s: Invalid archive format"),
|
---|
159 | quotearg_colon (name)));
|
---|
160 |
|
---|
161 | archive_format = p->fmt;
|
---|
162 | }
|
---|
163 |
|
---|
164 | const char *
|
---|
165 | archive_format_string (enum archive_format fmt)
|
---|
166 | {
|
---|
167 | struct fmttab const *p;
|
---|
168 |
|
---|
169 | for (p = fmttab; p->name; p++)
|
---|
170 | if (p->fmt == fmt)
|
---|
171 | return p->name;
|
---|
172 | return "unknown?";
|
---|
173 | }
|
---|
174 |
|
---|
175 | #define FORMAT_MASK(n) (1<<(n))
|
---|
176 |
|
---|
177 | static void
|
---|
178 | assert_format(unsigned fmt_mask)
|
---|
179 | {
|
---|
180 | if ((FORMAT_MASK (archive_format) & fmt_mask) == 0)
|
---|
181 | USAGE_ERROR ((0, 0,
|
---|
182 | _("GNU features wanted on incompatible archive format")));
|
---|
183 | }
|
---|
184 |
|
---|
185 | const char *
|
---|
186 | subcommand_string (enum subcommand c)
|
---|
187 | {
|
---|
188 | switch (c)
|
---|
189 | {
|
---|
190 | case UNKNOWN_SUBCOMMAND:
|
---|
191 | return "unknown?";
|
---|
192 |
|
---|
193 | case APPEND_SUBCOMMAND:
|
---|
194 | return "-r";
|
---|
195 |
|
---|
196 | case CAT_SUBCOMMAND:
|
---|
197 | return "-A";
|
---|
198 |
|
---|
199 | case CREATE_SUBCOMMAND:
|
---|
200 | return "-c";
|
---|
201 |
|
---|
202 | case DELETE_SUBCOMMAND:
|
---|
203 | return "-D";
|
---|
204 |
|
---|
205 | case DIFF_SUBCOMMAND:
|
---|
206 | return "-d";
|
---|
207 |
|
---|
208 | case EXTRACT_SUBCOMMAND:
|
---|
209 | return "-x";
|
---|
210 |
|
---|
211 | case LIST_SUBCOMMAND:
|
---|
212 | return "-t";
|
---|
213 |
|
---|
214 | case UPDATE_SUBCOMMAND:
|
---|
215 | return "-u";
|
---|
216 |
|
---|
217 | default:
|
---|
218 | abort ();
|
---|
219 | }
|
---|
220 | }
|
---|
221 |
|
---|
222 | void
|
---|
223 | tar_list_quoting_styles (argp_fmtstream_t fs, char *prefix)
|
---|
224 | {
|
---|
225 | int i;
|
---|
226 |
|
---|
227 | for (i = 0; quoting_style_args[i]; i++)
|
---|
228 | argp_fmtstream_printf (fs, "%s%s\n", prefix, quoting_style_args[i]);
|
---|
229 | }
|
---|
230 |
|
---|
231 | void
|
---|
232 | tar_set_quoting_style (char *arg)
|
---|
233 | {
|
---|
234 | int i;
|
---|
235 |
|
---|
236 | for (i = 0; quoting_style_args[i]; i++)
|
---|
237 | if (strcmp (arg, quoting_style_args[i]) == 0)
|
---|
238 | {
|
---|
239 | set_quoting_style (NULL, i);
|
---|
240 | return;
|
---|
241 | }
|
---|
242 | FATAL_ERROR ((0, 0,
|
---|
243 | _("Unknown quoting style `%s'. Try `%s --quoting-style=help' to get a list."), arg, program_invocation_short_name));
|
---|
244 | }
|
---|
245 |
|
---|
246 | |
---|
247 |
|
---|
248 | /* Options. */
|
---|
249 |
|
---|
250 | enum
|
---|
251 | {
|
---|
252 | ANCHORED_OPTION = CHAR_MAX + 1,
|
---|
253 | ATIME_PRESERVE_OPTION,
|
---|
254 | BACKUP_OPTION,
|
---|
255 | CHECKPOINT_OPTION,
|
---|
256 | DELAY_DIRECTORY_RESTORE_OPTION,
|
---|
257 | DELETE_OPTION,
|
---|
258 | EXCLUDE_CACHES_OPTION,
|
---|
259 | EXCLUDE_OPTION,
|
---|
260 | EXCLUDE_TAG_OPTION,
|
---|
261 | FORCE_LOCAL_OPTION,
|
---|
262 | GROUP_OPTION,
|
---|
263 | HANG_OPTION,
|
---|
264 | IGNORE_CASE_OPTION,
|
---|
265 | IGNORE_COMMAND_ERROR_OPTION,
|
---|
266 | IGNORE_FAILED_READ_OPTION,
|
---|
267 | INDEX_FILE_OPTION,
|
---|
268 | KEEP_NEWER_FILES_OPTION,
|
---|
269 | MODE_OPTION,
|
---|
270 | MTIME_OPTION,
|
---|
271 | NEWER_MTIME_OPTION,
|
---|
272 | NO_ANCHORED_OPTION,
|
---|
273 | NO_DELAY_DIRECTORY_RESTORE_OPTION,
|
---|
274 | NO_IGNORE_CASE_OPTION,
|
---|
275 | NO_IGNORE_COMMAND_ERROR_OPTION,
|
---|
276 | NO_OVERWRITE_DIR_OPTION,
|
---|
277 | NO_QUOTE_CHARS_OPTION,
|
---|
278 | NO_RECURSION_OPTION,
|
---|
279 | NO_SAME_OWNER_OPTION,
|
---|
280 | NO_SAME_PERMISSIONS_OPTION,
|
---|
281 | NO_UNQUOTE_OPTION,
|
---|
282 | NO_WILDCARDS_MATCH_SLASH_OPTION,
|
---|
283 | NO_WILDCARDS_OPTION,
|
---|
284 | NULL_OPTION,
|
---|
285 | NUMERIC_OWNER_OPTION,
|
---|
286 | OCCURRENCE_OPTION,
|
---|
287 | OLD_ARCHIVE_OPTION,
|
---|
288 | ONE_FILE_SYSTEM_OPTION,
|
---|
289 | OVERWRITE_DIR_OPTION,
|
---|
290 | OVERWRITE_OPTION,
|
---|
291 | OWNER_OPTION,
|
---|
292 | PAX_OPTION,
|
---|
293 | POSIX_OPTION,
|
---|
294 | PRESERVE_OPTION,
|
---|
295 | QUOTE_CHARS_OPTION,
|
---|
296 | QUOTING_STYLE_OPTION,
|
---|
297 | RECORD_SIZE_OPTION,
|
---|
298 | RECURSION_OPTION,
|
---|
299 | RECURSIVE_UNLINK_OPTION,
|
---|
300 | REMOVE_FILES_OPTION,
|
---|
301 | RESTRICT_OPTION,
|
---|
302 | RMT_COMMAND_OPTION,
|
---|
303 | RSH_COMMAND_OPTION,
|
---|
304 | SAME_OWNER_OPTION,
|
---|
305 | SHOW_DEFAULTS_OPTION,
|
---|
306 | SHOW_OMITTED_DIRS_OPTION,
|
---|
307 | SHOW_TRANSFORMED_NAMES_OPTION,
|
---|
308 | SPARSE_VERSION_OPTION,
|
---|
309 | STRIP_COMPONENTS_OPTION,
|
---|
310 | SUFFIX_OPTION,
|
---|
311 | TEST_LABEL_OPTION,
|
---|
312 | TOTALS_OPTION,
|
---|
313 | TO_COMMAND_OPTION,
|
---|
314 | TRANSFORM_OPTION,
|
---|
315 | UNQUOTE_OPTION,
|
---|
316 | USAGE_OPTION,
|
---|
317 | USE_COMPRESS_PROGRAM_OPTION,
|
---|
318 | UTC_OPTION,
|
---|
319 | VERSION_OPTION,
|
---|
320 | VOLNO_FILE_OPTION,
|
---|
321 | WILDCARDS_MATCH_SLASH_OPTION,
|
---|
322 | WILDCARDS_OPTION
|
---|
323 | };
|
---|
324 |
|
---|
325 | const char *argp_program_version = "tar (" PACKAGE_NAME ") " VERSION;
|
---|
326 | const char *argp_program_bug_address = "<" PACKAGE_BUGREPORT ">";
|
---|
327 | static char const doc[] = N_("\
|
---|
328 | GNU `tar' saves many files together into a single tape or disk archive, \
|
---|
329 | and can restore individual files from the archive.\n\
|
---|
330 | \n\
|
---|
331 | Examples:\n\
|
---|
332 | tar -cf archive.tar foo bar # Create archive.tar from files foo and bar.\n\
|
---|
333 | tar -tvf archive.tar # List all files in archive.tar verbosely.\n\
|
---|
334 | tar -xf archive.tar # Extract all files from archive.tar.\n")
|
---|
335 | "\v"
|
---|
336 | N_("The backup suffix is `~', unless set with --suffix or SIMPLE_BACKUP_SUFFIX.\n\
|
---|
337 | The version control may be set with --backup or VERSION_CONTROL, values are:\n\n\
|
---|
338 | none, off never make backups\n\
|
---|
339 | t, numbered make numbered backups\n\
|
---|
340 | nil, existing numbered if numbered backups exist, simple otherwise\n\
|
---|
341 | never, simple always make simple backups\n");
|
---|
342 |
|
---|
343 |
|
---|
344 | /* NOTE:
|
---|
345 |
|
---|
346 | Available option letters are DEIJQY and aeqy. Consider the following
|
---|
347 | assignments:
|
---|
348 |
|
---|
349 | [For Solaris tar compatibility =/= Is it important at all?]
|
---|
350 | e exit immediately with a nonzero exit status if unexpected errors occur
|
---|
351 | E use extended headers (--format=posix)
|
---|
352 |
|
---|
353 | [q alias for --occurrence=1 =/= this would better be used for quiet?]
|
---|
354 | [I same as T =/= will harm star compatibility]
|
---|
355 |
|
---|
356 | y per-file gzip compression
|
---|
357 | Y per-block gzip compression */
|
---|
358 |
|
---|
359 | static struct argp_option options[] = {
|
---|
360 | #define GRID 10
|
---|
361 | {NULL, 0, NULL, 0,
|
---|
362 | N_("Main operation mode:"), GRID },
|
---|
363 |
|
---|
364 | {"list", 't', 0, 0,
|
---|
365 | N_("list the contents of an archive"), GRID+1 },
|
---|
366 | {"extract", 'x', 0, 0,
|
---|
367 | N_("extract files from an archive"), GRID+1 },
|
---|
368 | {"get", 0, 0, OPTION_ALIAS, NULL, GRID+1 },
|
---|
369 | {"create", 'c', 0, 0,
|
---|
370 | N_("create a new archive"), GRID+1 },
|
---|
371 | {"diff", 'd', 0, 0,
|
---|
372 | N_("find differences between archive and file system"), GRID+1 },
|
---|
373 | {"compare", 0, 0, OPTION_ALIAS, NULL, GRID+1 },
|
---|
374 | {"append", 'r', 0, 0,
|
---|
375 | N_("append files to the end of an archive"), GRID+1 },
|
---|
376 | {"update", 'u', 0, 0,
|
---|
377 | N_("only append files newer than copy in archive"), GRID+1 },
|
---|
378 | {"catenate", 'A', 0, 0,
|
---|
379 | N_("append tar files to an archive"), GRID+1 },
|
---|
380 | {"concatenate", 0, 0, OPTION_ALIAS, NULL, GRID+1 },
|
---|
381 | {"delete", DELETE_OPTION, 0, 0,
|
---|
382 | N_("delete from the archive (not on mag tapes!)"), GRID+1 },
|
---|
383 | {"test-label", TEST_LABEL_OPTION, NULL, 0,
|
---|
384 | N_("test the archive volume label and exit"), GRID+1 },
|
---|
385 | #undef GRID
|
---|
386 |
|
---|
387 | #define GRID 20
|
---|
388 | {NULL, 0, NULL, 0,
|
---|
389 | N_("Operation modifiers:"), GRID },
|
---|
390 |
|
---|
391 | {"sparse", 'S', 0, 0,
|
---|
392 | N_("handle sparse files efficiently"), GRID+1 },
|
---|
393 | {"sparse-version", SPARSE_VERSION_OPTION, N_("MAJOR[.MINOR]"), 0,
|
---|
394 | N_("set version of the sparse format to use (implies --sparse)"), GRID+1},
|
---|
395 | {"incremental", 'G', 0, 0,
|
---|
396 | N_("handle old GNU-format incremental backup"), GRID+1 },
|
---|
397 | {"listed-incremental", 'g', N_("FILE"), 0,
|
---|
398 | N_("handle new GNU-format incremental backup"), GRID+1 },
|
---|
399 | {"ignore-failed-read", IGNORE_FAILED_READ_OPTION, 0, 0,
|
---|
400 | N_("do not exit with nonzero on unreadable files"), GRID+1 },
|
---|
401 | {"occurrence", OCCURRENCE_OPTION, N_("NUMBER"), OPTION_ARG_OPTIONAL,
|
---|
402 | N_("process only the NUMBERth occurrence of each file in the archive;"
|
---|
403 | " this option is valid only in conjunction with one of the subcommands"
|
---|
404 | " --delete, --diff, --extract or --list and when a list of files"
|
---|
405 | " is given either on the command line or via the -T option;"
|
---|
406 | " NUMBER defaults to 1"), GRID+1 },
|
---|
407 | {"seek", 'n', NULL, 0,
|
---|
408 | N_("archive is seekable"), GRID+1 },
|
---|
409 | #undef GRID
|
---|
410 |
|
---|
411 | #define GRID 30
|
---|
412 | {NULL, 0, NULL, 0,
|
---|
413 | N_("Overwrite control:"), GRID },
|
---|
414 |
|
---|
415 | {"verify", 'W', 0, 0,
|
---|
416 | N_("attempt to verify the archive after writing it"), GRID+1 },
|
---|
417 | {"remove-files", REMOVE_FILES_OPTION, 0, 0,
|
---|
418 | N_("remove files after adding them to the archive"), GRID+1 },
|
---|
419 | {"keep-old-files", 'k', 0, 0,
|
---|
420 | N_("don't replace existing files when extracting"), GRID+1 },
|
---|
421 | {"keep-newer-files", KEEP_NEWER_FILES_OPTION, 0, 0,
|
---|
422 | N_("don't replace existing files that are newer than their archive copies"), GRID+1 },
|
---|
423 | {"overwrite", OVERWRITE_OPTION, 0, 0,
|
---|
424 | N_("overwrite existing files when extracting"), GRID+1 },
|
---|
425 | {"unlink-first", 'U', 0, 0,
|
---|
426 | N_("remove each file prior to extracting over it"), GRID+1 },
|
---|
427 | {"recursive-unlink", RECURSIVE_UNLINK_OPTION, 0, 0,
|
---|
428 | N_("empty hierarchies prior to extracting directory"), GRID+1 },
|
---|
429 | {"no-overwrite-dir", NO_OVERWRITE_DIR_OPTION, 0, 0,
|
---|
430 | N_("preserve metadata of existing directories"), GRID+1 },
|
---|
431 | {"overwrite-dir", OVERWRITE_DIR_OPTION, 0, 0,
|
---|
432 | N_("overwrite metadata of existing directories when extracting (default)"),
|
---|
433 | GRID+1 },
|
---|
434 | #undef GRID
|
---|
435 |
|
---|
436 | #define GRID 40
|
---|
437 | {NULL, 0, NULL, 0,
|
---|
438 | N_("Select output stream:"), GRID },
|
---|
439 |
|
---|
440 | {"to-stdout", 'O', 0, 0,
|
---|
441 | N_("extract files to standard output"), GRID+1 },
|
---|
442 | {"to-command", TO_COMMAND_OPTION, N_("COMMAND"), 0,
|
---|
443 | N_("pipe extracted files to another program"), GRID+1 },
|
---|
444 | {"ignore-command-error", IGNORE_COMMAND_ERROR_OPTION, 0, 0,
|
---|
445 | N_("ignore exit codes of children"), GRID+1 },
|
---|
446 | {"no-ignore-command-error", NO_IGNORE_COMMAND_ERROR_OPTION, 0, 0,
|
---|
447 | N_("treat non-zero exit codes of children as error"), GRID+1 },
|
---|
448 | #undef GRID
|
---|
449 |
|
---|
450 | #define GRID 50
|
---|
451 | {NULL, 0, NULL, 0,
|
---|
452 | N_("Handling of file attributes:"), GRID },
|
---|
453 |
|
---|
454 | {"owner", OWNER_OPTION, N_("NAME"), 0,
|
---|
455 | N_("force NAME as owner for added files"), GRID+1 },
|
---|
456 | {"group", GROUP_OPTION, N_("NAME"), 0,
|
---|
457 | N_("force NAME as group for added files"), GRID+1 },
|
---|
458 | {"mtime", MTIME_OPTION, N_("DATE-OR-FILE"), 0,
|
---|
459 | N_("set mtime for added files from DATE-OR-FILE"), GRID+1 },
|
---|
460 | {"mode", MODE_OPTION, N_("CHANGES"), 0,
|
---|
461 | N_("force (symbolic) mode CHANGES for added files"), GRID+1 },
|
---|
462 | {"atime-preserve", ATIME_PRESERVE_OPTION,
|
---|
463 | N_("METHOD"), OPTION_ARG_OPTIONAL,
|
---|
464 | N_("preserve access times on dumped files, either by restoring the times"
|
---|
465 | " after reading (METHOD='replace'; default) or by not setting the times"
|
---|
466 | " in the first place (METHOD='system')"), GRID+1 },
|
---|
467 | {"touch", 'm', 0, 0,
|
---|
468 | N_("don't extract file modified time"), GRID+1 },
|
---|
469 | {"same-owner", SAME_OWNER_OPTION, 0, 0,
|
---|
470 | N_("try extracting files with the same ownership"), GRID+1 },
|
---|
471 | {"no-same-owner", NO_SAME_OWNER_OPTION, 0, 0,
|
---|
472 | N_("extract files as yourself"), GRID+1 },
|
---|
473 | {"numeric-owner", NUMERIC_OWNER_OPTION, 0, 0,
|
---|
474 | N_("always use numbers for user/group names"), GRID+1 },
|
---|
475 | {"preserve-permissions", 'p', 0, 0,
|
---|
476 | N_("extract information about file permissions (default for superuser)"),
|
---|
477 | GRID+1 },
|
---|
478 | {"same-permissions", 0, 0, OPTION_ALIAS, NULL, GRID+1 },
|
---|
479 | {"no-same-permissions", NO_SAME_PERMISSIONS_OPTION, 0, 0,
|
---|
480 | N_("apply the user's umask when extracting permissions from the archive (default for ordinary users)"), GRID+1 },
|
---|
481 | {"preserve-order", 's', 0, 0,
|
---|
482 | N_("sort names to extract to match archive"), GRID+1 },
|
---|
483 | {"same-order", 0, 0, OPTION_ALIAS, NULL, GRID+1 },
|
---|
484 | {"preserve", PRESERVE_OPTION, 0, 0,
|
---|
485 | N_("same as both -p and -s"), GRID+1 },
|
---|
486 | {"delay-directory-restore", DELAY_DIRECTORY_RESTORE_OPTION, 0, 0,
|
---|
487 | N_("delay setting modification times and permissions of extracted"
|
---|
488 | " directories until the end of extraction"), GRID+1 },
|
---|
489 | {"no-delay-directory-restore", NO_DELAY_DIRECTORY_RESTORE_OPTION, 0, 0,
|
---|
490 | N_("cancel the effect of --delay-directory-restore option"), GRID+1 },
|
---|
491 | #undef GRID
|
---|
492 |
|
---|
493 | #define GRID 60
|
---|
494 | {NULL, 0, NULL, 0,
|
---|
495 | N_("Device selection and switching:"), GRID },
|
---|
496 |
|
---|
497 | {"file", 'f', N_("ARCHIVE"), 0,
|
---|
498 | N_("use archive file or device ARCHIVE"), GRID+1 },
|
---|
499 | {"force-local", FORCE_LOCAL_OPTION, 0, 0,
|
---|
500 | N_("archive file is local even if it has a colon"), GRID+1 },
|
---|
501 | {"rmt-command", RMT_COMMAND_OPTION, N_("COMMAND"), 0,
|
---|
502 | N_("use given rmt COMMAND instead of rmt"), GRID+1 },
|
---|
503 | {"rsh-command", RSH_COMMAND_OPTION, N_("COMMAND"), 0,
|
---|
504 | N_("use remote COMMAND instead of rsh"), GRID+1 },
|
---|
505 | #ifdef DEVICE_PREFIX
|
---|
506 | {"-[0-7][lmh]", 0, NULL, OPTION_DOC, /* It is OK, since `name' will never be
|
---|
507 | translated */
|
---|
508 | N_("specify drive and density"), GRID+1 },
|
---|
509 | #endif
|
---|
510 | {NULL, '0', NULL, OPTION_HIDDEN, NULL, GRID+1 },
|
---|
511 | {NULL, '1', NULL, OPTION_HIDDEN, NULL, GRID+1 },
|
---|
512 | {NULL, '2', NULL, OPTION_HIDDEN, NULL, GRID+1 },
|
---|
513 | {NULL, '3', NULL, OPTION_HIDDEN, NULL, GRID+1 },
|
---|
514 | {NULL, '4', NULL, OPTION_HIDDEN, NULL, GRID+1 },
|
---|
515 | {NULL, '5', NULL, OPTION_HIDDEN, NULL, GRID+1 },
|
---|
516 | {NULL, '6', NULL, OPTION_HIDDEN, NULL, GRID+1 },
|
---|
517 | {NULL, '7', NULL, OPTION_HIDDEN, NULL, GRID+1 },
|
---|
518 | {NULL, '8', NULL, OPTION_HIDDEN, NULL, GRID+1 },
|
---|
519 | {NULL, '9', NULL, OPTION_HIDDEN, NULL, GRID+1 },
|
---|
520 |
|
---|
521 | {"multi-volume", 'M', 0, 0,
|
---|
522 | N_("create/list/extract multi-volume archive"), GRID+1 },
|
---|
523 | {"tape-length", 'L', N_("NUMBER"), 0,
|
---|
524 | N_("change tape after writing NUMBER x 1024 bytes"), GRID+1 },
|
---|
525 | {"info-script", 'F', N_("NAME"), 0,
|
---|
526 | N_("run script at end of each tape (implies -M)"), GRID+1 },
|
---|
527 | {"new-volume-script", 0, 0, OPTION_ALIAS, NULL, GRID+1 },
|
---|
528 | {"volno-file", VOLNO_FILE_OPTION, N_("FILE"), 0,
|
---|
529 | N_("use/update the volume number in FILE"), GRID+1 },
|
---|
530 | #undef GRID
|
---|
531 |
|
---|
532 | #define GRID 70
|
---|
533 | {NULL, 0, NULL, 0,
|
---|
534 | N_("Device blocking:"), GRID },
|
---|
535 |
|
---|
536 | {"blocking-factor", 'b', N_("BLOCKS"), 0,
|
---|
537 | N_("BLOCKS x 512 bytes per record"), GRID+1 },
|
---|
538 | {"record-size", RECORD_SIZE_OPTION, N_("NUMBER"), 0,
|
---|
539 | N_("NUMBER of bytes per record, multiple of 512"), GRID+1 },
|
---|
540 | {"ignore-zeros", 'i', 0, 0,
|
---|
541 | N_("ignore zeroed blocks in archive (means EOF)"), GRID+1 },
|
---|
542 | {"read-full-records", 'B', 0, 0,
|
---|
543 | N_("reblock as we read (for 4.2BSD pipes)"), GRID+1 },
|
---|
544 | #undef GRID
|
---|
545 |
|
---|
546 | #define GRID 80
|
---|
547 | {NULL, 0, NULL, 0,
|
---|
548 | N_("Archive format selection:"), GRID },
|
---|
549 |
|
---|
550 | {"format", 'H', N_("FORMAT"), 0,
|
---|
551 | N_("create archive of the given format"), GRID+1 },
|
---|
552 |
|
---|
553 | {NULL, 0, NULL, 0, N_("FORMAT is one of the following:"), GRID+2 },
|
---|
554 | {" v7", 0, NULL, OPTION_DOC|OPTION_NO_TRANS, N_("old V7 tar format"),
|
---|
555 | GRID+3 },
|
---|
556 | {" oldgnu", 0, NULL, OPTION_DOC|OPTION_NO_TRANS,
|
---|
557 | N_("GNU format as per tar <= 1.12"), GRID+3 },
|
---|
558 | {" gnu", 0, NULL, OPTION_DOC|OPTION_NO_TRANS,
|
---|
559 | N_("GNU tar 1.13.x format"), GRID+3 },
|
---|
560 | {" ustar", 0, NULL, OPTION_DOC|OPTION_NO_TRANS,
|
---|
561 | N_("POSIX 1003.1-1988 (ustar) format"), GRID+3 },
|
---|
562 | {" pax", 0, NULL, OPTION_DOC|OPTION_NO_TRANS,
|
---|
563 | N_("POSIX 1003.1-2001 (pax) format"), GRID+3 },
|
---|
564 | {" posix", 0, NULL, OPTION_DOC|OPTION_NO_TRANS, N_("same as pax"), GRID+3 },
|
---|
565 |
|
---|
566 | {"old-archive", OLD_ARCHIVE_OPTION, 0, 0, /* FIXME */
|
---|
567 | N_("same as --format=v7"), GRID+8 },
|
---|
568 | {"portability", 0, 0, OPTION_ALIAS, NULL, GRID+8 },
|
---|
569 | {"posix", POSIX_OPTION, 0, 0,
|
---|
570 | N_("same as --format=posix"), GRID+8 },
|
---|
571 | {"pax-option", PAX_OPTION, N_("keyword[[:]=value][,keyword[[:]=value]]..."), 0,
|
---|
572 | N_("control pax keywords"), GRID+8 },
|
---|
573 | {"label", 'V', N_("TEXT"), 0,
|
---|
574 | N_("create archive with volume name TEXT; at list/extract time, use TEXT as a globbing pattern for volume name"), GRID+8 },
|
---|
575 | {"bzip2", 'j', 0, 0,
|
---|
576 | N_("filter the archive through bzip2"), GRID+8 },
|
---|
577 | {"gzip", 'z', 0, 0,
|
---|
578 | N_("filter the archive through gzip"), GRID+8 },
|
---|
579 | {"gunzip", 0, 0, OPTION_ALIAS, NULL, GRID+8 },
|
---|
580 | {"ungzip", 0, 0, OPTION_ALIAS, NULL, GRID+8 },
|
---|
581 | {"compress", 'Z', 0, 0,
|
---|
582 | N_("filter the archive through compress"), GRID+8 },
|
---|
583 | {"uncompress", 0, 0, OPTION_ALIAS, NULL, GRID+8 },
|
---|
584 | {"use-compress-program", USE_COMPRESS_PROGRAM_OPTION, N_("PROG"), 0,
|
---|
585 | N_("filter through PROG (must accept -d)"), GRID+8 },
|
---|
586 | #undef GRID
|
---|
587 |
|
---|
588 | #define GRID 90
|
---|
589 | {NULL, 0, NULL, 0,
|
---|
590 | N_("Local file selection:"), GRID },
|
---|
591 |
|
---|
592 | {"add-file", ARGP_KEY_ARG, N_("FILE"), 0,
|
---|
593 | N_("add given FILE to the archive (useful if its name starts with a dash)"), GRID+1 },
|
---|
594 | {"directory", 'C', N_("DIR"), 0,
|
---|
595 | N_("change to directory DIR"), GRID+1 },
|
---|
596 | {"files-from", 'T', N_("FILE"), 0,
|
---|
597 | N_("get names to extract or create from FILE"), GRID+1 },
|
---|
598 | {"null", NULL_OPTION, 0, 0,
|
---|
599 | N_("-T reads null-terminated names, disable -C"), GRID+1 },
|
---|
600 | {"unquote", UNQUOTE_OPTION, 0, 0,
|
---|
601 | N_("unquote filenames read with -T (default)"), GRID+1 },
|
---|
602 | {"no-unquote", NO_UNQUOTE_OPTION, 0, 0,
|
---|
603 | N_("do not unquote filenames read with -T"), GRID+1 },
|
---|
604 | {"exclude", EXCLUDE_OPTION, N_("PATTERN"), 0,
|
---|
605 | N_("exclude files, given as a PATTERN"), GRID+1 },
|
---|
606 | {"exclude-from", 'X', N_("FILE"), 0,
|
---|
607 | N_("exclude patterns listed in FILE"), GRID+1 },
|
---|
608 | {"exclude-caches", EXCLUDE_CACHES_OPTION, 0, 0,
|
---|
609 | N_("exclude directories containing a cache tag"), GRID+1 },
|
---|
610 | {"exclude-tag", EXCLUDE_TAG_OPTION, N_("FILE"), 0,
|
---|
611 | N_("exclude directories containing FILE"), GRID+1 },
|
---|
612 | {"no-recursion", NO_RECURSION_OPTION, 0, 0,
|
---|
613 | N_("avoid descending automatically in directories"), GRID+1 },
|
---|
614 | {"one-file-system", ONE_FILE_SYSTEM_OPTION, 0, 0,
|
---|
615 | N_("stay in local file system when creating archive"), GRID+1 },
|
---|
616 | {"recursion", RECURSION_OPTION, 0, 0,
|
---|
617 | N_("recurse into directories (default)"), GRID+1 },
|
---|
618 | {"absolute-names", 'P', 0, 0,
|
---|
619 | N_("don't strip leading `/'s from file names"), GRID+1 },
|
---|
620 | {"dereference", 'h', 0, 0,
|
---|
621 | N_("follow symlinks; archive and dump the files they point to"), GRID+1 },
|
---|
622 | {"starting-file", 'K', N_("MEMBER-NAME"), 0,
|
---|
623 | N_("begin at member MEMBER-NAME in the archive"), GRID+1 },
|
---|
624 | {"newer", 'N', N_("DATE-OR-FILE"), 0,
|
---|
625 | N_("only store files newer than DATE-OR-FILE"), GRID+1 },
|
---|
626 | {"after-date", 0, 0, OPTION_ALIAS, NULL, GRID+1 },
|
---|
627 | {"newer-mtime", NEWER_MTIME_OPTION, N_("DATE"), 0,
|
---|
628 | N_("compare date and time when data changed only"), GRID+1 },
|
---|
629 | {"backup", BACKUP_OPTION, N_("CONTROL"), OPTION_ARG_OPTIONAL,
|
---|
630 | N_("backup before removal, choose version CONTROL"), GRID+1 },
|
---|
631 | {"suffix", SUFFIX_OPTION, N_("STRING"), 0,
|
---|
632 | N_("backup before removal, override usual suffix ('~' unless overridden by environment variable SIMPLE_BACKUP_SUFFIX)"), GRID+1 },
|
---|
633 | #undef GRID
|
---|
634 |
|
---|
635 | #define GRID 92
|
---|
636 | {NULL, 0, NULL, 0,
|
---|
637 | N_("File name transformations:"), GRID },
|
---|
638 | {"strip-components", STRIP_COMPONENTS_OPTION, N_("NUMBER"), 0,
|
---|
639 | N_("strip NUMBER leading components from file names on extraction"),
|
---|
640 | GRID+1 },
|
---|
641 | {"transform", TRANSFORM_OPTION, N_("EXPRESSION"), 0,
|
---|
642 | N_("use sed replace EXPRESSION to transform file names"), GRID+1 },
|
---|
643 | #undef GRID
|
---|
644 |
|
---|
645 | #define GRID 95
|
---|
646 | {NULL, 0, NULL, 0,
|
---|
647 | N_("File name matching options (affect both exclude and include patterns):"),
|
---|
648 | GRID },
|
---|
649 | {"ignore-case", IGNORE_CASE_OPTION, 0, 0,
|
---|
650 | N_("ignore case"), GRID+1 },
|
---|
651 | {"anchored", ANCHORED_OPTION, 0, 0,
|
---|
652 | N_("patterns match file name start"), GRID+1 },
|
---|
653 | {"no-anchored", NO_ANCHORED_OPTION, 0, 0,
|
---|
654 | N_("patterns match after any `/' (default for exclusion)"), GRID+1 },
|
---|
655 | {"no-ignore-case", NO_IGNORE_CASE_OPTION, 0, 0,
|
---|
656 | N_("case sensitive matching (default)"), GRID+1 },
|
---|
657 | {"wildcards", WILDCARDS_OPTION, 0, 0,
|
---|
658 | N_("use wildcards (default for exclusion)"), GRID+1 },
|
---|
659 | {"no-wildcards", NO_WILDCARDS_OPTION, 0, 0,
|
---|
660 | N_("verbatim string matching"), GRID+1 },
|
---|
661 | {"no-wildcards-match-slash", NO_WILDCARDS_MATCH_SLASH_OPTION, 0, 0,
|
---|
662 | N_("wildcards do not match `/'"), GRID+1 },
|
---|
663 | {"wildcards-match-slash", WILDCARDS_MATCH_SLASH_OPTION, 0, 0,
|
---|
664 | N_("wildcards match `/' (default for exclusion)"), GRID+1 },
|
---|
665 | #undef GRID
|
---|
666 |
|
---|
667 | #define GRID 100
|
---|
668 | {NULL, 0, NULL, 0,
|
---|
669 | N_("Informative output:"), GRID },
|
---|
670 |
|
---|
671 | {"verbose", 'v', 0, 0,
|
---|
672 | N_("verbosely list files processed"), GRID+1 },
|
---|
673 | {"checkpoint", CHECKPOINT_OPTION, N_("[.]NUMBER"), OPTION_ARG_OPTIONAL,
|
---|
674 | N_("display progress messages every NUMBERth record (default 10)"),
|
---|
675 | GRID+1 },
|
---|
676 | {"check-links", 'l', 0, 0,
|
---|
677 | N_("print a message if not all links are dumped"), GRID+1 },
|
---|
678 | {"totals", TOTALS_OPTION, N_("SIGNAL"), OPTION_ARG_OPTIONAL,
|
---|
679 | N_("print total bytes after processing the archive; "
|
---|
680 | "with an argument - print total bytes when this SIGNAL is delivered; "
|
---|
681 | "Allowed signals are: SIGHUP, SIGQUIT, SIGINT, SIGUSR1 and SIGUSR2; "
|
---|
682 | "the names without SIG prefix are also accepted"), GRID+1 },
|
---|
683 | {"utc", UTC_OPTION, 0, 0,
|
---|
684 | N_("print file modification dates in UTC"), GRID+1 },
|
---|
685 | {"index-file", INDEX_FILE_OPTION, N_("FILE"), 0,
|
---|
686 | N_("send verbose output to FILE"), GRID+1 },
|
---|
687 | {"block-number", 'R', 0, 0,
|
---|
688 | N_("show block number within archive with each message"), GRID+1 },
|
---|
689 | {"interactive", 'w', 0, 0,
|
---|
690 | N_("ask for confirmation for every action"), GRID+1 },
|
---|
691 | {"confirmation", 0, 0, OPTION_ALIAS, NULL, GRID+1 },
|
---|
692 | {"show-defaults", SHOW_DEFAULTS_OPTION, 0, 0,
|
---|
693 | N_("show tar defaults"), GRID+1 },
|
---|
694 | {"show-omitted-dirs", SHOW_OMITTED_DIRS_OPTION, 0, 0,
|
---|
695 | N_("when listing or extracting, list each directory that does not match search criteria"), GRID+1 },
|
---|
696 | {"show-transformed-names", SHOW_TRANSFORMED_NAMES_OPTION, 0, 0,
|
---|
697 | N_("show file or archive names after transformation"),
|
---|
698 | GRID+1 },
|
---|
699 | {"show-stored-names", 0, 0, OPTION_ALIAS, NULL, GRID+1 },
|
---|
700 | {"quoting-style", QUOTING_STYLE_OPTION, N_("STYLE"), 0,
|
---|
701 | N_("set name quoting style; see below for valid STYLE values"), GRID+1 },
|
---|
702 | {"quote-chars", QUOTE_CHARS_OPTION, N_("STRING"), 0,
|
---|
703 | N_("additionally quote characters from STRING"), GRID+1 },
|
---|
704 | {"no-quote-chars", NO_QUOTE_CHARS_OPTION, N_("STRING"), 0,
|
---|
705 | N_("disable quoting for characters from STRING"), GRID+1 },
|
---|
706 | #undef GRID
|
---|
707 |
|
---|
708 | #define GRID 110
|
---|
709 | {NULL, 0, NULL, 0,
|
---|
710 | N_("Compatibility options:"), GRID },
|
---|
711 |
|
---|
712 | {NULL, 'o', 0, 0,
|
---|
713 | N_("when creating, same as --old-archive; when extracting, same as --no-same-owner"), GRID+1 },
|
---|
714 | #undef GRID
|
---|
715 |
|
---|
716 | #define GRID 120
|
---|
717 | {NULL, 0, NULL, 0,
|
---|
718 | N_("Other options:"), GRID },
|
---|
719 |
|
---|
720 | {"restrict", RESTRICT_OPTION, 0, 0,
|
---|
721 | N_("disable use of some potentially harmful options"), -1 },
|
---|
722 |
|
---|
723 | {"help", '?', 0, 0, N_("give this help list"), -1},
|
---|
724 | {"usage", USAGE_OPTION, 0, 0, N_("give a short usage message"), -1},
|
---|
725 | {"version", VERSION_OPTION, 0, 0, N_("print program version"), -1},
|
---|
726 | /* FIXME -V (--label) conflicts with the default short option for
|
---|
727 | --version */
|
---|
728 | {"HANG", HANG_OPTION, "SECS", OPTION_ARG_OPTIONAL | OPTION_HIDDEN,
|
---|
729 | N_("hang for SECS seconds (default 3600)"), 0},
|
---|
730 | #undef GRID
|
---|
731 |
|
---|
732 | {0, 0, 0, 0, 0, 0}
|
---|
733 | };
|
---|
734 |
|
---|
735 | static char const *const atime_preserve_args[] =
|
---|
736 | {
|
---|
737 | "replace", "system", NULL
|
---|
738 | };
|
---|
739 |
|
---|
740 | static enum atime_preserve const atime_preserve_types[] =
|
---|
741 | {
|
---|
742 | replace_atime_preserve, system_atime_preserve
|
---|
743 | };
|
---|
744 |
|
---|
745 | /* Make sure atime_preserve_types has as much entries as atime_preserve_args
|
---|
746 | (minus 1 for NULL guard) */
|
---|
747 | ARGMATCH_VERIFY (atime_preserve_args, atime_preserve_types);
|
---|
748 |
|
---|
749 | /* Wildcard matching settings */
|
---|
750 | enum wildcards
|
---|
751 | {
|
---|
752 | default_wildcards, /* For exclusion == enable_wildcards,
|
---|
753 | for inclusion == disable_wildcards */
|
---|
754 | disable_wildcards,
|
---|
755 | enable_wildcards
|
---|
756 | };
|
---|
757 |
|
---|
758 | struct tar_args /* Variables used during option parsing */
|
---|
759 | {
|
---|
760 | struct textual_date *textual_date; /* Keeps the arguments to --newer-mtime
|
---|
761 | and/or --date option if they are
|
---|
762 | textual dates */
|
---|
763 | enum wildcards wildcards; /* Wildcard settings (--wildcards/
|
---|
764 | --no-wildcards) */
|
---|
765 | int matching_flags; /* exclude_fnmatch options */
|
---|
766 | int include_anchored; /* Pattern anchoring options used for
|
---|
767 | file inclusion */
|
---|
768 | bool o_option; /* True if -o option was given */
|
---|
769 | bool pax_option; /* True if --pax-option was given */
|
---|
770 | char const *backup_suffix_string; /* --suffix option argument */
|
---|
771 | char const *version_control_string; /* --backup option argument */
|
---|
772 | bool input_files; /* True if some input files where given */
|
---|
773 | };
|
---|
774 |
|
---|
775 | #define MAKE_EXCL_OPTIONS(args) \
|
---|
776 | ((((args)->wildcards != disable_wildcards) ? EXCLUDE_WILDCARDS : 0) \
|
---|
777 | | (args)->matching_flags \
|
---|
778 | | recursion_option)
|
---|
779 |
|
---|
780 | #define MAKE_INCL_OPTIONS(args) \
|
---|
781 | ((((args)->wildcards == enable_wildcards) ? EXCLUDE_WILDCARDS : 0) \
|
---|
782 | | (args)->include_anchored \
|
---|
783 | | (args)->matching_flags \
|
---|
784 | | recursion_option)
|
---|
785 |
|
---|
786 | #ifdef REMOTE_SHELL
|
---|
787 | # define DECL_SHOW_DEFAULT_SETTINGS(stream, printer) \
|
---|
788 | { \
|
---|
789 | printer (stream, \
|
---|
790 | "--format=%s -f%s -b%d --quoting-style=%s --rmt-command=%s", \
|
---|
791 | archive_format_string (DEFAULT_ARCHIVE_FORMAT), \
|
---|
792 | DEFAULT_ARCHIVE, DEFAULT_BLOCKING, \
|
---|
793 | quoting_style_args[DEFAULT_QUOTING_STYLE], \
|
---|
794 | DEFAULT_RMT_COMMAND); \
|
---|
795 | printer (stream, " --rsh-command=%s", REMOTE_SHELL); \
|
---|
796 | printer (stream, "\n"); \
|
---|
797 | }
|
---|
798 | #else
|
---|
799 | # define DECL_SHOW_DEFAULT_SETTINGS(stream, printer) \
|
---|
800 | { \
|
---|
801 | printer (stream, \
|
---|
802 | "--format=%s -f%s -b%d --quoting-style=%s --rmt-command=%s", \
|
---|
803 | archive_format_string (DEFAULT_ARCHIVE_FORMAT), \
|
---|
804 | DEFAULT_ARCHIVE, DEFAULT_BLOCKING, \
|
---|
805 | quoting_style_args[DEFAULT_QUOTING_STYLE], \
|
---|
806 | DEFAULT_RMT_COMMAND); \
|
---|
807 | printer (stream, "\n"); \
|
---|
808 | }
|
---|
809 | #endif
|
---|
810 |
|
---|
811 | static void
|
---|
812 | show_default_settings (FILE *fp)
|
---|
813 | DECL_SHOW_DEFAULT_SETTINGS(fp, fprintf)
|
---|
814 |
|
---|
815 | static void
|
---|
816 | show_default_settings_fs (argp_fmtstream_t fs)
|
---|
817 | DECL_SHOW_DEFAULT_SETTINGS(fs, argp_fmtstream_printf)
|
---|
818 |
|
---|
819 | static void
|
---|
820 | set_subcommand_option (enum subcommand subcommand)
|
---|
821 | {
|
---|
822 | if (subcommand_option != UNKNOWN_SUBCOMMAND
|
---|
823 | && subcommand_option != subcommand)
|
---|
824 | USAGE_ERROR ((0, 0,
|
---|
825 | _("You may not specify more than one `-Acdtrux' option")));
|
---|
826 |
|
---|
827 | subcommand_option = subcommand;
|
---|
828 | }
|
---|
829 |
|
---|
830 | static void
|
---|
831 | set_use_compress_program_option (const char *string)
|
---|
832 | {
|
---|
833 | if (use_compress_program_option
|
---|
834 | && strcmp (use_compress_program_option, string) != 0)
|
---|
835 | USAGE_ERROR ((0, 0, _("Conflicting compression options")));
|
---|
836 |
|
---|
837 | use_compress_program_option = string;
|
---|
838 | }
|
---|
839 | |
---|
840 |
|
---|
841 | static RETSIGTYPE
|
---|
842 | sigstat (int signo)
|
---|
843 | {
|
---|
844 | compute_duration ();
|
---|
845 | print_total_stats ();
|
---|
846 | #ifndef HAVE_SIGACTION
|
---|
847 | signal (signo, sigstat);
|
---|
848 | #endif
|
---|
849 | }
|
---|
850 |
|
---|
851 | static void
|
---|
852 | stat_on_signal (int signo)
|
---|
853 | {
|
---|
854 | #ifdef HAVE_SIGACTION
|
---|
855 | struct sigaction act;
|
---|
856 | act.sa_handler = sigstat;
|
---|
857 | sigemptyset (&act.sa_mask);
|
---|
858 | act.sa_flags = 0;
|
---|
859 | sigaction (signo, &act, NULL);
|
---|
860 | #else
|
---|
861 | signal (signo, sigstat);
|
---|
862 | #endif
|
---|
863 | }
|
---|
864 |
|
---|
865 | void
|
---|
866 | set_stat_signal (const char *name)
|
---|
867 | {
|
---|
868 | static struct sigtab
|
---|
869 | {
|
---|
870 | char *name;
|
---|
871 | int signo;
|
---|
872 | } sigtab[] = {
|
---|
873 | { "SIGUSR1", SIGUSR1 },
|
---|
874 | { "USR1", SIGUSR1 },
|
---|
875 | { "SIGUSR2", SIGUSR2 },
|
---|
876 | { "USR2", SIGUSR2 },
|
---|
877 | { "SIGHUP", SIGHUP },
|
---|
878 | { "HUP", SIGHUP },
|
---|
879 | { "SIGINT", SIGINT },
|
---|
880 | { "INT", SIGINT },
|
---|
881 | { "SIGQUIT", SIGQUIT },
|
---|
882 | { "QUIT", SIGQUIT }
|
---|
883 | };
|
---|
884 | struct sigtab *p;
|
---|
885 |
|
---|
886 | for (p = sigtab; p < sigtab + sizeof (sigtab) / sizeof (sigtab[0]); p++)
|
---|
887 | if (strcmp (p->name, name) == 0)
|
---|
888 | {
|
---|
889 | stat_on_signal (p->signo);
|
---|
890 | return;
|
---|
891 | }
|
---|
892 | FATAL_ERROR ((0, 0, _("Unknown signal name: %s"), name));
|
---|
893 | }
|
---|
894 |
|
---|
895 | |
---|
896 |
|
---|
897 | struct textual_date
|
---|
898 | {
|
---|
899 | struct textual_date *next;
|
---|
900 | struct timespec *ts;
|
---|
901 | const char *option;
|
---|
902 | const char *date;
|
---|
903 | };
|
---|
904 |
|
---|
905 | static void
|
---|
906 | get_date_or_file (struct tar_args *args, const char *option,
|
---|
907 | const char *str, struct timespec *ts)
|
---|
908 | {
|
---|
909 | if (FILE_SYSTEM_PREFIX_LEN (str) != 0
|
---|
910 | || ISSLASH (*str)
|
---|
911 | || *str == '.')
|
---|
912 | {
|
---|
913 | struct stat st;
|
---|
914 | if (deref_stat (dereference_option, str, &st) != 0)
|
---|
915 | {
|
---|
916 | stat_error (str);
|
---|
917 | USAGE_ERROR ((0, 0, _("Date sample file not found")));
|
---|
918 | }
|
---|
919 | *ts = get_stat_mtime (&st);
|
---|
920 | }
|
---|
921 | else
|
---|
922 | {
|
---|
923 | if (! get_date (ts, str, NULL))
|
---|
924 | {
|
---|
925 | WARN ((0, 0, _("Substituting %s for unknown date format %s"),
|
---|
926 | tartime (*ts, false), quote (str)));
|
---|
927 | ts->tv_nsec = 0;
|
---|
928 | }
|
---|
929 | else
|
---|
930 | {
|
---|
931 | struct textual_date *p = xmalloc (sizeof (*p));
|
---|
932 | p->ts = ts;
|
---|
933 | p->option = option;
|
---|
934 | p->date = str;
|
---|
935 | p->next = args->textual_date;
|
---|
936 | args->textual_date = p;
|
---|
937 | }
|
---|
938 | }
|
---|
939 | }
|
---|
940 |
|
---|
941 | static void
|
---|
942 | report_textual_dates (struct tar_args *args)
|
---|
943 | {
|
---|
944 | struct textual_date *p;
|
---|
945 | for (p = args->textual_date; p; )
|
---|
946 | {
|
---|
947 | struct textual_date *next = p->next;
|
---|
948 | char const *treated_as = tartime (*p->ts, true);
|
---|
949 | if (strcmp (p->date, treated_as) != 0)
|
---|
950 | WARN ((0, 0, _("Option %s: Treating date `%s' as %s"),
|
---|
951 | p->option, p->date, treated_as));
|
---|
952 | free (p);
|
---|
953 | p = next;
|
---|
954 | }
|
---|
955 | }
|
---|
956 |
|
---|
957 | |
---|
958 |
|
---|
959 | static volatile int _argp_hang;
|
---|
960 |
|
---|
961 | enum read_file_list_state /* Result of reading file name from the list file */
|
---|
962 | {
|
---|
963 | file_list_success, /* OK, name read successfully */
|
---|
964 | file_list_end, /* End of list file */
|
---|
965 | file_list_zero, /* Zero separator encountered where it should not */
|
---|
966 | file_list_skip /* Empty (zero-length) entry encountered, skip it */
|
---|
967 | };
|
---|
968 |
|
---|
969 | /* Read from FP a sequence of characters up to FILENAME_TERMINATOR and put them
|
---|
970 | into STK.
|
---|
971 | */
|
---|
972 | static enum read_file_list_state
|
---|
973 | read_name_from_file (FILE *fp, struct obstack *stk)
|
---|
974 | {
|
---|
975 | int c;
|
---|
976 | size_t counter = 0;
|
---|
977 |
|
---|
978 | for (c = getc (fp); c != EOF && c != filename_terminator; c = getc (fp))
|
---|
979 | {
|
---|
980 | if (c == 0)
|
---|
981 | {
|
---|
982 | /* We have read a zero separator. The file possibly is
|
---|
983 | zero-separated */
|
---|
984 | return file_list_zero;
|
---|
985 | }
|
---|
986 | obstack_1grow (stk, c);
|
---|
987 | counter++;
|
---|
988 | }
|
---|
989 |
|
---|
990 | if (counter == 0 && c != EOF)
|
---|
991 | return file_list_skip;
|
---|
992 |
|
---|
993 | obstack_1grow (stk, 0);
|
---|
994 |
|
---|
995 | return (counter == 0 && c == EOF) ? file_list_end : file_list_success;
|
---|
996 | }
|
---|
997 |
|
---|
998 | |
---|
999 |
|
---|
1000 | static bool files_from_option; /* When set, tar will not refuse to create
|
---|
1001 | empty archives */
|
---|
1002 | static struct obstack argv_stk; /* Storage for additional command line options
|
---|
1003 | read using -T option */
|
---|
1004 |
|
---|
1005 | /* Prevent recursive inclusion of the same file */
|
---|
1006 | struct file_id_list
|
---|
1007 | {
|
---|
1008 | struct file_id_list *next;
|
---|
1009 | ino_t ino;
|
---|
1010 | dev_t dev;
|
---|
1011 | };
|
---|
1012 |
|
---|
1013 | static struct file_id_list *file_id_list;
|
---|
1014 |
|
---|
1015 | static void
|
---|
1016 | add_file_id (const char *filename)
|
---|
1017 | {
|
---|
1018 | struct file_id_list *p;
|
---|
1019 | struct stat st;
|
---|
1020 |
|
---|
1021 | if (stat (filename, &st))
|
---|
1022 | stat_fatal (filename);
|
---|
1023 | for (p = file_id_list; p; p = p->next)
|
---|
1024 | if (p->ino == st.st_ino && p->dev == st.st_dev)
|
---|
1025 | {
|
---|
1026 | FATAL_ERROR ((0, 0, _("%s: file list already read"),
|
---|
1027 | quotearg_colon (filename)));
|
---|
1028 | }
|
---|
1029 | p = xmalloc (sizeof *p);
|
---|
1030 | p->next = file_id_list;
|
---|
1031 | p->ino = st.st_ino;
|
---|
1032 | p->dev = st.st_dev;
|
---|
1033 | file_id_list = p;
|
---|
1034 | }
|
---|
1035 |
|
---|
1036 | /* Default density numbers for [0-9][lmh] device specifications */
|
---|
1037 |
|
---|
1038 | #ifndef LOW_DENSITY_NUM
|
---|
1039 | # define LOW_DENSITY_NUM 0
|
---|
1040 | #endif
|
---|
1041 |
|
---|
1042 | #ifndef MID_DENSITY_NUM
|
---|
1043 | # define MID_DENSITY_NUM 8
|
---|
1044 | #endif
|
---|
1045 |
|
---|
1046 | #ifndef HIGH_DENSITY_NUM
|
---|
1047 | # define HIGH_DENSITY_NUM 16
|
---|
1048 | #endif
|
---|
1049 |
|
---|
1050 | static void
|
---|
1051 | update_argv (const char *filename, struct argp_state *state)
|
---|
1052 | {
|
---|
1053 | FILE *fp;
|
---|
1054 | size_t count = 0, i;
|
---|
1055 | char *start, *p;
|
---|
1056 | char **new_argv;
|
---|
1057 | size_t new_argc;
|
---|
1058 | bool is_stdin = false;
|
---|
1059 | enum read_file_list_state read_state;
|
---|
1060 |
|
---|
1061 | if (!strcmp (filename, "-"))
|
---|
1062 | {
|
---|
1063 | is_stdin = true;
|
---|
1064 | request_stdin ("-T");
|
---|
1065 | fp = stdin;
|
---|
1066 | }
|
---|
1067 | else
|
---|
1068 | {
|
---|
1069 | add_file_id (filename);
|
---|
1070 | if ((fp = fopen (filename, "r")) == NULL)
|
---|
1071 | open_fatal (filename);
|
---|
1072 | }
|
---|
1073 |
|
---|
1074 | while ((read_state = read_name_from_file (fp, &argv_stk)) != file_list_end)
|
---|
1075 | {
|
---|
1076 | switch (read_state)
|
---|
1077 | {
|
---|
1078 | case file_list_success:
|
---|
1079 | count++;
|
---|
1080 | break;
|
---|
1081 |
|
---|
1082 | case file_list_end: /* won't happen, just to pacify gcc */
|
---|
1083 | break;
|
---|
1084 |
|
---|
1085 | case file_list_zero:
|
---|
1086 | {
|
---|
1087 | size_t size;
|
---|
1088 |
|
---|
1089 | WARN ((0, 0, N_("%s: file name read contains nul character"),
|
---|
1090 | quotearg_colon (filename)));
|
---|
1091 |
|
---|
1092 | /* Prepare new stack contents */
|
---|
1093 | size = obstack_object_size (&argv_stk);
|
---|
1094 | p = obstack_finish (&argv_stk);
|
---|
1095 | for (; size > 0; size--, p++)
|
---|
1096 | if (*p)
|
---|
1097 | obstack_1grow (&argv_stk, *p);
|
---|
1098 | else
|
---|
1099 | obstack_1grow (&argv_stk, '\n');
|
---|
1100 | obstack_1grow (&argv_stk, 0);
|
---|
1101 | count = 1;
|
---|
1102 | /* Read rest of files using new filename terminator */
|
---|
1103 | filename_terminator = 0;
|
---|
1104 | break;
|
---|
1105 | }
|
---|
1106 |
|
---|
1107 | case file_list_skip:
|
---|
1108 | break;
|
---|
1109 | }
|
---|
1110 | }
|
---|
1111 |
|
---|
1112 | if (!is_stdin)
|
---|
1113 | fclose (fp);
|
---|
1114 |
|
---|
1115 | if (count == 0)
|
---|
1116 | return;
|
---|
1117 |
|
---|
1118 | start = obstack_finish (&argv_stk);
|
---|
1119 |
|
---|
1120 | if (filename_terminator == 0)
|
---|
1121 | for (p = start; *p; p += strlen (p) + 1)
|
---|
1122 | if (p[0] == '-')
|
---|
1123 | count++;
|
---|
1124 |
|
---|
1125 | new_argc = state->argc + count;
|
---|
1126 | new_argv = xmalloc (sizeof (state->argv[0]) * (new_argc + 1));
|
---|
1127 | memcpy (new_argv, state->argv, sizeof (state->argv[0]) * (state->argc + 1));
|
---|
1128 | state->argv = new_argv;
|
---|
1129 | memmove (&state->argv[state->next + count], &state->argv[state->next],
|
---|
1130 | (state->argc - state->next + 1) * sizeof (state->argv[0]));
|
---|
1131 |
|
---|
1132 | state->argc = new_argc;
|
---|
1133 |
|
---|
1134 | for (i = state->next, p = start; *p; p += strlen (p) + 1, i++)
|
---|
1135 | {
|
---|
1136 | if (filename_terminator == 0 && p[0] == '-')
|
---|
1137 | state->argv[i++] = "--add-file";
|
---|
1138 | state->argv[i] = p;
|
---|
1139 | }
|
---|
1140 | }
|
---|
1141 |
|
---|
1142 | |
---|
1143 |
|
---|
1144 | static void
|
---|
1145 | tar_help (struct argp_state *state)
|
---|
1146 | {
|
---|
1147 | argp_fmtstream_t fs;
|
---|
1148 | state->flags |= ARGP_NO_EXIT;
|
---|
1149 | argp_state_help (state, state->out_stream,
|
---|
1150 | ARGP_HELP_STD_HELP & ~ARGP_HELP_BUG_ADDR);
|
---|
1151 | /* FIXME: use struct uparams.rmargin (from argp-help.c) instead of 79 */
|
---|
1152 | fs = argp_make_fmtstream (state->out_stream, 0, 79, 0);
|
---|
1153 |
|
---|
1154 | argp_fmtstream_printf (fs, "\n%s\n\n",
|
---|
1155 | _("Valid arguments for --quoting-style options are:"));
|
---|
1156 | tar_list_quoting_styles (fs, " ");
|
---|
1157 |
|
---|
1158 | argp_fmtstream_puts (fs, _("\n*This* tar defaults to:\n"));
|
---|
1159 | show_default_settings_fs (fs);
|
---|
1160 | argp_fmtstream_putc (fs, '\n');
|
---|
1161 | argp_fmtstream_printf (fs, _("Report bugs to %s.\n"),
|
---|
1162 | argp_program_bug_address);
|
---|
1163 | argp_fmtstream_free (fs);
|
---|
1164 | }
|
---|
1165 | |
---|
1166 |
|
---|
1167 | static error_t
|
---|
1168 | parse_opt (int key, char *arg, struct argp_state *state)
|
---|
1169 | {
|
---|
1170 | struct tar_args *args = state->input;
|
---|
1171 |
|
---|
1172 | switch (key)
|
---|
1173 | {
|
---|
1174 | case ARGP_KEY_ARG:
|
---|
1175 | /* File name or non-parsed option, because of ARGP_IN_ORDER */
|
---|
1176 | name_add_name (arg, MAKE_INCL_OPTIONS (args));
|
---|
1177 | args->input_files = true;
|
---|
1178 | break;
|
---|
1179 |
|
---|
1180 | case 'A':
|
---|
1181 | set_subcommand_option (CAT_SUBCOMMAND);
|
---|
1182 | break;
|
---|
1183 |
|
---|
1184 | case 'b':
|
---|
1185 | {
|
---|
1186 | uintmax_t u;
|
---|
1187 | if (! (xstrtoumax (arg, 0, 10, &u, "") == LONGINT_OK
|
---|
1188 | && u == (blocking_factor = u)
|
---|
1189 | && 0 < blocking_factor
|
---|
1190 | && u == (record_size = u * BLOCKSIZE) / BLOCKSIZE))
|
---|
1191 | USAGE_ERROR ((0, 0, "%s: %s", quotearg_colon (arg),
|
---|
1192 | _("Invalid blocking factor")));
|
---|
1193 | }
|
---|
1194 | break;
|
---|
1195 |
|
---|
1196 | case 'B':
|
---|
1197 | /* Try to reblock input records. For reading 4.2BSD pipes. */
|
---|
1198 |
|
---|
1199 | /* It would surely make sense to exchange -B and -R, but it seems
|
---|
1200 | that -B has been used for a long while in Sun tar and most
|
---|
1201 | BSD-derived systems. This is a consequence of the block/record
|
---|
1202 | terminology confusion. */
|
---|
1203 |
|
---|
1204 | read_full_records_option = true;
|
---|
1205 | break;
|
---|
1206 |
|
---|
1207 | case 'c':
|
---|
1208 | set_subcommand_option (CREATE_SUBCOMMAND);
|
---|
1209 | break;
|
---|
1210 |
|
---|
1211 | case 'C':
|
---|
1212 | name_add_dir (arg);
|
---|
1213 | break;
|
---|
1214 |
|
---|
1215 | case 'd':
|
---|
1216 | set_subcommand_option (DIFF_SUBCOMMAND);
|
---|
1217 | break;
|
---|
1218 |
|
---|
1219 | case 'f':
|
---|
1220 | if (archive_names == allocated_archive_names)
|
---|
1221 | archive_name_array = x2nrealloc (archive_name_array,
|
---|
1222 | &allocated_archive_names,
|
---|
1223 | sizeof (archive_name_array[0]));
|
---|
1224 |
|
---|
1225 | archive_name_array[archive_names++] = arg;
|
---|
1226 | break;
|
---|
1227 |
|
---|
1228 | case 'F':
|
---|
1229 | /* Since -F is only useful with -M, make it implied. Run this
|
---|
1230 | script at the end of each tape. */
|
---|
1231 |
|
---|
1232 | info_script_option = arg;
|
---|
1233 | multi_volume_option = true;
|
---|
1234 | break;
|
---|
1235 |
|
---|
1236 | case 'g':
|
---|
1237 | listed_incremental_option = arg;
|
---|
1238 | after_date_option = true;
|
---|
1239 | /* Fall through. */
|
---|
1240 |
|
---|
1241 | case 'G':
|
---|
1242 | /* We are making an incremental dump (FIXME: are we?); save
|
---|
1243 | directories at the beginning of the archive, and include in each
|
---|
1244 | directory its contents. */
|
---|
1245 |
|
---|
1246 | incremental_option = true;
|
---|
1247 | break;
|
---|
1248 |
|
---|
1249 | case 'h':
|
---|
1250 | /* Follow symbolic links. */
|
---|
1251 | dereference_option = true;
|
---|
1252 | break;
|
---|
1253 |
|
---|
1254 | case 'i':
|
---|
1255 | /* Ignore zero blocks (eofs). This can't be the default,
|
---|
1256 | because Unix tar writes two blocks of zeros, then pads out
|
---|
1257 | the record with garbage. */
|
---|
1258 |
|
---|
1259 | ignore_zeros_option = true;
|
---|
1260 | break;
|
---|
1261 |
|
---|
1262 | case 'I':
|
---|
1263 | USAGE_ERROR ((0, 0,
|
---|
1264 | _("Warning: the -I option is not supported;"
|
---|
1265 | " perhaps you meant -j or -T?")));
|
---|
1266 | break;
|
---|
1267 |
|
---|
1268 | case 'j':
|
---|
1269 | set_use_compress_program_option ("bzip2");
|
---|
1270 | break;
|
---|
1271 |
|
---|
1272 | case 'k':
|
---|
1273 | /* Don't replace existing files. */
|
---|
1274 | old_files_option = KEEP_OLD_FILES;
|
---|
1275 | break;
|
---|
1276 |
|
---|
1277 | case 'K':
|
---|
1278 | starting_file_option = true;
|
---|
1279 | addname (arg, 0);
|
---|
1280 | break;
|
---|
1281 |
|
---|
1282 | case ONE_FILE_SYSTEM_OPTION:
|
---|
1283 | /* When dumping directories, don't dump files/subdirectories
|
---|
1284 | that are on other filesystems. */
|
---|
1285 | one_file_system_option = true;
|
---|
1286 | break;
|
---|
1287 |
|
---|
1288 | case 'l':
|
---|
1289 | check_links_option = 1;
|
---|
1290 | break;
|
---|
1291 |
|
---|
1292 | case 'L':
|
---|
1293 | {
|
---|
1294 | uintmax_t u;
|
---|
1295 | if (xstrtoumax (arg, 0, 10, &u, "") != LONGINT_OK)
|
---|
1296 | USAGE_ERROR ((0, 0, "%s: %s", quotearg_colon (arg),
|
---|
1297 | _("Invalid tape length")));
|
---|
1298 | tape_length_option = 1024 * (tarlong) u;
|
---|
1299 | multi_volume_option = true;
|
---|
1300 | }
|
---|
1301 | break;
|
---|
1302 |
|
---|
1303 | case 'm':
|
---|
1304 | touch_option = true;
|
---|
1305 | break;
|
---|
1306 |
|
---|
1307 | case 'M':
|
---|
1308 | /* Make multivolume archive: when we can't write any more into
|
---|
1309 | the archive, re-open it, and continue writing. */
|
---|
1310 |
|
---|
1311 | multi_volume_option = true;
|
---|
1312 | break;
|
---|
1313 |
|
---|
1314 | case MTIME_OPTION:
|
---|
1315 | get_date_or_file (args, "--mtime", arg, &mtime_option);
|
---|
1316 | set_mtime_option = true;
|
---|
1317 | break;
|
---|
1318 |
|
---|
1319 | case 'n':
|
---|
1320 | seekable_archive = true;
|
---|
1321 | break;
|
---|
1322 |
|
---|
1323 | case 'N':
|
---|
1324 | after_date_option = true;
|
---|
1325 | /* Fall through. */
|
---|
1326 |
|
---|
1327 | case NEWER_MTIME_OPTION:
|
---|
1328 | if (NEWER_OPTION_INITIALIZED (newer_mtime_option))
|
---|
1329 | USAGE_ERROR ((0, 0, _("More than one threshold date")));
|
---|
1330 | get_date_or_file (args,
|
---|
1331 | key == NEWER_MTIME_OPTION ? "--newer-mtime"
|
---|
1332 | : "--after-date", arg, &newer_mtime_option);
|
---|
1333 | break;
|
---|
1334 |
|
---|
1335 | case 'o':
|
---|
1336 | args->o_option = true;
|
---|
1337 | break;
|
---|
1338 |
|
---|
1339 | case 'O':
|
---|
1340 | to_stdout_option = true;
|
---|
1341 | break;
|
---|
1342 |
|
---|
1343 | case 'p':
|
---|
1344 | same_permissions_option = true;
|
---|
1345 | break;
|
---|
1346 |
|
---|
1347 | case 'P':
|
---|
1348 | absolute_names_option = true;
|
---|
1349 | break;
|
---|
1350 |
|
---|
1351 | case 'r':
|
---|
1352 | set_subcommand_option (APPEND_SUBCOMMAND);
|
---|
1353 | break;
|
---|
1354 |
|
---|
1355 | case 'R':
|
---|
1356 | /* Print block numbers for debugging bad tar archives. */
|
---|
1357 |
|
---|
1358 | /* It would surely make sense to exchange -B and -R, but it seems
|
---|
1359 | that -B has been used for a long while in Sun tar and most
|
---|
1360 | BSD-derived systems. This is a consequence of the block/record
|
---|
1361 | terminology confusion. */
|
---|
1362 |
|
---|
1363 | block_number_option = true;
|
---|
1364 | break;
|
---|
1365 |
|
---|
1366 | case 's':
|
---|
1367 | /* Names to extract are sorted. */
|
---|
1368 |
|
---|
1369 | same_order_option = true;
|
---|
1370 | break;
|
---|
1371 |
|
---|
1372 | case 'S':
|
---|
1373 | sparse_option = true;
|
---|
1374 | break;
|
---|
1375 |
|
---|
1376 | case SPARSE_VERSION_OPTION:
|
---|
1377 | sparse_option = true;
|
---|
1378 | {
|
---|
1379 | char *p;
|
---|
1380 | tar_sparse_major = strtoul (arg, &p, 10);
|
---|
1381 | if (*p)
|
---|
1382 | {
|
---|
1383 | if (*p != '.')
|
---|
1384 | USAGE_ERROR ((0, 0, _("Invalid sparse version value")));
|
---|
1385 | tar_sparse_minor = strtoul (p + 1, &p, 10);
|
---|
1386 | if (*p)
|
---|
1387 | USAGE_ERROR ((0, 0, _("Invalid sparse version value")));
|
---|
1388 | }
|
---|
1389 | }
|
---|
1390 | break;
|
---|
1391 |
|
---|
1392 | case 't':
|
---|
1393 | set_subcommand_option (LIST_SUBCOMMAND);
|
---|
1394 | verbose_option++;
|
---|
1395 | break;
|
---|
1396 |
|
---|
1397 | case TEST_LABEL_OPTION:
|
---|
1398 | set_subcommand_option (LIST_SUBCOMMAND);
|
---|
1399 | test_label_option = true;
|
---|
1400 | break;
|
---|
1401 |
|
---|
1402 | case 'T':
|
---|
1403 | update_argv (arg, state);
|
---|
1404 | /* Indicate we've been given -T option. This is for backward
|
---|
1405 | compatibility only, so that `tar cfT archive /dev/null will
|
---|
1406 | succeed */
|
---|
1407 | files_from_option = true;
|
---|
1408 | break;
|
---|
1409 |
|
---|
1410 | case 'u':
|
---|
1411 | set_subcommand_option (UPDATE_SUBCOMMAND);
|
---|
1412 | break;
|
---|
1413 |
|
---|
1414 | case 'U':
|
---|
1415 | old_files_option = UNLINK_FIRST_OLD_FILES;
|
---|
1416 | break;
|
---|
1417 |
|
---|
1418 | case UTC_OPTION:
|
---|
1419 | utc_option = true;
|
---|
1420 | break;
|
---|
1421 |
|
---|
1422 | case 'v':
|
---|
1423 | verbose_option++;
|
---|
1424 | break;
|
---|
1425 |
|
---|
1426 | case 'V':
|
---|
1427 | volume_label_option = arg;
|
---|
1428 | break;
|
---|
1429 |
|
---|
1430 | case 'w':
|
---|
1431 | interactive_option = true;
|
---|
1432 | break;
|
---|
1433 |
|
---|
1434 | case 'W':
|
---|
1435 | verify_option = true;
|
---|
1436 | break;
|
---|
1437 |
|
---|
1438 | case 'x':
|
---|
1439 | set_subcommand_option (EXTRACT_SUBCOMMAND);
|
---|
1440 | break;
|
---|
1441 |
|
---|
1442 | case 'X':
|
---|
1443 | if (add_exclude_file (add_exclude, excluded, arg,
|
---|
1444 | MAKE_EXCL_OPTIONS (args), '\n')
|
---|
1445 | != 0)
|
---|
1446 | {
|
---|
1447 | int e = errno;
|
---|
1448 | FATAL_ERROR ((0, e, "%s", quotearg_colon (arg)));
|
---|
1449 | }
|
---|
1450 | break;
|
---|
1451 |
|
---|
1452 | case 'z':
|
---|
1453 | set_use_compress_program_option ("gzip");
|
---|
1454 | break;
|
---|
1455 |
|
---|
1456 | case 'Z':
|
---|
1457 | set_use_compress_program_option ("compress");
|
---|
1458 | break;
|
---|
1459 |
|
---|
1460 | case ANCHORED_OPTION:
|
---|
1461 | args->matching_flags |= EXCLUDE_ANCHORED;
|
---|
1462 | break;
|
---|
1463 |
|
---|
1464 | case ATIME_PRESERVE_OPTION:
|
---|
1465 | atime_preserve_option =
|
---|
1466 | (arg
|
---|
1467 | ? XARGMATCH ("--atime-preserve", arg,
|
---|
1468 | atime_preserve_args, atime_preserve_types)
|
---|
1469 | : replace_atime_preserve);
|
---|
1470 | if (! O_NOATIME && atime_preserve_option == system_atime_preserve)
|
---|
1471 | FATAL_ERROR ((0, 0,
|
---|
1472 | _("--atime-preserve='system' is not supported"
|
---|
1473 | " on this platform")));
|
---|
1474 | break;
|
---|
1475 |
|
---|
1476 | case CHECKPOINT_OPTION:
|
---|
1477 | if (arg)
|
---|
1478 | {
|
---|
1479 | char *p;
|
---|
1480 |
|
---|
1481 | if (*arg == '.')
|
---|
1482 | {
|
---|
1483 | checkpoint_style = checkpoint_dot;
|
---|
1484 | arg++;
|
---|
1485 | }
|
---|
1486 | checkpoint_option = strtoul (arg, &p, 0);
|
---|
1487 | if (*p)
|
---|
1488 | FATAL_ERROR ((0, 0,
|
---|
1489 | _("--checkpoint value is not an integer")));
|
---|
1490 | }
|
---|
1491 | else
|
---|
1492 | checkpoint_option = 10;
|
---|
1493 | break;
|
---|
1494 |
|
---|
1495 | case BACKUP_OPTION:
|
---|
1496 | backup_option = true;
|
---|
1497 | if (arg)
|
---|
1498 | args->version_control_string = arg;
|
---|
1499 | break;
|
---|
1500 |
|
---|
1501 | case DELAY_DIRECTORY_RESTORE_OPTION:
|
---|
1502 | delay_directory_restore_option = true;
|
---|
1503 | break;
|
---|
1504 |
|
---|
1505 | case NO_DELAY_DIRECTORY_RESTORE_OPTION:
|
---|
1506 | delay_directory_restore_option = false;
|
---|
1507 | break;
|
---|
1508 |
|
---|
1509 | case DELETE_OPTION:
|
---|
1510 | set_subcommand_option (DELETE_SUBCOMMAND);
|
---|
1511 | break;
|
---|
1512 |
|
---|
1513 | case EXCLUDE_OPTION:
|
---|
1514 | add_exclude (excluded, arg, MAKE_EXCL_OPTIONS (args));
|
---|
1515 | break;
|
---|
1516 |
|
---|
1517 | case EXCLUDE_CACHES_OPTION:
|
---|
1518 | exclude_caches_option = true;
|
---|
1519 | break;
|
---|
1520 |
|
---|
1521 | case EXCLUDE_TAG_OPTION:
|
---|
1522 | add_exclude_tag (arg);
|
---|
1523 | break;
|
---|
1524 |
|
---|
1525 | case FORCE_LOCAL_OPTION:
|
---|
1526 | force_local_option = true;
|
---|
1527 | break;
|
---|
1528 |
|
---|
1529 | case 'H':
|
---|
1530 | set_archive_format (arg);
|
---|
1531 | break;
|
---|
1532 |
|
---|
1533 | case INDEX_FILE_OPTION:
|
---|
1534 | index_file_name = arg;
|
---|
1535 | break;
|
---|
1536 |
|
---|
1537 | case IGNORE_CASE_OPTION:
|
---|
1538 | args->matching_flags |= FNM_CASEFOLD;
|
---|
1539 | break;
|
---|
1540 |
|
---|
1541 | case IGNORE_COMMAND_ERROR_OPTION:
|
---|
1542 | ignore_command_error_option = true;
|
---|
1543 | break;
|
---|
1544 |
|
---|
1545 | case IGNORE_FAILED_READ_OPTION:
|
---|
1546 | ignore_failed_read_option = true;
|
---|
1547 | break;
|
---|
1548 |
|
---|
1549 | case KEEP_NEWER_FILES_OPTION:
|
---|
1550 | old_files_option = KEEP_NEWER_FILES;
|
---|
1551 | break;
|
---|
1552 |
|
---|
1553 | case GROUP_OPTION:
|
---|
1554 | if (! (strlen (arg) < GNAME_FIELD_SIZE
|
---|
1555 | && gname_to_gid (arg, &group_option)))
|
---|
1556 | {
|
---|
1557 | uintmax_t g;
|
---|
1558 | if (xstrtoumax (arg, 0, 10, &g, "") == LONGINT_OK
|
---|
1559 | && g == (gid_t) g)
|
---|
1560 | group_option = g;
|
---|
1561 | else
|
---|
1562 | FATAL_ERROR ((0, 0, "%s: %s", quotearg_colon (arg),
|
---|
1563 | _("%s: Invalid group")));
|
---|
1564 | }
|
---|
1565 | break;
|
---|
1566 |
|
---|
1567 | case MODE_OPTION:
|
---|
1568 | mode_option = mode_compile (arg);
|
---|
1569 | if (!mode_option)
|
---|
1570 | FATAL_ERROR ((0, 0, _("Invalid mode given on option")));
|
---|
1571 | initial_umask = umask (0);
|
---|
1572 | umask (initial_umask);
|
---|
1573 | break;
|
---|
1574 |
|
---|
1575 | case NO_ANCHORED_OPTION:
|
---|
1576 | args->include_anchored = 0; /* Clear the default for comman line args */
|
---|
1577 | args->matching_flags &= ~ EXCLUDE_ANCHORED;
|
---|
1578 | break;
|
---|
1579 |
|
---|
1580 | case NO_IGNORE_CASE_OPTION:
|
---|
1581 | args->matching_flags &= ~ FNM_CASEFOLD;
|
---|
1582 | break;
|
---|
1583 |
|
---|
1584 | case NO_IGNORE_COMMAND_ERROR_OPTION:
|
---|
1585 | ignore_command_error_option = false;
|
---|
1586 | break;
|
---|
1587 |
|
---|
1588 | case NO_OVERWRITE_DIR_OPTION:
|
---|
1589 | old_files_option = NO_OVERWRITE_DIR_OLD_FILES;
|
---|
1590 | break;
|
---|
1591 |
|
---|
1592 | case NO_QUOTE_CHARS_OPTION:
|
---|
1593 | for (;*arg; arg++)
|
---|
1594 | set_char_quoting (NULL, *arg, 0);
|
---|
1595 | break;
|
---|
1596 |
|
---|
1597 | case NO_WILDCARDS_OPTION:
|
---|
1598 | args->wildcards = disable_wildcards;
|
---|
1599 | break;
|
---|
1600 |
|
---|
1601 | case NO_WILDCARDS_MATCH_SLASH_OPTION:
|
---|
1602 | args->matching_flags |= FNM_FILE_NAME;
|
---|
1603 | break;
|
---|
1604 |
|
---|
1605 | case NULL_OPTION:
|
---|
1606 | filename_terminator = '\0';
|
---|
1607 | break;
|
---|
1608 |
|
---|
1609 | case NUMERIC_OWNER_OPTION:
|
---|
1610 | numeric_owner_option = true;
|
---|
1611 | break;
|
---|
1612 |
|
---|
1613 | case OCCURRENCE_OPTION:
|
---|
1614 | if (!arg)
|
---|
1615 | occurrence_option = 1;
|
---|
1616 | else
|
---|
1617 | {
|
---|
1618 | uintmax_t u;
|
---|
1619 | if (xstrtoumax (arg, 0, 10, &u, "") == LONGINT_OK)
|
---|
1620 | occurrence_option = u;
|
---|
1621 | else
|
---|
1622 | FATAL_ERROR ((0, 0, "%s: %s", quotearg_colon (arg),
|
---|
1623 | _("Invalid number")));
|
---|
1624 | }
|
---|
1625 | break;
|
---|
1626 |
|
---|
1627 | case OVERWRITE_DIR_OPTION:
|
---|
1628 | old_files_option = DEFAULT_OLD_FILES;
|
---|
1629 | break;
|
---|
1630 |
|
---|
1631 | case OVERWRITE_OPTION:
|
---|
1632 | old_files_option = OVERWRITE_OLD_FILES;
|
---|
1633 | break;
|
---|
1634 |
|
---|
1635 | case OWNER_OPTION:
|
---|
1636 | if (! (strlen (arg) < UNAME_FIELD_SIZE
|
---|
1637 | && uname_to_uid (arg, &owner_option)))
|
---|
1638 | {
|
---|
1639 | uintmax_t u;
|
---|
1640 | if (xstrtoumax (arg, 0, 10, &u, "") == LONGINT_OK
|
---|
1641 | && u == (uid_t) u)
|
---|
1642 | owner_option = u;
|
---|
1643 | else
|
---|
1644 | FATAL_ERROR ((0, 0, "%s: %s", quotearg_colon (arg),
|
---|
1645 | _("Invalid owner")));
|
---|
1646 | }
|
---|
1647 | break;
|
---|
1648 |
|
---|
1649 | case QUOTE_CHARS_OPTION:
|
---|
1650 | for (;*arg; arg++)
|
---|
1651 | set_char_quoting (NULL, *arg, 1);
|
---|
1652 | break;
|
---|
1653 |
|
---|
1654 | case QUOTING_STYLE_OPTION:
|
---|
1655 | tar_set_quoting_style (arg);
|
---|
1656 | break;
|
---|
1657 |
|
---|
1658 | case PAX_OPTION:
|
---|
1659 | args->pax_option = true;
|
---|
1660 | xheader_set_option (arg);
|
---|
1661 | break;
|
---|
1662 |
|
---|
1663 | case POSIX_OPTION:
|
---|
1664 | set_archive_format ("posix");
|
---|
1665 | break;
|
---|
1666 |
|
---|
1667 | case PRESERVE_OPTION:
|
---|
1668 | /* FIXME: What it is good for? */
|
---|
1669 | same_permissions_option = true;
|
---|
1670 | same_order_option = true;
|
---|
1671 | break;
|
---|
1672 |
|
---|
1673 | case RECORD_SIZE_OPTION:
|
---|
1674 | {
|
---|
1675 | uintmax_t u;
|
---|
1676 | if (! (xstrtoumax (arg, 0, 10, &u, "") == LONGINT_OK
|
---|
1677 | && u == (size_t) u))
|
---|
1678 | USAGE_ERROR ((0, 0, "%s: %s", quotearg_colon (arg),
|
---|
1679 | _("Invalid record size")));
|
---|
1680 | record_size = u;
|
---|
1681 | if (record_size % BLOCKSIZE != 0)
|
---|
1682 | USAGE_ERROR ((0, 0, _("Record size must be a multiple of %d."),
|
---|
1683 | BLOCKSIZE));
|
---|
1684 | blocking_factor = record_size / BLOCKSIZE;
|
---|
1685 | }
|
---|
1686 | break;
|
---|
1687 |
|
---|
1688 | case RECURSIVE_UNLINK_OPTION:
|
---|
1689 | recursive_unlink_option = true;
|
---|
1690 | break;
|
---|
1691 |
|
---|
1692 | case REMOVE_FILES_OPTION:
|
---|
1693 | remove_files_option = true;
|
---|
1694 | break;
|
---|
1695 |
|
---|
1696 | case RESTRICT_OPTION:
|
---|
1697 | restrict_option = true;
|
---|
1698 | break;
|
---|
1699 |
|
---|
1700 | case RMT_COMMAND_OPTION:
|
---|
1701 | rmt_command = arg;
|
---|
1702 | break;
|
---|
1703 |
|
---|
1704 | case RSH_COMMAND_OPTION:
|
---|
1705 | rsh_command_option = arg;
|
---|
1706 | break;
|
---|
1707 |
|
---|
1708 | case SHOW_DEFAULTS_OPTION:
|
---|
1709 | show_default_settings (stdout);
|
---|
1710 | close_stdout ();
|
---|
1711 | exit (0);
|
---|
1712 |
|
---|
1713 | case STRIP_COMPONENTS_OPTION:
|
---|
1714 | {
|
---|
1715 | uintmax_t u;
|
---|
1716 | if (! (xstrtoumax (arg, 0, 10, &u, "") == LONGINT_OK
|
---|
1717 | && u == (size_t) u))
|
---|
1718 | USAGE_ERROR ((0, 0, "%s: %s", quotearg_colon (arg),
|
---|
1719 | _("Invalid number of elements")));
|
---|
1720 | strip_name_components = u;
|
---|
1721 | }
|
---|
1722 | break;
|
---|
1723 |
|
---|
1724 | case SHOW_OMITTED_DIRS_OPTION:
|
---|
1725 | show_omitted_dirs_option = true;
|
---|
1726 | break;
|
---|
1727 |
|
---|
1728 | case SHOW_TRANSFORMED_NAMES_OPTION:
|
---|
1729 | show_transformed_names_option = true;
|
---|
1730 | break;
|
---|
1731 |
|
---|
1732 | case SUFFIX_OPTION:
|
---|
1733 | backup_option = true;
|
---|
1734 | args->backup_suffix_string = arg;
|
---|
1735 | break;
|
---|
1736 |
|
---|
1737 | case TO_COMMAND_OPTION:
|
---|
1738 | if (to_command_option)
|
---|
1739 | USAGE_ERROR ((0, 0, _("Only one --to-command option allowed")));
|
---|
1740 | to_command_option = arg;
|
---|
1741 | break;
|
---|
1742 |
|
---|
1743 | case TOTALS_OPTION:
|
---|
1744 | if (arg)
|
---|
1745 | set_stat_signal (arg);
|
---|
1746 | else
|
---|
1747 | totals_option = true;
|
---|
1748 | break;
|
---|
1749 |
|
---|
1750 | case TRANSFORM_OPTION:
|
---|
1751 | set_transform_expr (arg);
|
---|
1752 | break;
|
---|
1753 |
|
---|
1754 | case USE_COMPRESS_PROGRAM_OPTION:
|
---|
1755 | set_use_compress_program_option (arg);
|
---|
1756 | break;
|
---|
1757 |
|
---|
1758 | case VOLNO_FILE_OPTION:
|
---|
1759 | volno_file_option = arg;
|
---|
1760 | break;
|
---|
1761 |
|
---|
1762 | case WILDCARDS_OPTION:
|
---|
1763 | args->wildcards = enable_wildcards;
|
---|
1764 | break;
|
---|
1765 |
|
---|
1766 | case WILDCARDS_MATCH_SLASH_OPTION:
|
---|
1767 | args->matching_flags &= ~ FNM_FILE_NAME;
|
---|
1768 | break;
|
---|
1769 |
|
---|
1770 | case NO_RECURSION_OPTION:
|
---|
1771 | recursion_option = 0;
|
---|
1772 | break;
|
---|
1773 |
|
---|
1774 | case NO_SAME_OWNER_OPTION:
|
---|
1775 | same_owner_option = -1;
|
---|
1776 | break;
|
---|
1777 |
|
---|
1778 | case NO_SAME_PERMISSIONS_OPTION:
|
---|
1779 | same_permissions_option = -1;
|
---|
1780 | break;
|
---|
1781 |
|
---|
1782 | case RECURSION_OPTION:
|
---|
1783 | recursion_option = FNM_LEADING_DIR;
|
---|
1784 | break;
|
---|
1785 |
|
---|
1786 | case SAME_OWNER_OPTION:
|
---|
1787 | same_owner_option = 1;
|
---|
1788 | break;
|
---|
1789 |
|
---|
1790 | case UNQUOTE_OPTION:
|
---|
1791 | unquote_option = true;
|
---|
1792 | break;
|
---|
1793 |
|
---|
1794 | case NO_UNQUOTE_OPTION:
|
---|
1795 | unquote_option = false;
|
---|
1796 | break;
|
---|
1797 |
|
---|
1798 | case '0':
|
---|
1799 | case '1':
|
---|
1800 | case '2':
|
---|
1801 | case '3':
|
---|
1802 | case '4':
|
---|
1803 | case '5':
|
---|
1804 | case '6':
|
---|
1805 | case '7':
|
---|
1806 |
|
---|
1807 | #ifdef DEVICE_PREFIX
|
---|
1808 | {
|
---|
1809 | int device = key - '0';
|
---|
1810 | int density;
|
---|
1811 | static char buf[sizeof DEVICE_PREFIX + 10];
|
---|
1812 | char *cursor;
|
---|
1813 |
|
---|
1814 | if (arg[1])
|
---|
1815 | argp_error (state, _("Malformed density argument: %s"), quote (arg));
|
---|
1816 |
|
---|
1817 | strcpy (buf, DEVICE_PREFIX);
|
---|
1818 | cursor = buf + strlen (buf);
|
---|
1819 |
|
---|
1820 | #ifdef DENSITY_LETTER
|
---|
1821 |
|
---|
1822 | sprintf (cursor, "%d%c", device, arg[0]);
|
---|
1823 |
|
---|
1824 | #else /* not DENSITY_LETTER */
|
---|
1825 |
|
---|
1826 | switch (arg[0])
|
---|
1827 | {
|
---|
1828 | case 'l':
|
---|
1829 | device += LOW_DENSITY_NUM;
|
---|
1830 | break;
|
---|
1831 |
|
---|
1832 | case 'm':
|
---|
1833 | device += MID_DENSITY_NUM;
|
---|
1834 | break;
|
---|
1835 |
|
---|
1836 | case 'h':
|
---|
1837 | device += HIGH_DENSITY_NUM;
|
---|
1838 | break;
|
---|
1839 |
|
---|
1840 | default:
|
---|
1841 | argp_error (state, _("Unknown density: `%c'"), arg[0]);
|
---|
1842 | }
|
---|
1843 | sprintf (cursor, "%d", device);
|
---|
1844 |
|
---|
1845 | #endif /* not DENSITY_LETTER */
|
---|
1846 |
|
---|
1847 | if (archive_names == allocated_archive_names)
|
---|
1848 | archive_name_array = x2nrealloc (archive_name_array,
|
---|
1849 | &allocated_archive_names,
|
---|
1850 | sizeof (archive_name_array[0]));
|
---|
1851 | archive_name_array[archive_names++] = xstrdup (buf);
|
---|
1852 | }
|
---|
1853 | break;
|
---|
1854 |
|
---|
1855 | #else /* not DEVICE_PREFIX */
|
---|
1856 |
|
---|
1857 | argp_error (state,
|
---|
1858 | _("Options `-[0-7][lmh]' not supported by *this* tar"));
|
---|
1859 |
|
---|
1860 | #endif /* not DEVICE_PREFIX */
|
---|
1861 |
|
---|
1862 | case '?':
|
---|
1863 | tar_help (state);
|
---|
1864 | close_stdout ();
|
---|
1865 | exit (0);
|
---|
1866 |
|
---|
1867 | case USAGE_OPTION:
|
---|
1868 | argp_state_help (state, state->out_stream, ARGP_HELP_USAGE);
|
---|
1869 | close_stdout ();
|
---|
1870 | exit (0);
|
---|
1871 |
|
---|
1872 | case VERSION_OPTION:
|
---|
1873 | version_etc (state->out_stream, "tar", PACKAGE_NAME, VERSION,
|
---|
1874 | "John Gilmore", "Jay Fenlason", (char *) NULL);
|
---|
1875 | close_stdout ();
|
---|
1876 | exit (0);
|
---|
1877 |
|
---|
1878 | case HANG_OPTION:
|
---|
1879 | _argp_hang = atoi (arg ? arg : "3600");
|
---|
1880 | while (_argp_hang-- > 0)
|
---|
1881 | sleep (1);
|
---|
1882 | break;
|
---|
1883 |
|
---|
1884 | default:
|
---|
1885 | return ARGP_ERR_UNKNOWN;
|
---|
1886 | }
|
---|
1887 | return 0;
|
---|
1888 | }
|
---|
1889 |
|
---|
1890 | static struct argp argp = {
|
---|
1891 | options,
|
---|
1892 | parse_opt,
|
---|
1893 | N_("[FILE]..."),
|
---|
1894 | doc,
|
---|
1895 | NULL,
|
---|
1896 | NULL,
|
---|
1897 | NULL
|
---|
1898 | };
|
---|
1899 |
|
---|
1900 | void
|
---|
1901 | usage (int status)
|
---|
1902 | {
|
---|
1903 | argp_help (&argp, stderr, ARGP_HELP_SEE, (char*) program_name);
|
---|
1904 | close_stdout ();
|
---|
1905 | exit (status);
|
---|
1906 | }
|
---|
1907 |
|
---|
1908 | /* Parse the options for tar. */
|
---|
1909 |
|
---|
1910 | static struct argp_option *
|
---|
1911 | find_argp_option (struct argp_option *options, int letter)
|
---|
1912 | {
|
---|
1913 | for (;
|
---|
1914 | !(options->name == NULL
|
---|
1915 | && options->key == 0
|
---|
1916 | && options->arg == 0
|
---|
1917 | && options->flags == 0
|
---|
1918 | && options->doc == NULL); options++)
|
---|
1919 | if (options->key == letter)
|
---|
1920 | return options;
|
---|
1921 | return NULL;
|
---|
1922 | }
|
---|
1923 |
|
---|
1924 | static void
|
---|
1925 | decode_options (int argc, char **argv)
|
---|
1926 | {
|
---|
1927 | int index;
|
---|
1928 | struct tar_args args;
|
---|
1929 |
|
---|
1930 | /* Set some default option values. */
|
---|
1931 | args.textual_date = NULL;
|
---|
1932 | args.wildcards = default_wildcards;
|
---|
1933 | args.matching_flags = 0;
|
---|
1934 | args.include_anchored = EXCLUDE_ANCHORED;
|
---|
1935 | args.o_option = false;
|
---|
1936 | args.pax_option = false;
|
---|
1937 | args.backup_suffix_string = getenv ("SIMPLE_BACKUP_SUFFIX");
|
---|
1938 | args.version_control_string = 0;
|
---|
1939 | args.input_files = false;
|
---|
1940 |
|
---|
1941 | subcommand_option = UNKNOWN_SUBCOMMAND;
|
---|
1942 | archive_format = DEFAULT_FORMAT;
|
---|
1943 | blocking_factor = DEFAULT_BLOCKING;
|
---|
1944 | record_size = DEFAULT_BLOCKING * BLOCKSIZE;
|
---|
1945 | excluded = new_exclude ();
|
---|
1946 | newer_mtime_option.tv_sec = TYPE_MINIMUM (time_t);
|
---|
1947 | newer_mtime_option.tv_nsec = -1;
|
---|
1948 | recursion_option = FNM_LEADING_DIR;
|
---|
1949 | unquote_option = true;
|
---|
1950 | tar_sparse_major = 1;
|
---|
1951 | tar_sparse_minor = 0;
|
---|
1952 |
|
---|
1953 | owner_option = -1;
|
---|
1954 | group_option = -1;
|
---|
1955 |
|
---|
1956 | /* Convert old-style tar call by exploding option element and rearranging
|
---|
1957 | options accordingly. */
|
---|
1958 |
|
---|
1959 | if (argc > 1 && argv[1][0] != '-')
|
---|
1960 | {
|
---|
1961 | int new_argc; /* argc value for rearranged arguments */
|
---|
1962 | char **new_argv; /* argv value for rearranged arguments */
|
---|
1963 | char *const *in; /* cursor into original argv */
|
---|
1964 | char **out; /* cursor into rearranged argv */
|
---|
1965 | const char *letter; /* cursor into old option letters */
|
---|
1966 | char buffer[3]; /* constructed option buffer */
|
---|
1967 |
|
---|
1968 | /* Initialize a constructed option. */
|
---|
1969 |
|
---|
1970 | buffer[0] = '-';
|
---|
1971 | buffer[2] = '\0';
|
---|
1972 |
|
---|
1973 | /* Allocate a new argument array, and copy program name in it. */
|
---|
1974 |
|
---|
1975 | new_argc = argc - 1 + strlen (argv[1]);
|
---|
1976 | new_argv = xmalloc ((new_argc + 1) * sizeof (char *));
|
---|
1977 | in = argv;
|
---|
1978 | out = new_argv;
|
---|
1979 | *out++ = *in++;
|
---|
1980 |
|
---|
1981 | /* Copy each old letter option as a separate option, and have the
|
---|
1982 | corresponding argument moved next to it. */
|
---|
1983 |
|
---|
1984 | for (letter = *in++; *letter; letter++)
|
---|
1985 | {
|
---|
1986 | struct argp_option *opt;
|
---|
1987 |
|
---|
1988 | buffer[1] = *letter;
|
---|
1989 | *out++ = xstrdup (buffer);
|
---|
1990 | opt = find_argp_option (options, *letter);
|
---|
1991 | if (opt && opt->arg)
|
---|
1992 | {
|
---|
1993 | if (in < argv + argc)
|
---|
1994 | *out++ = *in++;
|
---|
1995 | else
|
---|
1996 | USAGE_ERROR ((0, 0, _("Old option `%c' requires an argument."),
|
---|
1997 | *letter));
|
---|
1998 | }
|
---|
1999 | }
|
---|
2000 |
|
---|
2001 | /* Copy all remaining options. */
|
---|
2002 |
|
---|
2003 | while (in < argv + argc)
|
---|
2004 | *out++ = *in++;
|
---|
2005 | *out = 0;
|
---|
2006 |
|
---|
2007 | /* Replace the old option list by the new one. */
|
---|
2008 |
|
---|
2009 | argc = new_argc;
|
---|
2010 | argv = new_argv;
|
---|
2011 | }
|
---|
2012 |
|
---|
2013 | /* Parse all options and non-options as they appear. */
|
---|
2014 |
|
---|
2015 | prepend_default_options (getenv ("TAR_OPTIONS"), &argc, &argv);
|
---|
2016 |
|
---|
2017 | if (argp_parse (&argp, argc, argv, ARGP_IN_ORDER|ARGP_NO_HELP,
|
---|
2018 | &index, &args))
|
---|
2019 | exit (TAREXIT_FAILURE);
|
---|
2020 |
|
---|
2021 |
|
---|
2022 | /* Special handling for 'o' option:
|
---|
2023 |
|
---|
2024 | GNU tar used to say "output old format".
|
---|
2025 | UNIX98 tar says don't chown files after extracting (we use
|
---|
2026 | "--no-same-owner" for this).
|
---|
2027 |
|
---|
2028 | The old GNU tar semantics is retained when used with --create
|
---|
2029 | option, otherwise UNIX98 semantics is assumed */
|
---|
2030 |
|
---|
2031 | if (args.o_option)
|
---|
2032 | {
|
---|
2033 | if (subcommand_option == CREATE_SUBCOMMAND)
|
---|
2034 | {
|
---|
2035 | /* GNU Tar <= 1.13 compatibility */
|
---|
2036 | set_archive_format ("v7");
|
---|
2037 | }
|
---|
2038 | else
|
---|
2039 | {
|
---|
2040 | /* UNIX98 compatibility */
|
---|
2041 | same_owner_option = -1;
|
---|
2042 | }
|
---|
2043 | }
|
---|
2044 |
|
---|
2045 | /* Handle operands after any "--" argument. */
|
---|
2046 | for (; index < argc; index++)
|
---|
2047 | {
|
---|
2048 | name_add_name (argv[index], MAKE_INCL_OPTIONS (&args));
|
---|
2049 | args.input_files = true;
|
---|
2050 | }
|
---|
2051 |
|
---|
2052 | /* Warn about implicit use of the wildcards in command line arguments.
|
---|
2053 | See TODO */
|
---|
2054 | warn_regex_usage = args.wildcards == default_wildcards;
|
---|
2055 |
|
---|
2056 | /* Derive option values and check option consistency. */
|
---|
2057 |
|
---|
2058 | if (archive_format == DEFAULT_FORMAT)
|
---|
2059 | {
|
---|
2060 | if (args.pax_option)
|
---|
2061 | archive_format = POSIX_FORMAT;
|
---|
2062 | else
|
---|
2063 | archive_format = DEFAULT_ARCHIVE_FORMAT;
|
---|
2064 | }
|
---|
2065 |
|
---|
2066 | if ((volume_label_option && subcommand_option == CREATE_SUBCOMMAND)
|
---|
2067 | || incremental_option
|
---|
2068 | || multi_volume_option
|
---|
2069 | || sparse_option)
|
---|
2070 | assert_format (FORMAT_MASK (OLDGNU_FORMAT)
|
---|
2071 | | FORMAT_MASK (GNU_FORMAT)
|
---|
2072 | | FORMAT_MASK (POSIX_FORMAT));
|
---|
2073 |
|
---|
2074 | if (occurrence_option)
|
---|
2075 | {
|
---|
2076 | if (!args.input_files)
|
---|
2077 | USAGE_ERROR ((0, 0,
|
---|
2078 | _("--occurrence is meaningless without a file list")));
|
---|
2079 | if (subcommand_option != DELETE_SUBCOMMAND
|
---|
2080 | && subcommand_option != DIFF_SUBCOMMAND
|
---|
2081 | && subcommand_option != EXTRACT_SUBCOMMAND
|
---|
2082 | && subcommand_option != LIST_SUBCOMMAND)
|
---|
2083 | USAGE_ERROR ((0, 0,
|
---|
2084 | _("--occurrence cannot be used in the requested operation mode")));
|
---|
2085 | }
|
---|
2086 |
|
---|
2087 | if (seekable_archive && subcommand_option == DELETE_SUBCOMMAND)
|
---|
2088 | {
|
---|
2089 | /* The current code in delete.c is based on the assumption that
|
---|
2090 | skip_member() reads all data from the archive. So, we should
|
---|
2091 | make sure it won't use seeks. On the other hand, the same code
|
---|
2092 | depends on the ability to backspace a record in the archive,
|
---|
2093 | so setting seekable_archive to false is technically incorrect.
|
---|
2094 | However, it is tested only in skip_member(), so it's not a
|
---|
2095 | problem. */
|
---|
2096 | seekable_archive = false;
|
---|
2097 | }
|
---|
2098 |
|
---|
2099 | if (archive_names == 0)
|
---|
2100 | {
|
---|
2101 | /* If no archive file name given, try TAPE from the environment, or
|
---|
2102 | else, DEFAULT_ARCHIVE from the configuration process. */
|
---|
2103 |
|
---|
2104 | archive_names = 1;
|
---|
2105 | archive_name_array[0] = getenv ("TAPE");
|
---|
2106 | if (! archive_name_array[0])
|
---|
2107 | archive_name_array[0] = DEFAULT_ARCHIVE;
|
---|
2108 | }
|
---|
2109 |
|
---|
2110 | /* Allow multiple archives only with `-M'. */
|
---|
2111 |
|
---|
2112 | if (archive_names > 1 && !multi_volume_option)
|
---|
2113 | USAGE_ERROR ((0, 0,
|
---|
2114 | _("Multiple archive files require `-M' option")));
|
---|
2115 |
|
---|
2116 | if (listed_incremental_option
|
---|
2117 | && NEWER_OPTION_INITIALIZED (newer_mtime_option))
|
---|
2118 | USAGE_ERROR ((0, 0,
|
---|
2119 | _("Cannot combine --listed-incremental with --newer")));
|
---|
2120 |
|
---|
2121 | if (volume_label_option)
|
---|
2122 | {
|
---|
2123 | if (archive_format == GNU_FORMAT || archive_format == OLDGNU_FORMAT)
|
---|
2124 | {
|
---|
2125 | size_t volume_label_max_len =
|
---|
2126 | (sizeof current_header->header.name
|
---|
2127 | - 1 /* for trailing '\0' */
|
---|
2128 | - (multi_volume_option
|
---|
2129 | ? (sizeof " Volume "
|
---|
2130 | - 1 /* for null at end of " Volume " */
|
---|
2131 | + INT_STRLEN_BOUND (int) /* for volume number */
|
---|
2132 | - 1 /* for sign, as 0 <= volno */)
|
---|
2133 | : 0));
|
---|
2134 | if (volume_label_max_len < strlen (volume_label_option))
|
---|
2135 | USAGE_ERROR ((0, 0,
|
---|
2136 | ngettext ("%s: Volume label is too long (limit is %lu byte)",
|
---|
2137 | "%s: Volume label is too long (limit is %lu bytes)",
|
---|
2138 | volume_label_max_len),
|
---|
2139 | quotearg_colon (volume_label_option),
|
---|
2140 | (unsigned long) volume_label_max_len));
|
---|
2141 | }
|
---|
2142 | /* else FIXME
|
---|
2143 | Label length in PAX format is limited by the volume size. */
|
---|
2144 | }
|
---|
2145 |
|
---|
2146 | if (verify_option)
|
---|
2147 | {
|
---|
2148 | if (multi_volume_option)
|
---|
2149 | USAGE_ERROR ((0, 0, _("Cannot verify multi-volume archives")));
|
---|
2150 | if (use_compress_program_option)
|
---|
2151 | USAGE_ERROR ((0, 0, _("Cannot verify compressed archives")));
|
---|
2152 | }
|
---|
2153 |
|
---|
2154 | if (use_compress_program_option)
|
---|
2155 | {
|
---|
2156 | if (multi_volume_option)
|
---|
2157 | USAGE_ERROR ((0, 0, _("Cannot use multi-volume compressed archives")));
|
---|
2158 | if (subcommand_option == UPDATE_SUBCOMMAND
|
---|
2159 | || subcommand_option == APPEND_SUBCOMMAND
|
---|
2160 | || subcommand_option == DELETE_SUBCOMMAND)
|
---|
2161 | USAGE_ERROR ((0, 0, _("Cannot update compressed archives")));
|
---|
2162 | if (subcommand_option == CAT_SUBCOMMAND)
|
---|
2163 | USAGE_ERROR ((0, 0, _("Cannot concatenate compressed archives")));
|
---|
2164 | }
|
---|
2165 |
|
---|
2166 | /* It is no harm to use --pax-option on non-pax archives in archive
|
---|
2167 | reading mode. It may even be useful, since it allows to override
|
---|
2168 | file attributes from tar headers. Therefore I allow such usage.
|
---|
2169 | --gray */
|
---|
2170 | if (args.pax_option
|
---|
2171 | && archive_format != POSIX_FORMAT
|
---|
2172 | && (subcommand_option != EXTRACT_SUBCOMMAND
|
---|
2173 | || subcommand_option != DIFF_SUBCOMMAND
|
---|
2174 | || subcommand_option != LIST_SUBCOMMAND))
|
---|
2175 | USAGE_ERROR ((0, 0, _("--pax-option can be used only on POSIX archives")));
|
---|
2176 |
|
---|
2177 | /* If ready to unlink hierarchies, so we are for simpler files. */
|
---|
2178 | if (recursive_unlink_option)
|
---|
2179 | old_files_option = UNLINK_FIRST_OLD_FILES;
|
---|
2180 |
|
---|
2181 |
|
---|
2182 | if (test_label_option)
|
---|
2183 | {
|
---|
2184 | /* --test-label is silent if the user has specified the label name to
|
---|
2185 | compare against. */
|
---|
2186 | if (!args.input_files)
|
---|
2187 | verbose_option++;
|
---|
2188 | }
|
---|
2189 | else if (utc_option)
|
---|
2190 | verbose_option = 2;
|
---|
2191 |
|
---|
2192 | /* Forbid using -c with no input files whatsoever. Check that `-f -',
|
---|
2193 | explicit or implied, is used correctly. */
|
---|
2194 |
|
---|
2195 | switch (subcommand_option)
|
---|
2196 | {
|
---|
2197 | case CREATE_SUBCOMMAND:
|
---|
2198 | if (!args.input_files && !files_from_option)
|
---|
2199 | USAGE_ERROR ((0, 0,
|
---|
2200 | _("Cowardly refusing to create an empty archive")));
|
---|
2201 | break;
|
---|
2202 |
|
---|
2203 | case EXTRACT_SUBCOMMAND:
|
---|
2204 | case LIST_SUBCOMMAND:
|
---|
2205 | case DIFF_SUBCOMMAND:
|
---|
2206 | for (archive_name_cursor = archive_name_array;
|
---|
2207 | archive_name_cursor < archive_name_array + archive_names;
|
---|
2208 | archive_name_cursor++)
|
---|
2209 | if (!strcmp (*archive_name_cursor, "-"))
|
---|
2210 | request_stdin ("-f");
|
---|
2211 | break;
|
---|
2212 |
|
---|
2213 | case CAT_SUBCOMMAND:
|
---|
2214 | case UPDATE_SUBCOMMAND:
|
---|
2215 | case APPEND_SUBCOMMAND:
|
---|
2216 | for (archive_name_cursor = archive_name_array;
|
---|
2217 | archive_name_cursor < archive_name_array + archive_names;
|
---|
2218 | archive_name_cursor++)
|
---|
2219 | if (!strcmp (*archive_name_cursor, "-"))
|
---|
2220 | USAGE_ERROR ((0, 0,
|
---|
2221 | _("Options `-Aru' are incompatible with `-f -'")));
|
---|
2222 |
|
---|
2223 | default:
|
---|
2224 | break;
|
---|
2225 | }
|
---|
2226 |
|
---|
2227 | /* Initialize stdlis */
|
---|
2228 | if (index_file_name)
|
---|
2229 | {
|
---|
2230 | stdlis = fopen (index_file_name, "w");
|
---|
2231 | if (! stdlis)
|
---|
2232 | open_error (index_file_name);
|
---|
2233 | }
|
---|
2234 | else
|
---|
2235 | stdlis = to_stdout_option ? stderr : stdout;
|
---|
2236 |
|
---|
2237 | archive_name_cursor = archive_name_array;
|
---|
2238 |
|
---|
2239 | /* Prepare for generating backup names. */
|
---|
2240 |
|
---|
2241 | if (args.backup_suffix_string)
|
---|
2242 | simple_backup_suffix = xstrdup (args.backup_suffix_string);
|
---|
2243 |
|
---|
2244 | if (backup_option)
|
---|
2245 | {
|
---|
2246 | backup_type = xget_version ("--backup", args.version_control_string);
|
---|
2247 | /* No backup is needed either if explicitely disabled or if
|
---|
2248 | the extracted files are not being written to disk. */
|
---|
2249 | if (backup_type == no_backups || EXTRACT_OVER_PIPE)
|
---|
2250 | backup_option = false;
|
---|
2251 | }
|
---|
2252 |
|
---|
2253 | if (verbose_option)
|
---|
2254 | report_textual_dates (&args);
|
---|
2255 | }
|
---|
2256 |
|
---|
2257 | |
---|
2258 |
|
---|
2259 | /* Tar proper. */
|
---|
2260 |
|
---|
2261 | /* Main routine for tar. */
|
---|
2262 | int
|
---|
2263 | main (int argc, char **argv)
|
---|
2264 | {
|
---|
2265 | set_start_time ();
|
---|
2266 | program_name = argv[0];
|
---|
2267 |
|
---|
2268 | setlocale (LC_ALL, "");
|
---|
2269 | bindtextdomain (PACKAGE, LOCALEDIR);
|
---|
2270 | textdomain (PACKAGE);
|
---|
2271 |
|
---|
2272 | exit_failure = TAREXIT_FAILURE;
|
---|
2273 | exit_status = TAREXIT_SUCCESS;
|
---|
2274 | filename_terminator = '\n';
|
---|
2275 | set_quoting_style (0, DEFAULT_QUOTING_STYLE);
|
---|
2276 |
|
---|
2277 | /* Make sure we have first three descriptors available */
|
---|
2278 | stdopen ();
|
---|
2279 |
|
---|
2280 | /* Close all inherited open descriptors, except for the first three */
|
---|
2281 | closeopen ();
|
---|
2282 |
|
---|
2283 | /* Pre-allocate a few structures. */
|
---|
2284 |
|
---|
2285 | allocated_archive_names = 10;
|
---|
2286 | archive_name_array =
|
---|
2287 | xmalloc (sizeof (const char *) * allocated_archive_names);
|
---|
2288 | archive_names = 0;
|
---|
2289 |
|
---|
2290 | obstack_init (&argv_stk);
|
---|
2291 |
|
---|
2292 | #ifdef SIGCHLD
|
---|
2293 | /* System V fork+wait does not work if SIGCHLD is ignored. */
|
---|
2294 | signal (SIGCHLD, SIG_DFL);
|
---|
2295 | #endif
|
---|
2296 |
|
---|
2297 | /* Decode options. */
|
---|
2298 |
|
---|
2299 | decode_options (argc, argv);
|
---|
2300 | name_init ();
|
---|
2301 |
|
---|
2302 | /* Main command execution. */
|
---|
2303 |
|
---|
2304 | if (volno_file_option)
|
---|
2305 | init_volume_number ();
|
---|
2306 |
|
---|
2307 | switch (subcommand_option)
|
---|
2308 | {
|
---|
2309 | case UNKNOWN_SUBCOMMAND:
|
---|
2310 | USAGE_ERROR ((0, 0,
|
---|
2311 | _("You must specify one of the `-Acdtrux' options")));
|
---|
2312 |
|
---|
2313 | case CAT_SUBCOMMAND:
|
---|
2314 | case UPDATE_SUBCOMMAND:
|
---|
2315 | case APPEND_SUBCOMMAND:
|
---|
2316 | update_archive ();
|
---|
2317 | break;
|
---|
2318 |
|
---|
2319 | case DELETE_SUBCOMMAND:
|
---|
2320 | delete_archive_members ();
|
---|
2321 | break;
|
---|
2322 |
|
---|
2323 | case CREATE_SUBCOMMAND:
|
---|
2324 | create_archive ();
|
---|
2325 | break;
|
---|
2326 |
|
---|
2327 | case EXTRACT_SUBCOMMAND:
|
---|
2328 | extr_init ();
|
---|
2329 | read_and (extract_archive);
|
---|
2330 |
|
---|
2331 | /* FIXME: should extract_finish () even if an ordinary signal is
|
---|
2332 | received. */
|
---|
2333 | extract_finish ();
|
---|
2334 |
|
---|
2335 | break;
|
---|
2336 |
|
---|
2337 | case LIST_SUBCOMMAND:
|
---|
2338 | read_and (list_archive);
|
---|
2339 | break;
|
---|
2340 |
|
---|
2341 | case DIFF_SUBCOMMAND:
|
---|
2342 | diff_init ();
|
---|
2343 | read_and (diff_archive);
|
---|
2344 | break;
|
---|
2345 | }
|
---|
2346 |
|
---|
2347 | if (totals_option)
|
---|
2348 | print_total_stats ();
|
---|
2349 |
|
---|
2350 | if (check_links_option)
|
---|
2351 | check_links ();
|
---|
2352 |
|
---|
2353 | if (volno_file_option)
|
---|
2354 | closeout_volume_number ();
|
---|
2355 |
|
---|
2356 | /* Dispose of allocated memory, and return. */
|
---|
2357 |
|
---|
2358 | free (archive_name_array);
|
---|
2359 | name_term ();
|
---|
2360 |
|
---|
2361 | if (exit_status == TAREXIT_FAILURE)
|
---|
2362 | error (0, 0, _("Error exit delayed from previous errors"));
|
---|
2363 |
|
---|
2364 | if (stdlis == stdout)
|
---|
2365 | close_stdout ();
|
---|
2366 | else if (ferror (stderr) || fclose (stderr) != 0)
|
---|
2367 | exit_status = TAREXIT_FAILURE;
|
---|
2368 |
|
---|
2369 | return exit_status;
|
---|
2370 | }
|
---|
2371 |
|
---|
2372 | void
|
---|
2373 | tar_stat_init (struct tar_stat_info *st)
|
---|
2374 | {
|
---|
2375 | memset (st, 0, sizeof (*st));
|
---|
2376 | }
|
---|
2377 |
|
---|
2378 | void
|
---|
2379 | tar_stat_destroy (struct tar_stat_info *st)
|
---|
2380 | {
|
---|
2381 | free (st->orig_file_name);
|
---|
2382 | free (st->file_name);
|
---|
2383 | free (st->link_name);
|
---|
2384 | free (st->uname);
|
---|
2385 | free (st->gname);
|
---|
2386 | free (st->sparse_map);
|
---|
2387 | free (st->dumpdir);
|
---|
2388 | memset (st, 0, sizeof (*st));
|
---|
2389 | }
|
---|
2390 |
|
---|
2391 | /* Format mask for all available formats that support nanosecond
|
---|
2392 | timestamp resolution. */
|
---|
2393 | #define NS_PRECISION_FORMAT_MASK FORMAT_MASK (POSIX_FORMAT)
|
---|
2394 |
|
---|
2395 | /* Same as timespec_cmp, but ignore nanoseconds if current archive
|
---|
2396 | format does not provide sufficient resolution. */
|
---|
2397 | int
|
---|
2398 | tar_timespec_cmp (struct timespec a, struct timespec b)
|
---|
2399 | {
|
---|
2400 | if (!(FORMAT_MASK (current_format) & NS_PRECISION_FORMAT_MASK))
|
---|
2401 | a.tv_nsec = b.tv_nsec = 0;
|
---|
2402 | return timespec_cmp (a, b);
|
---|
2403 | }
|
---|