From 5015e6c7a84243200c00c467d892b1b2105ee9bb Mon Sep 17 00:00:00 2001 From: bescoto Date: Sat, 21 Jun 2003 01:29:18 +0000 Subject: Fixed quoted hardlinks, added --windows-restore, fixed a couple tests git-svn-id: http://svn.savannah.nongnu.org/svn/rdiff-backup/trunk@320 2b77aa54-bcbc-44c9-a7ec-4f6cf2b41109 --- rdiff-backup/CHANGELOG | 15 ++++++++++++++- rdiff-backup/TODO | 5 +++++ rdiff-backup/rdiff-backup.1 | 18 ++++++++++++------ rdiff-backup/rdiff_backup/Hardlink.py | 3 +-- rdiff-backup/rdiff_backup/Main.py | 7 +++++-- rdiff-backup/rdiff_backup/Security.py | 1 + rdiff-backup/rdiff_backup/backup.py | 8 ++++++-- rdiff-backup/rdiff_backup/rorpiter.py | 26 +++++++++++++++----------- rdiff-backup/testing/finaltest.py | 29 +++++++++++++++++++++++++---- rdiff-backup/testing/regressiontest.py | 23 +++++++++++++++++++++++ 10 files changed, 107 insertions(+), 28 deletions(-) diff --git a/rdiff-backup/CHANGELOG b/rdiff-backup/CHANGELOG index 9e03576..371640a 100644 --- a/rdiff-backup/CHANGELOG +++ b/rdiff-backup/CHANGELOG @@ -1,4 +1,4 @@ -New in v0.12.0 (2003/??/??) +New in v0.11.5 (2003/06/20) --------------------------- Added EDEADLOCK to the list of skippable errors. (Thanks to Dave @@ -9,6 +9,19 @@ Added --list-at-time option at request of Farkas Levente. Various fixes for backing up onto windows directories. Thanks to Keith Edmunds for bug reports and testing. +Fixed possible crash when a file would be deleted while being +processed (reported by Robert Weber). + +Handle better cases when there are two files with the same name in the +same directory. + +Added --windows-restore switch, for use when when restoring from a +windows-style file system to a normal one. Use --windows-mode when +backing up. + +Scott Bender's patch fixes backing up hard links when first linked +file is quoted. + New in v0.11.4 (2003/03/15) --------------------------- diff --git a/rdiff-backup/TODO b/rdiff-backup/TODO index 7787e74..7b401fb 100644 --- a/rdiff-backup/TODO +++ b/rdiff-backup/TODO @@ -2,8 +2,13 @@ Make restores tolerant of missing files Look into hard linking on windows +Added --include/--exclude options for restoring + ---------[ Medium term ]--------------------------------------- +Don't require increments..dir files to be setuid/setgid, or +don't even have the backup files. (Andrew Bressen) + Examine default settings with --windows-mode Look at Kent Borg's suggestion for restore options and digests. diff --git a/rdiff-backup/rdiff-backup.1 b/rdiff-backup/rdiff-backup.1 index 69e1a2c..9680840 100644 --- a/rdiff-backup/rdiff-backup.1 +++ b/rdiff-backup/rdiff-backup.1 @@ -361,12 +361,18 @@ is noisiest). This determines how much is written to the log file. Print the current version and exit .TP .B --windows-mode -This option is short for "--chars to quote A-Z: --windows-time-format ---no-hard-links --exclude-special-files" and is appropriate when -backing a normal unix file system to one that doesn't allow colons in -filenames, is not case sensitive, and cannot store special files or -hard links. If this switch is used for backing up, it must also be -used when restoring, listing increments, etc. +This option quotes characters not allowable on windows, and does not +try to preserve ownership, hardlinks, or permissions on the +destination side. It is appropriate when backing up a normal unix +file system to a windows one such as VFS, or a file system with +similar limitations. Because metadata is stored in a separate regular +file, this option does not prevent all data from being restored. +.TP +.B --windows-restore +This option turns on windows quoting, but does not disable +permissions, hard linking, or ownership. Use this when restoring from +an rdiff-backup directory on a windows file system to a unix file +system. .SH EXAMPLES Simplest case---backup directory foo to directory bar, with increments diff --git a/rdiff-backup/rdiff_backup/Hardlink.py b/rdiff-backup/rdiff_backup/Hardlink.py index f9836fb..453672e 100644 --- a/rdiff-backup/rdiff_backup/Hardlink.py +++ b/rdiff-backup/rdiff_backup/Hardlink.py @@ -169,8 +169,7 @@ def restore_link(index, rpath): def link_rp(diff_rorp, dest_rpath, dest_root = None): """Make dest_rpath into a link using link flag in diff_rorp""" if not dest_root: dest_root = dest_rpath # use base of dest_rpath - dest_link_rpath = rpath.RPath(dest_root.conn, dest_root.base, - diff_rorp.get_link_flag()) + dest_link_rpath = dest_root.new_index(diff_rorp.get_link_flag()) dest_rpath.hardlink(dest_link_rpath.path) diff --git a/rdiff-backup/rdiff_backup/Main.py b/rdiff-backup/rdiff_backup/Main.py index 4fa911b..04ce247 100644 --- a/rdiff-backup/rdiff_backup/Main.py +++ b/rdiff-backup/rdiff_backup/Main.py @@ -60,7 +60,7 @@ def parse_cmdlineoptions(arglist): "restrict=", "restrict-read-only=", "restrict-update-only=", "server", "ssh-no-compression", "terminal-verbosity=", "test-server", "verbosity=", "version", "windows-mode", - "windows-time-format"]) + "windows-restore"]) except getopt.error, e: commandline_error("Bad commandline options: %s" % str(e)) @@ -145,12 +145,15 @@ def parse_cmdlineoptions(arglist): sys.exit(0) elif opt == "-v" or opt == "--verbosity": Log.setverbosity(arg) elif opt == "--windows-mode": - Globals.set('chars_to_quote', "^a-z._ -") + Globals.set('chars_to_quote', "^a-z0-9._ -") Globals.set('quoting_enabled', 1) Globals.set('preserve_hardlinks', 0) Globals.set('change_ownership', 0) Globals.set('change_permissions', 0) Globals.set('fsync_directories', 0) + elif opt == '--windows-restore': + Globals.set('chars_to_quote', "^a-z0-9._ -") + Globals.set('quoting_enabled', 1) else: Log.FatalError("Unknown option %s" % opt) def isincfilename(path): diff --git a/rdiff-backup/rdiff_backup/Security.py b/rdiff-backup/rdiff_backup/Security.py index b1785d6..b02d335 100644 --- a/rdiff-backup/rdiff_backup/Security.py +++ b/rdiff-backup/rdiff_backup/Security.py @@ -121,6 +121,7 @@ def set_allowed_requests(sec_level): elif sec_level == "read-only" or sec_level == "update-only": allowed_requests.extend( ["C.make_file_dict", + "log.Log.log_to_file", "os.getuid", "os.listdir", "Time.setcurtime_local", diff --git a/rdiff-backup/rdiff_backup/backup.py b/rdiff-backup/rdiff_backup/backup.py index cd46c5e..36a207d 100644 --- a/rdiff-backup/rdiff_backup/backup.py +++ b/rdiff-backup/rdiff_backup/backup.py @@ -283,8 +283,12 @@ class CacheCollatedPostProcess: """Remove one element from cache, possibly adding it to metadata""" first_index = self.cache_indicies[0] del self.cache_indicies[0] - old_source_rorp, old_dest_rorp, changed_flag, success_flag, inc = \ - self.cache_dict[first_index] + try: (old_source_rorp, old_dest_rorp, changed_flag, + success_flag, inc) = self.cache_dict[first_index] + except KeyError: # probably caused by error in file system (dup) + log.Log("Warning index %s missing from CCPP cache" % + (first_index,),2) + return del self.cache_dict[first_index] self.post_process(old_source_rorp, old_dest_rorp, changed_flag, success_flag, inc) diff --git a/rdiff-backup/rdiff_backup/rorpiter.py b/rdiff-backup/rdiff_backup/rorpiter.py index 7db4fea..d683650 100644 --- a/rdiff-backup/rdiff_backup/rorpiter.py +++ b/rdiff-backup/rdiff_backup/rorpiter.py @@ -30,7 +30,7 @@ files), where files is the number of files attached (usually 1 or from __future__ import generators import os, tempfile, UserList, types -import Globals, rpath, iterfile +import Globals, rpath, iterfile, log def CollateIterators(*rorp_iters): @@ -266,16 +266,20 @@ class IterTreeReducer: else: self.root_branch.start_process(*args) self.index = index return 1 - assert index > self.index, "Index out of order" - - if self.finish_branches(index) is None: - return None # We are no longer in the main tree - last_branch = self.branches[-1] - if last_branch.can_fast_process(*args): - last_branch.fast_process(*args) - else: - branch = self.add_branch(index) - branch.start_process(*args) + if index == self.index: + log.Log("Warning, repeated index %s, bad filesystem?" + % (index,), 2) + elif index < self.index: + assert 0, "Bad index order: %s >= %s" % (self.index, index) + else: # normal case + if self.finish_branches(index) is None: + return None # We are no longer in the main tree + last_branch = self.branches[-1] + if last_branch.can_fast_process(*args): + last_branch.fast_process(*args) + else: + branch = self.add_branch(index) + branch.start_process(*args) self.index = index return 1 diff --git a/rdiff-backup/testing/finaltest.py b/rdiff-backup/testing/finaltest.py index 301bb1e..9837437 100644 --- a/rdiff-backup/testing/finaltest.py +++ b/rdiff-backup/testing/finaltest.py @@ -37,6 +37,9 @@ class Local: timbar_in = get_local_rp('increment1/timbar.pyc') timbar_out = get_local_rp('../timbar.pyc') # in cur directory + wininc2 = get_local_rp('win-increment2') + wininc3 = get_local_rp('win-increment3') + class PathSetter(unittest.TestCase): def setUp(self): self.reset_schema() @@ -239,7 +242,23 @@ class Final(PathSetter): self.exec_rb(None, '../../../../../../proc', 'testfiles/procoutput') def testWindowsMode(self): - """Test backup with the --windows-mode option""" + """Test backup with the --windows-mode option + + We need to delete from the increment? directories long file + names, because quoting adds too many extra letters. + + """ + def delete_long(base_rp, length = 100): + """Delete filenames longer than length given""" + for rp in selection.Select(base_rp).set_iter(): + if len(rp.dirsplit()[1]) > length: rp.delete() + + if not Local.wininc2.lstat() or not Local.wininc3.lstat(): + os.system("cp -a testfiles/increment2 testfiles/win-increment2") + os.system("cp -a testfiles/increment3 testfiles/win-increment3") + delete_long(Local.wininc2) + delete_long(Local.wininc3) + old_schema = self.rb_schema self.rb_schema = old_schema + " --windows-mode " self.set_connections(None, None, None, None) @@ -247,12 +266,14 @@ class Final(PathSetter): self.delete_tmpdirs() # Back up increment2, this contains a file with colons - self.exec_rb(20000, 'testfiles/increment2', 'testfiles/output') + self.exec_rb(20000, 'testfiles/win-increment2', 'testfiles/output') time.sleep(1) # Back up increment3 - self.exec_rb(30000, 'testfiles/increment3', 'testfiles/output') + self.exec_rb(30000, 'testfiles/win-increment3', 'testfiles/output') + # Start restore + self.rb_schema = old_schema + ' --windows-restore ' Globals.time_separator = "_" inc_paths = self.getinc_paths("increments.", "testfiles/output/rdiff-backup-data", 1) @@ -260,7 +281,7 @@ class Final(PathSetter): assert len(inc_paths) == 1, inc_paths # Restore increment2 self.exec_rb(None, inc_paths[0], 'testfiles/restoretarget2') - assert CompareRecursive(Local.inc2rp, Local.rpout2, + assert CompareRecursive(Local.wininc2, Local.rpout2, compare_hardlinks = 0) # Now check to make sure no ":" in output directory diff --git a/rdiff-backup/testing/regressiontest.py b/rdiff-backup/testing/regressiontest.py index 90b9d66..b2192c1 100644 --- a/rdiff-backup/testing/regressiontest.py +++ b/rdiff-backup/testing/regressiontest.py @@ -158,6 +158,29 @@ class IncrementTest1(unittest.TestCase): InternalBackup(1, 1, "testfiles/longfilenames1", Local.rpout.path, 100) InternalBackup(1, 1, "testfiles/longfilenames2", Local.rpout.path, 200) + def test_quoted_hardlinks(self): + """Test backing up a directory with quoted hardlinks in it""" + hldir = rpath.RPath(Globals.local_connection, + "testfiles/quoted_hardlinks") + if hldir.lstat(): + Myrm(hldir.path) + hldir.setdata() + hldir.mkdir() + hl1 = hldir.append("HardLink1") + hl1.touch() + hl2 = hldir.append("HardLink2") + hl2.hardlink(hl1.path) + + Myrm(Local.rpout.path) + old_settings = (Globals.quoting_enabled, Globals.chars_to_quote, + Globals.quoting_char) + Globals.quoting_enabled = 1 + Globals.chars_to_quote = 'A-Z' + Globals.quoting_char = ';' + InternalBackup(1, 1, hldir.path, Local.rpout.path, current_time = 1) + InternalBackup(1, 1, "testfiles/empty", Local.rpout.path, + current_time = 10000) + def test_long_socket(self): """Test backing up a directory with long sockets in them -- cgit v1.2.1