X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=src%2Fcompare.c;h=e93ccb0a2ccd49c23f88d4bcb6ce29e8344ca06d;hb=2433f6813ec6a0c00e6c49b8f38725cd4a78c66c;hp=9191364f05019bf243cf0bd3194b5008dbe4fe44;hpb=c1b9212b16a53da408548efa3f9c8b1a62335b42;p=chaz%2Ftar diff --git a/src/compare.c b/src/compare.c index 9191364..e93ccb0 100644 --- a/src/compare.c +++ b/src/compare.c @@ -1,7 +1,7 @@ /* Diff files from a tar archive. Copyright (C) 1988, 1992, 1993, 1994, 1996, 1997, 1999, 2000, 2001, - 2003 Free Software Foundation, Inc. + 2003, 2004 Free Software Foundation, Inc. Written by John Gilmore, on 1987-04-30. @@ -19,7 +19,7 @@ with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include "system.h" +#include #if HAVE_UTIME_H # include @@ -38,7 +38,7 @@ struct utimbuf #include #include "common.h" -#include "rmt.h" +#include #include /* Nonzero if we are verifying at the moment. */ @@ -54,15 +54,15 @@ static char *diff_buffer; void diff_init (void) { - diff_buffer = valloc (record_size); - if (!diff_buffer) - xalloc_die (); + void *ptr; + diff_buffer = page_aligned_alloc (&ptr, record_size); } /* 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, ...) +report_difference (struct tar_stat_info *st __attribute__ ((unused)), + const char *fmt, ...) { if (fmt) { @@ -74,35 +74,35 @@ report_difference (const char *fmt, ...) va_end (ap); fprintf (stdlis, "\n"); } - + if (exit_status == TAREXIT_SUCCESS) exit_status = TAREXIT_DIFFERS; } /* Take a buffer returned by read_and_process and do nothing with it. */ static int -process_noop (size_t size, char *data) +process_noop (size_t size __attribute__ ((unused)), + char *data __attribute__ ((unused))) { - /* 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 (size_t bytes, char *buffer) { - ssize_t status = safe_read (diff_handle, diff_buffer, bytes); + size_t status = safe_read (diff_handle, diff_buffer, bytes); if (status != bytes) { - if (status < 0) + if (status == SAFE_READ_ERROR) { read_error (current_stat_info.file_name); - report_difference (NULL); + report_difference (¤t_stat_info, NULL); } else { - report_difference (ngettext ("Could only read %lu of %lu byte", + report_difference (¤t_stat_info, + ngettext ("Could only read %lu of %lu byte", "Could only read %lu of %lu bytes", bytes), (unsigned long) status, (unsigned long) bytes); @@ -112,7 +112,8 @@ process_rawdata (size_t bytes, char *buffer) if (memcmp (buffer, diff_buffer, bytes)) { - report_difference (_("Contents differ")); + report_difference (¤t_stat_info, + _("Contents differ")); return 0; } @@ -128,7 +129,7 @@ process_dumpdir (size_t bytes, char *buffer) { if (memcmp (buffer, dumpdir_cursor, bytes)) { - report_difference (_("Contents differ")); + report_difference (¤t_stat_info, _("Contents differ")); return 0; } @@ -171,152 +172,6 @@ read_and_process (off_t size, int (*processor) (size_t, char *)) } } -/* 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 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. */ - -/* FIXME: This does not look very solid to me, at first glance. Zero areas - are not checked, spurious sparse entries seemingly goes undetected, and - I'm not sure overall identical sparsity is verified. */ - -static void -diff_sparse_files (void) -{ - 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; - - if (! fill_in_sparse_array ()) - fatal_exit (); - - while (remaining_size > 0) - { - ssize_t status; - size_t chunk_size; - off_t offset; - -#if 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; - - 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 = xrealloc (buffer, buffer_size * sizeof (char)); - } - - while (chunk_size > BLOCKSIZE) - { - if (status = safe_read (diff_handle, buffer, BLOCKSIZE), - status != BLOCKSIZE) - { - if (status < 0) - { - read_error (current_stat_info.file_name); - report_difference (NULL); - } - else - { - 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, BLOCKSIZE)) - { - different = 1; - break; - } - - chunk_size -= status; - 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 = safe_read (diff_handle, buffer, chunk_size), - status != chunk_size) - { - if (status < 0) - { - read_error (current_stat_info.file_name); - report_difference (NULL); - } - else - { - 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, chunk_size)) - { - different = 1; - break; - } -#if 0 - amount_read += chunk_size; - if (amount_read >= BLOCKSIZE) - { - 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); - counter++; - remaining_size -= chunk_size; - } - -#if 0 - /* If the number of bytes read isn't the number of bytes supposedly in - the file, they're different. */ - - if (amount_read != current_stat_info.stat.st_size) - different = 1; -#endif - - set_next_block_after (data_block); - free (sparsearray); - - if (different) - 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. */ @@ -331,7 +186,7 @@ get_stat_data (char const *file_name, struct stat *stat_data) stat_warn (file_name); else stat_error (file_name); - report_difference (NULL); + report_difference (¤t_stat_info, NULL); return 0; } @@ -355,7 +210,7 @@ diff_archive (void) { if (now_verifying) fprintf (stdlis, _("Verify ")); - print_header (-1); + print_header (¤t_stat_info, -1); } switch (current_header->header.typeflag) @@ -384,22 +239,26 @@ diff_archive (void) if (!S_ISREG (stat_data.st_mode)) { - report_difference (_("File type differs")); + report_difference (¤t_stat_info, _("File type differs")); skip_member (); goto quit; } - if ((current_stat_info.stat.st_mode & MODE_ALL) != (stat_data.st_mode & MODE_ALL)) - report_difference (_("Mode differs")); + if ((current_stat_info.stat.st_mode & MODE_ALL) != + (stat_data.st_mode & MODE_ALL)) + report_difference (¤t_stat_info, _("Mode differs")); - sys_compare_uid_gid (&stat_data, ¤t_stat_info.stat); + if (!sys_compare_uid (&stat_data, ¤t_stat_info.stat)) + report_difference (¤t_stat_info, _("Uid differs")); + if (!sys_compare_gid (&stat_data, ¤t_stat_info.stat)) + report_difference (¤t_stat_info, _("Gid differs")); if (stat_data.st_mtime != current_stat_info.stat.st_mtime) - report_difference (_("Mod time differs")); + report_difference (¤t_stat_info, _("Mod time differs")); if (current_header->header.typeflag != GNUTYPE_SPARSE && stat_data.st_size != current_stat_info.stat.st_size) { - report_difference (_("Size differs")); + report_difference (¤t_stat_info, _("Size differs")); skip_member (); goto quit; } @@ -410,7 +269,7 @@ diff_archive (void) { open_error (current_stat_info.file_name); skip_member (); - report_difference (NULL); + report_difference (¤t_stat_info, NULL); goto quit; } @@ -419,8 +278,8 @@ diff_archive (void) /* Need to treat sparse files completely differently here. */ - if (current_header->header.typeflag == GNUTYPE_SPARSE) - diff_sparse_files (); + if (current_stat_info.is_sparse) + sparse_diff_file (diff_handle, ¤t_stat_info); else { if (multi_volume_option) @@ -448,16 +307,20 @@ diff_archive (void) case LNKTYPE: { - struct stat link_data, stat_data; + struct stat file_data; + struct stat link_data; - if (!get_stat_data (current_stat_info.file_name, &stat_data)) + if (!get_stat_data (current_stat_info.file_name, &file_data)) break; if (!get_stat_data (current_stat_info.link_name, &link_data)) break; - sys_compare_links (&stat_data, &link_data); + if (!sys_compare_links (&file_data, &link_data)) + report_difference (¤t_stat_info, + _("Not linked to %s"), + quote (current_stat_info.link_name)); } break; - + #ifdef HAVE_READLINK case SYMTYPE: { @@ -472,11 +335,11 @@ diff_archive (void) readlink_warn (current_stat_info.file_name); else readlink_error (current_stat_info.file_name); - report_difference (NULL); + report_difference (¤t_stat_info, NULL); } else if (status != len || strncmp (current_stat_info.link_name, linkbuf, len) != 0) - report_difference (_("Symlink differs")); + report_difference (¤t_stat_info, _("Symlink differs")); break; } @@ -498,7 +361,7 @@ diff_archive (void) : /* current_header->header.typeflag == FIFOTYPE */ !S_ISFIFO (stat_data.st_mode)) { - report_difference (_("File type differs")); + report_difference (¤t_stat_info, _("File type differs")); break; } @@ -506,13 +369,13 @@ diff_archive (void) || current_header->header.typeflag == BLKTYPE) && current_stat_info.stat.st_rdev != stat_data.st_rdev) { - report_difference (_("Device number differs")); + report_difference (¤t_stat_info, _("Device number differs")); break; } if ((current_stat_info.stat.st_mode & MODE_ALL) != (stat_data.st_mode & MODE_ALL)) { - report_difference (_("Mode differs")); + report_difference (¤t_stat_info, _("Mode differs")); break; } @@ -550,13 +413,13 @@ diff_archive (void) if (!S_ISDIR (stat_data.st_mode)) { - report_difference (_("File type differs")); + report_difference (¤t_stat_info, _("File type differs")); break; } if ((current_stat_info.stat.st_mode & MODE_ALL) != (stat_data.st_mode & MODE_ALL)) { - report_difference (_("Mode differs")); + report_difference (¤t_stat_info, _("Mode differs")); break; } @@ -577,7 +440,7 @@ diff_archive (void) if (!S_ISREG (stat_data.st_mode)) { - report_difference (_("File type differs")); + report_difference (¤t_stat_info, _("File type differs")); skip_member (); break; } @@ -585,7 +448,7 @@ diff_archive (void) 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")); + report_difference (¤t_stat_info, _("Size differs")); skip_member (); break; } @@ -595,7 +458,7 @@ diff_archive (void) if (diff_handle < 0) { open_error (current_stat_info.file_name); - report_difference (NULL); + report_difference (¤t_stat_info, NULL); skip_member (); break; } @@ -603,7 +466,7 @@ diff_archive (void) if (lseek (diff_handle, offset, SEEK_SET) < 0) { seek_error_details (current_stat_info.file_name, offset); - report_difference (NULL); + report_difference (¤t_stat_info, NULL); break; } @@ -631,6 +494,14 @@ diff_archive (void) void verify_volume (void) { + if (removed_prefixes_p ()) + { + WARN((0, 0, + _("Archive contains file names with leading prefixes removed."))); + WARN((0, 0, + _("Verification may fail to locate original files."))); + } + if (!diff_buffer) diff_init (); @@ -692,6 +563,7 @@ verify_volume (void) do { counter++; + set_next_block_after (current_header); status = read_header (false); } while (status == HEADER_FAILURE); @@ -705,6 +577,8 @@ verify_volume (void) break; diff_archive (); + tar_stat_destroy (¤t_stat_info); + xheader_destroy (&extended_header); } access_mode = ACCESS_WRITE;