X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=src%2Fcompare.c;h=c23601d97e400a26dd3658b3019d6d6ece10d3fa;hb=8ad985ea6c89f2bb21d4655973ebdb542f7bb39a;hp=0ad12233c9b3d2ec85eb882bb756eaf40d13d779;hpb=120e96c480fbfc5fa31fba0f59ba1a45953b838e;p=chaz%2Ftar diff --git a/src/compare.c b/src/compare.c index 0ad1223..c23601d 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, 2004 Free Software Foundation, Inc. + 2003, 2004, 2005, 2006 Free Software Foundation, Inc. Written by John Gilmore, on 1987-04-30. @@ -20,24 +20,14 @@ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include - -#if HAVE_UTIME_H -# include -#else -struct utimbuf - { - long actime; - long modtime; - }; -#endif +#include #if HAVE_LINUX_FD_H # include #endif -#include - #include "common.h" +#include #include #include @@ -63,14 +53,13 @@ diff_init (void) /* 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 (struct tar_stat_info *st __attribute__ ((unused)), - const char *fmt, ...) +report_difference (struct tar_stat_info *st, const char *fmt, ...) { if (fmt) { va_list ap; - fprintf (stdlis, "%s: ", quotearg_colon (current_stat_info.file_name)); + fprintf (stdlis, "%s: ", quotearg_colon (st->file_name)); va_start (ap, fmt); vfprintf (stdlis, fmt, ap); va_end (ap); @@ -143,14 +132,15 @@ process_dumpdir (size_t bytes, char *buffer) 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 (off_t size, int (*processor) (size_t, char *)) +read_and_process (struct tar_stat_info *st, int (*processor) (size_t, char *)) { union block *data_block; size_t data_size; + size_t size = st->stat.st_size; - if (multi_volume_option) - save_sizeleft = size; + mv_begin (st); while (size) { data_block = find_next_block (); @@ -168,9 +158,9 @@ read_and_process (off_t size, int (*processor) (size_t, char *)) set_next_block_after ((union block *) (data_block->buffer + data_size - 1)); size -= data_size; - if (multi_volume_option) - save_sizeleft -= data_size; + mv_size_left (size); } + mv_end (); } /* Call either stat or lstat over STAT_DATA, depending on @@ -196,7 +186,7 @@ get_stat_data (char const *file_name, struct stat *stat_data) static void -diff_dir () +diff_dir (void) { struct stat stat_data; @@ -211,11 +201,12 @@ diff_dir () } static void -diff_file () +diff_file (void) { + char const *file_name = current_stat_info.file_name; struct stat stat_data; - if (!get_stat_data (current_stat_info.file_name, &stat_data)) + if (!get_stat_data (file_name, &stat_data)) skip_member (); else if (!S_ISREG (stat_data.st_mode)) { @@ -233,64 +224,58 @@ diff_file () 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) + if (tar_timespec_cmp (get_stat_mtime (&stat_data), + current_stat_info.mtime)) 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) + if (current_header->header.typeflag != GNUTYPE_SPARSE + && stat_data.st_size != current_stat_info.stat.st_size) { report_difference (¤t_stat_info, _("Size differs")); skip_member (); } else { - diff_handle = open (current_stat_info.file_name, O_RDONLY | O_BINARY); + int atime_flag = + (atime_preserve_option == system_atime_preserve + ? O_NOATIME + : 0); + + diff_handle = open (file_name, O_RDONLY | O_BINARY | atime_flag); if (diff_handle < 0) { - open_error (current_stat_info.file_name); + open_error (file_name); skip_member (); report_difference (¤t_stat_info, NULL); } else { int status; - struct utimbuf restore_times; - - restore_times.actime = stat_data.st_atime; - restore_times.modtime = stat_data.st_mtime; if (current_stat_info.is_sparse) sparse_diff_file (diff_handle, ¤t_stat_info); else + read_and_process (¤t_stat_info, process_rawdata); + + if (atime_preserve_option == replace_atime_preserve) { - if (multi_volume_option) - { - assign_string (&save_name, - current_stat_info.orig_file_name); - save_totsize = current_stat_info.stat.st_size; - /* save_sizeleft is set in read_and_process. */ - } - - read_and_process (current_stat_info.stat.st_size, - process_rawdata); - - if (multi_volume_option) - assign_string (&save_name, 0); + struct timespec ts[2]; + ts[0] = get_stat_atime (&stat_data); + ts[1] = get_stat_mtime (&stat_data); + if (set_file_atime (diff_handle, file_name, ts) != 0) + utime_error (file_name); } status = close (diff_handle); if (status != 0) - close_error (current_stat_info.file_name); - - if (atime_preserve_option) - utime (current_stat_info.file_name, &restore_times); + close_error (file_name); } } } } static void -diff_link () +diff_link (void) { struct stat file_data; struct stat link_data; @@ -305,7 +290,7 @@ diff_link () #ifdef HAVE_READLINK static void -diff_symlink () +diff_symlink (void) { size_t len = strlen (current_stat_info.link_name); char *linkbuf = alloca (len + 1); @@ -327,7 +312,7 @@ diff_symlink () #endif static void -diff_special () +diff_special (void) { struct stat stat_data; @@ -361,33 +346,36 @@ diff_special () } static void -diff_dumpdir () +diff_dumpdir (void) { - char *dumpdir_buffer = get_directory_contents (current_stat_info.file_name, - 0); + char *dumpdir_buffer; + dev_t dev = 0; + struct stat stat; - if (multi_volume_option) + if (deref_stat (true, current_stat_info.file_name, &stat)) { - assign_string (&save_name, current_stat_info.orig_file_name); - save_totsize = current_stat_info.stat.st_size; - /* save_sizeleft is set in read_and_process. */ + if (errno == ENOENT) + stat_warn (current_stat_info.file_name); + else + stat_error (current_stat_info.file_name); } + else + dev = stat.st_dev; + + dumpdir_buffer = get_directory_contents (current_stat_info.file_name, dev); if (dumpdir_buffer) { dumpdir_cursor = dumpdir_buffer; - read_and_process (current_stat_info.stat.st_size, process_dumpdir); + read_and_process (¤t_stat_info, process_dumpdir); free (dumpdir_buffer); } else - read_and_process (current_stat_info.stat.st_size, process_noop); - - if (multi_volume_option) - assign_string (&save_name, 0); + read_and_process (¤t_stat_info, process_noop); } static void -diff_multivol () +diff_multivol (void) { struct stat stat_data; int fd, status; @@ -398,7 +386,7 @@ diff_multivol () diff_dir (); return; } - + if (!get_stat_data (current_stat_info.file_name, &stat_data)) return; @@ -418,7 +406,7 @@ diff_multivol () } fd = open (current_stat_info.file_name, O_RDONLY | O_BINARY); - + if (fd < 0) { open_error (current_stat_info.file_name); @@ -434,18 +422,8 @@ diff_multivol () return; } - if (multi_volume_option) - { - assign_string (&save_name, current_stat_info.orig_file_name); - save_totsize = stat_data.st_size; - /* save_sizeleft is set in read_and_process. */ - } - - read_and_process (current_stat_info.stat.st_size, process_rawdata); + read_and_process (¤t_stat_info, process_rawdata); - if (multi_volume_option) - assign_string (&save_name, 0); - status = close (fd); if (status != 0) close_error (current_stat_info.file_name); @@ -498,7 +476,7 @@ diff_archive (void) diff_symlink (); break; #endif - + case CHRTYPE: case BLKTYPE: case FIFOTYPE: @@ -508,7 +486,7 @@ diff_archive (void) case GNUTYPE_DUMPDIR: diff_dumpdir (); /* Fall through. */ - + case DIRTYPE: diff_dir (); break;