2 # -*- coding: utf-8 -*-
4 # ------------------------------------------------------------
7 # create a mirror filesystem folder as a new filesystem to mount
9 # This is directly based on xmp.py of the
10 # dev-python/fuse-python example
12 # Autor: Oliver Maurhart, <oliver.maurhart@ait.ac.at>
14 # Copyright (C) 2013 AIT Austrian Institute of Technology
15 # AIT Austrian Institute of Technology GmbH
16 # Donau-City-Strasse 1 | 1220 Vienna | Austria
17 # http://www.ait.ac.at
19 # This program is free software; you can redistribute it and/or
20 # modify it under the terms of the GNU General Public License
21 # as published by the Free Software Foundation version 2.
23 # This program is distributed in the hope that it will be useful,
24 # but WITHOUT ANY WARRANTY; without even the implied warranty of
25 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 # GNU General Public License for more details.
28 # You should have received a copy of the GNU General Public License
29 # along with this program; if not, write to the Free Software
30 # Foundation, Inc., 51 Franklin Street, Fifth Floor,
31 # Boston, MA 02110-1301, USA.
32 # ------------------------------------------------------------
35 # ------------------------------------------------------------
46 # ------------------------------------------------------------
53 # ------------------------------------------------------------
57 class MirrorFuse(Fuse):
59 """This is the Mirror FUSE in python.
61 This is to represnt a file hierarchy elsewhere (and intercept each file system call)
64 def __init__(self, *args, **kw):
65 fuse.fuse_python_api = (0, 2)
66 super(MirrorFuse, self).__init__(*args, **kw)
68 self.os_server_url = ''
70 def getattr(self, path):
71 return os.lstat("." + path)
75 # links are not allowed for a mirrored FS
77 def readlink(self, path):
81 def readdir(self, path, offset):
82 for e in os.listdir("." + path):
83 yield fuse.Direntry(e)
86 def unlink(self, path):
87 sys.stdout.write("===\nInsert Hook here! Deleting file %s\n===\n" % path)
91 def rmdir(self, path):
92 sys.stdout.write("===\nInsert Hook here! Deleting folder %s\n===\n" % path)
97 # links are not allowed for a mirrored FS
99 def symlink(self, path, path1):
103 def rename(self, path, path1):
104 sys.stdout.write("===\nInsert Hook here! Moving file %s --> %s\n===\n" % path % path1)
105 os.rename("." + path, "." + path1)
109 # links are not allowed for a mirrored FS
111 def link(self, path, path1):
116 # changing access mode is not allowed in mirrored FS
118 def chmod(self, path, mode):
123 # changing ownership is not allowed in mirrored FS
125 def chown(self, path, user, group):
129 def truncate(self, path, len):
130 f = open("." + path, "a")
135 def mknod(self, path, mode, dev):
136 sys.stdout.write("===\nInsert Hook here! Creating file %s\n===\n" % path)
137 os.mknod("." + path, mode, dev)
140 def mkdir(self, path, mode):
141 sys.stdout.write("===\nInsert Hook here! Creating folder %s\n===\n" % path)
142 os.mkdir("." + path, mode)
145 def utime(self, path, times):
146 os.utime("." + path, times)
149 def access(self, path, mode):
150 if not os.access("." + path, mode):
155 return os.statvfs(".")
162 def main(self, *a, **kw):
163 self.file_class = MirrorFuseFile
164 return Fuse.main(self, *a, **kw)
167 class MirrorFuseFile(object):
169 """This is a single "File" in the Mirror FUSE"""
171 def __init__(self, path, flags, *mode):
172 sys.stdout.write("===\nInsert Hook here! Opening file %s\n===\n" % path)
173 self.file = os.fdopen(os.open("." + path, flags, *mode), flag2mode(flags))
174 self.fd = self.file.fileno()
177 def read(self, length, offset):
178 self.file.seek(offset)
179 return self.file.read(length)
182 def write(self, buf, offset):
183 self.file.seek(offset)
188 def release(self, flags):
193 if 'w' in self.file.mode or 'a' in self.file.mode:
196 def fsync(self, isfsyncfile):
198 if isfsyncfile and hasattr(os, 'fdatasync'):
199 os.fdatasync(self.fd)
206 os.close(os.dup(self.fd))
210 return os.fstat(self.fd)
213 def ftruncate(self, len):
214 self.file.truncate(len)
217 def lock(self, cmd, owner, **kw):
218 op = {fcntl.F_UNLCK : fcntl.LOCK_UN, fcntl.F_RDLCK : fcntl.LOCK_SH, fcntl.F_WRLCK : fcntl.LOCK_EX}[kw['l_type']]
219 if cmd == fcntl.F_GETLK:
221 elif cmd == fcntl.F_SETLK:
222 if op != fcntl.LOCK_UN:
224 elif cmd == fcntl.F_SETLKW:
229 fcntl.lockf(self.fd, op, kw['l_start'], kw['l_len'])
232 def flag2mode(flags):
234 """Turn os flags into mode chars"""
236 md = {os.O_RDONLY: 'r', os.O_WRONLY: 'w', os.O_RDWR: 'w+'}
237 m = md[flags & (os.O_RDONLY | os.O_WRONLY | os.O_RDWR)]
238 if flags | os.O_APPEND:
239 m = m.replace('w', 'a', 1)
246 mirror the a file tree from some point on.
250 # launch the Fuse server
251 server = MirrorFuse(version = "%prog " + __version__, usage = usage, dash_s_do = 'setsingle')
252 server.parser.add_option(mountopt = "root", metavar = "PATH", default='/', help="mirror filesystem from under PATH [default: %default]")
253 server.parser.add_option(mountopt = "os_server_url", metavar = "URL", default='http://localhost:8080', help="URL to OpenSecurity Server [default: %default]")
254 server.parse(values=server, errex=1)
257 if server.fuse_args.mount_expected():
258 os.chdir(server.root)
260 print >> sys.stderr, "can't enter root of underlying filesystem"
267 if __name__ == "__main__":