AU: When checking if we've visited a file before, don't follow symlinks.
A bug caused a failure when a file existed on the old image that was a
symlink to a non-existent path. This CL fixes that bug.
BUG=chromium-os:12393
TEST=unittests/generated and tested a delta
Change-Id: Ifba711be2bfc3c1d96a4ed8536b16b5d7b8a0cae
Review URL: http://codereview.chromium.org/6551015
diff --git a/delta_diff_generator.cc b/delta_diff_generator.cc
index ccdf27a..a500054 100644
--- a/delta_diff_generator.cc
+++ b/delta_diff_generator.cc
@@ -149,6 +149,7 @@
for (FilesystemIterator fs_iter(new_root,
utils::SetWithValue<string>("/lost+found"));
!fs_iter.IsEnd(); fs_iter.Increment()) {
+ // We never diff symlinks (here, we check that dst file is not a symlink).
if (!S_ISREG(fs_iter.GetStat().st_mode))
continue;
@@ -169,11 +170,12 @@
// from using a graph/cycle detection/etc to generate diffs, and at that
// time, it will be easy (non-complex) to have many operations read
// from the same source blocks. At that time, this code can die. -adlr
- bool should_diff_from_source = true;
+ bool should_diff_from_source = false;
string src_path = old_root + fs_iter.GetPartialPath();
- if (utils::FileExists(src_path.c_str())) {
- struct stat src_stbuf;
- TEST_AND_RETURN_FALSE_ERRNO(0 == stat(src_path.c_str(), &src_stbuf));
+ struct stat src_stbuf;
+ // We never diff symlinks (here, we check that src file is not a symlink).
+ if (0 == lstat(src_path.c_str(), &src_stbuf) &&
+ S_ISREG(src_stbuf.st_mode)) {
should_diff_from_source = !utils::SetContainsKey(visited_src_inodes,
src_stbuf.st_ino);
visited_src_inodes.insert(src_stbuf.st_ino);
diff --git a/delta_performer_unittest.cc b/delta_performer_unittest.cc
index bf4dcc7..586d582 100755
--- a/delta_performer_unittest.cc
+++ b/delta_performer_unittest.cc
@@ -260,6 +260,9 @@
"mv %s/tmp %s/srchardlink1",
b_mnt.c_str(), b_mnt.c_str(),
b_mnt.c_str(), b_mnt.c_str()).c_str()));
+ EXPECT_EQ(0, system(StringPrintf("rm %s/boguslink && "
+ "echo foobar > %s/boguslink",
+ b_mnt.c_str(), b_mnt.c_str()).c_str()));
EXPECT_TRUE(utils::WriteFile(StringPrintf("%s/hardtocompress",
b_mnt.c_str()).c_str(),
reinterpret_cast<const char*>(kRandomString),
diff --git a/test_utils.cc b/test_utils.cc
index 3815d7b..85c73d7 100644
--- a/test_utils.cc
+++ b/test_utils.cc
@@ -211,12 +211,15 @@
EXPECT_EQ(0, System(StringPrintf("echo T > %s/srchardlink0", kMountPath)));
EXPECT_EQ(0, System(StringPrintf("ln %s/srchardlink0 %s/srchardlink1",
kMountPath, kMountPath)));
+ EXPECT_EQ(0, System(StringPrintf("ln -s bogus %s/boguslink",
+ kMountPath)));
EXPECT_EQ(0, System(StringPrintf("umount -d %s", kMountPath)));
if (out_paths) {
out_paths->clear();
out_paths->push_back("");
out_paths->push_back("/hi");
+ out_paths->push_back("/boguslink");
out_paths->push_back("/hello");
out_paths->push_back("/some_dir");
out_paths->push_back("/some_dir/empty_dir");