/* Diff files from a tar archive.
- Copyright (C) 1988, 92, 93, 94, 96, 97 Free Software Foundation, Inc.
+
+ Copyright (C) 1988, 1992, 1993, 1994, 1996, 1997, 1999, 2000, 2001,
+ 2003 Free Software Foundation, Inc.
+
Written by John Gilmore, on 1987-04-30.
This program is free software; you can redistribute it and/or modify it
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
- 59 Place - Suite 330, Boston, MA 02111-1307, USA. */
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "system.h"
+#if HAVE_UTIME_H
+# include <utime.h>
+#else
+struct utimbuf
+ {
+ long actime;
+ long modtime;
+ };
+#endif
+
#if HAVE_LINUX_FD_H
# include <linux/fd.h>
#endif
+#include <quotearg.h>
+
#include "common.h"
#include "rmt.h"
-
-/* Spare space for messages, hopefully safe even after gettext. */
-#define MESSAGE_BUFFER_SIZE 100
+#include <stdarg.h>
/* Nonzero if we are verifying at the moment. */
-int now_verifying = 0;
+bool now_verifying;
/* File descriptor for the file we are diffing. */
static int diff_handle;
/* Area for reading file contents into. */
-static char *diff_buffer = NULL;
-
-/*--------------------------------.
-| Initialize for a diff operation |
-`--------------------------------*/
+static char *diff_buffer;
+/* Initialize for a diff operation. */
void
diff_init (void)
{
- diff_buffer = (char *) valloc ((unsigned) record_size);
+ diff_buffer = valloc (record_size);
if (!diff_buffer)
- FATAL_ERROR ((0, 0,
- _("Could not allocate memory for diff buffer of %d bytes"),
- record_size));
+ xalloc_die ();
}
-/*------------------------------------------------------------------------.
-| Sigh about something that differs by writing a MESSAGE to stdlis, given |
-| MESSAGE is not NULL. Also set the exit status if not already. |
-`------------------------------------------------------------------------*/
-
-static void
-report_difference (const char *message)
+/* Sigh about something that differs by writing a MESSAGE to stdlis,
+ given MESSAGE is nonzero. Also set the exit status if not already. */
+void
+report_difference (const char *fmt, ...)
{
- if (message)
- fprintf (stdlis, "%s: %s\n", current_file_name, message);
+ if (fmt)
+ {
+ va_list ap;
+ fprintf (stdlis, "%s: ", quotearg_colon (current_stat_info.file_name));
+ va_start (ap, fmt);
+ vfprintf (stdlis, fmt, ap);
+ va_end (ap);
+ fprintf (stdlis, "\n");
+ }
+
if (exit_status == TAREXIT_SUCCESS)
exit_status = TAREXIT_DIFFERS;
}
-/*-----------------------------------------------------------------------.
-| Takes a buffer returned by read_and_process and does nothing with it. |
-`-----------------------------------------------------------------------*/
-
-/* Yes, I know. SIZE and DATA are unused in this function. Some compilers
- may even report it. That's OK, just relax! */
-
+/* Take a buffer returned by read_and_process and do nothing with it. */
static int
-process_noop (long size, char *data)
+process_noop (size_t size, char *data)
{
+ /* Yes, I know. SIZE and DATA are unused in this function. Some
+ compilers may even report it. That's OK, just relax! */
return 1;
}
-/*---.
-| ? |
-`---*/
-
static int
-process_rawdata (long bytes, char *buffer)
+process_rawdata (size_t bytes, char *buffer)
{
- int status = read (diff_handle, diff_buffer, (size_t) bytes);
- char message[MESSAGE_BUFFER_SIZE];
+ ssize_t status = safe_read (diff_handle, diff_buffer, bytes);
if (status != bytes)
{
if (status < 0)
{
- WARN ((0, errno, _("Cannot read %s"), current_file_name));
+ read_error (current_stat_info.file_name);
report_difference (NULL);
}
else
{
- sprintf (message, _("Could only read %d of %ld bytes"),
- status, bytes);
- report_difference (message);
+ report_difference (ngettext ("Could only read %lu of %lu byte",
+ "Could only read %lu of %lu bytes",
+ bytes),
+ (unsigned long) status, (unsigned long) bytes);
}
return 0;
}
- if (memcmp (buffer, diff_buffer, (size_t) bytes))
+ if (memcmp (buffer, diff_buffer, bytes))
{
- report_difference (_("Data differs"));
+ report_difference (_("Contents differ"));
return 0;
}
return 1;
}
-/*---.
-| ? |
-`---*/
-
/* Directory contents, only for GNUTYPE_DUMPDIR. */
static char *dumpdir_cursor;
static int
-process_dumpdir (long bytes, char *buffer)
+process_dumpdir (size_t bytes, char *buffer)
{
- if (memcmp (buffer, dumpdir_cursor, (size_t) bytes))
+ if (memcmp (buffer, dumpdir_cursor, bytes))
{
- report_difference (_("Data differs"));
+ report_difference (_("Contents differ"));
return 0;
}
return 1;
}
-/*------------------------------------------------------------------------.
-| Some other routine wants SIZE bytes in the archive. For each chunk of |
-| the archive, call PROCESSOR with the size of the chunk, and the address |
-| of the chunk it can work with. The PROCESSOR should return nonzero for |
-| success. It it return error once, continue skipping without calling |
-| PROCESSOR anymore. |
-`------------------------------------------------------------------------*/
-
+/* Some other routine wants SIZE bytes in the archive. For each chunk
+ of the archive, call PROCESSOR with the size of the chunk, and the
+ address of the chunk it can work with. The PROCESSOR should return
+ nonzero for success. It it return error once, continue skipping
+ without calling PROCESSOR anymore. */
static void
-read_and_process (long size, int (*processor) (long, char *))
+read_and_process (off_t size, int (*processor) (size_t, char *))
{
union block *data_block;
- long data_size;
+ size_t data_size;
if (multi_volume_option)
save_sizeleft = size;
while (size)
{
data_block = find_next_block ();
- if (data_block == NULL)
+ if (! data_block)
{
- ERROR ((0, 0, _("Unexpected EOF on archive file")));
+ ERROR ((0, 0, _("Unexpected EOF in archive")));
return;
}
}
}
-/*---.
-| ? |
-`---*/
-
-/* JK This routine should be used more often than it is ... look into
- that. Anyhow, what it does is translate the sparse information on the
- header, and in any subsequent extended headers, into an array of
- structures with true numbers, as opposed to character strings. It
- simply makes our life much easier, doing so many comparisong and such.
- */
-
-static void
-fill_in_sparse_array (void)
-{
- int counter;
-
- /* Allocate space for our scratch space; it's initially 10 elements
- long, but can change in this routine if necessary. */
-
- sp_array_size = 10;
- sparsearray = (struct sp_array *) xmalloc (sp_array_size * sizeof (struct sp_array));
-
- /* There are at most five of these structures in the header itself;
- read these in first. */
-
- for (counter = 0; counter < SPARSES_IN_OLDGNU_HEADER; counter++)
- {
- /* Compare to 0, or use !(int)..., for Pyramid's dumb compiler. */
- if (current_header->oldgnu_header.sp[counter].numbytes == 0)
- break;
-
- sparsearray[counter].offset =
- from_oct (1 + 12, current_header->oldgnu_header.sp[counter].offset);
- sparsearray[counter].numbytes =
- from_oct (1 + 12, current_header->oldgnu_header.sp[counter].numbytes);
- }
-
- /* If the header's extended, we gotta read in exhdr's till we're done. */
-
- if (current_header->oldgnu_header.isextended)
- {
- /* How far into the sparsearray we are `so far'. */
- static int so_far_ind = SPARSES_IN_OLDGNU_HEADER;
- union block *exhdr;
-
- while (1)
- {
- exhdr = find_next_block ();
- for (counter = 0; counter < SPARSES_IN_SPARSE_HEADER; counter++)
- {
- if (counter + so_far_ind > sp_array_size - 1)
- {
- /* We just ran out of room in our scratch area -
- realloc it. */
-
- sp_array_size *= 2;
- sparsearray = (struct sp_array *)
- xrealloc (sparsearray,
- sp_array_size * sizeof (struct sp_array));
- }
-
- /* Convert the character strings into longs. */
-
- sparsearray[counter + so_far_ind].offset =
- from_oct (1 + 12, exhdr->sparse_header.sp[counter].offset);
- sparsearray[counter + so_far_ind].numbytes =
- from_oct (1 + 12, exhdr->sparse_header.sp[counter].numbytes);
- }
-
- /* If this is the last extended header for this file, we can
- stop. */
-
- if (!exhdr->sparse_header.isextended)
- break;
-
- so_far_ind += SPARSES_IN_SPARSE_HEADER;
- set_next_block_after (exhdr);
- }
-
- /* Be sure to skip past the last one. */
-
- set_next_block_after (exhdr);
- }
-}
-
-/*---.
-| ? |
-`---*/
-
/* JK Diff'ing a sparse file with its counterpart on the tar file is a
bit of a different story than a normal file. First, we must know what
- areas of the file to skip through, i.e., we need to contruct a
+ areas of the file to skip through, i.e., we need to construct a
sparsearray, which will hold all the information we need. We must
compare small amounts of data at a time as we find it. */
I'm not sure overall identical sparsity is verified. */
static void
-diff_sparse_files (int size_of_file)
+diff_sparse_files (void)
{
- int remaining_size = size_of_file;
- char *buffer = (char *) xmalloc (BLOCKSIZE * sizeof (char));
- int buffer_size = BLOCKSIZE;
- union block *data_block = NULL;
+ off_t remaining_size = current_stat_info.stat.st_size;
+ char *buffer = xmalloc (BLOCKSIZE * sizeof (char));
+ size_t buffer_size = BLOCKSIZE;
+ union block *data_block = 0;
int counter = 0;
int different = 0;
- fill_in_sparse_array ();
+ if (! fill_in_sparse_array ())
+ fatal_exit ();
while (remaining_size > 0)
{
- int status;
- long chunk_size;
+ ssize_t status;
+ size_t chunk_size;
+ off_t offset;
+
#if 0
- int amount_read = 0;
+ off_t amount_read = 0;
#endif
data_block = find_next_block ();
+ if (!data_block)
+ FATAL_ERROR ((0, 0, _("Unexpected EOF in archive")));
chunk_size = sparsearray[counter].numbytes;
if (!chunk_size)
break;
- lseek (diff_handle, sparsearray[counter].offset, 0);
+ offset = sparsearray[counter].offset;
+ if (lseek (diff_handle, offset, SEEK_SET) < 0)
+ {
+ seek_error_details (current_stat_info.file_name, offset);
+ report_difference (NULL);
+ }
/* Take care to not run out of room in our buffer. */
while (buffer_size < chunk_size)
{
+ if (buffer_size * 2 < buffer_size)
+ xalloc_die ();
buffer_size *= 2;
- buffer = (char *) xrealloc (buffer, buffer_size * sizeof (char));
+ buffer = xrealloc (buffer, buffer_size * sizeof (char));
}
while (chunk_size > BLOCKSIZE)
{
- if (status = read (diff_handle, buffer, BLOCKSIZE),
+ if (status = safe_read (diff_handle, buffer, BLOCKSIZE),
status != BLOCKSIZE)
{
if (status < 0)
{
- WARN ((0, errno, _("Cannot read %s"), current_file_name));
+ read_error (current_stat_info.file_name);
report_difference (NULL);
}
else
{
- char message[MESSAGE_BUFFER_SIZE];
-
- sprintf (message, _("Could only read %d of %ld bytes"),
- status, chunk_size);
- report_difference (message);
+ report_difference (ngettext ("Could only read %lu of %lu byte",
+ "Could only read %lu of %lu bytes",
+ chunk_size),
+ (unsigned long) status,
+ (unsigned long) chunk_size);
}
break;
}
remaining_size -= status;
set_next_block_after (data_block);
data_block = find_next_block ();
+ if (!data_block)
+ FATAL_ERROR ((0, 0, _("Unexpected EOF in archive")));
}
- if (status = read (diff_handle, buffer, (size_t) chunk_size),
+ if (status = safe_read (diff_handle, buffer, chunk_size),
status != chunk_size)
{
if (status < 0)
{
- WARN ((0, errno, _("Cannot read %s"), current_file_name));
+ read_error (current_stat_info.file_name);
report_difference (NULL);
}
else
{
- char message[MESSAGE_BUFFER_SIZE];
-
- sprintf (message, _("Could only read %d of %ld bytes"),
- status, chunk_size);
- report_difference (message);
+ report_difference (ngettext ("Could only read %lu of %lu byte",
+ "Could only read %lu of %lu bytes",
+ chunk_size),
+ (unsigned long) status,
+ (unsigned long) chunk_size);
}
break;
}
- if (memcmp (buffer, data_block->buffer, (size_t) chunk_size))
+ if (memcmp (buffer, data_block->buffer, chunk_size))
{
different = 1;
break;
amount_read = 0;
set_next_block_after (data_block);
data_block = find_next_block ();
+ if (!data_block)
+ FATAL_ERROR ((0, 0, _("Unexpected EOF in archive")));
}
#endif
set_next_block_after (data_block);
/* If the number of bytes read isn't the number of bytes supposedly in
the file, they're different. */
- if (amount_read != size_of_file)
+ if (amount_read != current_stat_info.stat.st_size)
different = 1;
#endif
free (sparsearray);
if (different)
- report_difference (_("Data differs"));
+ report_difference (_("Contents differ"));
}
-/*---------------------------------------------------------------------.
-| Call either stat or lstat over STAT_DATA, depending on --dereference |
-| (-h), for a file which should exist. Diagnose any problem. Return |
-| nonzero for success, zero otherwise. |
-`---------------------------------------------------------------------*/
-
+/* Call either stat or lstat over STAT_DATA, depending on
+ --dereference (-h), for a file which should exist. Diagnose any
+ problem. Return nonzero for success, zero otherwise. */
static int
-get_stat_data (struct stat *stat_data)
+get_stat_data (char const *file_name, struct stat *stat_data)
{
- int status = (dereference_option
- ? stat (current_file_name, stat_data)
- : lstat (current_file_name, stat_data));
+ int status = deref_stat (dereference_option, file_name, stat_data);
- if (status < 0)
+ if (status != 0)
{
if (errno == ENOENT)
- report_difference (_("File does not exist"));
+ stat_warn (file_name);
else
- {
- ERROR ((0, errno, _("Cannot stat file %s"), current_file_name));
- report_difference (NULL);
- }
-#if 0
- skip_file ((long) current_stat.st_size);
-#endif
+ stat_error (file_name);
+ report_difference (NULL);
return 0;
}
return 1;
}
-/*----------------------------------.
-| Diff a file against the archive. |
-`----------------------------------*/
-
+/* Diff a file against the archive. */
void
diff_archive (void)
{
struct stat stat_data;
- int name_length;
int status;
-
- errno = EPIPE; /* FIXME: errno should be read-only */
- /* FIXME: remove perrors */
+ struct utimbuf restore_times;
set_next_block_after (current_header);
- decode_header (current_header, ¤t_stat, ¤t_format, 1);
+ decode_header (current_header, ¤t_stat_info, ¤t_format, 1);
- /* Print the block from `current_header' and `current_stat'. */
+ /* Print the block from current_header and current_stat_info. */
if (verbose_option)
{
if (now_verifying)
fprintf (stdlis, _("Verify "));
- print_header ();
+ print_header (-1);
}
switch (current_header->header.typeflag)
{
default:
- WARN ((0, 0, _("Unknown file type '%c' for %s, diffed as normal file"),
- current_header->header.typeflag, current_file_name));
+ ERROR ((0, 0, _("%s: Unknown file type '%c', diffed as normal file"),
+ quotearg_colon (current_stat_info.file_name),
+ current_header->header.typeflag));
/* Fall through. */
case AREGTYPE:
/* Appears to be a file. See if it's really a directory. */
- name_length = strlen (current_file_name) - 1;
- if (current_file_name[name_length] == '/')
+ if (current_stat_info.had_trailing_slash)
goto really_dir;
- if (!get_stat_data (&stat_data))
+ if (!get_stat_data (current_stat_info.file_name, &stat_data))
{
- if (current_header->oldgnu_header.isextended)
- skip_extended_headers ();
- skip_file ((long) current_stat.st_size);
+ skip_member ();
goto quit;
}
if (!S_ISREG (stat_data.st_mode))
{
- report_difference (_("Not a regular file"));
- skip_file ((long) current_stat.st_size);
+ report_difference (_("File type differs"));
+ skip_member ();
goto quit;
}
- stat_data.st_mode &= 07777;
- if (stat_data.st_mode != current_stat.st_mode)
+ if ((current_stat_info.stat.st_mode & MODE_ALL) != (stat_data.st_mode & MODE_ALL))
report_difference (_("Mode differs"));
-#if !MSDOS
- /* stat() in djgpp's C library gives a constant number of 42 as the
- uid and gid of a file. So, comparing an FTP'ed archive just after
- unpack would fail on MSDOS. */
- if (stat_data.st_uid != current_stat.st_uid)
- report_difference (_("Uid differs"));
- if (stat_data.st_gid != current_stat.st_gid)
- report_difference (_("Gid differs"));
-#endif
+ sys_compare_uid_gid (&stat_data, ¤t_stat_info.stat);
- if (stat_data.st_mtime != current_stat.st_mtime)
+ if (stat_data.st_mtime != current_stat_info.stat.st_mtime)
report_difference (_("Mod time differs"));
if (current_header->header.typeflag != GNUTYPE_SPARSE &&
- stat_data.st_size != current_stat.st_size)
+ stat_data.st_size != current_stat_info.stat.st_size)
{
report_difference (_("Size differs"));
- skip_file ((long) current_stat.st_size);
+ skip_member ();
goto quit;
}
- diff_handle = open (current_file_name, O_NDELAY | O_RDONLY | O_BINARY);
-
- if (diff_handle < 0 && !absolute_names_option)
- {
- char *tmpbuf = xmalloc (strlen (current_file_name) + 2);
+ diff_handle = open (current_stat_info.file_name, O_RDONLY | O_BINARY);
- *tmpbuf = '/';
- strcpy (tmpbuf + 1, current_file_name);
- diff_handle = open (tmpbuf, O_NDELAY | O_RDONLY);
- free (tmpbuf);
- }
if (diff_handle < 0)
{
- ERROR ((0, errno, _("Cannot open %s"), current_file_name));
- if (current_header->oldgnu_header.isextended)
- skip_extended_headers ();
- skip_file ((long) current_stat.st_size);
+ open_error (current_stat_info.file_name);
+ skip_member ();
report_difference (NULL);
goto quit;
}
+ restore_times.actime = stat_data.st_atime;
+ restore_times.modtime = stat_data.st_mtime;
+
/* Need to treat sparse files completely differently here. */
if (current_header->header.typeflag == GNUTYPE_SPARSE)
- diff_sparse_files (current_stat.st_size);
+ diff_sparse_files ();
else
{
if (multi_volume_option)
{
- assign_string (&save_name, current_file_name);
- save_totsize = current_stat.st_size;
+ assign_string (&save_name, current_stat_info.file_name);
+ save_totsize = current_stat_info.stat.st_size;
/* save_sizeleft is set in read_and_process. */
}
- read_and_process ((long) (current_stat.st_size), process_rawdata);
+ read_and_process (current_stat_info.stat.st_size, process_rawdata);
if (multi_volume_option)
- assign_string (&save_name, NULL);
+ assign_string (&save_name, 0);
}
status = close (diff_handle);
- if (status < 0)
- ERROR ((0, errno, _("Error while closing %s"), current_file_name));
+ if (status != 0)
+ close_error (current_stat_info.file_name);
+
+ if (atime_preserve_option)
+ utime (current_stat_info.file_name, &restore_times);
quit:
break;
-#if !MSDOS
case LNKTYPE:
{
- dev_t dev;
- ino_t ino;
+ struct stat link_data, stat_data;
- if (!get_stat_data (&stat_data))
+ if (!get_stat_data (current_stat_info.file_name, &stat_data))
break;
-
- dev = stat_data.st_dev;
- ino = stat_data.st_ino;
- status = stat (current_link_name, &stat_data);
- if (status < 0)
- {
- if (errno == ENOENT)
- report_difference (_("Does not exist"));
- else
- {
- WARN ((0, errno, _("Cannot stat file %s"), current_file_name));
- report_difference (NULL);
- }
- break;
- }
-
- if (stat_data.st_dev != dev || stat_data.st_ino != ino)
- {
- char *message = (char *)
- xmalloc (MESSAGE_BUFFER_SIZE + strlen (current_link_name));
-
- sprintf (message, _("Not linked to %s"), current_link_name);
- report_difference (message);
- free (message);
- break;
- }
-
- break;
+ if (!get_stat_data (current_stat_info.link_name, &link_data))
+ break;
+ sys_compare_links (&stat_data, &link_data);
}
-#endif /* not MSDOS */
-
-#ifdef S_ISLNK
+ break;
+
+#ifdef HAVE_READLINK
case SYMTYPE:
{
- char linkbuf[NAME_FIELD_SIZE + 3]; /* FIXME: may be too short. */
+ size_t len = strlen (current_stat_info.link_name);
+ char *linkbuf = alloca (len + 1);
- status = readlink (current_file_name, linkbuf, (sizeof linkbuf) - 1);
+ status = readlink (current_stat_info.file_name, linkbuf, len + 1);
if (status < 0)
{
if (errno == ENOENT)
- report_difference (_("No such file or directory"));
+ readlink_warn (current_stat_info.file_name);
else
- {
- WARN ((0, errno, _("Cannot read link %s"), current_file_name));
- report_difference (NULL);
- }
- break;
+ readlink_error (current_stat_info.file_name);
+ report_difference (NULL);
}
-
- linkbuf[status] = '\0'; /* null-terminate it */
- if (strncmp (current_link_name, linkbuf, (size_t) status) != 0)
+ else if (status != len
+ || strncmp (current_stat_info.link_name, linkbuf, len) != 0)
report_difference (_("Symlink differs"));
break;
}
-#endif /* not S_ISLNK */
+#endif
-#ifdef S_IFCHR
case CHRTYPE:
- current_stat.st_mode |= S_IFCHR;
- goto check_node;
-#endif /* not S_IFCHR */
-
-#ifdef S_IFBLK
- /* If local system doesn't support block devices, use default case. */
-
case BLKTYPE:
- current_stat.st_mode |= S_IFBLK;
- goto check_node;
-#endif /* not S_IFBLK */
-
-#ifdef S_ISFIFO
- /* If local system doesn't support FIFOs, use default case. */
-
case FIFOTYPE:
-# ifdef S_IFIFO
- current_stat.st_mode |= S_IFIFO;
-# endif
- current_stat.st_rdev = 0; /* FIXME: do we need this? */
- goto check_node;
-#endif /* S_ISFIFO */
-
- check_node:
+
/* FIXME: deal with umask. */
- if (!get_stat_data (&stat_data))
+ if (!get_stat_data (current_stat_info.file_name, &stat_data))
break;
- if (current_stat.st_rdev != stat_data.st_rdev)
+ if (current_header->header.typeflag == CHRTYPE
+ ? !S_ISCHR (stat_data.st_mode)
+ : current_header->header.typeflag == BLKTYPE
+ ? !S_ISBLK (stat_data.st_mode)
+ : /* current_header->header.typeflag == FIFOTYPE */
+ !S_ISFIFO (stat_data.st_mode))
{
- report_difference (_("Device numbers changed"));
+ report_difference (_("File type differs"));
break;
}
- if (
-#ifdef S_IFMT
- current_stat.st_mode != stat_data.st_mode
-#else
- /* POSIX lossage. */
- (current_stat.st_mode & 07777) != (stat_data.st_mode & 07777)
-#endif
- )
+ if ((current_header->header.typeflag == CHRTYPE
+ || current_header->header.typeflag == BLKTYPE)
+ && current_stat_info.stat.st_rdev != stat_data.st_rdev)
{
- report_difference (_("Mode or device-type changed"));
+ report_difference (_("Device number differs"));
+ break;
+ }
+
+ if ((current_stat_info.stat.st_mode & MODE_ALL) != (stat_data.st_mode & MODE_ALL))
+ {
+ report_difference (_("Mode differs"));
break;
}
case GNUTYPE_DUMPDIR:
{
- char *dumpdir_buffer = get_directory_contents (current_file_name, 0);
+ char *dumpdir_buffer = get_directory_contents (current_stat_info.file_name, 0);
if (multi_volume_option)
{
- assign_string (&save_name, current_file_name);
- save_totsize = current_stat.st_size;
+ assign_string (&save_name, current_stat_info.file_name);
+ save_totsize = current_stat_info.stat.st_size;
/* save_sizeleft is set in read_and_process. */
}
if (dumpdir_buffer)
{
dumpdir_cursor = dumpdir_buffer;
- read_and_process ((long) (current_stat.st_size), process_dumpdir);
+ read_and_process (current_stat_info.stat.st_size, process_dumpdir);
free (dumpdir_buffer);
}
else
- read_and_process ((long) (current_stat.st_size), process_noop);
+ read_and_process (current_stat_info.stat.st_size, process_noop);
if (multi_volume_option)
- assign_string (&save_name, NULL);
+ assign_string (&save_name, 0);
/* Fall through. */
}
case DIRTYPE:
- /* Check for trailing /. */
-
- name_length = strlen (current_file_name) - 1;
-
really_dir:
- while (name_length && current_file_name[name_length] == '/')
- current_file_name[name_length--] = '\0'; /* zap / */
-
- if (!get_stat_data (&stat_data))
+ if (!get_stat_data (current_stat_info.file_name, &stat_data))
break;
if (!S_ISDIR (stat_data.st_mode))
{
- report_difference (_("No longer a directory"));
+ report_difference (_("File type differs"));
+ break;
+ }
+
+ if ((current_stat_info.stat.st_mode & MODE_ALL) != (stat_data.st_mode & MODE_ALL))
+ {
+ report_difference (_("Mode differs"));
break;
}
- if ((stat_data.st_mode & 07777) != (current_stat.st_mode & 07777))
- report_difference (_("Mode differs"));
break;
case GNUTYPE_VOLHDR:
{
off_t offset;
- name_length = strlen (current_file_name) - 1;
- if (current_file_name[name_length] == '/')
+ if (current_stat_info.had_trailing_slash)
goto really_dir;
- if (!get_stat_data (&stat_data))
+ if (!get_stat_data (current_stat_info.file_name, &stat_data))
break;
if (!S_ISREG (stat_data.st_mode))
{
- report_difference (_("Not a regular file"));
- skip_file ((long) current_stat.st_size);
+ report_difference (_("File type differs"));
+ skip_member ();
break;
}
- stat_data.st_mode &= 07777;
- offset = from_oct (1 + 12, current_header->oldgnu_header.offset);
- if (stat_data.st_size != current_stat.st_size + offset)
+ offset = OFF_FROM_HEADER (current_header->oldgnu_header.offset);
+ if (stat_data.st_size != current_stat_info.stat.st_size + offset)
{
report_difference (_("Size differs"));
- skip_file ((long) current_stat.st_size);
+ skip_member ();
break;
}
- diff_handle = open (current_file_name, O_NDELAY | O_RDONLY | O_BINARY);
+ diff_handle = open (current_stat_info.file_name, O_RDONLY | O_BINARY);
if (diff_handle < 0)
{
- WARN ((0, errno, _("Cannot open file %s"), current_file_name));
+ open_error (current_stat_info.file_name);
report_difference (NULL);
- skip_file ((long) current_stat.st_size);
+ skip_member ();
break;
}
- status = lseek (diff_handle, offset, 0);
- if (status != offset)
+ if (lseek (diff_handle, offset, SEEK_SET) < 0)
{
- WARN ((0, errno, _("Cannot seek to %ld in file %s"),
- offset, current_file_name));
+ seek_error_details (current_stat_info.file_name, offset);
report_difference (NULL);
break;
}
if (multi_volume_option)
{
- assign_string (&save_name, current_file_name);
+ assign_string (&save_name, current_stat_info.file_name);
save_totsize = stat_data.st_size;
/* save_sizeleft is set in read_and_process. */
}
- read_and_process ((long) (current_stat.st_size), process_rawdata);
+ read_and_process (current_stat_info.stat.st_size, process_rawdata);
if (multi_volume_option)
- assign_string (&save_name, NULL);
+ assign_string (&save_name, 0);
status = close (diff_handle);
- if (status < 0)
- ERROR ((0, errno, _("Error while closing %s"), current_file_name));
+ if (status != 0)
+ close_error (current_stat_info.file_name);
break;
}
}
}
-/*---.
-| ? |
-`---*/
-
void
verify_volume (void)
{
status < 0))
{
#endif
- if (rmtlseek (archive, 0L, 0) != 0)
+ if (rmtlseek (archive, (off_t) 0, SEEK_SET) != 0)
{
/* Lseek failed. Try a different method. */
-
- WARN ((0, errno,
- _("Could not rewind archive file for verify")));
+ seek_warn (archive_name_array[0]);
return;
}
#ifdef MTIOCTOP
flush_read ();
while (1)
{
- enum read_header status = read_header ();
+ enum read_header status = read_header (false);
if (status == HEADER_FAILURE)
{
int counter = 0;
- while (status == HEADER_FAILURE);
+ do
{
counter++;
- status = read_header ();
+ status = read_header (false);
}
+ while (status == HEADER_FAILURE);
+
ERROR ((0, 0,
- _("VERIFY FAILURE: %d invalid header(s) detected"), counter));
+ ngettext ("VERIFY FAILURE: %d invalid header detected",
+ "VERIFY FAILURE: %d invalid headers detected",
+ counter), counter));
}
if (status == HEADER_ZERO_BLOCK || status == HEADER_END_OF_FILE)
break;