* 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.
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.
@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
* defaults::
* verbose::
* checkpoints::
+* warnings::
* interactive::
The Three Option Styles
* defaults::
* verbose::
* checkpoints::
+* warnings::
* interactive::
@end menu
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.
@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
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
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)
+
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)));
}
}
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
{
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));
&& 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
{
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;
}
&& (!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;
}
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;
&& !(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;
}
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
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;
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)));
}
}
}
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);
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
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;
}
case KEEP_NEWER_FILES:
if (file_newer_p (file_name, ¤t_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;
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);
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;
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);
{
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)
}
if (has_tempdir)
- WARN ((0, 0, _("Malformed dumpdir: 'X' never used")));
+ WARNOPT (WARN_BAD_DUMPDIR,
+ (0, 0, _("Malformed dumpdir: 'X' never used")));
return true;
}
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;
UTC_OPTION,
VERSION_OPTION,
VOLNO_FILE_OPTION,
+ WARNING_OPTION,
WILDCARDS_MATCH_SLASH_OPTION,
WILDCARDS_OPTION
};
{"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 },
{
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);
unquote_option = false;
break;
+ case WARNING_OPTION:
+ set_warning_option (arg);
+ break;
+
case '0':
case '1':
case '2':
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