summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbescoto <bescoto@2b77aa54-bcbc-44c9-a7ec-4f6cf2b41109>2005-04-07 18:25:55 +0000
committerbescoto <bescoto@2b77aa54-bcbc-44c9-a7ec-4f6cf2b41109>2005-04-07 18:25:55 +0000
commit32f5a7d399adfe19601dc23872fa552e2c73c8e9 (patch)
treebd2c45893e2622436d79bcf583d4ee65ae29c871
parente16ab5aeb778d99a8982cb1a9ee4ff029121d93f (diff)
downloadrdiff-backup-32f5a7d399adfe19601dc23872fa552e2c73c8e9.tar.gz
Fixed Popple's symlink bug which threatened source directory
git-svn-id: http://svn.savannah.nongnu.org/svn/rdiff-backup/branches/r0-12@578 2b77aa54-bcbc-44c9-a7ec-4f6cf2b41109
-rw-r--r--rdiff-backup/CHANGELOG6
-rw-r--r--rdiff-backup/rdiff_backup/restore.py2
-rw-r--r--rdiff-backup/rdiff_backup/rpath.py4
-rw-r--r--rdiff-backup/testing/finaltest.py48
4 files changed, 59 insertions, 1 deletions
diff --git a/rdiff-backup/CHANGELOG b/rdiff-backup/CHANGELOG
index a31ecc5..04dc441 100644
--- a/rdiff-backup/CHANGELOG
+++ b/rdiff-backup/CHANGELOG
@@ -11,6 +11,12 @@ was a timezone bug. (Thanks to Stephen Isard)
Fixed timezone bug. Hopefully this is the last one. (Thanks to
Randall Nortman for bug report.)
+************** Serious bug fix ******************
+If a directory in the source directory was replaced by certain
+symlinks, then if later backups failed they could cause files in the
+directory that the symlink pointed to to be deleted! Much thanks to
+Alistair Popple for pointing this bug out and providing a test case.
+
New in v0.12.7 (2004/05/31)
---------------------------
diff --git a/rdiff-backup/rdiff_backup/restore.py b/rdiff-backup/rdiff_backup/restore.py
index f82ede9..b4ba50c 100644
--- a/rdiff-backup/rdiff_backup/restore.py
+++ b/rdiff-backup/rdiff_backup/restore.py
@@ -510,7 +510,7 @@ as data loss may result.\n""" % (self.mirror_rp.get_indexpath(),), 2)
inc_list = []
else: inc_rp, inc_list = inc_pair
if not mirror_rp:
- mirror_rp = self.mirror_rp.new_index(inc_rp.index)
+ mirror_rp = self.mirror_rp.new_index_empty(inc_rp.index)
yield self.__class__(mirror_rp, inc_rp, inc_list)
def yield_mirrorrps(self, mirrorrp):
diff --git a/rdiff-backup/rdiff_backup/rpath.py b/rdiff-backup/rdiff_backup/rpath.py
index 15aacc0..9aa685b 100644
--- a/rdiff-backup/rdiff_backup/rpath.py
+++ b/rdiff-backup/rdiff_backup/rpath.py
@@ -790,6 +790,10 @@ class RPath(RORPath):
"""Return similar RPath but with new index"""
return self.__class__(self.conn, self.base, index)
+ def new_index_empty(self, index):
+ """Return similar RPath with given index, but initialize to empty"""
+ return self.__class__(self.conn, self.base, index, {'type': None})
+
def open(self, mode, compress = None):
"""Return open file. Supports modes "w" and "r".
diff --git a/rdiff-backup/testing/finaltest.py b/rdiff-backup/testing/finaltest.py
index 9426e18..dd517ea 100644
--- a/rdiff-backup/testing/finaltest.py
+++ b/rdiff-backup/testing/finaltest.py
@@ -596,5 +596,53 @@ class FinalMisc(PathSetter):
for inc in self.get_all_increments(rbdir):
assert inc.getinctime() >= 20000
+
+class FinalBugs(PathSetter):
+ """Test for specific bugs that have been reported"""
+ def test_symlink_popple(self):
+ """Test for Popple's symlink bug
+
+ Earlier, certain symlinks could cause data loss in _source_
+ directory when regressing. See mailing lists around 4/2/05
+ for more info.
+
+ """
+ self.delete_tmpdirs()
+ self.set_connections(None, None, None, None)
+
+ # Make directories
+ rp1 = rpath.RPath(Globals.local_connection, 'testfiles/sym_in1')
+ if rp1.lstat(): rp1.delete()
+ rp1.mkdir()
+ rp1_d = rp1.append('subdir')
+ rp1_d.mkdir()
+ rp1_d_f = rp1_d.append('file')
+ rp1_d_f.touch()
+
+ rp2 = rpath.RPath(Globals.local_connection, 'testfiles/sym_in2')
+ if rp2.lstat(): rp2.delete()
+ rp2.mkdir()
+ rp2_s = rp2.append('subdir')
+ rp2_s.symlink("%s/%s" % (os.getcwd(), rp1_d.path))
+
+ # Backup
+ self.exec_rb(10000, rp1.path, 'testfiles/output')
+ self.exec_rb(20000, rp2.path, 'testfiles/output')
+
+ # Make failed backup
+ rbdir = rpath.RPath(Globals.local_connection,
+ 'testfiles/output/rdiff-backup-data')
+ curmir = rbdir.append('current_mirror.%s.data' %
+ (Time.timetostring(30000),))
+ curmir.touch()
+
+ # Regress
+ self.exec_rb_extra_args(30000, '--check-destination-dir',
+ 'testfiles/output')
+
+ # Check to see if file still there
+ rp1_d_f.setdata()
+ assert rp1_d_f.isreg(), 'File %s corrupted' % (rp1_d_f.path,)
+
if __name__ == "__main__": unittest.main()