From: Daniel Garcia Moreno Date: Sun, 1 Sep 2013 10:54:15 +0000 (+0200) Subject: Fixed multivolume with encryption creation X-Git-Tag: v2.2~106 X-Git-Url: http://developer.intra2net.com/git/?a=commitdiff_plain;h=8825be52718fadfa6b01c14a1863ea829d43f887;p=python-delta-tar Fixed multivolume with encryption creation Adding the test test_restore_from_index_diff_backup3_multivol I've found a bug in the multivolume creation with encryption. The problem was that the first volume of data was created correctly, but the second and so were created in plain text. The problem was in the TarFile.open_volume method, just in the creation of the new volume file, the encryption data was not passed to the new _Stream object. --- diff --git a/deltatar/deltatar.py b/deltatar/deltatar.py index 1f610ba..4601e1d 100644 --- a/deltatar/deltatar.py +++ b/deltatar/deltatar.py @@ -1282,12 +1282,11 @@ class RestoreHelper(object): # seek tarfile if needed offset = file_data.get('offset', -1) if index_data['tarobj']: - # TODO review this code... - #member = index_data['tarobj'].next() - #if member.path != index_data['tarobj']: + member = index_data['tarobj'].next() + if not member or member.path != file_data['path']: # force a seek and reopen - index_data['tarobj'].close() - index_data['tarobj'] = None + index_data['tarobj'].close() + index_data['tarobj'] = None # open the tarfile if needed if not index_data['tarobj']: diff --git a/deltatar/tarfile.py b/deltatar/tarfile.py index e93ef1f..36c42af 100644 --- a/deltatar/tarfile.py +++ b/deltatar/tarfile.py @@ -2412,6 +2412,9 @@ class TarFile(object): comptype=self.fileobj.comptype, fileobj=None, bufsize=self.fileobj.bufsize, + password=self.fileobj.password, + key_length=self.fileobj.key_length, + enctype=self.fileobj.enctype, concat_stream=self.fileobj.concat_stream) else: fileobj = bltn_open(name, self._mode) diff --git a/testing/test_deltatar.py b/testing/test_deltatar.py index b85f669..fc8f765 100644 --- a/testing/test_deltatar.py +++ b/testing/test_deltatar.py @@ -169,6 +169,39 @@ class DeltaTarTest(BaseTest): if value: assert value == self.md5sum(key) + def test_restore_multivol2(self): + ''' + Creates a full backup without any filtering with multiple volumes and + restore it. + ''' + deltatar = DeltaTar(mode=self.MODE, password=self.PASSWORD, + logger=self.consoleLogger) + + shutil.copytree(".git", "source_dir2") + + # create first backup + deltatar.create_full_backup( + source_path="source_dir2", + backup_path="backup_dir", + max_volume_size=1) + + assert os.path.exists("backup_dir") + assert os.path.exists(os.path.join("backup_dir", + deltatar.volume_name_func("backup_dir", True, 0))) + assert os.path.exists(os.path.join("backup_dir", + deltatar.volume_name_func("backup_dir", True, 1))) + + shutil.rmtree("source_dir2") + + tar_filename = deltatar.volume_name_func('backup_dir', True, 0) + tar_path = os.path.join("backup_dir", tar_filename) + + # this should automatically restore all volumes + deltatar.restore_backup(target_path="source_dir2", + backup_tar_path=tar_path) + + self.check_equal_dirs('.git', 'source_dir2', deltatar) + def test_restore_multivol_manual_from_index(self): ''' Creates a full backup without any filtering with multiple volumes and @@ -1100,6 +1133,78 @@ class DeltaTarTest(BaseTest): # altered ".git" directory) self.check_equal_dirs('source_dir_diff', 'target_dir', deltatar) + def test_restore_from_index_diff_backup3_multivol(self): + ''' + Creates a full backup of .git, modifies some random files, creates a + diff backup, then restores the diff backup with the full backup as a + starting point. + ''' + # this test only works for uncompressed or concat compressed modes + if self.MODE.startswith(':') or self.MODE.startswith('|'): + return + + deltatar = DeltaTar(mode=self.MODE, password=self.PASSWORD, + logger=self.consoleLogger) + + shutil.rmtree("source_dir") + shutil.copytree(".git", "source_dir") + shutil.copytree(".git", "source_dir_diff") + + # create first backup + deltatar.create_full_backup( + source_path="source_dir", + backup_path="backup_dir", + max_volume_size=1) + + prev_index_filename = deltatar.index_name_func(is_full=True) + prev_index_path = os.path.join("backup_dir", prev_index_filename) + + # alter the source_dir randomly + source_it = deltatar._recursive_walk_dir('source_dir_diff') + + for path in source_it: + # if path doesn't exist (might have previously removed) ignore it. + # also ignore it (i.e. do not change it) 70% of the time + if not os.path.exists(path) or random.random() < 0.7: + continue + + # remove the file + if os.path.isdir(path): + shutil.rmtree(path) + else: + os.unlink(path) + + deltatar.create_diff_backup("source_dir_diff", "backup_dir2", + prev_index_path, max_volume_size=1) + + # first restore initial backup in target_dir + tar_filename = deltatar.volume_name_func('backup_dir', True, 0) + tar_path = os.path.join("backup_dir", tar_filename) + deltatar.restore_backup("target_dir", backup_tar_path=tar_path) + + # and check that target_dir equals to source_dir (which is the same as + # ".git" initially) + self.check_equal_dirs('source_dir', 'target_dir', deltatar) + + # then apply diff backup in target_dir + index_filename = deltatar.index_name_func(is_full=True) + index_path = os.path.join("backup_dir2", index_filename) + deltatar.restore_backup("target_dir", + backup_indexes_paths=[index_path, prev_index_path]) + + # and check that target_dir equals to source_dir_diff (the randomly + # altered ".git" directory) + self.check_equal_dirs('source_dir_diff', 'target_dir', deltatar) + + # then delete target_dir and apply diff backup from zero and check again + shutil.rmtree("target_dir") + deltatar.restore_backup("target_dir", + backup_indexes_paths=[index_path, prev_index_path]) + + # and check that target_dir equals to source_dir_diff (the randomly + # altered ".git" directory) + self.check_equal_dirs('source_dir_diff', 'target_dir', deltatar) + def check_equal_dirs(self, path1, path2, deltatar): ''' compare the two directories source_dir and target_dir and check