aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--_find_fuse_parts.py22
-rw-r--r--bundled_examples/hello.py92
-rw-r--r--bundled_examples/xmp.py (renamed from first_try.py)138
3 files changed, 188 insertions, 64 deletions
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 <strawman@astraw.com>
+#
+# 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/first_try.py b/bundled_examples/xmp.py
index 04a831e..a82c097 100644
--- a/first_try.py
+++ b/bundled_examples/xmp.py
@@ -1,7 +1,11 @@
#!/usr/bin/env python
-# July 2008: Bryan Newbold <bryannewbold.com>
-# Based on xmp.py
+# Copyright (C) 2001 Jeff Epler <jepler@unpythonic.dhs.org>
+# Copyright (C) 2006 Csaba Henk <csaba.henk@creo.hu>
+#
+# This program can be distributed under the terms of the GNU LGPL.
+# See the file COPYING.
+#
import os, sys
from errno import *
@@ -35,7 +39,7 @@ def flag2mode(flags):
return m
-class PyNamespace(Fuse):
+class Xmp(Fuse):
def __init__(self, *args, **kw):
@@ -44,7 +48,7 @@ class PyNamespace(Fuse):
# do stuff to set up your filesystem here, if you want
#import thread
#thread.start_new_thread(self.mythread, ())
- #self.root = '/'
+ self.root = '/'
# def mythread(self):
#
@@ -58,48 +62,49 @@ class PyNamespace(Fuse):
# print "mythread: ticking"
def getattr(self, path):
- return locals()[path].__repr__
+ return os.lstat("." + path)
def readlink(self, path):
- return str(path)
+ return os.readlink("." + path)
def readdir(self, path, offset):
for e in os.listdir("." + path):
yield fuse.Direntry(e)
def unlink(self, path):
- del locals()[path]
+ os.unlink("." + path)
def rmdir(self, path):
- del locals()[path]
+ os.rmdir("." + path)
def symlink(self, path, path1):
- locals()[path1] = locals()[path]
+ os.symlink(path, "." + path1)
def rename(self, path, path1):
- locals()[path1] = locals()[path]
- del locals()[path]
+ os.rename("." + path, "." + path1)
def link(self, path, path1):
- locals()[path1] = locals()[path]
+ os.link("." + path, "." + path1)
def chmod(self, path, mode):
- return -EPFNOSUPPORT
+ os.chmod("." + path, mode)
def chown(self, path, user, group):
- return -EPFNOSUPPORT
+ os.chown("." + path, user, group)
def truncate(self, path, len):
- return -EPFNOSUPPORT
+ f = open("." + path, "a")
+ f.truncate(len)
+ f.close()
def mknod(self, path, mode, dev):
- return -EPFNOSUPPORT
+ os.mknod("." + path, mode, dev)
def mkdir(self, path, mode):
- return -EPFNOSUPPORT
+ os.mkdir("." + path, mode)
def utime(self, path, times):
- return -EPFNOSUPPORT
+ 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
@@ -150,47 +155,52 @@ class PyNamespace(Fuse):
- 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
+
+ return os.statvfs(".")
def fsinit(self):
- #os.chdir(self.root)
- pass
+ os.chdir(self.root)
- class PyNamespaceFile(object):
+ class XmpFile(object):
def __init__(self, path, flags, *mode):
- self.fobject = locals()[path]
- self.fstr = StringIO(str(self.fobject))
+ self.file = os.fdopen(os.open("." + path, flags, *mode),
+ flag2mode(flags))
+ self.fd = self.file.fileno()
def read(self, length, offset):
- return self.fstr.read(length)
+ self.file.seek(offset)
+ return self.file.read(length)
def write(self, buf, offset):
- self.fstr.seek(offset)
- self.fstr.write(buf)
+ self.file.seek(offset)
+ self.file.write(buf)
return len(buf)
def release(self, flags):
- self.fstr.close()
+ self.file.close()
def _fflush(self):
- if 'w' in self.fstr.mode or 'a' in self.fstr.mode:
- self.fstr.flush()
+ if 'w' in self.file.mode or 'a' in self.file.mode:
+ self.file.flush()
def fsync(self, isfsyncfile):
- pass
+ self._fflush()
+ if isfsyncfile and hasattr(os, 'fdatasync'):
+ os.fdatasync(self.fd)
+ else:
+ os.fsync(self.fd)
def flush(self):
- pass
+ self._fflush()
+ # cf. xmp_flush() in fusexmp_fh.c
+ os.close(os.dup(self.fd))
def fgetattr(self):
- pass
+ return os.fstat(self.fd)
def ftruncate(self, len):
- self.fstr.truncate(len)
+ self.file.truncate(len)
def lock(self, cmd, owner, **kw):
# The code here is much rather just a demonstration of the locking
@@ -217,26 +227,25 @@ class PyNamespace(Fuse):
# 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'])
+ 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
+ self.file_class = self.XmpFile
return Fuse.main(self, *a, **kw)
@@ -244,23 +253,24 @@ class PyNamespace(Fuse):
def main():
usage = """
-Presents a python namespace as a filesystem for aesthetic reasons
+Userspace nullfs-alike: mirror the filesystem tree from some point on.
+
""" + Fuse.fusage
- server = PyNamespace(version="%prog " + fuse.__version__,
+ 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)
+ 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)
+ 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()