Commit 033e16c5 by rfkelly0

some additional robustness for expose.fuse

parent d54a6ec2
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
fs.expose.fuse: expose an FS object to the native filesystem via FUSE fs.expose.fuse: expose an FS object to the native filesystem via FUSE
This module provides the necessay interfaces to mount an FS object into This module provides the necessary interfaces to mount an FS object into
the local filesystem via FUSE: the local filesystem via FUSE:
http://fuse.sourceforge.net/ http://fuse.sourceforge.net/
...@@ -90,8 +90,13 @@ def handle_fs_errors(func): ...@@ -90,8 +90,13 @@ def handle_fs_errors(func):
def get_stat_dict(fs,path): def get_stat_dict(fs,path):
"""Build a 'stat' dictionary for the given file.""" """Build a 'stat' dictionary for the given file."""
uid, gid, pid = fuse_get_context()
info = fs.getinfo(path) info = fs.getinfo(path)
fill_stat_dict(fs,path,info)
return info
def fill_stat_dict(fs,path,info):
"""Fill default values in the stat dict."""
uid, gid, pid = fuse_get_context()
private_keys = [k for k in info if k.startswith("_")] private_keys = [k for k in info if k.startswith("_")]
for k in private_keys: for k in private_keys:
del info[k] del info[k]
...@@ -105,13 +110,14 @@ def get_stat_dict(fs,path): ...@@ -105,13 +110,14 @@ def get_stat_dict(fs,path):
info.setdefault("st_blocks",1) info.setdefault("st_blocks",1)
# The interesting stuff # The interesting stuff
info.setdefault("st_size",info.get("size",1024)) info.setdefault("st_size",info.get("size",1024))
info.setdefault("st_mode",info.get('st_mode',0700)) mode = info.get("st_mode",0700)
if fs.isdir(path): if not statinfo.S_ISDIR(mode) and not statinfo.S_ISREG(mode):
info["st_mode"] = info["st_mode"] | statinfo.S_IFDIR if fs.isdir(path):
info.setdefault("st_nlink",2) info["st_mode"] = mode | statinfo.S_IFDIR
else: info.setdefault("st_nlink",2)
info["st_mode"] = info["st_mode"] | statinfo.S_IFREG else:
info.setdefault("st_nlink",1) info["st_mode"] = mode | statinfo.S_IFREG
info.setdefault("st_nlink",1)
for (key1,key2) in [("st_atime","accessed_time"),("st_mtime","modified_time"),("st_ctime","created_time")]: for (key1,key2) in [("st_atime","accessed_time"),("st_mtime","modified_time"),("st_ctime","created_time")]:
if key1 not in info: if key1 not in info:
if key2 in info: if key2 in info:
...@@ -119,7 +125,7 @@ def get_stat_dict(fs,path): ...@@ -119,7 +125,7 @@ def get_stat_dict(fs,path):
else: else:
info[key1] = STARTUP_TIME info[key1] = STARTUP_TIME
return info return info
class FSOperations(Operations): class FSOperations(Operations):
"""FUSE Operations interface delegating all activities to an FS object.""" """FUSE Operations interface delegating all activities to an FS object."""
...@@ -224,8 +230,19 @@ class FSOperations(Operations): ...@@ -224,8 +230,19 @@ class FSOperations(Operations):
@handle_fs_errors @handle_fs_errors
def readdir(self,path,fh=None): def readdir(self,path,fh=None):
entries = [e.encode(NATIVE_ENCODING) for e in self.fs.listdir(path)] # If listdir() can return info dicts directly, it will save FUSE
return ['.', '..'] + entries # having to call getinfo() on each entry individually.
try:
entries = self.fs.listdir(path,info=True)
except TypeError:
entries = self.fs.listdir(path)
entries = [e.encode(NATIVE_ENCODING) for e in entries]
else:
entries = [(e["name"].encode(NATIVE_ENCODING),e,0) for e in entries]
for (name,attrs,offset) in entries:
fill_stat_dict(self.fs,pathjoin(path,name),attrs)
entries = [".",".."] + entries
return entries
@handle_fs_errors @handle_fs_errors
def readlink(self,path): def readlink(self,path):
...@@ -246,12 +263,16 @@ class FSOperations(Operations): ...@@ -246,12 +263,16 @@ class FSOperations(Operations):
@handle_fs_errors @handle_fs_errors
def rename(self,old,new): def rename(self,old,new):
if issamedir(old,new): if issamedir(old,new):
self.fs.rename(old,new) try:
else: self.fs.rename(old,new)
if self.fs.isdir(old): except ResourceInvalidError:
self.fs.movedir(old,new) pass
else: else:
self.fs.move(old,new) return None
if self.fs.isdir(old):
self.fs.movedir(old,new)
else:
self.fs.move(old,new)
@handle_fs_errors @handle_fs_errors
def rmdir(self, path): def rmdir(self, path):
...@@ -340,7 +361,9 @@ def unmount(path): ...@@ -340,7 +361,9 @@ def unmount(path):
FUSE filesystem. It works, but it would probably be better to use the FUSE filesystem. It works, but it would probably be better to use the
'unmount' method on the MountProcess class if you have it. 'unmount' method on the MountProcess class if you have it.
""" """
if os.system("fusermount -u '" + path + "'"): p = subprocess.Popen(["fusermount","-u",path],stderr=subprocess.PIPE)
(stdout,stderr) = p.communicate()
if p.returncode != 0 and "not mounted" not in stderr:
raise OSError("filesystem could not be unmounted: " + path) raise OSError("filesystem could not be unmounted: " + path)
......
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