summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbescoto <bescoto@2b77aa54-bcbc-44c9-a7ec-4f6cf2b41109>2003-08-23 23:58:08 +0000
committerbescoto <bescoto@2b77aa54-bcbc-44c9-a7ec-4f6cf2b41109>2003-08-23 23:58:08 +0000
commit188794d438954505a5c2effb74ddea5105b8b40e (patch)
tree0afc825adca627da6661f838e2863c65c2fef3a4
parent0cde1ef022765b5763cf68be308553460bcbaadb (diff)
downloadrdiff-backup-188794d438954505a5c2effb74ddea5105b8b40e.tar.gz
Mostly fixing unreadable reg root source/non-root dest bug
git-svn-id: http://svn.savannah.nongnu.org/svn/rdiff-backup/branches/r0-12@400 2b77aa54-bcbc-44c9-a7ec-4f6cf2b41109
-rw-r--r--rdiff-backup/CHANGELOG4
-rw-r--r--rdiff-backup/rdiff_backup/backup.py23
-rw-r--r--rdiff-backup/rdiff_backup/increment.py8
-rw-r--r--rdiff-backup/rdiff_backup/regress.py6
-rw-r--r--rdiff-backup/rdiff_backup/rpath.py8
-rw-r--r--rdiff-backup/testing/roottest.py66
6 files changed, 99 insertions, 16 deletions
diff --git a/rdiff-backup/CHANGELOG b/rdiff-backup/CHANGELOG
index d91ebbd..0946d3b 100644
--- a/rdiff-backup/CHANGELOG
+++ b/rdiff-backup/CHANGELOG
@@ -4,6 +4,10 @@ New in v0.12.4 (??????????)
Specified socket type as SOCK_STREAM. (Error reported by Erik
Forsberg.)
+Fixed bug backing up unreadable regular files when rdiff-backup is run
+by root on the source site and non-root on the destination side.
+(Reported by Troels Arvin and Arkadiusz Miskiewicz.)
+
New in v0.12.3 (2003/08/08)
---------------------------
diff --git a/rdiff-backup/rdiff_backup/backup.py b/rdiff-backup/rdiff_backup/backup.py
index 5040de6..e0a66a2 100644
--- a/rdiff-backup/rdiff_backup/backup.py
+++ b/rdiff-backup/rdiff_backup/backup.py
@@ -181,15 +181,26 @@ class DestinationStruct:
elif dest_rorp:
dest_sig = dest_rorp.getRORPath()
if dest_rorp.isreg():
- dest_rp = dest_base_rpath.new_index(index)
- if not dest_rp.isreg():
- log.ErrorLog.write_if_open("UpdateError", dest_rp,
- "File changed from regular file before signature")
- return None
- dest_sig.setfile(Rdiff.get_signature(dest_rp))
+ sig_fp = cls.get_one_sig_fp(dest_base_rpath.new_index(index))
+ if sig_fp is None: return None
+ dest_sig.setfile(sig_fp)
else: dest_sig = rpath.RORPath(index)
return dest_sig
+ def get_one_sig_fp(cls, dest_rp):
+ """Return a signature fp of given index, corresponding to reg file"""
+ if not dest_rp.isreg():
+ log.ErrorLog.write_if_open("UpdateError", dest_rp,
+ "File changed from regular file before signature")
+ return None
+ if Globals.process_uid != 0 and not dest_rp.readable():
+ # This branch can happen with root source and non-root
+ # destination. Permissions are changed permanently, which
+ # should propogate to the diffs
+ assert dest_rp.isowner(), 'no ownership of %s' % (dest_rp.path,)
+ dest_rp.chmod(0400 | dest_rp.getperms())
+ return Rdiff.get_signature(dest_rp)
+
def patch(cls, dest_rpath, source_diffiter, start_index = ()):
"""Patch dest_rpath with an rorpiter of diffs"""
ITR = rorpiter.IterTreeReducer(PatchITRB, [dest_rpath, cls.CCPP])
diff --git a/rdiff-backup/rdiff_backup/increment.py b/rdiff-backup/rdiff_backup/increment.py
index ce6585c..d0341ef 100644
--- a/rdiff-backup/rdiff_backup/increment.py
+++ b/rdiff-backup/rdiff_backup/increment.py
@@ -79,7 +79,13 @@ def makediff(new, mirror, incpref):
if compress: diff = get_inc(incpref, "diff.gz")
else: diff = get_inc(incpref, "diff")
- Rdiff.write_delta(new, mirror, diff, compress)
+ if Globals.process_uid != 0 and not new.readable():
+ # Check for unreadable files
+ old_new_perms = new.getperms()
+ new.chmod(0400 | old_new_perms)
+ Rdiff.write_delta(new, mirror, diff, compress)
+ new.chmod(old_new_perms)
+ else: Rdiff.write_delta(new, mirror, diff, compress)
rpath.copy_attribs(mirror, diff)
return diff
diff --git a/rdiff-backup/rdiff_backup/regress.py b/rdiff-backup/rdiff_backup/regress.py
index 883c609..464314c 100644
--- a/rdiff-backup/rdiff_backup/regress.py
+++ b/rdiff-backup/rdiff_backup/regress.py
@@ -27,9 +27,9 @@ metadata file (which we assume is intact) and delete the extra
increments. For regular files we examine the mirror file and use the
increment file to get the old data if the mirror file is out of date.
-Currently this does recover hard links. This make make the regressed
-directory take up more disk space, but hard links can still be
-recovered.
+Currently this does not recover hard links. This may make the
+regressed directory take up more disk space, but hard links can still
+be recovered.
"""
diff --git a/rdiff-backup/rdiff_backup/rpath.py b/rdiff-backup/rdiff_backup/rpath.py
index ec513fd..0f3ddc1 100644
--- a/rdiff-backup/rdiff_backup/rpath.py
+++ b/rdiff-backup/rdiff_backup/rpath.py
@@ -828,6 +828,14 @@ class RPath(RORPath):
raise RPathException("Error closing file")
self.setdata()
+ def write_string(self, s, compress = None):
+ """Write string s into rpath"""
+ assert not self.lstat(), "File %s already exists" % (self.path,)
+ outfp = self.open("wb", compress = compress)
+ outfp.write(s)
+ assert not outfp.close()
+ self.setdata()
+
def isincfile(self):
"""Return true if path looks like an increment file
diff --git a/rdiff-backup/testing/roottest.py b/rdiff-backup/testing/roottest.py
index 6193893..ab0c580 100644
--- a/rdiff-backup/testing/roottest.py
+++ b/rdiff-backup/testing/roottest.py
@@ -2,15 +2,19 @@ import unittest, os
from commontest import *
from rdiff_backup import Globals, log
-"""Root tests
+"""Root tests - contain tests which need to be run as root.
+
+Some of the quoting here may not work with csh (works on bash). Also,
+if you aren't me, check out the 'user' global variable.
-This is mainly a copy of regressiontest.py, but contains the two tests
-that are meant to be run as root.
"""
Globals.set('change_source_perms', None)
Globals.counter = 0
-log.Log.setverbosity(6)
+verbosity = 3
+log.Log.setverbosity(verbosity)
+user = 'ben' # Non-root user to su to
+assert os.getuid() == 0, "Run this test as root!"
def Run(cmd):
print "Running: ", cmd
@@ -24,6 +28,56 @@ class RootTest(unittest.TestCase):
def testLocal2(self): BackupRestoreSeries(1, 1, self.dirlist2)
def testRemote(self): BackupRestoreSeries(None, None, self.dirlist1)
+class HalfRoot(unittest.TestCase):
+ """Backing up files where origin is root and destination is non-root"""
+ def make_dirs(self):
+ """Make source directories, return rpaths
+
+ These make a directory with a changing file that is not
+ self-readable. (Caused problems earlier.)
+
+ """
+ rp1 = rpath.RPath(Globals.local_connection, "testfiles/root_half1")
+ if rp1.lstat(): Myrm(rp1.path)
+ rp1.mkdir()
+ rp1_1 = rp1.append('foo')
+ rp1_1.write_string('hello')
+ rp1_1.chmod(0)
+ rp1_2 = rp1.append('to be deleted')
+ rp1_2.write_string('aosetuhaosetnuhontu')
+ rp1_2.chmod(0)
+
+ rp2 = rpath.RPath(Globals.local_connection, "testfiles/root_half2")
+ if rp2.lstat(): Myrm(rp2.path)
+ rp2.mkdir()
+ rp2_1 = rp2.append('foo')
+ rp2_1.write_string('goodbye')
+ rp2_1.chmod(0)
+ return rp1, rp2
+
+ def test_backup(self):
+ """Right now just test backing up"""
+ in_rp1, in_rp2 = self.make_dirs()
+ outrp = rpath.RPath(Globals.local_connection, "testfiles/output")
+ if outrp.lstat(): outrp.delete()
+ remote_schema = 'su -c "rdiff-backup --server" %s' % (user,)
+ cmd_schema = ("rdiff-backup -v" + str(verbosity) +
+ " --current-time %s --remote-schema '%%s' %s '%s'::%s")
+
+ cmd1 = cmd_schema % (10000, in_rp1.path, remote_schema, outrp.path)
+ print "Executing: ", cmd1
+ assert not os.system(cmd1)
+ in_rp1.setdata()
+ outrp.setdata()
+ assert CompareRecursive(in_rp1, outrp)
+
+ cmd2 = cmd_schema % (20000, in_rp2.path, remote_schema, outrp.path)
+ print "Executing: ", cmd2
+ assert not os.system(cmd2)
+ in_rp2.setdata()
+ outrp.setdata()
+ assert CompareRecursive(in_rp2, outrp)
+
class NonRoot(unittest.TestCase):
"""Test backing up as non-root user
@@ -32,7 +86,6 @@ class NonRoot(unittest.TestCase):
root, everything should be restored normally.
"""
- user = 'ben'
def make_root_dirs(self):
"""Make directory createable only by root"""
rp = rpath.RPath(Globals.local_connection, "testfiles/root_out1")
@@ -61,10 +114,11 @@ class NonRoot(unittest.TestCase):
return rp, sp
def backup(self, input_rp, output_rp, time):
+ global user
backup_cmd = ("rdiff-backup --no-compare-inode "
"--current-time %s %s %s" %
(time, input_rp.path, output_rp.path))
- Run("su %s -c '%s'" % (self.user, backup_cmd))
+ Run("su %s -c '%s'" % (user, backup_cmd))
def restore(self, dest_rp, restore_rp, time = None):
assert restore_rp.path == "testfiles/rest_out"