First hack at a version
[invirt/packages/python-routefs.git] / routefs / __init__.py
1 import fuse
2 import routes
3 import errno
4 import stat
5
6 fuse.fuse_python_api = (0, 2)
7
8 class RouteStat(fuse.Stat):
9     def __init__(self):
10         self.st_mode = 0
11         self.st_ino = 0
12         self.st_dev = 0
13         self.st_nlink = 0
14         self.st_uid = 0
15         self.st_gid = 0
16         self.st_size = 0
17         self.st_atime = 0
18         self.st_mtime = 0
19         self.st_ctime = 0
20
21 class RouteMeta(type):
22     def __init__(cls, classname, bases, dict_):
23         super(RouteMeta, cls).__init__(classname, bases, dict_)
24         if bases != (fuse.Fuse,):
25             new_funcs = set(dict_.keys()).difference(dir(RouteFS))
26             cls.controllers([func for func in new_funcs \
27                                  if not func.startswith('_')])
28
29 class RouteFS(fuse.Fuse):
30     __metaclass__ = RouteMeta
31     def __init__(self, *args, **kwargs):
32         super(RouteFS, self).__init__(*args, **kwargs)
33         
34         self.map = self.make_map()
35         self.map.create_regs(self.controller_list)
36         
37     def make_map(self):
38         m = routes.Mapper()
39         
40         m.connect(':controller')
41         
42         return m
43     
44     @classmethod
45     def controllers(cls, lst):
46         cls.controller_list = lst
47     
48     def _get_file(self, path):
49         match = self.map.match(path)
50         if match is None:
51             return
52         controller = match.pop('controller')
53         result = getattr(self, controller)(**match)
54         return result
55     
56     def readdir(self, path, offset):
57         obj = self._get_file(path)
58         if type(obj) is not Directory:
59             return
60         else:
61             for member in ['.', '..'] + obj:
62                 yield fuse.Direntry(str(member))
63     
64     def getattr(self, path):
65         obj = self._get_file(path)
66         if obj is None:
67             return -errno.ENOENT
68         
69         st = RouteStat()
70         if type(obj) is Directory:
71             st.st_mode = stat.S_IFDIR | 0755
72             st.st_nlink = 2
73         elif type(obj) is Symlink:
74             st.st_mode = stat.S_IFLNK | 0777
75             st.st_nlink = 1
76             st.st_size = len(obj)
77         else:
78             st.st_mode = stat.S_IFREG | 0444
79             st.st_nlink = 1
80             st.st_size = len(obj)
81         
82         return st
83     
84     def read(self, path, length, offset):
85         obj = self._get_file(path)
86         if obj is None:
87             return -errno.ENOENT
88         elif type(obj) in (Directory, Symlink):
89             return -errno.EINVAL
90         else:
91             return obj[offset:offset + length]
92     
93     def readlink(self, path):
94         obj = self._get_file(path)
95         if type(obj) is not Symlink:
96             return -errno.EINVAL
97         else:
98             return obj
99
100 class Directory(list):
101     """
102     A dummy class representing a filesystem entry that should be a
103     directory
104     """
105     pass
106
107 class Symlink(str):
108     """
109     A dummy class representing something that should be a symlink
110     """
111     pass
112
113 def main(cls):
114     server = cls(version="%prog " + fuse.__version__,
115                  usage=fuse.Fuse.fusage,
116                  dash_s_do='setsingle')
117     server.parse(errex=1)
118     server.main()