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 (????/??/??)
---------------------------
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)
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"]
#
# The keys are files request, the value is the index of the argument
# 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.rename':0, 'os.renames':0, 'os.rmdir':0, 'os.unlink':0,
'os.utime':0, 'os.lchown':0, 'os.link':1, 'os.symlink':1,
......@@ -136,7 +136,7 @@ def set_allowed_requests(sec_level):
"sys.stdout.write", "robust.install_signal_handlers"]
if (sec_level == "read-only" or sec_level == "update-only" or
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",
"log.Log.log_to_file", "os.getuid", "Time.setcurtime_local",
"rpath.gzip_open_local_read", "rpath.open_local_read",
......
......@@ -36,7 +36,7 @@ are dealing with are local or remote.
"""
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):
......@@ -264,16 +264,65 @@ def rename(rp_source, rp_dest):
rp_dest.data = rp_source.data
rp_source.data = {'type': None}
def tupled_lstat(filename):
"""Like os.lstat, but return only a tuple, or None if os.error
def make_file_dict(filename):
"""Generate the data dictionary for the given RPath
Later versions of os.lstat return a special lstat object,
which can confuse the pickler and cause errors in remote
operations. This has been fixed in Python 2.2.1.
This is a global function so that os.name can be called locally,
thus avoiding network lag and so that we only need to send the
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))
except os.error: return None
try:
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):
"""Make a local socket at the given path
......@@ -826,51 +875,10 @@ class RPath(RORPath):
self.path = "/".join((self.base,) + self.index)
def setdata(self):
"""Set data dictionary using C extension"""
try:
self.data = self.conn.C.make_file_dict(self.path)
except AttributeError:
self.data = self.make_file_dict_python()
"""Set data dictionary using the wrapper"""
self.data = self.conn.rpath.make_file_dict(self.path)
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):
"""Raise an error if consistency of rp broken
......@@ -884,11 +892,6 @@ class RPath(RORPath):
"\nName: %s\nOld: %s --> New: %s\n" % \
(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):
"""Wrapper around os.chmod"""
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