2 RouteFS is a base class for developing read-only FUSE filesystems that
3 lets you focus on the directory tree instead of the system calls.
5 RouteFS uses the Routes library developed for Pylons. URLs were
6 inspired by filesystems, and now you can have filesystems inspired by
18 fuse.fuse_python_api = (0, 2)
21 class RouteStat(fuse.Stat):
23 RouteStat is a descendent of fuse.Stat, defined to make sure that
24 all of the necessary attributes are always defined
39 class RouteFS(fuse.Fuse):
41 RouteFS: Web 2.0 for filesystems
43 Any method that will be used as the controller in a Routes mapping
44 (either by explicitly specifying the controller or by using the
45 ':controller' variable) must be added to RouteFS.controllers
48 def __init__(self, *args, **kwargs):
49 super(RouteFS, self).__init__(*args, **kwargs)
51 self.map = self.make_map()
52 self.map.create_regs(self.controllers)
56 This method should be overridden by descendents of RouteFS to
57 define the routing for the filesystem
61 m.connect(':controller')
65 def _get_file(self, path):
67 Find the filesystem entry object for a given path
69 match = self.map.match(path)
72 controller = match.pop('controller')
73 result = getattr(self, controller)(**match)
76 if type(result) is str:
78 if type(result) is list:
79 result = Directory(result)
82 def readdir(self, path, offset):
84 If the path referred to is a directory, return the elements of
87 return self._get_file(path).readdir(offset)
89 def getattr(self, path):
91 Return the stat information for a path
93 The stat information for a directory, symlink, or file is
94 predetermined based on which it is.
96 return self._get_file(path).getattr()
98 def read(self, path, length, offset):
100 If the path specified is a file, return the requested portion
103 return self._get_file(path).read(length, offset)
105 def readlink(self, path):
107 If the path specified is a symlink, return the target
109 return self._get_file(path).readlink()
111 def write(self, path, buf, offset):
113 If the path specified is a file, call the appropriate member
116 return self._get_file(path).write(buf, offset)
119 class TreeKey(object):
122 def readdir(self, offset):
124 def read(self, length, offset):
128 def write(self, length, offset):
132 class NoEntry(TreeKey):
135 def readdir(self, offset):
137 def read(self, length, offset):
141 def write(self, length, offset):
145 class TreeEntry(TreeKey):
148 def __new__(cls, contents, mode=None):
149 return super(TreeEntry, cls).__new__(cls, contents)
151 def __init__(self, contents, mode=None):
153 self.mode = self.default_mode
157 super(TreeEntry, self).__init__(contents)
160 class Directory(TreeEntry, list):
162 A dummy class representing a filesystem entry that should be a
169 st.st_mode = stat.S_IFDIR | self.mode
173 def readdir(self, offset):
174 for member in ['.', '..'] + self:
175 yield fuse.Direntry(str(member))
178 class Symlink(TreeEntry, str):
180 A dummy class representing something that should be a symlink
186 st.st_mode = stat.S_IFLNK | self.mode
188 st.st_size = len(self)
195 class File(TreeEntry, str):
197 A dummy class representing something that should be a file
203 st.st_mode = stat.S_IFREG | self.mode
205 st.st_size = len(self)
208 def read(self, length, offset):
209 return self[offset:offset + length]
214 A convenience function for initializing a RouteFS filesystem
216 server = cls(version="%prog " + fuse.__version__,
217 usage=fuse.Fuse.fusage,
218 dash_s_do='setsingle')
219 server.parse(values=server, errex=1)
223 from dictfs import DictFS
225 __all__ = ['RouteFS', 'DictFS', 'Symlink', 'Directory', 'File', 'main']