123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597 |
- // SPDX-License-Identifier: AGPL-3.0-or-later
- use super::{Handle, Inode};
- use btlib::{
- bterr, crypto::ConcretePub, BlockMetaSecrets, DirEntry, DirEntryKind, Epoch, IssuedProcRec,
- };
- use btmsg::CallMsg;
- use core::time::Duration;
- use paste::paste;
- use serde::{Deserialize, Serialize};
- use std::{
- fmt::Display,
- io,
- ops::{BitOr, BitOrAssign},
- };
- #[derive(Serialize, Deserialize)]
- pub enum FsMsg<'a> {
- #[serde(borrow)]
- Lookup(Lookup<'a>),
- #[serde(borrow)]
- Create(Create<'a>),
- Open(Open),
- Read(Read),
- #[serde(borrow)]
- Write(Write<&'a [u8]>),
- Flush(Flush),
- ReadDir(ReadDir),
- #[serde(borrow)]
- Link(Link<'a>),
- #[serde(borrow)]
- Unlink(Unlink<'a>),
- ReadMeta(ReadMeta),
- WriteMeta(WriteMeta),
- Allocate(Allocate),
- Close(Close),
- Forget(Forget),
- Lock(Lock),
- Unlock(Unlock),
- AddReadcap(AddReadcap),
- GrantAccess(GrantAccess),
- }
- #[derive(Serialize, Deserialize)]
- pub enum FsReply<'a> {
- Ack(()),
- Lookup(LookupReply),
- Create(CreateReply),
- Open(OpenReply),
- #[serde(borrow)]
- Read(ReadReply<'a>),
- Write(WriteReply),
- ReadDir(ReadDirReply),
- Link(LinkReply),
- ReadMeta(ReadMetaReply),
- WriteMeta(WriteMetaReply),
- }
- impl<'a> CallMsg<'a> for FsMsg<'a> {
- type Reply<'b> = FsReply<'b>;
- }
- #[derive(Debug, Serialize, Deserialize)]
- pub enum FsError {
- Other,
- }
- impl Display for FsError {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- match self {
- Self::Other => write!(f, "uncategorized error"),
- }
- }
- }
- impl std::error::Error for FsError {}
- #[repr(u64)]
- /// An enumeration of special Inodes.
- pub enum SpecInodes {
- RootDir = 1,
- Sb = 2,
- FirstFree = 11,
- }
- impl SpecInodes {
- pub fn value(self) -> Inode {
- self as Inode
- }
- }
- impl From<SpecInodes> for Inode {
- fn from(special: SpecInodes) -> Self {
- special.value()
- }
- }
- #[derive(Debug, Clone, Hash, PartialEq, Eq, Serialize, Deserialize)]
- #[repr(u32)] // This type needs to match `libc::mode_t`.
- /// The type of a file (regular, directory, etc).
- pub enum FileType {
- /// Directory.
- Dir = libc::S_IFDIR,
- /// Regular file.
- Reg = libc::S_IFREG,
- }
- impl FileType {
- /// Returns the underlying mode bits for this file type.
- pub fn value(self) -> libc::mode_t {
- self as libc::mode_t
- }
- /// Attempts to convert the given mode bits into a `FileType` enum value.
- pub fn from_value(value: libc::mode_t) -> btlib::Result<Self> {
- if (value & libc::S_IFDIR) != 0 {
- return Ok(FileType::Dir);
- }
- if (value & libc::S_IFREG) != 0 {
- return Ok(FileType::Reg);
- }
- Err(bterr!("unknown file type: 0o{value:0o}"))
- }
- pub fn dir_entry_kind(self) -> DirEntryKind {
- match self {
- Self::Dir => DirEntryKind::Directory,
- Self::Reg => DirEntryKind::File,
- }
- }
- }
- impl From<FileType> for libc::mode_t {
- fn from(file_type: FileType) -> Self {
- file_type.value()
- }
- }
- impl TryFrom<libc::mode_t> for FileType {
- type Error = btlib::Error;
- fn try_from(value: libc::mode_t) -> btlib::Result<Self> {
- Self::from_value(value)
- }
- }
- impl From<FileType> for DirEntryKind {
- fn from(value: FileType) -> Self {
- value.dir_entry_kind()
- }
- }
- impl BitOr<libc::mode_t> for FileType {
- type Output = libc::mode_t;
- fn bitor(self, rhs: libc::mode_t) -> Self::Output {
- self.value() | rhs
- }
- }
- #[derive(Debug, Clone, Hash, PartialEq, Eq, Serialize, Deserialize)]
- #[repr(i32)]
- /// The generators for the group of [Flags]. These are mostly copied from [libc], save for
- /// several custom values. Note that the presence of a flag in this enum does not guarantee
- /// it's supported.
- pub enum FlagValue {
- // Standard flags.
- ReadOnly = libc::O_RDONLY,
- WriteOnly = libc::O_WRONLY,
- ReadWrite = libc::O_RDWR,
- AccMode = libc::O_ACCMODE,
- Create = libc::O_CREAT,
- Exclusive = libc::O_EXCL,
- NoCtty = libc::O_NOCTTY,
- Truncate = libc::O_TRUNC,
- Append = libc::O_APPEND,
- NonBlock = libc::O_NONBLOCK,
- Dsync = libc::O_DSYNC,
- Async = libc::O_ASYNC,
- Direct = libc::O_DIRECT,
- Directory = libc::O_DIRECTORY,
- NoFollow = libc::O_NOFOLLOW,
- NoAtime = libc::O_NOATIME,
- CloseExec = libc::O_CLOEXEC,
- Rsync = libc::O_RSYNC,
- Path = libc::O_PATH,
- TmpFile = libc::O_TMPFILE,
- // Custom flags.
- /// Indicates that a process block should be created.
- Process = 0x01000000,
- /// Indicates that a server block be created.
- Server = 0x02000000,
- }
- impl FlagValue {
- pub const fn value(self) -> i32 {
- self as i32
- }
- }
- impl Copy for FlagValue {}
- impl From<FlagValue> for i32 {
- fn from(flag_value: FlagValue) -> Self {
- flag_value.value()
- }
- }
- impl BitOr for FlagValue {
- type Output = Flags;
- fn bitor(self, rhs: Self) -> Self::Output {
- Flags::new(self.value() | rhs.value())
- }
- }
- #[derive(Debug, Clone, Hash, PartialEq, Eq, Serialize, Deserialize)]
- /// A wrapper type around [i32] with convenience methods for checking if `libc::O_*`
- /// flags have been set.
- pub struct Flags(i32);
- impl Copy for Flags {}
- impl Flags {
- pub const fn new(value: i32) -> Self {
- Self(value)
- }
- pub const fn value(self) -> i32 {
- self.0
- }
- /// Returns true if and only if the given open flags allow the file to be written to.
- pub const fn writeable(self) -> bool {
- const MASK: i32 = FlagValue::ReadWrite.value() | FlagValue::WriteOnly.value();
- self.0 & MASK != 0
- }
- pub const fn readable(self) -> bool {
- !self.write_only()
- }
- pub const fn read_only(self) -> bool {
- self.0 == FlagValue::ReadOnly.value()
- }
- pub const fn write_only(self) -> bool {
- self.0 & FlagValue::WriteOnly.value() != 0
- }
- pub const fn directory(self) -> bool {
- self.0 & FlagValue::Directory.value() != 0
- }
- pub const fn process(self) -> bool {
- self.0 & FlagValue::Process.value() != 0
- }
- pub const fn server(self) -> bool {
- self.0 & FlagValue::Server.value() != 0
- }
- pub fn assert_readable(self) -> Result<(), io::Error> {
- if !self.readable() {
- Err(io::Error::from_raw_os_error(libc::EACCES))
- } else {
- Ok(())
- }
- }
- pub fn assert_writeable(self) -> Result<(), io::Error> {
- if !self.writeable() {
- Err(io::Error::from_raw_os_error(libc::EACCES))
- } else {
- Ok(())
- }
- }
- }
- impl From<i32> for Flags {
- fn from(value: i32) -> Self {
- Self::new(value)
- }
- }
- impl From<Flags> for i32 {
- fn from(flags: Flags) -> Self {
- flags.value()
- }
- }
- impl From<FlagValue> for Flags {
- fn from(flag_value: FlagValue) -> Self {
- Self::new(flag_value.value())
- }
- }
- impl BitOr<Flags> for Flags {
- type Output = Flags;
- fn bitor(self, rhs: Flags) -> Self::Output {
- Self::new(self.value() | rhs.value())
- }
- }
- impl BitOr<FlagValue> for Flags {
- type Output = Flags;
- fn bitor(self, rhs: FlagValue) -> Self::Output {
- Self::new(self.value() | rhs.value())
- }
- }
- impl Display for Flags {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- self.value().fmt(f)
- }
- }
- impl Default for Flags {
- fn default() -> Self {
- Self::new(0)
- }
- }
- #[derive(Serialize, Deserialize, PartialEq, Eq, Clone, Hash, Default)]
- pub struct Attrs {
- pub mode: u32,
- pub uid: u32,
- pub gid: u32,
- pub atime: Epoch,
- pub mtime: Epoch,
- pub ctime: Epoch,
- pub tags: Vec<(String, Vec<u8>)>,
- }
- #[derive(Serialize, Deserialize, PartialEq, Eq, Clone, Hash)]
- /// A type for indicating which fields in [Attrs] have been set and which should be ignored. This
- /// method was chosen over using [Option] for greater efficiency on the wire.
- pub struct AttrsSet(u16);
- macro_rules! field {
- ($index:expr, $name:ident) => {
- pub const $name: AttrsSet = AttrsSet::new(1 << $index);
- paste! {
- pub fn [<$name:lower>](self) -> bool {
- const MASK: u16 = 1 << $index;
- self.0 & MASK != 0
- }
- }
- };
- }
- impl AttrsSet {
- field!(0, MODE);
- field!(1, UID);
- field!(2, GID);
- field!(3, ATIME);
- field!(4, MTIME);
- field!(5, CTIME);
- pub const ALL: Self = Self::new(
- Self::MODE.0 | Self::UID.0 | Self::GID.0 | Self::ATIME.0 | Self::MTIME.0 | Self::CTIME.0,
- );
- pub const fn new(value: u16) -> Self {
- Self(value)
- }
- pub const fn none() -> Self {
- Self(0)
- }
- pub const fn value(self) -> u16 {
- self.0
- }
- }
- impl Copy for AttrsSet {}
- impl From<u16> for AttrsSet {
- fn from(value: u16) -> Self {
- Self::new(value)
- }
- }
- impl From<AttrsSet> for u16 {
- fn from(attr: AttrsSet) -> Self {
- attr.value()
- }
- }
- impl BitOr<Self> for AttrsSet {
- type Output = Self;
- fn bitor(self, rhs: Self) -> Self::Output {
- AttrsSet::new(self.value() | rhs.value())
- }
- }
- impl BitOrAssign<Self> for AttrsSet {
- fn bitor_assign(&mut self, rhs: Self) {
- self.0 |= rhs.0
- }
- }
- #[derive(Debug, Serialize, Deserialize)]
- pub struct Entry {
- pub attr: BlockMetaSecrets,
- pub attr_timeout: Duration,
- pub entry_timeout: Duration,
- }
- #[derive(Serialize, Deserialize)]
- pub struct Lookup<'a> {
- pub parent: Inode,
- pub name: &'a str,
- }
- #[derive(Debug, Serialize, Deserialize)]
- pub struct LookupReply {
- pub inode: Inode,
- pub generation: u64,
- pub entry: Entry,
- }
- #[derive(Serialize, Deserialize)]
- pub struct Create<'a> {
- pub parent: Inode,
- pub name: &'a str,
- pub flags: Flags,
- pub mode: u32,
- pub umask: u32,
- }
- #[derive(Serialize, Deserialize)]
- pub struct CreateReply {
- pub inode: Inode,
- pub handle: Handle,
- pub entry: Entry,
- }
- #[derive(Serialize, Deserialize)]
- pub struct Open {
- pub inode: Inode,
- pub flags: Flags,
- }
- #[derive(Serialize, Deserialize)]
- pub struct OpenReply {
- pub handle: Handle,
- }
- #[derive(Serialize, Deserialize)]
- pub struct Read {
- pub inode: Inode,
- pub handle: Handle,
- pub offset: u64,
- pub size: u64,
- }
- #[derive(Serialize, Deserialize)]
- pub struct ReadReply<'a> {
- pub data: &'a [u8],
- }
- #[derive(Serialize, Deserialize)]
- pub struct Write<R> {
- pub inode: Inode,
- pub handle: Handle,
- pub offset: u64,
- pub data: R,
- }
- #[derive(Serialize, Deserialize)]
- pub struct WriteReply {
- pub written: u64,
- }
- #[derive(Serialize, Deserialize)]
- pub struct Flush {
- pub inode: Inode,
- pub handle: Handle,
- }
- #[derive(Serialize, Deserialize)]
- pub struct ReadDir {
- pub inode: Inode,
- pub handle: Handle,
- /// The maximum number of directory entries to return in a single response. A value of 0
- /// indicates there is no limit. Note that the server may impose it's own limit.
- pub limit: u32,
- /// An opaque value which the server uses to keep track of the client's position in reading
- /// the directory. A value of 0 indicates the directory is to be iterated from the beginning.
- pub state: u64,
- }
- #[derive(Serialize, Deserialize)]
- pub struct ReadDirReply {
- pub entries: Vec<(String, DirEntry)>,
- /// This is the value to pass in a subsequent [ReadDir] message to continue reading this
- /// directory. A value of 0 indicates that all entries have been returned.
- pub new_state: u64,
- }
- #[derive(Serialize, Deserialize)]
- pub struct Link<'a> {
- pub inode: Inode,
- pub new_parent: Inode,
- pub name: &'a str,
- }
- #[derive(Serialize, Deserialize)]
- pub struct LinkReply {
- pub entry: Entry,
- }
- #[derive(Serialize, Deserialize)]
- pub struct Unlink<'a> {
- pub parent: Inode,
- pub name: &'a str,
- }
- #[derive(Serialize, Deserialize)]
- pub struct ReadMeta {
- pub inode: Inode,
- pub handle: Option<Handle>,
- }
- #[derive(Serialize, Deserialize)]
- pub struct ReadMetaReply {
- pub attrs: BlockMetaSecrets,
- pub valid_for: Duration,
- }
- #[derive(Serialize, Deserialize)]
- pub struct WriteMeta {
- pub inode: Inode,
- pub handle: Option<Handle>,
- pub attrs: Attrs,
- /// The bits in this value indicate which fields in `attrs` have been initialized.
- pub attrs_set: AttrsSet,
- }
- #[derive(Serialize, Deserialize)]
- pub struct WriteMetaReply {
- pub attrs: BlockMetaSecrets,
- pub valid_for: Duration,
- }
- #[derive(Serialize, Deserialize)]
- pub struct Allocate {
- pub inode: Inode,
- pub handle: Handle,
- pub offset: Option<u64>,
- pub size: u64,
- }
- #[derive(Serialize, Deserialize)]
- pub struct Close {
- pub inode: Inode,
- pub handle: Handle,
- }
- #[derive(Serialize, Deserialize)]
- pub struct Forget {
- pub inode: Inode,
- pub count: u64,
- }
- #[derive(Serialize, Deserialize)]
- pub struct LockDesc {
- pub offset: u64,
- pub size: u64,
- pub exclusive: bool,
- }
- #[derive(Serialize, Deserialize)]
- pub struct Lock {
- pub inode: Inode,
- pub handle: Handle,
- pub desc: LockDesc,
- }
- #[derive(Serialize, Deserialize)]
- pub struct Unlock {
- pub inode: Inode,
- pub handle: Handle,
- }
- #[derive(Serialize, Deserialize)]
- pub struct AddReadcap {
- pub inode: Inode,
- pub handle: Handle,
- pub pub_creds: ConcretePub,
- }
- #[derive(Serialize, Deserialize)]
- pub struct GrantAccess {
- pub inode: Inode,
- pub record: IssuedProcRec,
- }
|