| 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 | }
|
|---|