/* A tar (tape archiver) program.
Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1999, 2000,
- 2001, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+ 2001, 2003, 2004, 2005, 2006, 2007, 2009 Free Software Foundation, Inc.
Written by John Gilmore, starting 1985-08-25.
#include <version-etc.h>
#include <xstrtol.h>
#include <stdopen.h>
+#include <priv-set.h>
/* Local declarations. */
DELAY_DIRECTORY_RESTORE_OPTION,
HARD_DEREFERENCE_OPTION,
DELETE_OPTION,
+ EXCLUDE_BACKUPS_OPTION,
EXCLUDE_CACHES_OPTION,
EXCLUDE_CACHES_UNDER_OPTION,
EXCLUDE_CACHES_ALL_OPTION,
IGNORE_FAILED_READ_OPTION,
INDEX_FILE_OPTION,
KEEP_NEWER_FILES_OPTION,
+ LEVEL_OPTION,
+ LZMA_OPTION,
LZOP_OPTION,
MODE_OPTION,
MTIME_OPTION,
NO_RECURSION_OPTION,
NO_SAME_OWNER_OPTION,
NO_SAME_PERMISSIONS_OPTION,
+ NO_SEEK_OPTION,
NO_UNQUOTE_OPTION,
NO_WILDCARDS_MATCH_SLASH_OPTION,
NO_WILDCARDS_OPTION,
UTC_OPTION,
VERSION_OPTION,
VOLNO_FILE_OPTION,
+ WARNING_OPTION,
WILDCARDS_MATCH_SLASH_OPTION,
WILDCARDS_OPTION
};
[q alias for --occurrence=1 =/= this would better be used for quiet?]
y per-file gzip compression
- Y per-block gzip compression */
+ Y per-block gzip compression.
+
+ Additionally, the 'n' letter is assigned for option --seek, which
+ is probably not needed and should be marked as deprecated, so that
+ -n may become available in the future.
+*/
static struct argp_option options[] = {
#define GRID 10
N_("handle old GNU-format incremental backup"), GRID+1 },
{"listed-incremental", 'g', N_("FILE"), 0,
N_("handle new GNU-format incremental backup"), GRID+1 },
+ {"level", LEVEL_OPTION, N_("NUMBER"), 0,
+ N_("dump level for created listed-incremental archive"), GRID+1 },
{"ignore-failed-read", IGNORE_FAILED_READ_OPTION, 0, 0,
N_("do not exit with nonzero on unreadable files"), GRID+1 },
{"occurrence", OCCURRENCE_OPTION, N_("NUMBER"), OPTION_ARG_OPTIONAL,
" NUMBER defaults to 1"), GRID+1 },
{"seek", 'n', NULL, 0,
N_("archive is seekable"), GRID+1 },
+ {"no-seek", NO_SEEK_OPTION, NULL, 0,
+ N_("archive is not seekable"), GRID+1 },
{"no-check-device", NO_CHECK_DEVICE_OPTION, NULL, 0,
N_("do not check device numbers when creating incremental archives"),
GRID+1 },
{"touch", 'm', 0, 0,
N_("don't extract file modified time"), GRID+1 },
{"same-owner", SAME_OWNER_OPTION, 0, 0,
- N_("try extracting files with the same ownership"), GRID+1 },
+ N_("try extracting files with the same ownership as exists in the archive (default for superuser)"), GRID+1 },
{"no-same-owner", NO_SAME_OWNER_OPTION, 0, 0,
- N_("extract files as yourself"), GRID+1 },
+ N_("extract files as yourself (default for ordinary users)"), GRID+1 },
{"numeric-owner", NUMERIC_OWNER_OPTION, 0, 0,
N_("always use numbers for user/group names"), GRID+1 },
{"preserve-permissions", 'p', 0, 0,
{"auto-compress", 'a', 0, 0,
N_("use archive suffix to determine the compression program"), GRID+1 },
{"no-auto-compress", NO_AUTO_COMPRESS_OPTION, 0, 0,
- N_("do not use use archive suffix to determine the compression program"),
+ N_("do not use archive suffix to determine the compression program"),
GRID+1 },
{"bzip2", 'j', 0, 0,
N_("filter the archive through bzip2"), GRID+1 },
{"compress", 'Z', 0, 0,
N_("filter the archive through compress"), GRID+1 },
{"uncompress", 0, 0, OPTION_ALIAS, NULL, GRID+1 },
- {"lzma", 'J', 0, 0,
+ {"lzma", LZMA_OPTION, 0, 0,
N_("filter the archive through lzma"), GRID+1 },
{"lzop", LZOP_OPTION, 0, 0,
N_("filter the archive through lzop"), GRID+8 },
+ {"xz", 'J', 0, 0,
+ N_("filter the archive through xz"), GRID+8 },
{"use-compress-program", 'I', N_("PROG"), 0,
N_("filter through PROG (must accept -d)"), GRID+1 },
#undef GRID
N_("exclude directories containing FILE"), GRID+1 },
{"exclude-vcs", EXCLUDE_VCS_OPTION, NULL, 0,
N_("exclude version control system directories"), GRID+1 },
+ {"exclude-backups", EXCLUDE_BACKUPS_OPTION, NULL, 0,
+ N_("exclude backup and lock files"), GRID+1 },
{"no-recursion", NO_RECURSION_OPTION, 0, 0,
N_("avoid descending automatically in directories"), GRID+1 },
{"one-file-system", ONE_FILE_SYSTEM_OPTION, 0, 0,
{"verbose", 'v', 0, 0,
N_("verbosely list files processed"), GRID+1 },
+ {"warning", WARNING_OPTION, N_("KEYWORD"), 0,
+ N_("warning control"), GRID+1 },
{"checkpoint", CHECKPOINT_OPTION, N_("NUMBER"), OPTION_ARG_OPTIONAL,
N_("display progress messages every NUMBERth record (default 10)"),
GRID+1 },
| (args)->matching_flags \
| recursion_option)
+static char const * const vcs_file_table[] = {
+ /* CVS: */
+ "CVS",
+ ".cvsignore",
+ /* RCS: */
+ "RCS",
+ /* SCCS: */
+ "SCCS",
+ /* SVN: */
+ ".svn",
+ /* git: */
+ ".git",
+ ".gitignore",
+ /* Arch: */
+ ".arch-ids",
+ "{arch}",
+ "=RELEASE-ID",
+ "=meta-update",
+ "=update",
+ /* Bazaar */
+ ".bzr",
+ ".bzrignore",
+ ".bzrtags",
+ /* Mercurial */
+ ".hg",
+ ".hgignore",
+ ".hgtags",
+ /* darcs */
+ "_darcs",
+ NULL
+};
+
+static char const * const backup_file_table[] = {
+ ".#*",
+ "*~",
+ "#*#",
+ NULL
+};
+
void
-exclude_vcs_files ()
+add_exclude_array (char const * const * fv)
{
int i;
- static char *vcs_file[] = {
- /* CVS: */
- "CVS",
- ".cvsignore",
- /* RCS: */
- "RCS",
- /* SCCS: */
- "SCCS",
- /* SVN: */
- ".svn",
- /* git: */
- ".git",
- ".gitignore",
- /* Arch: */
- ".arch-ids",
- "{arch}",
- "=RELEASE-ID",
- "=meta-update",
- "=update",
- /* Bazaar */
- ".bzr",
- ".bzrignore",
- ".bzrtags",
- /* Mercurial */
- ".hg",
- ".hgignore",
- ".hgtags",
- /* darcs */
- "_darcs",
- NULL
- };
- for (i = 0; vcs_file[i]; i++)
- add_exclude (excluded, vcs_file[i], 0);
+ for (i = 0; fv[i]; i++)
+ add_exclude (excluded, fv[i], 0);
}
\f
{
size_t size;
- WARN ((0, 0, N_("%s: file name read contains nul character"),
- quotearg_colon (filename)));
+ WARNOPT (WARN_FILENAME_WITH_NULS,
+ (0, 0, N_("%s: file name read contains nul character"),
+ quotearg_colon (filename)));
/* Prepare new stack contents */
size = obstack_object_size (&argv_stk);
break;
case 'J':
- set_use_compress_program_option ("lzma");
+ set_use_compress_program_option ("xz");
break;
case 'k':
case 'K':
starting_file_option = true;
- addname (arg, 0);
+ addname (arg, 0, true, NULL);
break;
case ONE_FILE_SYSTEM_OPTION:
}
break;
+ case LEVEL_OPTION:
+ {
+ char *p;
+ incremental_level = strtoul (arg, &p, 10);
+ if (*p)
+ USAGE_ERROR ((0, 0, _("Invalid incremental level value")));
+ }
+ break;
+
+ case LZMA_OPTION:
+ set_use_compress_program_option ("lzma");
+ break;
+
case LZOP_OPTION:
set_use_compress_program_option ("lzop");
break;
break;
case 'n':
- seekable_archive = true;
+ seek_option = 1;
break;
+ case NO_SEEK_OPTION:
+ seek_option = 0;
+ break;
+
case 'N':
after_date_option = true;
/* Fall through. */
case 'v':
verbose_option++;
+ warning_option |= WARN_VERBOSE_WARNINGS;
break;
case 'V':
set_subcommand_option (DELETE_SUBCOMMAND);
break;
+ case EXCLUDE_BACKUPS_OPTION:
+ add_exclude_array (backup_file_table);
+ break;
+
case EXCLUDE_OPTION:
add_exclude (excluded, arg, MAKE_EXCL_OPTIONS (args));
break;
break;
case EXCLUDE_VCS_OPTION:
- exclude_vcs_files ();
+ add_exclude_array (vcs_file_table);
break;
case FORCE_LOCAL_OPTION:
unquote_option = false;
break;
+ case WARNING_OPTION:
+ set_warning_option (arg);
+ break;
+
case '0':
case '1':
case '2':
group_option = -1;
check_device_option = true;
+
+ incremental_level = -1;
+
+ seek_option = -1;
/* Convert old-style tar call by exploding option element and rearranging
options accordingly. */
_("--occurrence cannot be used in the requested operation mode")));
}
- if (seekable_archive && subcommand_option == DELETE_SUBCOMMAND)
- {
- /* The current code in delete.c is based on the assumption that
- skip_member() reads all data from the archive. So, we should
- make sure it won't use seeks. On the other hand, the same code
- depends on the ability to backspace a record in the archive,
- so setting seekable_archive to false is technically incorrect.
- However, it is tested only in skip_member(), so it's not a
- problem. */
- seekable_archive = false;
- }
-
if (archive_names == 0)
{
/* If no archive file name given, try TAPE from the environment, or
&& NEWER_OPTION_INITIALIZED (newer_mtime_option))
USAGE_ERROR ((0, 0,
_("Cannot combine --listed-incremental with --newer")));
-
+ if (incremental_level != -1 && !listed_incremental_option)
+ WARN ((0, 0,
+ _("--level is meaningless without --listed-incremental")));
+
if (volume_label_option)
{
if (archive_format == GNU_FORMAT || archive_format == OLDGNU_FORMAT)
obstack_init (&argv_stk);
-#ifdef SIGCHLD
+ /* Ensure default behavior for some signals */
+ signal (SIGPIPE, SIG_DFL);
/* System V fork+wait does not work if SIGCHLD is ignored. */
signal (SIGCHLD, SIG_DFL);
-#endif
+ /* Try to disable the ability to unlink a directory. */
+ priv_set_remove_linkdir ();
+
/* Decode options. */
decode_options (argc, argv);