Do you like methaphors? FlatFS is like watching a tree through glasses that were flattened by a steam roller.
FlatFS is a fuse filesystem that displays all files found in a certain directory (the source) and subdirectories thereof in a single directory (the target).
It works by simply substituting /
with something else.
By default it uses ___
(triple underscore) but this is configurable.
If you make a new file in the target-dir containing the triple underscore pattern new directories will be made accordingly in the source-directory.
$ tree source
source
├── bar
├── baz
│ ├── one
│ └── two
└── zzz
$ tree target
target
├── bar
├── baz___one
├── baz___two
└── zzz
$ cd target
$ touch baz___three
$ ls ../source/baz
one two three
$ touch flatfs___rocks___yeah
$ ls ../source
bar baz flatfs zzz
$ ls -R ../source/flatfs
flatfs/:
rocks
rocks/:
yeah
Well… you get it.
A good way to mess things up is by using a special pattern that is already present in the original file tree. Depending on what you do with your files FlatFS could move or copy the file to a new subdirectory.
But is it useful? I guess not; but who knows? For me it was a way to learn more about Fuse.
Anyhow, here’s the full source code:
#!/usr/bin/python
# FlatFS provides a different view on a directory by redirecting file-system calls.
# Copyright (C) 2006 Tijn Schuurmans
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
import fuse
from fuse import Fuse
fuse.fuse_python_api = (0, 2)
import os
import sys
from errno import *
from stat import *
import thread
sourcedir = ""
DEBUG = True
def escape(path):
return path.replace("/", "____")
def unescape(path):
return path.replace("____", "/")
def realpath(path):
return sourcedir + unescape(path);
class Flatfs(Fuse):
def __init__(self, *args, **kw):
Fuse.__init__(self, *args, **kw)
def getattr(self, path):
return os.lstat(realpath(path))
def readlink(self, path):
return os.readlink(realpath(path))
def getdir(self, path):
rp = realpath(path);
files = []
for root, dirs, realfiles in os.walk(rp):
for name in realfiles:
f = os.path.join(root, name)
f = f.replace(sourcedir+"/","") # FIXME: make more robust by matching the beginning of the line
files.append(escape(f))
return map(lambda x: (x,0), files)
def open(self, path, flags):
rp = realpath(path)
os.close(os.open(rp, flags))
return 0
def read(self, path, lenght, offset):
rp = realpath(path)
f = open(rp, "r")
f.seek(offset)
return f.read(lenght)
def unlink(self, path):
rp = realpath(path)
return os.unlink(rp)
def rename(self, path, path1):
rp = realpath(path)
realpath1 = realpath(path1)
return os.rename(rp, realpath1)
def chmod(self, path, mode):
rp = realpath(path)
return os.chmod(rp, mode)
def chown(self, path, user, group):
rp = realpath(path)
return os.chown(rp, user, group)
def truncate(self, path, size):
rp = realpath(path)
f = open(rp, "w+")
return f.truncate(size)
def utime(self, path, times):
rp = realpath(path)
return os.utime(rp, times)
def write(self, path, buf, off):
rp = realpath(path)
f = open(rp, "r+")
f.seek(off)
f.write(buf)
return len(buf)
def release(self, path, flags):
return 0
def statfs(self):
blocks_size = 0
blocks = 0
blocks_free = 0
files = 0
files_free = 0
namelen = 0
return (blocks_size, blocks, blocks_free, files, files_free, namelen)
def fsync(self, path, isfsyncfile):
return 0
if __name__ == '__main__':
if len(sys.argv)<2:
print "Usage:", sys.argv[0], "[mountpoint] [sourcedir]"
sys.exit()
mountdir = sys.argv[1]
sourcedir = sys.argv[2]
print "Flat filesytem off directory", sourcedir
server = Flatfs(sys.argv)
server.main()