fuse memory filesystem

pull/30/head
deadc0de6 1 year ago
parent 7590ad02c3
commit 04b8d6e770

@ -21,6 +21,7 @@ from .catalog import Catalog
from .walker import Walker from .walker import Walker
from .noder import Noder from .noder import Noder
from .utils import ask, edit from .utils import ask, edit
from .fuser import Fuser
from .exceptions import BadFormatException, CatcliException from .exceptions import BadFormatException, CatcliException
NAME = 'catcli' NAME = 'catcli'
@ -43,6 +44,7 @@ Usage:
{NAME} find [--catalog=<path>] [--format=<fmt>] [-aBCbdVsP] [--path=<path>] [<term>] {NAME} find [--catalog=<path>] [--format=<fmt>] [-aBCbdVsP] [--path=<path>] [<term>]
{NAME} index [--catalog=<path>] [--meta=<meta>...] [-aBCcfnV] <name> <path> {NAME} index [--catalog=<path>] [--meta=<meta>...] [-aBCcfnV] <name> <path>
{NAME} update [--catalog=<path>] [-aBCcfnV] [--lpath=<path>] <name> <path> {NAME} update [--catalog=<path>] [-aBCcfnV] [--lpath=<path>] <name> <path>
{NAME} mount [--catalog=<path>] [-V] <mountpoint>
{NAME} rm [--catalog=<path>] [-BCfV] <storage> {NAME} rm [--catalog=<path>] [-BCfV] <storage>
{NAME} rename [--catalog=<path>] [-BCfV] <storage> <name> {NAME} rename [--catalog=<path>] [-BCfV] <storage> <name>
{NAME} edit [--catalog=<path>] [-BCfV] <storage> {NAME} edit [--catalog=<path>] [-BCfV] <storage>
@ -76,6 +78,12 @@ Options:
""" # nopep8 """ # nopep8
def cmd_mount(args, top, noder):
"""mount action"""
mountpoint = args['<mountpoint>']
Fuser(mountpoint, top, noder)
def cmd_index(args, noder, catalog, top): def cmd_index(args, noder, catalog, top):
"""index action""" """index action"""
path = args['<path>'] path = args['<path>']
@ -320,6 +328,11 @@ def main():
Logger.err(f'no such catalog: {catalog_path}') Logger.err(f'no such catalog: {catalog_path}')
return False return False
cmd_ls(args, noder, top) cmd_ls(args, noder, top)
elif args['mount']:
if not catalog.exists():
Logger.err(f'no such catalog: {catalog_path}')
return False
cmd_mount(args, top, noder)
elif args['rm']: elif args['rm']:
if not catalog.exists(): if not catalog.exists():
Logger.err(f'no such catalog: {catalog_path}') Logger.err(f'no such catalog: {catalog_path}')

@ -0,0 +1,134 @@
"""
author: deadc0de6 (https://github.com/deadc0de6)
Copyright (c) 2023, deadc0de6
fuse for catcli
"""
import os
import logging
from time import time
from stat import S_IFDIR, S_IFREG
import fuse
from .noder import Noder
# build custom logger to log in /tmp
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)
fh = logging.FileHandler('/tmp/fuse-catcli.log')
fh.setLevel(logging.DEBUG)
logger.addHandler(fh)
# globals
WILD = '*'
SEPARATOR = '/'
class Fuser:
"""fuser filesystem"""
def __init__(self, mountpoint, top, noder):
"""fuse filesystem"""
filesystem = CatcliFilesystem(top, noder)
fuse.FUSE(filesystem,
mountpoint,
foreground=True,
allow_other=True,
nothreads=True,
debug=True)
class CatcliFilesystem(fuse.LoggingMixIn, fuse.Operations):
"""in-memory filesystem for catcli catalog"""
def __init__(self, top, noder):
"""init fuse filesystem"""
self.top = top
self.noder = noder
def _get_entry(self, path):
pre = f'{SEPARATOR}{self.noder.NAME_TOP}'
if not path.startswith(pre):
path = pre + path
found = self.noder.list(self.top, path,
rec=False,
fmt='native',
raw=True)
if found:
return found[0]
return []
def _get_entries(self, path):
pre = f'{SEPARATOR}{self.noder.NAME_TOP}'
if not path.startswith(pre):
path = pre + path
if not path.endswith(SEPARATOR):
path += SEPARATOR
if not path.endswith(WILD):
path += WILD
found = self.noder.list(self.top, path,
rec=False,
fmt='native',
raw=True)
return found
def _getattr(self, path):
entry = self._get_entry(path)
if not entry:
return None
curt = time()
mode = S_IFREG
if entry.type == Noder.TYPE_ARC:
mode = S_IFREG
elif entry.type == Noder.TYPE_DIR:
mode = S_IFDIR
elif entry.type == Noder.TYPE_FILE:
mode = S_IFREG
elif entry.type == Noder.TYPE_STORAGE:
mode = S_IFDIR
elif entry.type == Noder.TYPE_META:
mode = S_IFREG
elif entry.type == Noder.TYPE_TOP:
mode = S_IFREG
return {
'st_mode': (mode),
'st_nlink': 1,
'st_size': 0,
'st_ctime': curt,
'st_mtime': curt,
'st_atime': curt,
'st_uid': os.getuid(),
'st_gid': os.getgid(),
}
def getattr(self, path, _fh=None):
"""return attr of file pointed by path"""
logger.info('getattr path: %s', path)
if path == '/':
# mountpoint
curt = time()
meta = {
'st_mode': (S_IFDIR),
'st_nlink': 1,
'st_size': 0,
'st_ctime': curt,
'st_mtime': curt,
'st_atime': curt,
'st_uid': os.getuid(),
'st_gid': os.getgid(),
}
return meta
meta = self._getattr(path)
return meta
def readdir(self, path, _fh):
"""read directory content"""
logger.info('readdir path: %s', path)
content = ['.', '..']
entries = self._get_entries(path)
for entry in entries:
content.append(entry.name)
return content

@ -15,6 +15,9 @@ import datetime
from catcli.exceptions import CatcliException from catcli.exceptions import CatcliException
SEPARATOR = '/'
def md5sum(path): def md5sum(path):
""" """
calculate md5 sum of a file calculate md5 sum of a file

@ -1,3 +1,4 @@
docopt; python_version >= '3.0' docopt; python_version >= '3.0'
anytree; python_version >= '3.0' anytree; python_version >= '3.0'
pyfzf; python_version >= '3.0' pyfzf; python_version >= '3.0'
fusepy; python_version >= '3.0'

@ -21,6 +21,7 @@ pyflakes tests/
# R0915: Too many statements # R0915: Too many statements
# R0911: Too many return statements # R0911: Too many return statements
# R0903: Too few public methods # R0903: Too few public methods
# R0801: Similar lines in 2 files
pylint --version pylint --version
pylint \ pylint \
--disable=R0914 \ --disable=R0914 \
@ -29,6 +30,7 @@ pylint \
--disable=R0915 \ --disable=R0915 \
--disable=R0911 \ --disable=R0911 \
--disable=R0903 \ --disable=R0903 \
--disable=R0801 \
catcli/ catcli/
pylint \ pylint \
--disable=W0212 \ --disable=W0212 \

Loading…
Cancel
Save