mirror of https://github.com/perkeep/perkeep.git
123 lines
3.7 KiB
Python
123 lines
3.7 KiB
Python
|
#!/usr/bin/env python
|
||
|
|
||
|
from collections import defaultdict
|
||
|
from errno import ENOENT
|
||
|
from stat import S_IFDIR, S_IFLNK, S_IFREG
|
||
|
from sys import argv, exit
|
||
|
from time import time
|
||
|
|
||
|
from fuse import FUSE, FuseOSError, Operations, LoggingMixIn
|
||
|
|
||
|
|
||
|
class Memory(LoggingMixIn, Operations):
|
||
|
"""Example memory filesystem. Supports only one level of files."""
|
||
|
|
||
|
def __init__(self):
|
||
|
self.files = {}
|
||
|
self.data = defaultdict(str)
|
||
|
self.fd = 0
|
||
|
now = time()
|
||
|
self.files['/'] = dict(st_mode=(S_IFDIR | 0755), st_ctime=now,
|
||
|
st_mtime=now, st_atime=now, st_nlink=2)
|
||
|
|
||
|
def chmod(self, path, mode):
|
||
|
self.files[path]['st_mode'] &= 0770000
|
||
|
self.files[path]['st_mode'] |= mode
|
||
|
return 0
|
||
|
|
||
|
def chown(self, path, uid, gid):
|
||
|
self.files[path]['st_uid'] = uid
|
||
|
self.files[path]['st_gid'] = gid
|
||
|
|
||
|
def create(self, path, mode):
|
||
|
self.files[path] = dict(st_mode=(S_IFREG | mode), st_nlink=1,
|
||
|
st_size=0, st_ctime=time(), st_mtime=time(), st_atime=time())
|
||
|
self.fd += 1
|
||
|
return self.fd
|
||
|
|
||
|
def getattr(self, path, fh=None):
|
||
|
if path not in self.files:
|
||
|
raise FuseOSError(ENOENT)
|
||
|
st = self.files[path]
|
||
|
return st
|
||
|
|
||
|
def getxattr(self, path, name, position=0):
|
||
|
attrs = self.files[path].get('attrs', {})
|
||
|
try:
|
||
|
return attrs[name]
|
||
|
except KeyError:
|
||
|
return '' # Should return ENOATTR
|
||
|
|
||
|
def listxattr(self, path):
|
||
|
attrs = self.files[path].get('attrs', {})
|
||
|
return attrs.keys()
|
||
|
|
||
|
def mkdir(self, path, mode):
|
||
|
self.files[path] = dict(st_mode=(S_IFDIR | mode), st_nlink=2,
|
||
|
st_size=0, st_ctime=time(), st_mtime=time(), st_atime=time())
|
||
|
self.files['/']['st_nlink'] += 1
|
||
|
|
||
|
def open(self, path, flags):
|
||
|
self.fd += 1
|
||
|
return self.fd
|
||
|
|
||
|
def read(self, path, size, offset, fh):
|
||
|
return self.data[path][offset:offset + size]
|
||
|
|
||
|
def readdir(self, path, fh):
|
||
|
return ['.', '..'] + [x[1:] for x in self.files if x != '/']
|
||
|
|
||
|
def readlink(self, path):
|
||
|
return self.data[path]
|
||
|
|
||
|
def removexattr(self, path, name):
|
||
|
attrs = self.files[path].get('attrs', {})
|
||
|
try:
|
||
|
del attrs[name]
|
||
|
except KeyError:
|
||
|
pass # Should return ENOATTR
|
||
|
|
||
|
def rename(self, old, new):
|
||
|
self.files[new] = self.files.pop(old)
|
||
|
|
||
|
def rmdir(self, path):
|
||
|
self.files.pop(path)
|
||
|
self.files['/']['st_nlink'] -= 1
|
||
|
|
||
|
def setxattr(self, path, name, value, options, position=0):
|
||
|
# Ignore options
|
||
|
attrs = self.files[path].setdefault('attrs', {})
|
||
|
attrs[name] = value
|
||
|
|
||
|
def statfs(self, path):
|
||
|
return dict(f_bsize=512, f_blocks=4096, f_bavail=2048)
|
||
|
|
||
|
def symlink(self, target, source):
|
||
|
self.files[target] = dict(st_mode=(S_IFLNK | 0777), st_nlink=1,
|
||
|
st_size=len(source))
|
||
|
self.data[target] = source
|
||
|
|
||
|
def truncate(self, path, length, fh=None):
|
||
|
self.data[path] = self.data[path][:length]
|
||
|
self.files[path]['st_size'] = length
|
||
|
|
||
|
def unlink(self, path):
|
||
|
self.files.pop(path)
|
||
|
|
||
|
def utimens(self, path, times=None):
|
||
|
now = time()
|
||
|
atime, mtime = times if times else (now, now)
|
||
|
self.files[path]['st_atime'] = atime
|
||
|
self.files[path]['st_mtime'] = mtime
|
||
|
|
||
|
def write(self, path, data, offset, fh):
|
||
|
self.data[path] = self.data[path][:offset] + data
|
||
|
self.files[path]['st_size'] = len(self.data[path])
|
||
|
return len(data)
|
||
|
|
||
|
|
||
|
if __name__ == "__main__":
|
||
|
if len(argv) != 2:
|
||
|
print 'usage: %s <mountpoint>' % argv[0]
|
||
|
exit(1)
|
||
|
fuse = FUSE(Memory(), argv[1], foreground=True)
|