Commit 32855043 authored by owsla's avatar owsla

Move make_file_dict_python so that it is run on the remote end instead of

the local end.


git-svn-id: http://svn.savannah.nongnu.org/svn/rdiff-backup@912 2b77aa54-bcbc-44c9-a7ec-4f6cf2b41109
parent 028ba830
New in v1.1.17 (????/??/??) New in v1.1.17 (????/??/??)
--------------------------- ---------------------------
Move make_file_dict_python so that it is run on the remote end instead of
the local end. This improves performance for Windows hosts since it eliminates
the lag due to checking os.name. It also makes the Windows design parallel
to the Posix design, since the Windows method now returns a dictionary across
the wire. (Andrew Ferguson)
Catch EPERM error when trying to write extended attributes. (Andrew Ferguson) Catch EPERM error when trying to write extended attributes. (Andrew Ferguson)
Allow rdiff-backup to be built into a single executable on Windows using Allow rdiff-backup to be built into a single executable on Windows using
......
...@@ -41,7 +41,7 @@ disallowed_server_globals = ["server", "security_level", "restrict_path"] ...@@ -41,7 +41,7 @@ disallowed_server_globals = ["server", "security_level", "restrict_path"]
# #
# The keys are files request, the value is the index of the argument # The keys are files request, the value is the index of the argument
# taking a file. # taking a file.
file_requests = {'os.listdir':0, 'C.make_file_dict':0, 'os.chmod':0, file_requests = {'os.listdir':0, 'rpath.make_file_dict':0, 'os.chmod':0,
'os.chown':0, 'os.remove':0, 'os.removedirs':0, 'os.chown':0, 'os.remove':0, 'os.removedirs':0,
'os.rename':0, 'os.renames':0, 'os.rmdir':0, 'os.unlink':0, 'os.rename':0, 'os.renames':0, 'os.rmdir':0, 'os.unlink':0,
'os.utime':0, 'os.lchown':0, 'os.link':1, 'os.symlink':1, 'os.utime':0, 'os.lchown':0, 'os.link':1, 'os.symlink':1,
...@@ -136,7 +136,7 @@ def set_allowed_requests(sec_level): ...@@ -136,7 +136,7 @@ def set_allowed_requests(sec_level):
"sys.stdout.write", "robust.install_signal_handlers"] "sys.stdout.write", "robust.install_signal_handlers"]
if (sec_level == "read-only" or sec_level == "update-only" or if (sec_level == "read-only" or sec_level == "update-only" or
sec_level == "all"): sec_level == "all"):
l.extend(["C.make_file_dict", "os.listdir", "rpath.ea_get", l.extend(["rpath.make_file_dict", "os.listdir", "rpath.ea_get",
"rpath.acl_get", "rpath.setdata_local", "rpath.acl_get", "rpath.setdata_local",
"log.Log.log_to_file", "os.getuid", "Time.setcurtime_local", "log.Log.log_to_file", "os.getuid", "Time.setcurtime_local",
"rpath.gzip_open_local_read", "rpath.open_local_read", "rpath.gzip_open_local_read", "rpath.open_local_read",
......
...@@ -36,7 +36,7 @@ are dealing with are local or remote. ...@@ -36,7 +36,7 @@ are dealing with are local or remote.
""" """
import os, stat, re, sys, shutil, gzip, socket, time, errno import os, stat, re, sys, shutil, gzip, socket, time, errno
import Globals, Time, static, log, user_group import Globals, Time, static, log, user_group, C
class SkipFileException(Exception): class SkipFileException(Exception):
...@@ -264,16 +264,65 @@ def rename(rp_source, rp_dest): ...@@ -264,16 +264,65 @@ def rename(rp_source, rp_dest):
rp_dest.data = rp_source.data rp_dest.data = rp_source.data
rp_source.data = {'type': None} rp_source.data = {'type': None}
def tupled_lstat(filename): def make_file_dict(filename):
"""Like os.lstat, but return only a tuple, or None if os.error """Generate the data dictionary for the given RPath
Later versions of os.lstat return a special lstat object, This is a global function so that os.name can be called locally,
which can confuse the pickler and cause errors in remote thus avoiding network lag and so that we only need to send the
operations. This has been fixed in Python 2.2.1. filename over the network, thus avoiding the need to pickle an
(incomplete) rpath object.
"""
if os.name != 'nt':
return C.make_file_dict(filename)
else:
return make_file_dict_python(filename)
def make_file_dict_python(filename):
"""Create the data dictionary using a Python call to os.lstat
We do this on Windows since Python's implementation is much better
than the one in cmodule.c Eventually, we will move to using
this on all platforms since CPUs have gotten much faster than
they were when it was necessary to write cmodule.c
""" """
try: return tuple(os.lstat(filename)) try:
except os.error: return None statblock = os.lstat(filename)
except os.error:
return {'type':None}
data = {}
mode = statblock[stat.ST_MODE]
if stat.S_ISREG(mode): type = 'reg'
elif stat.S_ISDIR(mode): type = 'dir'
elif stat.S_ISCHR(mode):
type = 'dev'
s = statblock.st_rdev
data['devnums'] = ('c',) + (s >> 8, s & 0xff)
elif stat.S_ISBLK(mode):
type = 'dev'
s = statblock.st_rdev
data['devnums'] = ('b',) + (s >> 8, s & 0xff)
elif stat.S_ISFIFO(mode): type = 'fifo'
elif stat.S_ISLNK(mode):
type = 'sym'
data['linkname'] = os.readlink(filename)
elif stat.S_ISSOCK(mode): type = 'sock'
else: raise C.UnknownFileError(filename)
data['type'] = type
data['size'] = statblock[stat.ST_SIZE]
data['perms'] = stat.S_IMODE(mode)
data['uid'] = statblock[stat.ST_UID]
data['gid'] = statblock[stat.ST_GID]
data['inode'] = statblock[stat.ST_INO]
data['devloc'] = statblock[stat.ST_DEV]
data['nlink'] = statblock[stat.ST_NLINK]
if not (type == 'sym' or type == 'dev'):
# mtimes on symlinks and dev files don't work consistently
data['mtime'] = long(statblock[stat.ST_MTIME])
data['atime'] = long(statblock[stat.ST_ATIME])
data['ctime'] = long(statblock[stat.ST_CTIME])
return data
def make_socket_local(rpath): def make_socket_local(rpath):
"""Make a local socket at the given path """Make a local socket at the given path
...@@ -826,51 +875,10 @@ class RPath(RORPath): ...@@ -826,51 +875,10 @@ class RPath(RORPath):
self.path = "/".join((self.base,) + self.index) self.path = "/".join((self.base,) + self.index)
def setdata(self): def setdata(self):
"""Set data dictionary using C extension""" """Set data dictionary using the wrapper"""
try: self.data = self.conn.rpath.make_file_dict(self.path)
self.data = self.conn.C.make_file_dict(self.path)
except AttributeError:
self.data = self.make_file_dict_python()
if self.lstat(): self.conn.rpath.setdata_local(self) if self.lstat(): self.conn.rpath.setdata_local(self)
def make_file_dict_python(self):
"""Create the data dictionary"""
statblock = self.conn.rpath.tupled_lstat(self.path)
if statblock is None:
return {'type':None}
data = {}
mode = statblock[stat.ST_MODE]
if stat.S_ISREG(mode): type = 'reg'
elif stat.S_ISDIR(mode): type = 'dir'
elif stat.S_ISCHR(mode):
type = 'dev'
data['devnums'] = ('c',) + self._getdevnums()
elif stat.S_ISBLK(mode):
type = 'dev'
data['devnums'] = ('b',) + self._getdevnums()
elif stat.S_ISFIFO(mode): type = 'fifo'
elif stat.S_ISLNK(mode):
type = 'sym'
data['linkname'] = self.conn.os.readlink(self.path)
elif stat.S_ISSOCK(mode): type = 'sock'
else: raise C.UnknownFileError(self.path)
data['type'] = type
data['size'] = statblock[stat.ST_SIZE]
data['perms'] = stat.S_IMODE(mode)
data['uid'] = statblock[stat.ST_UID]
data['gid'] = statblock[stat.ST_GID]
data['inode'] = statblock[stat.ST_INO]
data['devloc'] = statblock[stat.ST_DEV]
data['nlink'] = statblock[stat.ST_NLINK]
if not (type == 'sym' or type == 'dev'):
# mtimes on symlinks and dev files don't work consistently
data['mtime'] = long(statblock[stat.ST_MTIME])
data['atime'] = long(statblock[stat.ST_ATIME])
data['ctime'] = long(statblock[stat.ST_CTIME])
return data
def check_consistency(self): def check_consistency(self):
"""Raise an error if consistency of rp broken """Raise an error if consistency of rp broken
...@@ -884,11 +892,6 @@ class RPath(RORPath): ...@@ -884,11 +892,6 @@ class RPath(RORPath):
"\nName: %s\nOld: %s --> New: %s\n" % \ "\nName: %s\nOld: %s --> New: %s\n" % \
(self.path, temptype, self.data['type']) (self.path, temptype, self.data['type'])
def _getdevnums(self):
"""Return tuple for special file (major, minor)"""
s = self.conn.reval("lambda path: os.lstat(path).st_rdev", self.path)
return (s >> 8, s & 0xff)
def chmod(self, permissions): def chmod(self, permissions):
"""Wrapper around os.chmod""" """Wrapper around os.chmod"""
try: try:
......
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