php-fuse, user-space file systems implemented in PHP

Creating a filesystem with FUSE, and PHP is quite easy, once you’ve read the code, read up about fuse and done about three hours of research. Ergo, it’s a fucking bitch.

If you’re lazy, or in a rush I’ve collated some of the steps, and filtered some of the crap. Hopefully this helps someone in the future.

I’m using it to do some nifty things for work, and plan to extend it for some more nifty things for my hobby, which at the moment is transcoding of video and rewriting lots of DLNA servers.

1.) Build the gree php-fuse module:

apt-get install libfuse2 libfuse-dev fuse-utils fuse-module php5-cli php5-dev
wget https://github.com/fujimoto/php-fuse/tarball/master -O php-fuse.tar.gz
tar xvfz php-fuse.tar.gz
cd fujimoto-php-fuse-*
phpize
./configure
make
make test
sudo make install

2.) Use the following php-cli script to test


#!/usr/bin/php -n
<?php
// vim: set sw=4 sts=4 et tw=100 smarttab :

dl("fuse.so");

class FuseTest extends Fuse {

        public function getdir ($path, &$retval) {
                echo("FuseTest:getdir: $path\n");
                switch ($path) {
                        case "/" : {
                                $retval["."] = array ('type' => FUSE_DT_DIR);
                                $retval[".."] = array ('type' => FUSE_DT_DIR);
                                $retval["subdir"] = array ('type' => FUSE_DT_DIR);
                                $retval["test.txt"] = array ('type' => FUSE_DT_REG);
                                break;
                        }
                        case "/subdir" : {
                                $retval["."] = Array ('type' => FUSE_DT_DIR);
                                $retval[".."] = array ('type' => FUSE_DT_DIR);
                                $retval["test2.txt"] = array ('type' => FUSE_DT_REG);
                                break;
                        }
                        default : return -FUSE_ENOENT;
                }
                return 0;
        }

        public function getattr ($path, &$st) {
                echo("getattr: $path");
                $st['dev'] = 0;
                $st['ino'] = 0;
                $st['mode'] = 0;
                $st['nlink'] = 0;
                $st['uid'] = 0;
                $st['gid'] = 0;
                $st['rdev'] = 0;
                $st['size'] = 0;
                $st['atime'] = time();
                $st['mtime'] = time();
                $st['ctime'] = 0;
                $st['blksize'] = 0;
                $st['blocks'] = 0;


                if ($path == "/" || $path=="/subdir") {
                        $st['mode'] = FUSE_S_IFDIR | 0775;
                        $st['nlink'] = 3;
                        $st['size'] = 0;
                } Else if (substr($path,-4,4) == ".txt") { //return same attrs for all 'txt' files
                        $st['mode'] = FUSE_S_IFREG | 0664;
                        $st['nlink'] = 1;
                        $st['size'] = 12;
                }
                return 0;
        }

        public function open ($path, $mode) {
                echo("open: $path");
                return 1;
        }

        public function read ($path, $fh, $offset, $buf_len, &$buf) {
                echo("read: $path");
                $buf = "hello world \n";
                return strlen ($buf);
        }

        public function release ($path, $fh) {
                echo("release: $path");
                return 0;
        }
}

$fuse = new FuseTest();
$fuse->mount("/mnt", "fsname=fusetest,debug,allow_other");

3). Now run with ./fusetest and use regular commands like “ls -l /mnt/” or “cat /mnt/test.txt” to see your data. The default for $fuse-mount() is to fork, and thread, hence the “debug” option being passed to the mount. If you don’t add the “debug” option you will never see what happens in your code, and all logging will just disappear. Of course, this may be what you want.

4.) Profit.

Author: roelf on May 10, 2012
Category: Uncategorized

Leave a Reply

*

Last articles