1. Summary
  2. Files
  3. Support
  4. Report Spam
  5. Create account
  6. Log in

FUSE Python tutorial

From fuse

Jump to: navigation, search

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.

Personal tools