From 75a6e8910e22b4588a0856e8907d7e6be30ed616 Mon Sep 17 00:00:00 2001 From: bescoto Date: Sat, 5 Nov 2005 02:56:21 +0000 Subject: quoted filename too long fix git-svn-id: http://svn.savannah.nongnu.org/svn/rdiff-backup/branches/r1-0@671 2b77aa54-bcbc-44c9-a7ec-4f6cf2b41109 --- rdiff-backup/CHANGELOG | 2 ++ rdiff-backup/rdiff_backup/backup.py | 44 ++++++++++++++++------------- rdiff-backup/testing/FilenameMappingtest.py | 29 ++++++++++++++++++- 3 files changed, 54 insertions(+), 21 deletions(-) diff --git a/rdiff-backup/CHANGELOG b/rdiff-backup/CHANGELOG index 476c155..bd175db 100644 --- a/rdiff-backup/CHANGELOG +++ b/rdiff-backup/CHANGELOG @@ -5,6 +5,8 @@ Applied Alec Berryman's patch to update the no-compression regexp. Alec Berryman's fs_abilities patch is supposed to help with AFS. +Fixed filename-too-long crash when quoting. + New in v1.0.2 (2005/10/24) -------------------------- diff --git a/rdiff-backup/rdiff_backup/backup.py b/rdiff-backup/rdiff_backup/backup.py index 3ee760e..a34eb73 100644 --- a/rdiff-backup/rdiff_backup/backup.py +++ b/rdiff-backup/rdiff_backup/backup.py @@ -465,14 +465,27 @@ class PatchITRB(rorpiter.ITRBranch): self.cached_rp = self.basis_root_rp.new_index(index) return self.cached_rp + def check_long_name(self, func, *args): + """Execute function, checking for ENAMETOOLONG error""" + try: result = func(*args) + except OSError, exc: + if (errno.errorcode.has_key(exc[0]) and + errno.errorcode[exc[0]] == 'ENAMETOOLONG'): + self.error_handler(exc, args[0]) + return None + else: raise + return result + def can_fast_process(self, index, diff_rorp): """True if diff_rorp and mirror are not directories""" - rp = self.get_rp_from_root(index) - return not diff_rorp.isdir() and not rp.isdir() + rp = self.check_long_name(self.get_rp_from_root, index) + # filename too long error qualifies (hack) + return not rp or (not diff_rorp.isdir() and not rp.isdir()) def fast_process(self, index, diff_rorp): """Patch base_rp with diff_rorp (case where neither is directory)""" - rp = self.get_rp_from_root(index) + rp = self.check_long_name(self.get_rp_from_root, index) + if not rp: return tf = TempFile.new(rp) if self.patch_to_temp(rp, diff_rorp, tf): if tf.lstat(): @@ -593,23 +606,14 @@ class IncrementITRB(PatchITRB): self.cached_incrp = self.inc_root_rp.new_index(index) return self.cached_incrp - def inc_with_checking(self, new, old, inc_rp): - """Produce increment taking new to old checking for errors""" - try: inc = increment.Increment(new, old, inc_rp) - except OSError, exc: - if (errno.errorcode.has_key(exc[0]) and - errno.errorcode[exc[0]] == 'ENAMETOOLONG'): - self.error_handler(exc, old) - return None - else: raise - return inc - def fast_process(self, index, diff_rorp): """Patch base_rp with diff_rorp and write increment (neither is dir)""" - rp = self.get_rp_from_root(index) + rp = self.check_long_name(self.get_rp_from_root, index) + if not rp: return tf = TempFile.new(rp) if self.patch_to_temp(rp, diff_rorp, tf): - inc = self.inc_with_checking(tf, rp, self.get_incrp(index)) + inc = self.check_long_name(increment.Increment, + tf, rp, self.get_incrp(index)) if inc is not None: self.CCPP.set_inc(index, inc) if inc.isreg(): @@ -629,14 +633,14 @@ class IncrementITRB(PatchITRB): base_rp = self.base_rp = self.get_rp_from_root(index) assert diff_rorp.isdir() or base_rp.isdir() if diff_rorp.isdir(): - inc = self.inc_with_checking(diff_rorp, base_rp, - self.get_incrp(index)) + inc = self.check_long_name(increment.Increment, + diff_rorp, base_rp, self.get_incrp(index)) if inc and inc.isreg(): inc.fsync_with_dir() # must write inc before rp changed self.prepare_dir(diff_rorp, base_rp) elif self.set_dir_replacement(diff_rorp, base_rp): - inc = self.inc_with_checking(self.dir_replacement, base_rp, - self.get_incrp(index)) + inc = self.check_long_name(increment.Increment, + self.dir_replacement, base_rp, self.get_incrp(index)) if inc: self.CCPP.set_inc(index, inc) self.CCPP.flag_success(index) diff --git a/rdiff-backup/testing/FilenameMappingtest.py b/rdiff-backup/testing/FilenameMappingtest.py index e364c59..1bc1b6c 100644 --- a/rdiff-backup/testing/FilenameMappingtest.py +++ b/rdiff-backup/testing/FilenameMappingtest.py @@ -1,6 +1,6 @@ import unittest from commontest import * -from rdiff_backup import FilenameMapping +from rdiff_backup import FilenameMapping, rpath, Globals class FilenameMappingTest(unittest.TestCase): """Test the FilenameMapping class, for quoting filenames""" @@ -29,4 +29,31 @@ class FilenameMappingTest(unittest.TestCase): assert (qrp.index[0] == "mirror_metadata.1969-12-31T21:33:20-07:00.data.gz") + def testLongFilenames(self): + """See if long quoted filenames cause crash""" + MakeOutputDir() + outrp = rpath.RPath(Globals.local_connection, "testfiles/output") + inrp = rpath.RPath(Globals.local_connection, "testfiles/quotetest") + re_init_dir(inrp) + long_filename = "A"*200 # when quoted should cause overflow + longrp = inrp.append(long_filename) + longrp.touch() + shortrp = inrp.append("B") + shortrp.touch() + + rdiff_backup(1, 1, inrp.path, outrp.path, 100000, + extra_options = "--override-chars-to-quote A") + + longrp_out = outrp.append(long_filename) + assert not longrp_out.lstat() + shortrp_out = outrp.append('B') + assert shortrp_out.lstat() + + rdiff_backup(1, 1, "testfiles/empty", outrp.path, 200000) + shortrp_out.setdata() + assert not shortrp_out.lstat() + rdiff_backup(1, 1, inrp.path, outrp.path, 300000) + shortrp_out.setdata() + assert shortrp_out.lstat() + if __name__ == "__main__": unittest.main() -- cgit v1.2.1