From b6efed641aecd3d2f9922c7eb2fa1a3d75657518 Mon Sep 17 00:00:00 2001 From: edef Date: Mon, 11 Apr 2022 17:17:31 +0000 Subject: ripple/fossil/mount: serve a small, static filesystem Serve up an entirely hardcoded minimal filesystem tree, so we can see most of the FUSE plumbing working already. Change-Id: I13c4b534c8dd159d2d2e177497b33f1bec3849ad --- ripple/fossil/src/bin/mount.rs | 157 +++++++++++++++++++++++++++++++++++------ 1 file changed, 137 insertions(+), 20 deletions(-) (limited to 'ripple/fossil/src/bin') diff --git a/ripple/fossil/src/bin/mount.rs b/ripple/fossil/src/bin/mount.rs index 5e4063e..4aaa0e0 100644 --- a/ripple/fossil/src/bin/mount.rs +++ b/ripple/fossil/src/bin/mount.rs @@ -2,15 +2,79 @@ // SPDX-License-Identifier: OSL-3.0 use { - libc::{c_int, ENOSYS, EROFS}, + lazy_static::lazy_static, + libc::{c_int, ENOENT, ENOSYS, EROFS}, log::{debug, warn}, + std::{ + time::{Duration, SystemTime, UNIX_EPOCH}, + }, }; +lazy_static! { + static ref EPOCH_PLUS_ONE: SystemTime = UNIX_EPOCH + Duration::from_secs(1); +} + +enum Kind { + Link, + File, + Directory, +} + +fn file_attr(ino: u64, kind: Kind, size: u64) -> fuser::FileAttr { + let blksize = 512; + fuser::FileAttr { + /// Inode number + ino, + /// Size in bytes + size, + /// Size in blocks + // TODO(edef): switch to u64::div_ceil + blocks: (size + blksize as u64 - 1) / (blksize as u64), + /// Time of last access + atime: *EPOCH_PLUS_ONE, + /// Time of last modification + mtime: *EPOCH_PLUS_ONE, + /// Time of last change + ctime: *EPOCH_PLUS_ONE, + /// Time of creation (macOS only) + crtime: *EPOCH_PLUS_ONE, + /// Kind of file (directory, file, pipe, etc) + kind: match kind { + Kind::Directory => fuser::FileType::Directory, + Kind::File => fuser::FileType::RegularFile, + Kind::Link => fuser::FileType::Symlink, + }, + /// Permissions + perm: match kind { + Kind::Directory => 0o755, + _ => 0o644, + }, + /// Number of hard links + nlink: 1, + /// User id + uid: 1000, + /// Group id + gid: 100, + /// Rdev + rdev: 0, + /// Block size + blksize, + /// Flags (macOS only, see chflags(2)) + flags: 0, + } +} + fn main() { env_logger::init(); let store = fossil::Store::open("fossil.db").unwrap(); - fuser::mount2(Filesystem::open(store), "mnt", &[]).unwrap(); + + fuser::mount2( + Filesystem::open(store), + "mnt", + &[fuser::MountOption::DefaultPermissions], + ) + .unwrap(); } struct Filesystem { @@ -41,18 +105,39 @@ impl fuser::Filesystem for Filesystem { name: &std::ffi::OsStr, reply: fuser::ReplyEntry, ) { - warn!( - "[Not Implemented] lookup(parent: {:#x?}, name {:?})", - parent, name + if parent != 1 { + warn!( + "[Not Implemented] lookup(parent: {:#x?}, name {:?})", + parent, name + ); + reply.error(ENOSYS); + return; + } + if name != "hello" { + reply.error(ENOENT); + return; + } + reply.entry( + &Duration::ZERO, + &file_attr(2, Kind::File, "world".len() as u64), + 0, ); - 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); + match ino { + 1 => reply.attr(&Duration::ZERO, &file_attr(ino, Kind::Directory, 2)), + 2 => reply.attr( + &Duration::ZERO, + &file_attr(ino, Kind::File, "world".len() as u64), + ), + _ => { + warn!("[Not Implemented] getattr(ino: {:#x?})", ino); + reply.error(ENOSYS); + } + } } fn setattr( @@ -180,12 +265,27 @@ impl fuser::Filesystem for Filesystem { 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); + match ino { + 2 => { + let offset = offset as usize; + let size = size as usize; + + let content = b"world"; + let mut buffer = content.get(offset..).unwrap_or_default(); + if buffer.len() > size { + buffer = &buffer[..size]; + } + reply.data(buffer); + } + _ => { + 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( @@ -262,13 +362,30 @@ impl fuser::Filesystem for Filesystem { ino: u64, fh: u64, offset: i64, - reply: fuser::ReplyDirectory, + mut reply: fuser::ReplyDirectory, ) { - warn!( - "[Not Implemented] readdir(ino: {:#x?}, fh: {}, offset: {})", - ino, fh, offset - ); - reply.error(ENOSYS); + if ino != 1 { + warn!( + "[Not Implemented] readdir(ino: {:#x?}, fh: {}, offset: {})", + ino, fh, offset + ); + reply.error(ENOSYS); + return; + } + + let children = &[ + (ino, fuser::FileType::Directory, "."), + (ino, fuser::FileType::Directory, ".."), + (0x2, fuser::FileType::RegularFile, "hello"), + ]; + + for (offset, &(ino, kind, name)) in children.iter().enumerate().skip(offset as usize) { + if reply.add(ino, (offset + 1) as i64, kind, name) { + break; + } + } + + reply.ok(); } fn readdirplus( -- cgit 1.4.1