};
#endif
+#include <quotearg.h>
+
#include "common.h"
#ifndef MSDOS
{
int base256_allowed = (archive_format == GNU_FORMAT
|| archive_format == OLDGNU_FORMAT);
- uintmax_t v = negative ? -value : value;
/* Generate the POSIX octal representation if the number fits. */
- if (! negative && v <= MAX_VAL_WITH_DIGITS (size - 1, LG_8))
+ if (! negative && value <= MAX_VAL_WITH_DIGITS (size - 1, LG_8))
{
where[size - 1] = '\0';
- to_octal (v, where, size - 1);
+ to_octal (value, where, size - 1);
}
/* Otherwise, generate the base-256 representation if we are
generating an old or new GNU format and if the number fits. */
- else if (v - negative <= MAX_VAL_WITH_DIGITS (size - 1, LG_256)
+ else if (((negative ? -1 - value : value)
+ <= MAX_VAL_WITH_DIGITS (size - 1, LG_256))
&& base256_allowed)
{
where[0] = negative ? -1 : 1 << (LG_256 - 1);
- to_base256 (negative, v, where + 1, size - 1);
+ to_base256 (negative, value, where + 1, size - 1);
}
/* Otherwise, if the number is negative, and if it would not cause
if (! warned_once)
{
warned_once = 1;
- WARN ((0, 0, _("Generating negative octal headers\n")));
+ WARN ((0, 0, _("Generating negative octal headers")));
}
where[size - 1] = '\0';
to_octal (value & MAX_VAL_WITH_DIGITS (valsize * CHAR_BIT, 1),
? MAX_VAL_WITH_DIGITS (size - 1, LG_256)
: MAX_VAL_WITH_DIGITS (size - 1, LG_8));
char valbuf[UINTMAX_STRSIZE_BOUND + 1];
- char maxbuf[UINTMAX_STRSIZE_BOUND]
+ char maxbuf[UINTMAX_STRSIZE_BOUND];
char minbuf[UINTMAX_STRSIZE_BOUND + 1];
- char subbuf[UINTMAX_STRSIZE_BOUND + 1];
- char *value_string = STRINGIFY_BIGINT (v, valbuf + 1);
- char *maxval_string = STRINGIFY_BIGINT (maxval, maxbuf);
char const *minval_string;
+ char const *maxval_string = STRINGIFY_BIGINT (maxval, maxbuf);
+ char const *value_string;
+
if (base256_allowed)
{
uintmax_t m = maxval + 1 ? maxval + 1 : maxval / 2 + 1;
- minval_string = STRINGIFY_BIGINT (m, minbuf + 1);
- *--minval_string = '-';
+ char *p = STRINGIFY_BIGINT (m, minbuf + 1);
+ *--p = '-';
+ minval_string = p;
}
else
minval_string = "0";
+
if (negative)
- *--value_string = '-';
+ {
+ char *p = STRINGIFY_BIGINT (- value, valbuf + 1);
+ *--p = '-';
+ value_string = p;
+ }
+ else
+ value_string = STRINGIFY_BIGINT (value, valbuf);
+
if (substitute)
{
int negsub;
uintmax_t sub = substitute (&negsub) & maxval;
- uintmax_t s = (negsub &= archive_format == GNU_FORMAT) ? -sub : sub;
+ uintmax_t s = (negsub &= archive_format == GNU_FORMAT) ? - sub : sub;
+ char subbuf[UINTMAX_STRSIZE_BOUND + 1];
char *sub_string = STRINGIFY_BIGINT (s, subbuf + 1);
if (negsub)
*--sub_string = '-';
if (!warned_once)
{
warned_once = 1;
- WARN ((0, 0, _("Removing `%.*s' prefix from archive names"),
+ WARN ((0, 0, _("Removing `%.*s' prefix from member names"),
(int) prefix_len, name));
}
name += prefix_len;
if (!warned_once)
{
warned_once = 1;
- WARN ((0, 0, _("Removing leading `/' from archive names")));
+ WARN ((0, 0, _("Removing leading `/' from member names")));
}
name++;
}
+
+ {
+ static int warned_once;
+ if (! warned_once && contains_dot_dot (name))
+ {
+ warned_once = 1;
+ WARN ((0, 0, _("Member names contain `..'")));
+ }
+ }
}
if (sizeof header->header.name <= strlen (name))
uintmax_to_chars ((uintmax_t) sum, header->header.chksum, 7);
- set_next_block_after (header);
-
if (verbose_option
&& header->header.typeflag != GNUTYPE_LONGLINK
&& header->header.typeflag != GNUTYPE_LONGNAME)
current_format = archive_format;
print_header ();
}
+
+ set_next_block_after (header);
}
\f
/* Sparse file processing. */
ERROR ((0, 0, _("Wrote %s of %s bytes to file %s"),
STRINGIFY_BIGINT (fullsize - *sizeleft, buf1),
- STRINGIFY_BIGINT (fullsize, buf2),
- name));
+ STRINGIFY_BIGINT (fullsize, buf2), quote (name)));
break;
}
if (lseek (file, sparsearray[sparse_index++].offset, SEEK_SET) < 0)
{
char buf[UINTMAX_STRSIZE_BOUND];
- ERROR ((0, errno, _("lseek error at byte %s in file %s"),
- STRINGIFY_BIGINT (sparsearray[sparse_index - 1].offset, buf),
- name));
+ int e = errno;
+ ERROR ((0, e, _("lseek error at byte %s in file %s"),
+ STRINGIFY_BIGINT (sparsearray[sparse_index - 1].offset,
+ buf),
+ quote (name)));
break;
}
if (count < 0)
{
char buf[UINTMAX_STRSIZE_BOUND];
- ERROR ((0, errno,
+ int e = errno;
+ ERROR ((0, e,
_("Read error at byte %s, reading %lu bytes, in file %s"),
STRINGIFY_BIGINT (fullsize - *sizeleft, buf),
- (unsigned long) bufsize, name));
+ (unsigned long) bufsize, quote (name)));
return 1;
}
bufsize -= count;
if (count < 0)
{
char buf[UINTMAX_STRSIZE_BOUND];
-
- ERROR ((0, errno,
+ int e = errno;
+ ERROR ((0, e,
_("Read error at byte %s, reading %lu bytes, in file %s"),
STRINGIFY_BIGINT (fullsize - *sizeleft, buf),
- (unsigned long) bufsize, name));
+ (unsigned long) bufsize, quote (name)));
return 1;
}
#if 0
if (count != bufsize)
{
ERROR ((0, 0,
- _("File %s shrunk, padding with zeros"),
- name));
+ _("File %s shrunk, padding with zeros"), quote (name)));
return 1;
}
start = find_next_block ();
const char *q;
char *bufp;
- name_expand (1);
+ collect_and_sort_names ();
while (p = name_from_list (), p)
if (!excluded_name (p))
/* Dump a single file, recursing on directories. P is the file name
to dump. TOP_LEVEL tells whether this is a top-level call; zero
means no, positive means yes, and negative means an incremental
- dump where it's irrelevant. PARENT_DEVICE is the device of P's
+ dump. PARENT_DEVICE is the device of P's
parent directory; it is examined only if TOP_LEVEL is zero.
Set global CURRENT_STAT to stat output for this file. */
char type;
union block *exhdr;
char save_typeflag;
+ time_t original_ctime;
struct utimbuf restore_times;
- off_t restore_size;
/* FIXME: `header' and `upperbound' might be used uninitialized in this
function. Reported by Bruno Haible. */
if (deref_stat (dereference_option, p, ¤t_stat) != 0)
{
- WARN ((0, errno, _("Cannot add file %s"), p));
- if (!ignore_failed_read_option)
- exit_status = TAREXIT_FAILURE;
+ if (ignore_failed_read_option)
+ stat_error (p);
+ else
+ stat_warn (p);
return;
}
+ original_ctime = current_stat.st_ctime;
restore_times.actime = current_stat.st_atime;
restore_times.modtime = current_stat.st_mtime;
- restore_size = current_stat.st_size;
#ifdef S_ISHIDDEN
if (S_ISHIDDEN (current_stat.st_mode))
&& (!after_date_option || current_stat.st_ctime < newer_ctime_option))
{
if (0 < top_level)
- WARN ((0, 0, _("%s: is unchanged; not dumped"), p));
+ WARN ((0, 0, _("%s is unchanged; not dumped"), quote (p)));
/* FIXME: recheck this return. */
return;
}
if (ar_dev && current_stat.st_dev == ar_dev && current_stat.st_ino == ar_ino)
{
- WARN ((0, 0, _("%s is the archive; not dumped"), p));
+ WARN ((0, 0, _("%s is the archive; not dumped"), quote (p)));
return;
}
#endif
size_t len;
dev_t our_device = current_stat.st_dev;
- /* If this tar program is installed suid root, like for Amanda, the
- access might look like denied, while it is not really.
-
- FIXME: I have the feeling this test is done too early. Couldn't it
- just be bundled in later actions? I guess that the proper support
- of --ignore-failed-read is the key of the current writing. */
+ errno = 0;
- if (access (p, R_OK) == -1 && geteuid () != 0)
+ directory = opendir (p);
+ if (! directory)
{
- WARN ((0, errno, _("Cannot add directory %s"), p));
- if (!ignore_failed_read_option)
- exit_status = TAREXIT_FAILURE;
+ if (ignore_failed_read_option)
+ opendir_warn (p);
+ else
+ opendir_error (p);
return;
}
&& parent_device != current_stat.st_dev)
{
if (verbose_option)
- WARN ((0, 0, _("%s: On a different filesystem; not dumped"), p));
+ WARN ((0, 0, _("%s is on a different filesystem; not dumped"),
+ quote (p)));
return;
}
/* Now output all the files in the directory. */
- errno = 0; /* FIXME: errno should be read-only */
-
- directory = opendir (p);
- if (!directory)
- {
- ERROR ((0, errno, _("Cannot open directory %s"), p));
- return;
- }
-
/* FIXME: Should speed this up by cd-ing into the dir. */
- while (entry = readdir (directory), entry)
+ while (errno = 0, (entry = readdir (directory)))
{
/* Skip `.', `..', and excluded file names. */
}
strcpy (namebuf + len, entry->d_name);
if (!excluded_name (namebuf))
- dump_file (namebuf, our_device, 0);
+ dump_file (namebuf, 0, our_device);
+ }
+
+ if (errno)
+ {
+ if (ignore_failed_read_option)
+ readdir_warn (p);
+ else
+ readdir_error (p);
}
- closedir (directory);
+ if (closedir (directory) != 0)
+ closedir_error (p);
free (namebuf);
if (atime_preserve_option)
utime (p, &restore_times);
if (remove_files_option)
if (unlink (p) == -1)
- ERROR ((0, errno, _("Cannot remove %s"), p));
+ unlink_error (p);
/* We dumped it. */
return;
f = open (p, O_RDONLY | O_BINARY);
if (f < 0)
{
- WARN ((0, errno, _("Cannot add file %s"), p));
- if (!ignore_failed_read_option)
- exit_status = TAREXIT_FAILURE;
+ if (! top_level && errno == ENOENT)
+ WARN ((0, 0, _("File %s removed before we read it"),
+ quote (p)));
+ else if (ignore_failed_read_option)
+ open_warn (p);
+ else
+ open_error (p);
return;
}
}
if (save_typeflag == GNUTYPE_SPARSE)
{
if (f < 0
- || finish_sparse_file (f, &sizeleft, current_stat.st_size, p))
+ || finish_sparse_file (f, &sizeleft,
+ current_stat.st_size, p))
goto padit;
}
else
if (count < 0)
{
char buf[UINTMAX_STRSIZE_BOUND];
- ERROR ((0, errno,
+ int e = errno;
+ ERROR ((0, e,
_("Read error at byte %s, reading %lu bytes, in file %s"),
STRINGIFY_BIGINT (current_stat.st_size - sizeleft,
buf),
- (unsigned long) bufsize, p));
+ (unsigned long) bufsize, quote (p)));
goto padit;
}
sizeleft -= count;
char buf[UINTMAX_STRSIZE_BOUND];
ERROR ((0, 0,
_("File %s shrunk by %s bytes, padding with zeros"),
- p, STRINGIFY_BIGINT (sizeleft, buf)));
+ quote (p), STRINGIFY_BIGINT (sizeleft, buf)));
goto padit; /* short read */
}
}
{
struct stat final_stat;
if (fstat (f, &final_stat) != 0)
- ERROR ((0, errno, "%s: fstat", p));
- else if (final_stat.st_mtime != restore_times.modtime
- || final_stat.st_size != restore_size)
- ERROR ((0, errno, _("%s: file changed as we read it"), p));
+ stat_error (p);
+ else if (final_stat.st_ctime != original_ctime)
+ ERROR ((0, 0, _("File %s changed as we read it"), quote (p)));
if (close (f) != 0)
- ERROR ((0, errno, _("%s: close"), p));
+ close_error (p);
if (atime_preserve_option)
utime (p, &restore_times);
}
if (remove_files_option)
{
if (unlink (p) == -1)
- ERROR ((0, errno, _("Cannot remove %s"), p));
+ unlink_error (p);
}
return;
size = readlink (p, buffer, PATH_MAX + 1);
if (size < 0)
{
- WARN ((0, errno, _("Cannot add file %s"), p));
- if (!ignore_failed_read_option)
- exit_status = TAREXIT_FAILURE;
+ if (ignore_failed_read_option)
+ readlink_warn (p);
+ else
+ readlink_error (p);
return;
}
buffer[size] = '\0';
if (remove_files_option)
{
if (unlink (p) == -1)
- ERROR ((0, errno, _("Cannot remove %s"), p));
+ unlink_error (p);
}
return;
}
type = CHRTYPE;
else if (S_ISBLK (current_stat.st_mode))
type = BLKTYPE;
- else if (S_ISFIFO (current_stat.st_mode)
- || S_ISSOCK (current_stat.st_mode))
+ else if (S_ISFIFO (current_stat.st_mode))
type = FIFOTYPE;
+ else if (S_ISSOCK (current_stat.st_mode))
+ {
+ WARN ((0, 0, _("%s: socket ignored"), quotearg_colon (p)));
+ return;
+ }
+ else if (S_ISDOOR (current_stat.st_mode))
+ {
+ WARN ((0, 0, _("%s: door ignored"), quotearg_colon (p)));
+ return;
+ }
else
goto unknown;
}
if (remove_files_option)
{
if (unlink (p) == -1)
- ERROR ((0, errno, _("Cannot remove %s"), p));
+ unlink_error (p);
}
return;
unknown:
- ERROR ((0, 0, _("%s: Unknown file type; file ignored"), p));
+ ERROR ((0, 0, _("%s: Unknown file type; file ignored"),
+ quotearg_colon (p)));
}