Commit 2aae3044 authored by bescoto's avatar bescoto

Added tests for and fixed problem with backing up unreadable regular

files as root on source and non-root on dest.


git-svn-id: http://svn.savannah.nongnu.org/svn/rdiff-backup@399 2b77aa54-bcbc-44c9-a7ec-4f6cf2b41109
parent e6f02f86
......@@ -4,6 +4,10 @@ New in v0.13.2 (??????????)
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.13.1 (2003/08/08)
---------------------------
......
......@@ -423,8 +423,10 @@ def restore_set_fs_globals(target):
target_fsa = fs_abilities.FSAbilities('destination').init_readwrite(
target, 0)
Log(str(target_fsa), 3)
mirror_fsa = fs_abilities.FSAbilities('source').init_readwrite(
Globals.rbdir)
Log(str(mirror_fsa), 3)
update_bool_global('read_acls', target_fsa.acls)
update_bool_global('write_acls', target_fsa.acls)
......
......@@ -184,15 +184,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])
......
......@@ -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
......
......@@ -885,6 +885,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
......
......@@ -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"
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment