diff options
Diffstat (limited to 'FuseArchive/FileSystem.py')
-rw-r--r-- | FuseArchive/FileSystem.py | 154 |
1 files changed, 154 insertions, 0 deletions
diff --git a/FuseArchive/FileSystem.py b/FuseArchive/FileSystem.py new file mode 100644 index 0000000..dbdc8a3 --- /dev/null +++ b/FuseArchive/FileSystem.py @@ -0,0 +1,154 @@ +import fuse, os, logging, errno +from ChunkFile import ChunkFile + +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') + +class FileSystem(fuse.Fuse): + + def __init__(self, *args, **kw): + + fuse.Fuse.__init__(self, *args, **kw) + self.root = None + + # Fix getattr and fgetattr to? + def getattr(self, path): + treefile = "./tree" + path + + if os.path.isfile( treefile ): + logging.debug( "Delegating getattr to File for " + path ) + + # Check in the dirty cache first (to handle lseek and the + # relatively broken implmentation in fuse/python) + f = ChunkFile.get_dirty_file( path ) + if f: + logging.info( "WORKAROUND: lseek appears to do a gettattr if whence is SEEK_END, using dirty cache object" ) + stats = f.fgetattr() + # no release, it's still being used + else: + f = ChunkFile( path, os.O_RDONLY, 0 ) + stats = f.fgetattr() + f.release( 0 ) + else: + logging.debug( "Using os.lstat to get stats" ) + stats = os.lstat( treefile ) + + return stats + + def readlink(self, path): + return os.readlink("./tree" + path) + + def readdir(self, path, offset): + for e in os.listdir("./tree" + path): + yield fuse.Direntry(e) + + def unlink(self, path): + os.unlink("./tree" + path) + + def rmdir(self, path): + os.rmdir("./tree" + path) + + def symlink(self, path, path1): + os.symlink(path, "./tree" + path1) + + def rename(self, path, path1): + os.rename("./tree" + path, "./tree" + path1) + + def link(self, path, path1): + os.link("./tree" + path, "./tree" + path1) + + def chmod(self, path, mode): + os.chmod("./tree" + path, mode) + + def chown(self, path, user, group): + os.chown("./tree" + path, user, group) + + def truncate(self, path, len): + # Truncate using the ftruncate on the file + logging.debug( "Using FuseArchiveFile to truncate %s to %d" % ( path, len) ) + f = ChunkFile( path, os.O_RDWR, 0 ) + f.ftruncate(len) + f.release( 0 ) + + def mknod(self, path, mode, dev): + os.mknod("./tree" + path, mode, dev) + + def mkdir(self, path, mode): + os.mkdir("./tree" + path, mode) + + def utime(self, path, times): + os.utime("./tree" + 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("./tree" + path, mode): + return -errno.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) + + def main(self, *a, **kw): + + self.file_class = ChunkFile + + # This is where fragments go + if not os.path.exists( 'storage' ): + os.mkdir( 'storage' ) + + # This is where the real files exist + if not os.path.exists( 'tree' ): + os.mkdir( 'tree' ) + + return fuse.Fuse.main(self, *a, **kw) + |