// SPDX-FileCopyrightText: edef // SPDX-License-Identifier: OSL-3.0 use { libc::{c_int, ENOSYS, EPERM}, log::{debug, warn}, }; fn main() { env_logger::init(); let store = fossil::Store::open("fossil.db").unwrap(); fuser::mount2(Filesystem::open(store), "mnt", &[]).unwrap(); } struct Filesystem { store: fossil::Store, } impl Filesystem { fn open(store: fossil::Store) -> Filesystem { Filesystem { store } } } impl fuser::Filesystem for Filesystem { fn init( &mut self, _req: &fuser::Request<'_>, _config: &mut fuser::KernelConfig, ) -> Result<(), c_int> { Ok(()) } fn destroy(&mut self) {} fn lookup( &mut self, _req: &fuser::Request<'_>, parent: u64, name: &std::ffi::OsStr, reply: fuser::ReplyEntry, ) { warn!( "[Not Implemented] lookup(parent: {:#x?}, name {:?})", parent, name ); reply.error(ENOSYS); } fn forget(&mut self, _req: &fuser::Request<'_>, _ino: u64, _nlookup: u64) {} fn getattr(&mut self, _req: &fuser::Request<'_>, ino: u64, reply: fuser::ReplyAttr) { warn!("[Not Implemented] getattr(ino: {:#x?})", ino); reply.error(ENOSYS); } fn setattr( &mut self, _req: &fuser::Request<'_>, ino: u64, mode: Option, uid: Option, gid: Option, size: Option, _atime: Option, _mtime: Option, _ctime: Option, fh: Option, _crtime: Option, _chgtime: Option, _bkuptime: Option, flags: Option, reply: fuser::ReplyAttr, ) { debug!( "[Not Implemented] setattr(ino: {:#x?}, mode: {:?}, uid: {:?}, \ gid: {:?}, size: {:?}, fh: {:?}, flags: {:?})", ino, mode, uid, gid, size, fh, flags ); reply.error(ENOSYS); } fn readlink(&mut self, _req: &fuser::Request<'_>, ino: u64, reply: fuser::ReplyData) { debug!("[Not Implemented] readlink(ino: {:#x?})", ino); reply.error(ENOSYS); } fn mknod( &mut self, _req: &fuser::Request<'_>, parent: u64, name: &std::ffi::OsStr, mode: u32, umask: u32, rdev: u32, reply: fuser::ReplyEntry, ) { debug!( "[Not Implemented] mknod(parent: {:#x?}, name: {:?}, mode: {}, \ umask: {:#x?}, rdev: {})", parent, name, mode, umask, rdev ); reply.error(ENOSYS); } fn mkdir( &mut self, _req: &fuser::Request<'_>, parent: u64, name: &std::ffi::OsStr, mode: u32, umask: u32, reply: fuser::ReplyEntry, ) { debug!( "[Not Implemented] mkdir(parent: {:#x?}, name: {:?}, mode: {}, umask: {:#x?})", parent, name, mode, umask ); reply.error(ENOSYS); } fn unlink( &mut self, _req: &fuser::Request<'_>, parent: u64, name: &std::ffi::OsStr, reply: fuser::ReplyEmpty, ) { debug!( "[Not Implemented] unlink(parent: {:#x?}, name: {:?})", parent, name, ); reply.error(ENOSYS); } fn rmdir( &mut self, _req: &fuser::Request<'_>, parent: u64, name: &std::ffi::OsStr, reply: fuser::ReplyEmpty, ) { debug!( "[Not Implemented] rmdir(parent: {:#x?}, name: {:?})", parent, name, ); reply.error(ENOSYS); } fn symlink( &mut self, _req: &fuser::Request<'_>, parent: u64, name: &std::ffi::OsStr, link: &std::path::Path, reply: fuser::ReplyEntry, ) { debug!( "[Not Implemented] symlink(parent: {:#x?}, name: {:?}, link: {:?})", parent, name, link, ); reply.error(EPERM); } fn rename( &mut self, _req: &fuser::Request<'_>, parent: u64, name: &std::ffi::OsStr, newparent: u64, newname: &std::ffi::OsStr, flags: u32, reply: fuser::ReplyEmpty, ) { debug!( "[Not Implemented] rename(parent: {:#x?}, name: {:?}, newparent: {:#x?}, \ newname: {:?}, flags: {})", parent, name, newparent, newname, flags, ); reply.error(ENOSYS); } fn link( &mut self, _req: &fuser::Request<'_>, ino: u64, newparent: u64, newname: &std::ffi::OsStr, reply: fuser::ReplyEntry, ) { debug!( "[Not Implemented] link(ino: {:#x?}, newparent: {:#x?}, newname: {:?})", ino, newparent, newname ); reply.error(EPERM); } fn open(&mut self, _req: &fuser::Request<'_>, _ino: u64, _flags: i32, reply: fuser::ReplyOpen) { reply.opened(0, 0); } fn read( &mut self, _req: &fuser::Request<'_>, ino: u64, fh: u64, offset: i64, size: u32, flags: i32, lock_owner: Option, reply: fuser::ReplyData, ) { warn!( "[Not Implemented] read(ino: {:#x?}, fh: {}, offset: {}, size: {}, \ flags: {:#x?}, lock_owner: {:?})", ino, fh, offset, size, flags, lock_owner ); reply.error(ENOSYS); } fn write( &mut self, _req: &fuser::Request<'_>, ino: u64, fh: u64, offset: i64, data: &[u8], write_flags: u32, flags: i32, lock_owner: Option, reply: fuser::ReplyWrite, ) { debug!( "[Not Implemented] write(ino: {:#x?}, fh: {}, offset: {}, data.len(): {}, \ write_flags: {:#x?}, flags: {:#x?}, lock_owner: {:?})", ino, fh, offset, data.len(), write_flags, flags, lock_owner ); reply.error(ENOSYS); } fn flush( &mut self, _req: &fuser::Request<'_>, ino: u64, fh: u64, lock_owner: u64, reply: fuser::ReplyEmpty, ) { debug!( "[Not Implemented] flush(ino: {:#x?}, fh: {}, lock_owner: {:?})", ino, fh, lock_owner ); reply.error(ENOSYS); } fn release( &mut self, _req: &fuser::Request<'_>, _ino: u64, _fh: u64, _flags: i32, _lock_owner: Option, _flush: bool, reply: fuser::ReplyEmpty, ) { reply.ok(); } fn fsync( &mut self, _req: &fuser::Request<'_>, ino: u64, fh: u64, datasync: bool, reply: fuser::ReplyEmpty, ) { debug!( "[Not Implemented] fsync(ino: {:#x?}, fh: {}, datasync: {})", ino, fh, datasync ); reply.error(ENOSYS); } fn opendir( &mut self, _req: &fuser::Request<'_>, _ino: u64, _flags: i32, reply: fuser::ReplyOpen, ) { reply.opened(0, 0); } fn readdir( &mut self, _req: &fuser::Request<'_>, ino: u64, fh: u64, offset: i64, reply: fuser::ReplyDirectory, ) { warn!( "[Not Implemented] readdir(ino: {:#x?}, fh: {}, offset: {})", ino, fh, offset ); reply.error(ENOSYS); } fn readdirplus( &mut self, _req: &fuser::Request<'_>, ino: u64, fh: u64, offset: i64, reply: fuser::ReplyDirectoryPlus, ) { debug!( "[Not Implemented] readdirplus(ino: {:#x?}, fh: {}, offset: {})", ino, fh, offset ); reply.error(ENOSYS); } fn releasedir( &mut self, _req: &fuser::Request<'_>, _ino: u64, _fh: u64, _flags: i32, reply: fuser::ReplyEmpty, ) { reply.ok(); } fn fsyncdir( &mut self, _req: &fuser::Request<'_>, ino: u64, fh: u64, datasync: bool, reply: fuser::ReplyEmpty, ) { debug!( "[Not Implemented] fsyncdir(ino: {:#x?}, fh: {}, datasync: {})", ino, fh, datasync ); reply.error(ENOSYS); } fn statfs(&mut self, _req: &fuser::Request<'_>, _ino: u64, reply: fuser::ReplyStatfs) { reply.statfs(0, 0, 0, 0, 0, 512, 255, 0); } fn setxattr( &mut self, _req: &fuser::Request<'_>, ino: u64, name: &std::ffi::OsStr, _value: &[u8], flags: i32, position: u32, reply: fuser::ReplyEmpty, ) { debug!( "[Not Implemented] setxattr(ino: {:#x?}, name: {:?}, flags: {:#x?}, position: {})", ino, name, flags, position ); reply.error(ENOSYS); } fn getxattr( &mut self, _req: &fuser::Request<'_>, ino: u64, name: &std::ffi::OsStr, size: u32, reply: fuser::ReplyXattr, ) { debug!( "[Not Implemented] getxattr(ino: {:#x?}, name: {:?}, size: {})", ino, name, size ); reply.error(ENOSYS); } fn listxattr( &mut self, _req: &fuser::Request<'_>, ino: u64, size: u32, reply: fuser::ReplyXattr, ) { debug!( "[Not Implemented] listxattr(ino: {:#x?}, size: {})", ino, size ); reply.error(ENOSYS); } fn removexattr( &mut self, _req: &fuser::Request<'_>, ino: u64, name: &std::ffi::OsStr, reply: fuser::ReplyEmpty, ) { debug!( "[Not Implemented] removexattr(ino: {:#x?}, name: {:?})", ino, name ); reply.error(ENOSYS); } fn access(&mut self, _req: &fuser::Request<'_>, ino: u64, mask: i32, reply: fuser::ReplyEmpty) { debug!("[Not Implemented] access(ino: {:#x?}, mask: {})", ino, mask); reply.error(ENOSYS); } fn create( &mut self, _req: &fuser::Request<'_>, parent: u64, name: &std::ffi::OsStr, mode: u32, umask: u32, flags: i32, reply: fuser::ReplyCreate, ) { debug!( "[Not Implemented] create(parent: {:#x?}, name: {:?}, mode: {}, umask: {:#x?}, \ flags: {:#x?})", parent, name, mode, umask, flags ); reply.error(ENOSYS); } fn getlk( &mut self, _req: &fuser::Request<'_>, ino: u64, fh: u64, lock_owner: u64, start: u64, end: u64, typ: i32, pid: u32, reply: fuser::ReplyLock, ) { debug!( "[Not Implemented] getlk(ino: {:#x?}, fh: {}, lock_owner: {}, start: {}, \ end: {}, typ: {}, pid: {})", ino, fh, lock_owner, start, end, typ, pid ); reply.error(ENOSYS); } fn setlk( &mut self, _req: &fuser::Request<'_>, ino: u64, fh: u64, lock_owner: u64, start: u64, end: u64, typ: i32, pid: u32, sleep: bool, reply: fuser::ReplyEmpty, ) { debug!( "[Not Implemented] setlk(ino: {:#x?}, fh: {}, lock_owner: {}, start: {}, \ end: {}, typ: {}, pid: {}, sleep: {})", ino, fh, lock_owner, start, end, typ, pid, sleep ); reply.error(ENOSYS); } fn bmap( &mut self, _req: &fuser::Request<'_>, ino: u64, blocksize: u32, idx: u64, reply: fuser::ReplyBmap, ) { debug!( "[Not Implemented] bmap(ino: {:#x?}, blocksize: {}, idx: {})", ino, blocksize, idx, ); reply.error(ENOSYS); } fn ioctl( &mut self, _req: &fuser::Request<'_>, ino: u64, fh: u64, flags: u32, cmd: u32, in_data: &[u8], out_size: u32, reply: fuser::ReplyIoctl, ) { debug!( "[Not Implemented] ioctl(ino: {:#x?}, fh: {}, flags: {}, cmd: {}, \ in_data.len(): {}, out_size: {})", ino, fh, flags, cmd, in_data.len(), out_size, ); reply.error(ENOSYS); } fn fallocate( &mut self, _req: &fuser::Request<'_>, ino: u64, fh: u64, offset: i64, length: i64, mode: i32, reply: fuser::ReplyEmpty, ) { debug!( "[Not Implemented] fallocate(ino: {:#x?}, fh: {}, offset: {}, \ length: {}, mode: {})", ino, fh, offset, length, mode ); reply.error(ENOSYS); } fn lseek( &mut self, _req: &fuser::Request<'_>, ino: u64, fh: u64, offset: i64, whence: i32, reply: fuser::ReplyLseek, ) { debug!( "[Not Implemented] lseek(ino: {:#x?}, fh: {}, offset: {}, whence: {})", ino, fh, offset, whence ); reply.error(ENOSYS); } fn copy_file_range( &mut self, _req: &fuser::Request<'_>, ino_in: u64, fh_in: u64, offset_in: i64, ino_out: u64, fh_out: u64, offset_out: i64, len: u64, flags: u32, reply: fuser::ReplyWrite, ) { debug!( "[Not Implemented] copy_file_range(ino_in: {:#x?}, fh_in: {}, \ offset_in: {}, ino_out: {:#x?}, fh_out: {}, offset_out: {}, \ len: {}, flags: {})", ino_in, fh_in, offset_in, ino_out, fh_out, offset_out, len, flags ); reply.error(ENOSYS); } }