1 | #!/usr/bin/python2.5 |
---|
2 | |
---|
3 | # pyHesiodFS: |
---|
4 | # Copyright (C) 2007 Quentin Smith <quentin@mit.edu> |
---|
5 | # "Hello World" pyFUSE example: |
---|
6 | # Copyright (C) 2006 Andrew Straw <strawman@astraw.com> |
---|
7 | # |
---|
8 | # This program can be distributed under the terms of the GNU LGPL. |
---|
9 | # See the file COPYING. |
---|
10 | # |
---|
11 | |
---|
12 | import sys, os, stat, errno |
---|
13 | import fuse |
---|
14 | from fuse import Fuse |
---|
15 | |
---|
16 | import hesiod |
---|
17 | |
---|
18 | if not hasattr(fuse, '__version__'): |
---|
19 | raise RuntimeError, \ |
---|
20 | "your fuse-py doesn't know of fuse.__version__, probably it's too old." |
---|
21 | |
---|
22 | fuse.fuse_python_api = (0, 2) |
---|
23 | |
---|
24 | hello_path = '/README.txt' |
---|
25 | hello_str = """This is the pyhesiodfs FUSE autmounter. To access a Hesiod filsys, just access |
---|
26 | %(mountpoint)s/name. |
---|
27 | |
---|
28 | If you're using the Finder, try pressing Cmd+Shift+G and then entering |
---|
29 | %(mountpoint)s/name""" |
---|
30 | |
---|
31 | class MyStat(fuse.Stat): |
---|
32 | def __init__(self): |
---|
33 | self.st_mode = 0 |
---|
34 | self.st_ino = 0 |
---|
35 | self.st_dev = 0 |
---|
36 | self.st_nlink = 0 |
---|
37 | self.st_uid = 0 |
---|
38 | self.st_gid = 0 |
---|
39 | self.st_size = 0 |
---|
40 | self.st_atime = 0 |
---|
41 | self.st_mtime = 0 |
---|
42 | self.st_ctime = 0 |
---|
43 | |
---|
44 | class PyHesiodFS(Fuse): |
---|
45 | |
---|
46 | def __init__(self, *args, **kwargs): |
---|
47 | Fuse.__init__(self, *args, **kwargs) |
---|
48 | self.fuse_args.add("allow_other", True) |
---|
49 | self.fuse_args.add("noappledouble", True) |
---|
50 | self.fuse_args.add("noapplexattr", True) |
---|
51 | self.fuse_args.add("fsname", "pyHesiodFS") |
---|
52 | self.fuse_args.add("volname", "MIT") |
---|
53 | self.mounts = {} |
---|
54 | |
---|
55 | def getattr(self, path): |
---|
56 | st = MyStat() |
---|
57 | if path == '/': |
---|
58 | st.st_mode = stat.S_IFDIR | 0755 |
---|
59 | st.st_nlink = 2 |
---|
60 | elif path == hello_path: |
---|
61 | st.st_mode = stat.S_IFREG | 0444 |
---|
62 | st.st_nlink = 1 |
---|
63 | st.st_size = len(hello_str) |
---|
64 | elif '/' not in path[1:]: |
---|
65 | if self.findLocker(path[1:]): |
---|
66 | st.st_mode = stat.S_IFLNK | 0777 |
---|
67 | st.st_nlink = 1 |
---|
68 | st.st_size = len(self.findLocker(path[1:])) |
---|
69 | else: |
---|
70 | return -errno.ENOENT |
---|
71 | else: |
---|
72 | return -errno.ENOENT |
---|
73 | return st |
---|
74 | |
---|
75 | def getCachedLockers(self): |
---|
76 | return self.mounts.keys() |
---|
77 | |
---|
78 | def findLocker(self, name): |
---|
79 | """Lookup a locker in hesiod and return its path""" |
---|
80 | if name in self.mounts: |
---|
81 | return self.mounts[name] |
---|
82 | else: |
---|
83 | filsys = hesiod.FilsysLookup(name) |
---|
84 | # FIXME check if the first locker is valid |
---|
85 | if len(filsys.getFilsys()) >= 1: |
---|
86 | pointers = filsys.getFilsys() |
---|
87 | pointer = pointers[0] |
---|
88 | if pointer['type'] != 'AFS' and pointer['type'] != 'LOC': |
---|
89 | print >>sys.stderr, "Unknown locker type "+pointer.type+" for locker "+name+" ("+repr(pointer)+" )" |
---|
90 | return None |
---|
91 | else: |
---|
92 | self.mounts[name] = pointer['location'] |
---|
93 | print >>sys.stderr, "Mounting "+name+" on "+pointer['location'] |
---|
94 | return pointer['location'] |
---|
95 | else: |
---|
96 | print >>sys.stderr, "Couldn't find filsys for "+name |
---|
97 | return None |
---|
98 | |
---|
99 | def readdir(self, path, offset): |
---|
100 | for r in ['.', '..', hello_path[1:]]+self.getCachedLockers(): |
---|
101 | yield fuse.Direntry(r) |
---|
102 | |
---|
103 | def readlink(self, path): |
---|
104 | return self.findLocker(path[1:]) |
---|
105 | |
---|
106 | def open(self, path, flags): |
---|
107 | if path != hello_path: |
---|
108 | return -errno.ENOENT |
---|
109 | accmode = os.O_RDONLY | os.O_WRONLY | os.O_RDWR |
---|
110 | if (flags & accmode) != os.O_RDONLY: |
---|
111 | return -errno.EACCES |
---|
112 | |
---|
113 | def read(self, path, size, offset): |
---|
114 | if path != hello_path: |
---|
115 | return -errno.ENOENT |
---|
116 | slen = len(hello_str) |
---|
117 | if offset < slen: |
---|
118 | if offset + size > slen: |
---|
119 | size = slen - offset |
---|
120 | buf = hello_str[offset:offset+size] |
---|
121 | else: |
---|
122 | buf = '' |
---|
123 | return buf |
---|
124 | |
---|
125 | def main(): |
---|
126 | global hello_str |
---|
127 | usage=""" |
---|
128 | pyHesiodFS |
---|
129 | |
---|
130 | """ + Fuse.fusage |
---|
131 | server = PyHesiodFS(version="%prog " + fuse.__version__, |
---|
132 | usage=usage, |
---|
133 | dash_s_do='setsingle') |
---|
134 | |
---|
135 | server.parse(errex=1) |
---|
136 | hello_str = hello_str % {'mountpoint': server.parse(errex=1).mountpoint} |
---|
137 | server.main() |
---|
138 | |
---|
139 | if __name__ == '__main__': |
---|
140 | main() |
---|