From 09f012fb2e8d2357d5bfe91e33fbadce0cb345dc Mon Sep 17 00:00:00 2001 From: bryan newbold Date: Tue, 29 Jul 2008 02:34:19 -0400 Subject: helper files --- _find_fuse_parts.py | 22 ++++ bundled_examples/hello.py | 92 +++++++++++++++ bundled_examples/xmp.py | 279 ++++++++++++++++++++++++++++++++++++++++++++++ first_try.py | 269 -------------------------------------------- 4 files changed, 393 insertions(+), 269 deletions(-) create mode 100644 _find_fuse_parts.py create mode 100644 bundled_examples/hello.py create mode 100644 bundled_examples/xmp.py delete mode 100644 first_try.py diff --git a/_find_fuse_parts.py b/_find_fuse_parts.py new file mode 100644 index 0000000..2a04ab3 --- /dev/null +++ b/_find_fuse_parts.py @@ -0,0 +1,22 @@ +import sys, os, glob +from os.path import realpath, dirname, join +from traceback import format_exception + +ddd = realpath(join(dirname(sys.argv[0]), '..')) + +for d in [ddd, '.']: + for p in glob.glob(join(d, 'build', 'lib.*')): + sys.path.insert(0, p) + +try: + import fuse +except ImportError: + raise RuntimeError, """ + +! Got exception: +""" + "".join([ "> " + x for x in format_exception(*sys.exc_info()) ]) + """ +! Have you ran `python setup.py build'? +! +! We've done our best to find the necessary components of the FUSE bindings +! even if it's not installed, we've got no clue what went wrong for you... +""" diff --git a/bundled_examples/hello.py b/bundled_examples/hello.py new file mode 100644 index 0000000..b0775a6 --- /dev/null +++ b/bundled_examples/hello.py @@ -0,0 +1,92 @@ +#!/usr/bin/env python + +# Copyright (C) 2006 Andrew Straw +# +# This program can be distributed under the terms of the GNU LGPL. +# See the file COPYING. +# + +import os, stat, errno +# pull in some spaghetti to make this stuff work without fuse-py being installed +try: + import _find_fuse_parts +except ImportError: + pass +import fuse +from fuse import Fuse + + +if not hasattr(fuse, '__version__'): + raise RuntimeError, \ + "your fuse-py doesn't know of fuse.__version__, probably it's too old." + +fuse.fuse_python_api = (0, 2) + +hello_path = '/hello' +hello_str = 'Hello World!\n' + +class MyStat(fuse.Stat): + def __init__(self): + self.st_mode = 0 + self.st_ino = 0 + self.st_dev = 0 + self.st_nlink = 0 + self.st_uid = 0 + self.st_gid = 0 + self.st_size = 0 + self.st_atime = 0 + self.st_mtime = 0 + self.st_ctime = 0 + +class HelloFS(Fuse): + + def getattr(self, path): + st = MyStat() + if path == '/': + st.st_mode = stat.S_IFDIR | 0755 + st.st_nlink = 2 + elif path == hello_path: + st.st_mode = stat.S_IFREG | 0444 + st.st_nlink = 1 + st.st_size = len(hello_str) + else: + return -errno.ENOENT + return st + + def readdir(self, path, offset): + for r in '.', '..', hello_path[1:]: + yield fuse.Direntry(r) + + def open(self, path, flags): + if path != hello_path: + return -errno.ENOENT + accmode = os.O_RDONLY | os.O_WRONLY | os.O_RDWR + if (flags & accmode) != os.O_RDONLY: + return -errno.EACCES + + def read(self, path, size, offset): + if path != hello_path: + return -errno.ENOENT + slen = len(hello_str) + if offset < slen: + if offset + size > slen: + size = slen - offset + buf = hello_str[offset:offset+size] + else: + buf = '' + return buf + +def main(): + usage=""" +Userspace hello example + +""" + Fuse.fusage + server = HelloFS(version="%prog " + fuse.__version__, + usage=usage, + dash_s_do='setsingle') + + server.parse(errex=1) + server.main() + +if __name__ == '__main__': + main() diff --git a/bundled_examples/xmp.py b/bundled_examples/xmp.py new file mode 100644 index 0000000..a82c097 --- /dev/null +++ b/bundled_examples/xmp.py @@ -0,0 +1,279 @@ +#!/usr/bin/env python + +# Copyright (C) 2001 Jeff Epler +# Copyright (C) 2006 Csaba Henk +# +# This program can be distributed under the terms of the GNU LGPL. +# See the file COPYING. +# + +import os, sys +from errno import * +from stat import * +import fcntl +# pull in some spaghetti to make this stuff work without fuse-py being installed +try: + import _find_fuse_parts +except ImportError: + pass +import fuse +from fuse import Fuse + + +if not hasattr(fuse, '__version__'): + raise RuntimeError, \ + "your fuse-py doesn't know of fuse.__version__, probably it's too old." + +fuse.fuse_python_api = (0, 2) + +fuse.feature_assert('stateful_files', 'has_init') + + +def flag2mode(flags): + md = {os.O_RDONLY: 'r', os.O_WRONLY: 'w', os.O_RDWR: 'w+'} + m = md[flags & (os.O_RDONLY | os.O_WRONLY | os.O_RDWR)] + + if flags | os.O_APPEND: + m = m.replace('w', 'a', 1) + + return m + + +class Xmp(Fuse): + + def __init__(self, *args, **kw): + + Fuse.__init__(self, *args, **kw) + + # do stuff to set up your filesystem here, if you want + #import thread + #thread.start_new_thread(self.mythread, ()) + self.root = '/' + +# def mythread(self): +# +# """ +# The beauty of the FUSE python implementation is that with the python interp +# running in foreground, you can have threads +# """ +# print "mythread: started" +# while 1: +# time.sleep(120) +# print "mythread: ticking" + + def getattr(self, path): + return os.lstat("." + path) + + def readlink(self, path): + return os.readlink("." + path) + + def readdir(self, path, offset): + for e in os.listdir("." + path): + yield fuse.Direntry(e) + + def unlink(self, path): + os.unlink("." + path) + + def rmdir(self, path): + os.rmdir("." + path) + + def symlink(self, path, path1): + os.symlink(path, "." + path1) + + def rename(self, path, path1): + os.rename("." + path, "." + path1) + + def link(self, path, path1): + os.link("." + path, "." + path1) + + def chmod(self, path, mode): + os.chmod("." + path, mode) + + def chown(self, path, user, group): + os.chown("." + path, user, group) + + def truncate(self, path, len): + f = open("." + path, "a") + f.truncate(len) + f.close() + + def mknod(self, path, mode, dev): + os.mknod("." + path, mode, dev) + + def mkdir(self, path, mode): + os.mkdir("." + path, mode) + + def utime(self, path, times): + os.utime("." + path, times) + +# The following utimens method would do the same as the above utime method. +# We can't make it better though as the Python stdlib doesn't know of +# subsecond preciseness in acces/modify times. +# +# def utimens(self, path, ts_acc, ts_mod): +# os.utime("." + path, (ts_acc.tv_sec, ts_mod.tv_sec)) + + def access(self, path, mode): + if not os.access("." + path, mode): + return -EACCES + +# This is how we could add stub extended attribute handlers... +# (We can't have ones which aptly delegate requests to the underlying fs +# because Python lacks a standard xattr interface.) +# +# def getxattr(self, path, name, size): +# val = name.swapcase() + '@' + path +# if size == 0: +# # We are asked for size of the value. +# return len(val) +# return val +# +# def listxattr(self, path, size): +# # We use the "user" namespace to please XFS utils +# aa = ["user." + a for a in ("foo", "bar")] +# if size == 0: +# # We are asked for size of the attr list, ie. joint size of attrs +# # plus null separators. +# return len("".join(aa)) + len(aa) +# return aa + + def statfs(self): + """ + Should return an object with statvfs attributes (f_bsize, f_frsize...). + Eg., the return value of os.statvfs() is such a thing (since py 2.2). + If you are not reusing an existing statvfs object, start with + fuse.StatVFS(), and define the attributes. + + To provide usable information (ie., you want sensible df(1) + output, you are suggested to specify the following attributes: + + - f_bsize - preferred size of file blocks, in bytes + - f_frsize - fundamental size of file blcoks, in bytes + [if you have no idea, use the same as blocksize] + - f_blocks - total number of blocks in the filesystem + - f_bfree - number of free blocks + - f_files - total number of file inodes + - f_ffree - nunber of free file inodes + """ + + return os.statvfs(".") + + def fsinit(self): + os.chdir(self.root) + + class XmpFile(object): + + def __init__(self, path, flags, *mode): + self.file = os.fdopen(os.open("." + path, flags, *mode), + flag2mode(flags)) + self.fd = self.file.fileno() + + def read(self, length, offset): + self.file.seek(offset) + return self.file.read(length) + + def write(self, buf, offset): + self.file.seek(offset) + self.file.write(buf) + return len(buf) + + def release(self, flags): + self.file.close() + + def _fflush(self): + if 'w' in self.file.mode or 'a' in self.file.mode: + self.file.flush() + + def fsync(self, isfsyncfile): + self._fflush() + if isfsyncfile and hasattr(os, 'fdatasync'): + os.fdatasync(self.fd) + else: + os.fsync(self.fd) + + def flush(self): + self._fflush() + # cf. xmp_flush() in fusexmp_fh.c + os.close(os.dup(self.fd)) + + def fgetattr(self): + return os.fstat(self.fd) + + def ftruncate(self, len): + self.file.truncate(len) + + def lock(self, cmd, owner, **kw): + # The code here is much rather just a demonstration of the locking + # API than something which actually was seen to be useful. + + # Advisory file locking is pretty messy in Unix, and the Python + # interface to this doesn't make it better. + # We can't do fcntl(2)/F_GETLK from Python in a platfrom independent + # way. The following implementation *might* work under Linux. + # + # if cmd == fcntl.F_GETLK: + # import struct + # + # lockdata = struct.pack('hhQQi', kw['l_type'], os.SEEK_SET, + # kw['l_start'], kw['l_len'], kw['l_pid']) + # ld2 = fcntl.fcntl(self.fd, fcntl.F_GETLK, lockdata) + # flockfields = ('l_type', 'l_whence', 'l_start', 'l_len', 'l_pid') + # uld2 = struct.unpack('hhQQi', ld2) + # res = {} + # for i in xrange(len(uld2)): + # res[flockfields[i]] = uld2[i] + # + # return fuse.Flock(**res) + + # Convert fcntl-ish lock parameters to Python's weird + # lockf(3)/flock(2) medley locking API... + op = { fcntl.F_UNLCK : fcntl.LOCK_UN, + fcntl.F_RDLCK : fcntl.LOCK_SH, + fcntl.F_WRLCK : fcntl.LOCK_EX }[kw['l_type']] + if cmd == fcntl.F_GETLK: + return -EOPNOTSUPP + elif cmd == fcntl.F_SETLK: + if op != fcntl.LOCK_UN: + op |= fcntl.LOCK_NB + elif cmd == fcntl.F_SETLKW: + pass + else: + return -EINVAL + + fcntl.lockf(self.fd, op, kw['l_start'], kw['l_len']) + + + def main(self, *a, **kw): + + self.file_class = self.XmpFile + + return Fuse.main(self, *a, **kw) + + +def main(): + + usage = """ +Userspace nullfs-alike: mirror the filesystem tree from some point on. + +""" + Fuse.fusage + + server = Xmp(version="%prog " + fuse.__version__, + usage=usage, + dash_s_do='setsingle') + + server.parser.add_option(mountopt="root", metavar="PATH", default='/', + help="mirror filesystem from under PATH [default: %default]") + server.parse(values=server, errex=1) + + try: + if server.fuse_args.mount_expected(): + os.chdir(server.root) + except OSError: + print >> sys.stderr, "can't enter root of underlying filesystem" + sys.exit(1) + + server.main() + + +if __name__ == '__main__': + main() diff --git a/first_try.py b/first_try.py deleted file mode 100644 index 04a831e..0000000 --- a/first_try.py +++ /dev/null @@ -1,269 +0,0 @@ -#!/usr/bin/env python - -# July 2008: Bryan Newbold -# Based on xmp.py - -import os, sys -from errno import * -from stat import * -import fcntl -# pull in some spaghetti to make this stuff work without fuse-py being installed -try: - import _find_fuse_parts -except ImportError: - pass -import fuse -from fuse import Fuse - - -if not hasattr(fuse, '__version__'): - raise RuntimeError, \ - "your fuse-py doesn't know of fuse.__version__, probably it's too old." - -fuse.fuse_python_api = (0, 2) - -fuse.feature_assert('stateful_files', 'has_init') - - -def flag2mode(flags): - md = {os.O_RDONLY: 'r', os.O_WRONLY: 'w', os.O_RDWR: 'w+'} - m = md[flags & (os.O_RDONLY | os.O_WRONLY | os.O_RDWR)] - - if flags | os.O_APPEND: - m = m.replace('w', 'a', 1) - - return m - - -class PyNamespace(Fuse): - - def __init__(self, *args, **kw): - - Fuse.__init__(self, *args, **kw) - - # do stuff to set up your filesystem here, if you want - #import thread - #thread.start_new_thread(self.mythread, ()) - #self.root = '/' - -# def mythread(self): -# -# """ -# The beauty of the FUSE python implementation is that with the python interp -# running in foreground, you can have threads -# """ -# print "mythread: started" -# while 1: -# time.sleep(120) -# print "mythread: ticking" - - def getattr(self, path): - return locals()[path].__repr__ - - def readlink(self, path): - return str(path) - - def readdir(self, path, offset): - for e in os.listdir("." + path): - yield fuse.Direntry(e) - - def unlink(self, path): - del locals()[path] - - def rmdir(self, path): - del locals()[path] - - def symlink(self, path, path1): - locals()[path1] = locals()[path] - - def rename(self, path, path1): - locals()[path1] = locals()[path] - del locals()[path] - - def link(self, path, path1): - locals()[path1] = locals()[path] - - def chmod(self, path, mode): - return -EPFNOSUPPORT - - def chown(self, path, user, group): - return -EPFNOSUPPORT - - def truncate(self, path, len): - return -EPFNOSUPPORT - - def mknod(self, path, mode, dev): - return -EPFNOSUPPORT - - def mkdir(self, path, mode): - return -EPFNOSUPPORT - - def utime(self, path, times): - return -EPFNOSUPPORT - -# The following utimens method would do the same as the above utime method. -# We can't make it better though as the Python stdlib doesn't know of -# subsecond preciseness in acces/modify times. -# -# def utimens(self, path, ts_acc, ts_mod): -# os.utime("." + path, (ts_acc.tv_sec, ts_mod.tv_sec)) - - def access(self, path, mode): - if not os.access("." + path, mode): - return -EACCES - -# This is how we could add stub extended attribute handlers... -# (We can't have ones which aptly delegate requests to the underlying fs -# because Python lacks a standard xattr interface.) -# -# def getxattr(self, path, name, size): -# val = name.swapcase() + '@' + path -# if size == 0: -# # We are asked for size of the value. -# return len(val) -# return val -# -# def listxattr(self, path, size): -# # We use the "user" namespace to please XFS utils -# aa = ["user." + a for a in ("foo", "bar")] -# if size == 0: -# # We are asked for size of the attr list, ie. joint size of attrs -# # plus null separators. -# return len("".join(aa)) + len(aa) -# return aa - - def statfs(self): - """ - Should return an object with statvfs attributes (f_bsize, f_frsize...). - Eg., the return value of os.statvfs() is such a thing (since py 2.2). - If you are not reusing an existing statvfs object, start with - fuse.StatVFS(), and define the attributes. - - To provide usable information (ie., you want sensible df(1) - output, you are suggested to specify the following attributes: - - - f_bsize - preferred size of file blocks, in bytes - - f_frsize - fundamental size of file blcoks, in bytes - [if you have no idea, use the same as blocksize] - - f_blocks - total number of blocks in the filesystem - - f_bfree - number of free blocks - - f_files - total number of file inodes - - f_ffree - nunber of free file inodes - """ - rval = os.statvfs(".") - rval[3] = len(locals()) - rval[5] = len(locals()) - return rval - - def fsinit(self): - #os.chdir(self.root) - pass - - class PyNamespaceFile(object): - - def __init__(self, path, flags, *mode): - self.fobject = locals()[path] - self.fstr = StringIO(str(self.fobject)) - - def read(self, length, offset): - return self.fstr.read(length) - - def write(self, buf, offset): - self.fstr.seek(offset) - self.fstr.write(buf) - return len(buf) - - def release(self, flags): - self.fstr.close() - - def _fflush(self): - if 'w' in self.fstr.mode or 'a' in self.fstr.mode: - self.fstr.flush() - - def fsync(self, isfsyncfile): - pass - - def flush(self): - pass - - def fgetattr(self): - pass - - def ftruncate(self, len): - self.fstr.truncate(len) - - def lock(self, cmd, owner, **kw): - # The code here is much rather just a demonstration of the locking - # API than something which actually was seen to be useful. - - # Advisory file locking is pretty messy in Unix, and the Python - # interface to this doesn't make it better. - # We can't do fcntl(2)/F_GETLK from Python in a platfrom independent - # way. The following implementation *might* work under Linux. - # - # if cmd == fcntl.F_GETLK: - # import struct - # - # lockdata = struct.pack('hhQQi', kw['l_type'], os.SEEK_SET, - # kw['l_start'], kw['l_len'], kw['l_pid']) - # ld2 = fcntl.fcntl(self.fd, fcntl.F_GETLK, lockdata) - # flockfields = ('l_type', 'l_whence', 'l_start', 'l_len', 'l_pid') - # uld2 = struct.unpack('hhQQi', ld2) - # res = {} - # for i in xrange(len(uld2)): - # res[flockfields[i]] = uld2[i] - # - # return fuse.Flock(**res) - - # Convert fcntl-ish lock parameters to Python's weird - # lockf(3)/flock(2) medley locking API... - return -EOPNOTSUPP - #op = { fcntl.F_UNLCK : fcntl.LOCK_UN, - # fcntl.F_RDLCK : fcntl.LOCK_SH, - # fcntl.F_WRLCK : fcntl.LOCK_EX }[kw['l_type']] - #if cmd == fcntl.F_GETLK: - # return -EOPNOTSUPP - #elif cmd == fcntl.F_SETLK: - # if op != fcntl.LOCK_UN: - # op |= fcntl.LOCK_NB - #elif cmd == fcntl.F_SETLKW: - # pass - #else: - # return -EINVAL - - #fcntl.lockf(self.fd, op, kw['l_start'], kw['l_len']) - - - def main(self, *a, **kw): - - self.file_class = self.PyNamespaceFile - - return Fuse.main(self, *a, **kw) - - -def main(): - - usage = """ -Presents a python namespace as a filesystem for aesthetic reasons -""" + Fuse.fusage - - server = PyNamespace(version="%prog " + fuse.__version__, - usage=usage, - dash_s_do='setsingle') - - #server.parser.add_option(mountopt="root", metavar="PATH", default='/', - # help="mirror filesystem from under PATH [default: %default]") - #server.parse(values=server, errex=1) - - #try: - # if server.fuse_args.mount_expected(): - # os.chdir(server.root) - #except OSError: - # print >> sys.stderr, "can't enter root of underlying filesystem" - # sys.exit(1) - - server.main() - - -if __name__ == '__main__': - main() -- cgit v1.2.3