diff options
author | edef <edef@unfathomable.blue> | 2022-04-11 17:17:31 +0000 |
---|---|---|
committer | edef <edef@unfathomable.blue> | 2022-04-11 17:21:20 +0000 |
commit | b6efed641aecd3d2f9922c7eb2fa1a3d75657518 (patch) | |
tree | 4390f0ef3205d5ec5dcb545a7f8b193bec955f43 /ripple/fossil | |
parent | 43eca585e23e1c5f4b0420f2f1b7694aa07b438f (diff) | |
download | unf-legacy-b6efed641aecd3d2f9922c7eb2fa1a3d75657518.tar.zst |
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
Diffstat (limited to 'ripple/fossil')
-rw-r--r-- | ripple/fossil/Cargo.toml | 3 | ||||
-rw-r--r-- | ripple/fossil/src/bin/mount.rs | 157 |
2 files changed, 139 insertions, 21 deletions
diff --git a/ripple/fossil/Cargo.toml b/ripple/fossil/Cargo.toml index 86972c8..0634152 100644 --- a/ripple/fossil/Cargo.toml +++ b/ripple/fossil/Cargo.toml @@ -16,12 +16,13 @@ fuser = { version = "0.11.0", optional = true } log = { version = "0.4.14", optional = true } libc = { version = "0.2.112", optional = true } env_logger = { version = "0.9.0", optional = true } +lazy_static = { version = "1.4.0", optional = true } [build-dependencies] prost-build = "0.8.0" [features] -wip-mount = ["fuser", "log", "libc", "env_logger"] +wip-mount = ["fuser", "log", "libc", "env_logger", "lazy_static"] [[bin]] name = "mount" 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<u64>, 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( |