FUSE Python tutorial
From fuse
FUSE Python Tutorial
FUSE filesystems can be written in any language that has a binding to the FUSE libraries. Python is one such language. Writing a FUSE filesystem in Python is as easy as subclassing the Fuse object in the fuse module and writing your desired functionality into the proper class methods.
On Debian Linux (and derivatives such as Ubuntu), installing FUSE and its Python binding is as easy as using apt-get install python-fuse. On Fedora, using yum install fuse-python will install the FUSE Python binding. In such a case you may need to locate and install the packages manually or even compile from source. On Debian the newest Python binding for FUSE seems to be for version 2.3 of Python.
The FUSE Python binding can be found in the Gentoo's Portage repository as dev-python/fuse-python. To install it just run emerge fuse-python.
With the Python FUSE package comes an example filesystem called Xmp.py. This covers the basics of what you need to know to get started but doesn't provide much guidance beyond that point. It's also rather confussing as it isn't very well documented and is full of garbage documentation that makes it difficult to read. It's worth looking at but here we'll start with something a little cleaner. This class prints out a line when each function is called, along with the arguments as passed to that function, and then returns a "Not Implemented" value. Obviously, this class will not run as-is. This example code includes also a couple helper functions.
Example:
#!/usr/bin/python
from fuse import Fuse
from time import time
import stat # for file properties
import os # for filesystem modes (O_RDONLY, etc)
import errno # for error number codes (ENOENT, etc)
# - note: these must be returned as negatives
def dirFromList(list):
"""
Return a properly formatted list of items suitable to a directory listing.
[['a', 'b', 'c']] => [[('a', 0), ('b', 0), ('c', 0)]]
"""
return [[(x, 0) for x in list]]
def getDepth(path):
"""
Return the depth of a given path, zero-based from root ('/')
"""
if path <code></code> '/':
return 0
else:
return path.count('/')
def getParts(path):
"""
Return the slash-separated parts of a given path as a list
"""
if path <code></code> '/':
return [['/']]
else:
return path.split('/')
class NullFS(Fuse):
"""
"""
def __init__(self, *args, **kw):
Fuse.__init__(self, *args, **kw)
print 'Init complete.'
def getattr(self, path):
"""
- st_mode (protection bits)
- st_ino (inode number)
- st_dev (device)
- st_nlink (number of hard links)
- st_uid (user ID of owner)
- st_gid (group ID of owner)
- st_size (size of file, in bytes)
- st_atime (time of most recent access)
- st_mtime (time of most recent content modification)
- st_ctime (platform dependent; time of most recent metadata change on Unix,
or the time of creation on Windows).
"""
print '*** getattr', path
depth = getDepth(path) # depth of path, zero-based from root
pathparts = getParts(path) # the actual parts of the path
return -errno.ENOSYS
def getdir(self, path):
"""
return: [[('file1', 0), ('file2', 0), ... ]]
"""
print '*** getdir', path
return -errno.ENOSYS
def mythread ( self ):
print '*** mythread'
return -errno.ENOSYS
def chmod ( self, path, mode ):
print '*** chmod', path, oct(mode)
return -errno.ENOSYS
def chown ( self, path, uid, gid ):
print '*** chown', path, uid, gid
return -errno.ENOSYS
def fsync ( self, path, isFsyncFile ):
print '*** fsync', path, isFsyncFile
return -errno.ENOSYS
def link ( self, targetPath, linkPath ):
print '*** link', targetPath, linkPath
return -errno.ENOSYS
def mkdir ( self, path, mode ):
print '*** mkdir', path, oct(mode)
return -errno.ENOSYS
def mknod ( self, path, mode, dev ):
print '*** mknod', path, oct(mode), dev
return -errno.ENOSYS
def open ( self, path, flags ):
print '*** open', path, flags
return -errno.ENOSYS
def read ( self, path, length, offset ):
print '*** read', path, length, offset
return -errno.ENOSYS
def readlink ( self, path ):
print '*** readlink', path
return -errno.ENOSYS
def release ( self, path, flags ):
print '*** release', path, flags
return -errno.ENOSYS
def rename ( self, oldPath, newPath ):
print '*** rename', oldPath, newPath
return -errno.ENOSYS
def rmdir ( self, path ):
print '*** rmdir', path
return -errno.ENOSYS
def statfs ( self ):
print '*** statfs'
return -errno.ENOSYS
def symlink ( self, targetPath, linkPath ):
print '*** symlink', targetPath, linkPath
return -errno.ENOSYS
def truncate ( self, path, size ):
print '*** truncate', path, size
return -errno.ENOSYS
def unlink ( self, path ):
print '*** unlink', path
return -errno.ENOSYS
def utime ( self, path, times ):
print '*** utime', path, times
return -errno.ENOSYS
def write ( self, path, buf, offset ):
print '*** write', path, buf, offset
return -errno.ENOSYS
if __name__ == __main__:
fs = NullFS()
fs.flags = 0
fs.multithreaded = 0
fs.main()
__init__()
The normal object constructor. It needs to pass its inputs along to the constructor in the Fuse class. Besides that you can use it for whatever your filesystem needs to happen when it's initialized.
