cherry-pick an upstream patch to fix --compare issues
[debian/tar] / debian / patches / upstream-compare-fix
1 From d88b2a613f4b1a5554e8c34c8f75b91abff5f0e9 Mon Sep 17 00:00:00 2001
2 From: Sergey Poznyakoff <gray@gnu.org.ua>
3 Date: Tue, 15 Nov 2011 10:58:32 +0000
4 Subject: Fix operation of --verify in conjunction with --listed-incremental
5
6 * src/common.h (clear_directory_table): New proto.
7 * src/incremen.c (clear_directory_table): New function.
8 * src/compare.c (diff_dumpdir): Take a pointer to struct
9 tar_stat_info as argument.
10 Initialize its fd.
11 (diff_archive): Update call to diff_dumpdir.
12 (verify_volume): Call clear_directory_table.
13 ---
14 diff --git a/src/common.h b/src/common.h
15 index 0b9bd7a..6074ac3 100644
16 --- a/src/common.h
17 +++ b/src/common.h
18 @@ -522,6 +522,7 @@ void update_parent_directory (struct tar_stat_info *st);
19  
20  size_t dumpdir_size (const char *p);
21  bool is_dumpdir (struct tar_stat_info *stat_info);
22 +void clear_directory_table (void);
23  
24  /* Module list.c.  */
25  
26 diff --git a/src/compare.c b/src/compare.c
27 index 273269a..185a61a 100644
28 --- a/src/compare.c
29 +++ b/src/compare.c
30 @@ -359,31 +359,47 @@ dumpdir_cmp (const char *a, const char *b)
31  }
32  
33  static void
34 -diff_dumpdir (void)
35 +diff_dumpdir (struct tar_stat_info *dir)
36  {
37    const char *dumpdir_buffer;
38    dev_t dev = 0;
39    struct stat stat_data;
40  
41 -  if (deref_stat (current_stat_info.file_name, &stat_data) != 0)
42 +  if (deref_stat (dir->file_name, &stat_data) != 0)
43      {
44        if (errno == ENOENT)
45 -       stat_warn (current_stat_info.file_name);
46 +       stat_warn (dir->file_name);
47        else
48 -       stat_error (current_stat_info.file_name);
49 +       stat_error (dir->file_name);
50      }
51    else
52      dev = stat_data.st_dev;
53  
54 -  dumpdir_buffer = directory_contents (scan_directory (&current_stat_info));
55 +  if (dir->fd == 0)
56 +    {
57 +      void (*diag) (char const *) = NULL;
58 +      int fd = subfile_open (dir->parent, dir->orig_file_name, open_read_flags);
59 +      if (fd < 0)
60 +       diag = open_diag;
61 +      else if (fstat (fd, &dir->stat))
62 +       diag = stat_diag;
63 +      else
64 +       dir->fd = fd;
65 +      if (diag)
66 +       {
67 +         file_removed_diag (dir->orig_file_name, false, diag);
68 +         return;
69 +       }
70 +    }      
71 +  dumpdir_buffer = directory_contents (scan_directory (dir));
72  
73    if (dumpdir_buffer)
74      {
75 -      if (dumpdir_cmp (current_stat_info.dumpdir, dumpdir_buffer))
76 -       report_difference (&current_stat_info, _("Contents differ"));
77 +      if (dumpdir_cmp (dir->dumpdir, dumpdir_buffer))
78 +       report_difference (dir, _("Contents differ"));
79      }
80    else
81 -    read_and_process (&current_stat_info, process_noop);
82 +    read_and_process (dir, process_noop);
83  }
84  
85  static void
86 @@ -446,7 +462,7 @@ diff_multivol (void)
87  void
88  diff_archive (void)
89  {
90 -
91 +  
92    set_next_block_after (current_header);
93  
94    /* Print the block from current_header and current_stat_info.  */
95 @@ -498,7 +514,7 @@ diff_archive (void)
96      case GNUTYPE_DUMPDIR:
97      case DIRTYPE:
98        if (is_dumpdir (&current_stat_info))
99 -       diff_dumpdir ();
100 +       diff_dumpdir (&current_stat_info);
101        diff_dir ();
102        break;
103  
104 @@ -530,6 +546,8 @@ verify_volume (void)
105      WARN((0, 0,
106           _("Verification may fail to locate original files.")));
107  
108 +  clear_directory_table ();
109 +  
110    if (!diff_buffer)
111      diff_init ();
112  
113 diff --git a/src/incremen.c b/src/incremen.c
114 index b2ab5bf..69cbd59 100644
115 --- a/src/incremen.c
116 +++ b/src/incremen.c
117 @@ -300,6 +300,24 @@ dirlist_replace_prefix (const char *pref, const char *repl)
118      replace_prefix (&dp->name, pref, pref_len, repl, repl_len);
119  }
120  
121 +void
122 +clear_directory_table (void)
123 +{
124 +  struct directory *dp;
125 +
126 +  if (directory_table)
127 +    hash_clear (directory_table);
128 +  if (directory_meta_table)
129 +    hash_clear (directory_meta_table);
130 +  for (dp = dirhead; dp; )
131 +    {
132 +      struct directory *next = dp->next;
133 +      free_directory (dp);
134 +      dp = next;
135 +    }
136 +  dirhead = dirtail = NULL;
137 +}
138 +
139  /* Create and link a new directory entry for directory NAME, having a
140     device number DEV and an inode number INO, with NFS indicating
141     whether it is an NFS device and FOUND indicating whether we have
142 @@ -327,7 +345,8 @@ note_directory (char const *name, struct timespec mtime,
143    if (! ((directory_table
144           || (directory_table = hash_initialize (0, 0,
145                                                  hash_directory_canonical_name,
146 -                                                compare_directory_canonical_names, 0)))
147 +                                                compare_directory_canonical_names,
148 +                                                0)))
149          && hash_insert (directory_table, directory)))
150      xalloc_die ();
151