Commit 70835e69 authored by bescoto's avatar bescoto

Yet another change dealing with unreadable directories


git-svn-id: http://svn.savannah.nongnu.org/svn/rdiff-backup@431 2b77aa54-bcbc-44c9-a7ec-4f6cf2b41109
parent d629acfc
...@@ -53,9 +53,6 @@ process_gid = os.getgid() ...@@ -53,9 +53,6 @@ process_gid = os.getgid()
# If true, when copying attributes, also change target's uid/gid # If true, when copying attributes, also change target's uid/gid
change_ownership = None change_ownership = None
# If true, when copying attributes, also change target's permission.
change_permissions = 1
# If true, change the permissions of unwriteable mirror files # If true, change the permissions of unwriteable mirror files
# (such as directories) so that they can be written, and then # (such as directories) so that they can be written, and then
# change them back. This defaults to 1 just in case the process # change them back. This defaults to 1 just in case the process
......
...@@ -288,8 +288,7 @@ def backup_set_rbdir(rpin, rpout): ...@@ -288,8 +288,7 @@ def backup_set_rbdir(rpin, rpout):
assert rpout.lstat(), (rpout.path, rpout.lstat()) assert rpout.lstat(), (rpout.path, rpout.lstat())
if rpout.isdir() and not rpout.listdir(): # rpout is empty dir if rpout.isdir() and not rpout.listdir(): # rpout is empty dir
if Globals.change_permissions: rpout.chmod(0700) # just make sure permissions aren't too lax
rpout.chmod(0700) # just make sure permissions aren't too lax
elif not Globals.rbdir.lstat() and not force: Log.FatalError( elif not Globals.rbdir.lstat() and not force: Log.FatalError(
"""Destination directory """Destination directory
......
...@@ -234,7 +234,7 @@ static.MakeClass(DestinationStruct) ...@@ -234,7 +234,7 @@ static.MakeClass(DestinationStruct)
class CacheCollatedPostProcess: class CacheCollatedPostProcess:
"""Cache a collated iter of (source_rorp, dest_rorp) pairs """Cache a collated iter of (source_rorp, dest_rorp) pairs
This is necessary for two reasons: This is necessary for three reasons:
1. The patch function may need the original source_rorp or 1. The patch function may need the original source_rorp or
dest_rp information, which is not present in the diff it dest_rp information, which is not present in the diff it
...@@ -247,6 +247,11 @@ class CacheCollatedPostProcess: ...@@ -247,6 +247,11 @@ class CacheCollatedPostProcess:
any metadata until we know the file has been procesed any metadata until we know the file has been procesed
correctly. correctly.
3. We may lack permissions on certain destination directories.
The permissions of these directories need to be relaxed before
we enter them to computer signatures, and then reset after we
are done patching everything inside them.
The class caches older source_rorps and dest_rps so the patch The class caches older source_rorps and dest_rps so the patch
function can retrieve them if necessary. The patch function can function can retrieve them if necessary. The patch function can
also update the processed correctly flag. When an item falls out also update the processed correctly flag. When an item falls out
...@@ -281,6 +286,11 @@ class CacheCollatedPostProcess: ...@@ -281,6 +286,11 @@ class CacheCollatedPostProcess:
self.cache_dict = {} self.cache_dict = {}
self.cache_indicies = [] self.cache_indicies = []
# Contains a list of pairs (destination_rps, permissions) to
# be used to reset the permissions of certain directories
# after we're finished with them
self.dir_perms_list = []
def __iter__(self): return self def __iter__(self): return self
def next(self): def next(self):
...@@ -304,10 +314,21 @@ class CacheCollatedPostProcess: ...@@ -304,10 +314,21 @@ class CacheCollatedPostProcess:
""" """
if source_rorp: Hardlink.add_rorp(source_rorp, source = 1) if source_rorp: Hardlink.add_rorp(source_rorp, source = 1)
if dest_rorp: Hardlink.add_rorp(dest_rorp, source = 0) if dest_rorp: Hardlink.add_rorp(dest_rorp, source = 0)
if (dest_rorp and dest_rorp.isdir() and Globals.process_uid != 0 and if (dest_rorp and dest_rorp.isdir() and Globals.process_uid != 0
dest_rorp.getperms() % 01000 < 0700): and dest_rorp.getperms() % 01000 < 0700):
dest_rp = self.dest_root_rp.new_index(dest_rorp.index) self.unreadable_dir_init(source_rorp, dest_rorp)
dest_rp.chmod(0700 | dest_rorp.getperms())
def unreadable_dir_init(self, source_rorp, dest_rorp):
"""Initialize an unreadable dir.
Make it readable, and if necessary, store the old permissions
in self.dir_perms_list so the old perms can be restored.
"""
dest_rp = self.dest_root_rp.new_index(dest_rorp.index)
dest_rp.chmod(0700 | dest_rorp.getperms())
if source_rorp and source_rorp.isdir():
self.dir_perms_list.append((dest_rp, source_rorp.getperms()))
def shorten_cache(self): def shorten_cache(self):
"""Remove one element from cache, possibly adding it to metadata""" """Remove one element from cache, possibly adding it to metadata"""
...@@ -322,6 +343,7 @@ class CacheCollatedPostProcess: ...@@ -322,6 +343,7 @@ class CacheCollatedPostProcess:
del self.cache_dict[first_index] del self.cache_dict[first_index]
self.post_process(old_source_rorp, old_dest_rorp, self.post_process(old_source_rorp, old_dest_rorp,
changed_flag, success_flag, inc) changed_flag, success_flag, inc)
if self.dir_perms_list: self.reset_dir_perms(first_index)
def post_process(self, source_rorp, dest_rorp, changed, success, inc): def post_process(self, source_rorp, dest_rorp, changed, success, inc):
"""Post process source_rorp and dest_rorp. """Post process source_rorp and dest_rorp.
...@@ -352,12 +374,13 @@ class CacheCollatedPostProcess: ...@@ -352,12 +374,13 @@ class CacheCollatedPostProcess:
if Globals.file_statistics: if Globals.file_statistics:
statistics.FileStats.update(source_rorp, dest_rorp, changed, inc) statistics.FileStats.update(source_rorp, dest_rorp, changed, inc)
# Update permissions of unreadable directory def reset_dir_perms(self, current_index):
if (source_rorp and source_rorp.isdir() and Globals.process_uid != 0 """Reset the permissions of directories when we have left them"""
and success and source_rorp.getperms() % 01000 < 0700): dir_rp, perms = self.dir_perms_list[-1]
dest_rp = self.dest_root_rp.new_index(source_rorp.index) dir_index = dir_rp.index
assert dest_rp.isdir(), dest_rp if (current_index > dir_index and
dest_rp.chmod(source_rorp.getperms()) current_index[:len(dir_index)] != dir_index):
dir_rp.chmod(perms) # out of directory, reset perms now
def in_cache(self, index): def in_cache(self, index):
"""Return true if given index is cached""" """Return true if given index is cached"""
...@@ -506,6 +529,7 @@ class PatchITRB(rorpiter.ITRBranch): ...@@ -506,6 +529,7 @@ class PatchITRB(rorpiter.ITRBranch):
"""Set self.dir_replacement, which holds data until done with dir """Set self.dir_replacement, which holds data until done with dir
This is used when base_rp is a dir, and diff_rorp is not. This is used when base_rp is a dir, and diff_rorp is not.
Returns 1 for success or 0 for failure
""" """
assert diff_rorp.get_attached_filetype() == 'snapshot' assert diff_rorp.get_attached_filetype() == 'snapshot'
...@@ -515,10 +539,8 @@ class PatchITRB(rorpiter.ITRBranch): ...@@ -515,10 +539,8 @@ class PatchITRB(rorpiter.ITRBranch):
# Was an error, so now restore original directory # Was an error, so now restore original directory
rpath.copy_with_attribs(self.CCPP.get_mirror_rorp(diff_rorp.index), rpath.copy_with_attribs(self.CCPP.get_mirror_rorp(diff_rorp.index),
self.dir_replacement) self.dir_replacement)
success = 0 return 0
else: success = 1 else: return 1
if base_rp.isdir() and Globals.change_permissions: base_rp.chmod(0700)
return success
def prepare_dir(self, diff_rorp, base_rp): def prepare_dir(self, diff_rorp, base_rp):
"""Prepare base_rp to turn into a directory""" """Prepare base_rp to turn into a directory"""
...@@ -530,7 +552,6 @@ class PatchITRB(rorpiter.ITRBranch): ...@@ -530,7 +552,6 @@ class PatchITRB(rorpiter.ITRBranch):
else: # maybe no change, so query CCPP before tagging success else: # maybe no change, so query CCPP before tagging success
if self.CCPP.in_cache(diff_rorp.index): if self.CCPP.in_cache(diff_rorp.index):
self.CCPP.flag_success(diff_rorp.index) self.CCPP.flag_success(diff_rorp.index)
if Globals.change_permissions: base_rp.chmod(0700)
def end_process(self): def end_process(self):
"""Finish processing directory""" """Finish processing directory"""
......
...@@ -249,8 +249,7 @@ class RegressITRB(rorpiter.ITRBranch): ...@@ -249,8 +249,7 @@ class RegressITRB(rorpiter.ITRBranch):
if not rf.mirror_rp.isdir(): if not rf.mirror_rp.isdir():
if rf.mirror_rp.lstat(): rf.mirror_rp.delete() if rf.mirror_rp.lstat(): rf.mirror_rp.delete()
rf.mirror_rp.mkdir() rf.mirror_rp.mkdir()
if Globals.change_permissions and not rf.mirror_rp.hasfullperms(): if not rf.mirror_rp.hasfullperms(): rf.mirror_rp.chmod(0700)
rf.mirror_rp.chmod(0700)
self.rf = rf self.rf = rf
def end_process(self): def end_process(self):
......
...@@ -582,7 +582,7 @@ class PatchITRB(rorpiter.ITRBranch): ...@@ -582,7 +582,7 @@ class PatchITRB(rorpiter.ITRBranch):
assert diff_rorp.get_attached_filetype() == 'snapshot' assert diff_rorp.get_attached_filetype() == 'snapshot'
self.dir_replacement = TempFile.new(base_rp) self.dir_replacement = TempFile.new(base_rp)
rpath.copy_with_attribs(diff_rorp, self.dir_replacement) rpath.copy_with_attribs(diff_rorp, self.dir_replacement)
if base_rp.isdir() and Globals.change_permissions: base_rp.chmod(0700) if base_rp.isdir(): base_rp.chmod(0700)
def prepare_dir(self, diff_rorp, base_rp): def prepare_dir(self, diff_rorp, base_rp):
"""Prepare base_rp to turn into a directory""" """Prepare base_rp to turn into a directory"""
...@@ -590,7 +590,7 @@ class PatchITRB(rorpiter.ITRBranch): ...@@ -590,7 +590,7 @@ class PatchITRB(rorpiter.ITRBranch):
if not base_rp.isdir(): if not base_rp.isdir():
if base_rp.lstat(): base_rp.delete() if base_rp.lstat(): base_rp.delete()
base_rp.mkdir() base_rp.mkdir()
if Globals.change_permissions: base_rp.chmod(0700) base_rp.chmod(0700)
def end_process(self): def end_process(self):
"""Finish processing directory""" """Finish processing directory"""
......
...@@ -157,7 +157,7 @@ def copy_attribs(rpin, rpout, acls = 1): ...@@ -157,7 +157,7 @@ def copy_attribs(rpin, rpout, acls = 1):
rpout.write_resource_fork(rpin.get_resource_fork()) rpout.write_resource_fork(rpin.get_resource_fork())
if Globals.write_eas: rpout.write_ea(rpin.get_ea()) if Globals.write_eas: rpout.write_ea(rpin.get_ea())
if Globals.change_ownership: apply(rpout.chown, rpin.getuidgid()) if Globals.change_ownership: apply(rpout.chown, rpin.getuidgid())
if Globals.change_permissions: rpout.chmod(rpin.getperms()) rpout.chmod(rpin.getperms())
if Globals.write_acls and acls: rpout.write_acl(rpin.get_acl()) if Globals.write_acls and acls: rpout.write_acl(rpin.get_acl())
if not rpin.isdev(): rpout.setmtime(rpin.getmtime()) if not rpin.isdev(): rpout.setmtime(rpin.getmtime())
...@@ -267,7 +267,6 @@ class RORPath: ...@@ -267,7 +267,6 @@ class RORPath:
for key in self.data.keys(): # compare dicts key by key for key in self.data.keys(): # compare dicts key by key
if (key == 'uid' or key == 'gid') and self.issym(): if (key == 'uid' or key == 'gid') and self.issym():
pass # Don't compare gid/uid for symlinks pass # Don't compare gid/uid for symlinks
elif key == 'perms' and not Globals.change_permissions: pass
elif key == 'atime' and not Globals.preserve_atime: pass elif key == 'atime' and not Globals.preserve_atime: pass
elif key == 'ctime': pass elif key == 'ctime': pass
elif key == 'devloc' or key == 'nlink': pass elif key == 'devloc' or key == 'nlink': pass
...@@ -306,7 +305,6 @@ class RORPath: ...@@ -306,7 +305,6 @@ class RORPath:
elif key == 'ctime': pass elif key == 'ctime': pass
elif key == 'devloc' or key == 'nlink': pass elif key == 'devloc' or key == 'nlink': pass
elif key == 'size' and not self.isreg(): pass elif key == 'size' and not self.isreg(): pass
elif key == 'perms' and not Globals.change_permissions: pass
elif key == 'inode': pass elif key == 'inode': pass
elif key == 'ea' and not Globals.write_eas: pass elif key == 'ea' and not Globals.write_eas: pass
elif key == 'acl' and not Globals.write_acls: pass elif key == 'acl' and not Globals.write_acls: pass
...@@ -329,7 +327,6 @@ class RORPath: ...@@ -329,7 +327,6 @@ class RORPath:
(self.issym() or not compare_ownership)): (self.issym() or not compare_ownership)):
# Don't compare gid/uid for symlinks, or if told not to # Don't compare gid/uid for symlinks, or if told not to
pass pass
elif key == 'perms' and not Globals.change_permissions: pass
elif key == 'atime' and not Globals.preserve_atime: pass elif key == 'atime' and not Globals.preserve_atime: pass
elif key == 'ctime': pass elif key == 'ctime': pass
elif key == 'devloc' or key == 'nlink': pass elif key == 'devloc' or key == 'nlink': pass
......
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