Implement the --warning option.

* src/warning.c: New file.
* src/Makefile.am: Add warning.c
* src/common.h: Provide definitions for warning classes.
(warning_option): New global.
(WARNOPT): New define.
(set_warning_option): New prototype.
* src/tar.c: New option `--warning'.
* src/compare.c: When applicable WARNOPT instead of WARN.
* src/create.c: Likewise.
* src/extract.c: Likewise.
* src/incremen.c: Likewise.
* src/list.c: Likewise.

* NEWS, doc/tar.texi: Update.
This commit is contained in:
Sergey Poznyakoff
2009-08-05 13:52:38 +03:00
parent 471c0f76cd
commit 67a1a0eac5
11 changed files with 289 additions and 57 deletions
+13
View File
@@ -10,6 +10,19 @@ When listing or extracting archives, the actual record size is
reported only if the archive is read from a device (as opposed
to regular files and pipes).
* New command line option `--warning'
The `--warning' command line option allows to suppress or enable
particular warning messages during `tar' run. It takes a single
argument (a `keyword'), identifying the class of warning messages
to affect. If the argument is prefixed with `no-', such warning
messages are suppressed. For example,
tar --warning=no-alone-zero-block -x -f archive
suppresses the output of `A lone zero block' diagnostics, which is
normally issued if `archive' ends with a single block of zeros.
* Bugfixes
** Fix handling of hard link targets by -c --transform.
** Fix hard links recognition with -c --remove-files.
+149
View File
@@ -21,12 +21,14 @@
@include value.texi
@defcodeindex op
@defcodeindex kw
@c Put everything in one index (arbitrarily chosen to be the concept index).
@syncodeindex fn cp
@syncodeindex ky cp
@syncodeindex pg cp
@syncodeindex vr cp
@syncodeindex kw cp
@copying
@@ -177,6 +179,7 @@ Invoking @GNUTAR{}
* defaults::
* verbose::
* checkpoints::
* warnings::
* interactive::
The Three Option Styles
@@ -1801,6 +1804,7 @@ and @option{--interactive} options (@pxref{interactive}).
* defaults::
* verbose::
* checkpoints::
* warnings::
* interactive::
@end menu
@@ -3348,6 +3352,13 @@ Used in conjunction with @option{--multi-volume}. @command{tar} will
keep track of which volume of a multi-volume archive it is working in
@var{file}. @xref{volno-file}.
@opsummary{warning}
@item --warning=@var{keyword}
Enable or disable warning messages identified by @var{keyword}. The
messages are suppressed if @var{keyword} is prefixed with @samp{no-}.
@xref{warnings}.
@opsummary{wildcards}
@item --wildcards
Use wildcards when matching member names with patterns.
@@ -3951,6 +3962,144 @@ This example also illustrates the fact that
@option{--checkpoint}. In this case, the default checkpoint frequency
(at each 10th record) is assumed.
@node warnings
@section Controlling Warning Messages
Sometimes, while performing the requested task, @GNUTAR{} notices
some conditions that are not exactly erros, but which the user
should be aware of. When this happens, @command{tar} issues a
@dfn{warning message} describing the condition. Warning messages
are output to the standard error and they do not affect the exit
code of @command{tar} command.
@xopindex{warning, explained}
@GNUTAR{} allows the user to suppress some or all of its warning
messages:
@table @option
@item --warning=@var{keyword}
Control display of the warning messages identified by @var{keyword}.
If @var{keyword} starts with the prefix @samp{no-}, such messages are
suppressed. Otherwise, they are enabled.
Multiple @option{--warning} messages accumulate.
The tables below list allowed values for @var{keyword} along with the
warning messages they control.
@end table
@subheading Keywords controlling @command{tar} operation
@table @asis
@kwindex all
@item all
Enable all warning messages. This is the default.
@kwindex none
@item none
Disable all warning messages.
@kwindex filename-with-nuls
@cindex @samp{file name read contains nul character}, warning message
@item filename-with-nuls
@samp{%s: file name read contains nul character}
@kwindex alone-zero-block
@cindex @samp{A lone zero block at}, warning message
@item alone-zero-block
@samp{A lone zero block at %s}
@end table
@subheading Keywords applicable for @command{tar --create}
@table @asis
@kwindex cachedir
@cindex @samp{contains a cache directory tag}, warning message
@item cachedir
@samp{%s: contains a cache directory tag %s; %s}
@kwindex file-shrank
@cindex @samp{File shrank by %s bytes}, warning message
@item file-shrank
@samp{%s: File shrank by %s bytes; padding with zeros}
@kwindex xdev
@cindex @samp{file is on a different filesystem}, warning message
@item xdev
@samp{%s: file is on a different filesystem; not dumped}
@kwindex file-ignored
@cindex @samp{Unknown file type; file ignored}, warning message
@cindex @samp{socket ignored}, warning message
@cindex @samp{door ignored}, warning message
@item file-ignored
@samp{%s: Unknown file type; file ignored}
@samp{%s: socket ignored}
@*@samp{%s: door ignored}
@kwindex file-unchanged
@cindex @samp{file is unchanged; not dumped}, warning message
@item file-unchanged
@samp{%s: file is unchanged; not dumped}
@kwindex ignore-archive
@cindex @samp{file is the archive; not dumped}, warning message
@kwindex ignore-archive
@cindex @samp{file is the archive; not dumped}, warning message
@item ignore-archive
@samp{%s: file is the archive; not dumped}
@kwindex file-removed
@cindex @samp{File removed before we read it}, warning message
@item file-removed
@samp{%s: File removed before we read it}
@kwindex file-changed
@cindex @samp{file changed as we read it}, warning message
@item file-changed
@samp{%s: file changed as we read it}
@end table
@subheading Keywords applicable for @command{tar --extract}
@table @asis
@kwindex timestamp
@cindex @samp{implausibly old time stamp %s}, warning message
@cindex @samp{time stamp %s is %s s in the future}, warning message
@item timestamp
@samp{%s: implausibly old time stamp %s}
@*@samp{%s: time stamp %s is %s s in the future}
@kwindex contiguous-cast
@cindex @samp{Extracting contiguous files as regular files}, warning message
@item contiguous-cast
@samp{Extracting contiguous files as regular files}
@kwindex symlink-cast
@cindex @samp{Attempting extraction of symbolic links as hard links}, warning message
@item symlink-cast
@samp{Attempting extraction of symbolic links as hard links}
@kwindex unknown-cast
@cindex @samp{Unknown file type `%c', extracted as normal file}, warning message
@item unknown-cast
@samp{%s: Unknown file type `%c', extracted as normal file}
@kwindex ignore-newer
@cindex @samp{Current %s is newer or same age}, warning message
@item ignore-newer
@samp{Current %s is newer or same age}
@kwindex unknown-keyword
@cindex @samp{Ignoring unknown extended header keyword `%s'}, warning message
@item unknown-keyword
@samp{Ignoring unknown extended header keyword `%s'}
@end table
@subheading Keywords controlling incremental extraction:
@table @asis
@kwindex rename-directory
@cindex @samp{%s: Directory has been renamed from %s}, warning message
@cindex @samp{%s: Directory has been renamed}, warning message
@item rename-directory
@samp{%s: Directory has been renamed from %s}
@*@samp{%s: Directory has been renamed}
@kwindex new-directory
@cindex @samp{%s: Directory is new}, warning message
@item new-directory
@samp{%s: Directory is new}
@kwindex xdev
@cindex @samp{%s: directory is on a different device: not purging}, warning message
@item xdev
@samp{%s: directory is on a different device: not purging}
@kwindex bad-dumpdir
@cindex @samp{Malformed dumpdir: 'X' never used}, warning message
@item bad-dumpdir
@samp{Malformed dumpdir: 'X' never used}
@end table
@node interactive
@section Asking for Confirmation During Operations
@cindex Interactive operation
+2 -1
View File
@@ -39,7 +39,8 @@ tar_SOURCES = \
tar.c\
transform.c\
update.c\
utf8.c
utf8.c\
warning.c
INCLUDES = -I$(top_srcdir)/gnu -I../ -I../gnu -I$(top_srcdir)/lib -I../lib
+35
View File
@@ -752,3 +752,38 @@ void set_comression_program_by_suffix (const char *name, const char *defprog);
void checkpoint_compile_action (const char *str);
void checkpoint_finish_compile (void);
void checkpoint_run (bool do_write);
/* Module warning.c */
#define WARN_ALONE_ZERO_BLOCK 0x00000001
#define WARN_BAD_DUMPDIR 0x00000002
#define WARN_CACHEDIR 0x00000004
#define WARN_CONTIGUOUS_CAST 0x00000008
#define WARN_FILE_CHANGED 0x00000010
#define WARN_FILE_IGNORED 0x00000020
#define WARN_FILE_REMOVED 0x00000040
#define WARN_FILE_SHRANK 0x00000080
#define WARN_FILE_UNCHANGED 0x00000100
#define WARN_FILENAME_WITH_NULS 0x00000200
#define WARN_IGNORE_ARCHIVE 0x00000400
#define WARN_IGNORE_NEWER 0x00000800
#define WARN_NEW_DIRECTORY 0x00001000
#define WARN_RENAME_DIRECTORY 0x00002000
#define WARN_SYMLINK_CAST 0x00004000
#define WARN_TIMESTAMP 0x00008000
#define WARN_UNKNOWN_CAST 0x00010000
#define WARN_UNKNOWN_KEYWORD 0x00020000
#define WARN_XDEV 0x00040000
#define WARN_ALL 0xffffffff
void set_warning_option (const char *arg);
extern int warning_option;
#define WARNOPT(opt,args) \
do \
{ \
if (warning_option & opt) WARN (args); \
} \
while (0)
+3 -2
View File
@@ -609,8 +609,9 @@ verify_volume (void)
status = read_header (false);
if (status == HEADER_ZERO_BLOCK)
break;
WARN ((0, 0, _("A lone zero block at %s"),
STRINGIFY_BIGINT (current_block_ordinal (), buf)));
WARNOPT (WARN_ALONE_ZERO_BLOCK,
(0, 0, _("A lone zero block at %s"),
STRINGIFY_BIGINT (current_block_ordinal (), buf)));
}
}
+36 -26
View File
@@ -63,11 +63,12 @@ exclusion_tag_warning (const char *dirname, const char *tagname,
const char *message)
{
if (verbose_option)
WARN ((0, 0,
_("%s: contains a cache directory tag %s; %s"),
quotearg_colon (dirname),
quotearg_n (1, tagname),
message));
WARNOPT (WARN_CACHEDIR,
(0, 0,
_("%s: contains a cache directory tag %s; %s"),
quotearg_colon (dirname),
quotearg_n (1, tagname),
message));
}
enum exclusion_tag_type
@@ -1072,12 +1073,13 @@ dump_regular_file (int fd, struct tar_stat_info *st)
{
char buf[UINTMAX_STRSIZE_BOUND];
memset (blk->buffer + count, 0, bufsize - count);
WARN ((0, 0,
ngettext ("%s: File shrank by %s byte; padding with zeros",
"%s: File shrank by %s bytes; padding with zeros",
size_left),
quotearg_colon (st->orig_file_name),
STRINGIFY_BIGINT (size_left, buf)));
WARNOPT (WARN_FILE_SHRANK,
(0, 0,
ngettext ("%s: File shrank by %s byte; padding with zeros",
"%s: File shrank by %s bytes; padding with zeros",
size_left),
quotearg_colon (st->orig_file_name),
STRINGIFY_BIGINT (size_left, buf)));
if (! ignore_failed_read_option)
exit_status = TAREXIT_DIFFERS;
pad_archive (size_left - (bufsize - count));
@@ -1173,9 +1175,10 @@ dump_dir0 (char *directory,
&& parent_device != st->stat.st_dev)
{
if (verbose_option)
WARN ((0, 0,
_("%s: file is on a different filesystem; not dumped"),
quotearg_colon (st->orig_file_name)));
WARNOPT (WARN_XDEV,
(0, 0,
_("%s: file is on a different filesystem; not dumped"),
quotearg_colon (st->orig_file_name)));
}
else
{
@@ -1358,8 +1361,9 @@ compare_links (void const *entry1, void const *entry2)
static void
unknown_file_error (char const *p)
{
WARN ((0, 0, _("%s: Unknown file type; file ignored"),
quotearg_colon (p)));
WARNOPT (WARN_FILE_IGNORED,
(0, 0, _("%s: Unknown file type; file ignored"),
quotearg_colon (p)));
if (!ignore_failed_read_option)
exit_status = TAREXIT_FAILURE;
}
@@ -1539,16 +1543,18 @@ dump_file0 (struct tar_stat_info *st, const char *p,
&& (!after_date_option || OLDER_TAR_STAT_TIME (*st, c)))
{
if (!incremental_option && verbose_option)
WARN ((0, 0, _("%s: file is unchanged; not dumped"),
quotearg_colon (p)));
WARNOPT (WARN_FILE_UNCHANGED,
(0, 0, _("%s: file is unchanged; not dumped"),
quotearg_colon (p)));
return;
}
/* See if we are trying to dump the archive. */
if (sys_file_is_archive (st))
{
WARN ((0, 0, _("%s: file is the archive; not dumped"),
quotearg_colon (p)));
WARNOPT (WARN_IGNORE_ARCHIVE,
(0, 0, _("%s: file is the archive; not dumped"),
quotearg_colon (p)));
return;
}
@@ -1577,8 +1583,9 @@ dump_file0 (struct tar_stat_info *st, const char *p,
if (fd < 0)
{
if (!top_level && errno == ENOENT)
WARN ((0, 0, _("%s: File removed before we read it"),
quotearg_colon (p)));
WARNOPT (WARN_FILE_REMOVED,
(0, 0, _("%s: File removed before we read it"),
quotearg_colon (p)));
else
open_diag (p);
return;
@@ -1663,8 +1670,9 @@ dump_file0 (struct tar_stat_info *st, const char *p,
&& !(remove_files_option && is_dir))
|| original_size < final_stat.st_size)
{
WARN ((0, 0, _("%s: file changed as we read it"),
quotearg_colon (p)));
WARNOPT (WARN_FILE_CHANGED,
(0, 0, _("%s: file changed as we read it"),
quotearg_colon (p)));
if (exit_status == TAREXIT_SUCCESS)
exit_status = TAREXIT_DIFFERS;
}
@@ -1743,12 +1751,14 @@ dump_file0 (struct tar_stat_info *st, const char *p,
type = FIFOTYPE;
else if (S_ISSOCK (st->stat.st_mode))
{
WARN ((0, 0, _("%s: socket ignored"), quotearg_colon (p)));
WARNOPT (WARN_FILE_IGNORED,
(0, 0, _("%s: socket ignored"), quotearg_colon (p)));
return;
}
else if (S_ISDOOR (st->stat.st_mode))
{
WARN ((0, 0, _("%s: door ignored"), quotearg_colon (p)));
WARNOPT (WARN_FILE_IGNORED,
(0, 0, _("%s: door ignored"), quotearg_colon (p)));
return;
}
else
+18 -11
View File
@@ -207,8 +207,9 @@ static void
check_time (char const *file_name, struct timespec t)
{
if (t.tv_sec <= 0)
WARN ((0, 0, _("%s: implausibly old time stamp %s"),
file_name, tartime (t, true)));
WARNOPT (WARN_TIMESTAMP,
(0, 0, _("%s: implausibly old time stamp %s"),
file_name, tartime (t, true)));
else if (timespec_cmp (volume_start_time, t) < 0)
{
struct timespec now;
@@ -224,8 +225,9 @@ check_time (char const *file_name, struct timespec t)
diff.tv_nsec += BILLION;
diff.tv_sec--;
}
WARN ((0, 0, _("%s: time stamp %s is %s s in the future"),
file_name, tartime (t, true), code_timespec (diff, buf)));
WARNOPT (WARN_TIMESTAMP,
(0, 0, _("%s: time stamp %s is %s s in the future"),
file_name, tartime (t, true), code_timespec (diff, buf)));
}
}
}
@@ -753,7 +755,8 @@ open_output_file (char *file_name, int typeflag, mode_t mode)
if (!conttype_diagnosed)
{
conttype_diagnosed = 1;
WARN ((0, 0, _("Extracting contiguous files as regular files")));
WARNOPT (WARN_CONTIGUOUS_CAST,
(0, 0, _("Extracting contiguous files as regular files")));
}
}
fd = open (file_name, openflag, mode);
@@ -1031,7 +1034,9 @@ extract_symlink (char *file_name, int typeflag)
if (!warned_once)
{
warned_once = 1;
WARN ((0, 0, _("Attempting extraction of symbolic links as hard links")));
WARNOPT (WARN_SYMBOLIC_CAST,
(0, 0,
_("Attempting extraction of symbolic links as hard links")));
}
return extract_link (file_name, typeflag);
#endif
@@ -1189,9 +1194,10 @@ prepare_to_extract (char const *file_name, int typeflag, tar_extractor_t *fun)
break;
default:
WARN ((0, 0,
_("%s: Unknown file type `%c', extracted as normal file"),
quotearg_colon (file_name), typeflag));
WARNOPT (WARN_UNKNOWN_CAST,
(0, 0,
_("%s: Unknown file type `%c', extracted as normal file"),
quotearg_colon (file_name), typeflag));
*fun = extract_file;
}
@@ -1215,8 +1221,9 @@ prepare_to_extract (char const *file_name, int typeflag, tar_extractor_t *fun)
case KEEP_NEWER_FILES:
if (file_newer_p (file_name, &current_stat_info))
{
WARN ((0, 0, _("Current %s is newer or same age"),
quote (file_name)));
WARNOPT (WARN_IGNORE_NEWER,
(0, 0, _("Current %s is newer or same age"),
quote (file_name)));
return 0;
}
break;
+17 -11
View File
@@ -445,9 +445,11 @@ procdir (char *name_buffer, struct stat *stat_data,
if (strcmp (d->name, name_buffer))
{
if (verbose_option)
WARN ((0, 0, _("%s: Directory has been renamed from %s"),
quotearg_colon (name_buffer),
quote_n (1, d->name)));
WARNOPT (WARN_RENAME_DIRECTORY,
(0, 0,
_("%s: Directory has been renamed from %s"),
quotearg_colon (name_buffer),
quote_n (1, d->name)));
directory->orig = d;
DIR_SET_FLAG (directory, DIRF_RENAMED);
dirlist_replace_prefix (d->name, name_buffer);
@@ -457,8 +459,9 @@ procdir (char *name_buffer, struct stat *stat_data,
else
{
if (verbose_option)
WARN ((0, 0, _("%s: Directory has been renamed"),
quotearg_colon (name_buffer)));
WARNOPT (WARN_RENAME_DIRECTORY,
(0, 0, _("%s: Directory has been renamed"),
quotearg_colon (name_buffer)));
directory->children = ALL_CHILDREN;
directory->device_number = stat_data->st_dev;
directory->inode_number = stat_data->st_ino;
@@ -489,9 +492,10 @@ procdir (char *name_buffer, struct stat *stat_data,
if (strcmp (d->name, name_buffer))
{
if (flag & PD_VERBOSE)
WARN ((0, 0, _("%s: Directory has been renamed from %s"),
quotearg_colon (name_buffer),
quote_n (1, d->name)));
WARNOPT (WARN_RENAME_DIRECTORY,
(0, 0, _("%s: Directory has been renamed from %s"),
quotearg_colon (name_buffer),
quote_n (1, d->name)));
directory->orig = d;
DIR_SET_FLAG (directory, DIRF_RENAMED);
dirlist_replace_prefix (d->name, name_buffer);
@@ -502,8 +506,9 @@ procdir (char *name_buffer, struct stat *stat_data,
{
DIR_SET_FLAG (directory, DIRF_NEW);
if (flag & PD_VERBOSE)
WARN ((0, 0, _("%s: Directory is new"),
quotearg_colon (name_buffer)));
WARNOPT (WARN_NEW_DIRECTORY,
(0, 0, _("%s: Directory is new"),
quotearg_colon (name_buffer)));
directory->children =
(listed_incremental_option
|| (OLDER_STAT_TIME (*stat_data, m)
@@ -1504,7 +1509,8 @@ dumpdir_ok (char *dumpdir)
}
if (has_tempdir)
WARN ((0, 0, _("Malformed dumpdir: 'X' never used")));
WARNOPT (WARN_BAD_DUMPDIR,
(0, 0, _("Malformed dumpdir: 'X' never used")));
return true;
}
+3 -2
View File
@@ -141,8 +141,9 @@ read_and (void (*do_something) (void))
status = read_header (false);
if (status == HEADER_ZERO_BLOCK)
break;
WARN ((0, 0, _("A lone zero block at %s"),
STRINGIFY_BIGINT (current_block_ordinal (), buf)));
WARNOPT (WARN_ALONE_ZERO_BLOCK,
(0, 0, _("A lone zero block at %s"),
STRINGIFY_BIGINT (current_block_ordinal (), buf)));
break;
}
status = prev_status;
+10 -2
View File
@@ -328,6 +328,7 @@ enum
UTC_OPTION,
VERSION_OPTION,
VOLNO_FILE_OPTION,
WARNING_OPTION,
WILDCARDS_MATCH_SLASH_OPTION,
WILDCARDS_OPTION
};
@@ -719,6 +720,8 @@ static struct argp_option options[] = {
{"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 },
@@ -1183,8 +1186,9 @@ update_argv (const char *filename, struct argp_state *state)
{
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);
@@ -1949,6 +1953,10 @@ parse_opt (int key, char *arg, struct argp_state *state)
unquote_option = false;
break;
case WARNING_OPTION:
set_warning_option (arg);
break;
case '0':
case '1':
case '2':
+3 -2
View File
@@ -571,8 +571,9 @@ decx (void *data, char const *keyword, char const *value, size_t size)
if (t)
t->decoder (st, keyword, value, size);
else
WARN((0, 0, _("Ignoring unknown extended header keyword `%s'"),
keyword));
WARNOPT (WARN_UNKNOWN_KEYWORD,
(0, 0, _("Ignoring unknown extended header keyword `%s'"),
keyword));
}
void