msg.rs 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667
  1. // SPDX-License-Identifier: AGPL-3.0-or-later
  2. //! Definitions of messages passed between filesystem clients and servers.
  3. use super::{Handle, Inode};
  4. use btlib::{
  5. bterr, crypto::ConcretePub, BlockMetaSecrets, DirEntry, DirEntryKind, Epoch, IssuedProcRec,
  6. };
  7. use bttp::CallMsg;
  8. use core::time::Duration;
  9. use paste::paste;
  10. use serde::{Deserialize, Serialize};
  11. use std::{
  12. fmt::Display,
  13. io,
  14. ops::{BitOr, BitOrAssign},
  15. };
  16. /// Top-level message type for the filesystem protocol.
  17. /// All messages passed from clients to servers are of this type.
  18. #[derive(Serialize, Deserialize)]
  19. pub enum FsMsg<'a> {
  20. #[serde(borrow)]
  21. Lookup(Lookup<'a>),
  22. #[serde(borrow)]
  23. Create(Create<'a>),
  24. Open(Open),
  25. Read(Read),
  26. #[serde(borrow)]
  27. Write(Write<&'a [u8]>),
  28. Flush(Flush),
  29. ReadDir(ReadDir),
  30. #[serde(borrow)]
  31. Link(Link<'a>),
  32. #[serde(borrow)]
  33. Unlink(Unlink<'a>),
  34. ReadMeta(ReadMeta),
  35. WriteMeta(WriteMeta),
  36. Allocate(Allocate),
  37. Close(Close),
  38. Forget(Forget),
  39. Lock(Lock),
  40. Unlock(Unlock),
  41. AddReadcap(AddReadcap),
  42. GrantAccess(GrantAccess),
  43. }
  44. /// The type for every reply sent from servers to clients.
  45. #[derive(Serialize, Deserialize)]
  46. pub enum FsReply<'a> {
  47. /// Indicates a message was received successfully but does not provide any additional data.
  48. Ack(()),
  49. Lookup(LookupReply),
  50. Create(CreateReply),
  51. Open(OpenReply),
  52. #[serde(borrow)]
  53. Read(ReadReply<'a>),
  54. Write(WriteReply),
  55. ReadDir(ReadDirReply),
  56. Link(LinkReply),
  57. ReadMeta(ReadMetaReply),
  58. WriteMeta(WriteMetaReply),
  59. }
  60. impl<'a> CallMsg<'a> for FsMsg<'a> {
  61. type Reply<'b> = FsReply<'b>;
  62. }
  63. #[repr(u64)]
  64. /// An enumeration of special Inodes.
  65. pub enum SpecInodes {
  66. RootDir = 1,
  67. Sb = 2,
  68. FirstFree = 11,
  69. }
  70. impl SpecInodes {
  71. pub fn value(self) -> Inode {
  72. self as Inode
  73. }
  74. }
  75. impl From<SpecInodes> for Inode {
  76. fn from(special: SpecInodes) -> Self {
  77. special.value()
  78. }
  79. }
  80. #[derive(Debug, Clone, Hash, PartialEq, Eq, Serialize, Deserialize)]
  81. #[repr(u32)] // This type needs to match `libc::mode_t`.
  82. /// The type of a file (regular, directory, etc).
  83. pub enum FileType {
  84. /// Directory.
  85. Dir = libc::S_IFDIR,
  86. /// Regular file.
  87. Reg = libc::S_IFREG,
  88. }
  89. impl FileType {
  90. /// Returns the underlying mode bits for this file type.
  91. pub fn value(self) -> libc::mode_t {
  92. self as libc::mode_t
  93. }
  94. /// Attempts to convert the given mode bits into a `FileType` enum value.
  95. pub fn from_value(value: libc::mode_t) -> btlib::Result<Self> {
  96. if (value & libc::S_IFDIR) != 0 {
  97. return Ok(FileType::Dir);
  98. }
  99. if (value & libc::S_IFREG) != 0 {
  100. return Ok(FileType::Reg);
  101. }
  102. Err(bterr!("unknown file type: 0o{value:0o}"))
  103. }
  104. pub fn dir_entry_kind(self) -> DirEntryKind {
  105. match self {
  106. Self::Dir => DirEntryKind::Directory,
  107. Self::Reg => DirEntryKind::File,
  108. }
  109. }
  110. }
  111. impl From<FileType> for libc::mode_t {
  112. fn from(file_type: FileType) -> Self {
  113. file_type.value()
  114. }
  115. }
  116. impl TryFrom<libc::mode_t> for FileType {
  117. type Error = btlib::Error;
  118. fn try_from(value: libc::mode_t) -> btlib::Result<Self> {
  119. Self::from_value(value)
  120. }
  121. }
  122. impl From<FileType> for DirEntryKind {
  123. fn from(value: FileType) -> Self {
  124. value.dir_entry_kind()
  125. }
  126. }
  127. impl BitOr<libc::mode_t> for FileType {
  128. type Output = libc::mode_t;
  129. fn bitor(self, rhs: libc::mode_t) -> Self::Output {
  130. self.value() | rhs
  131. }
  132. }
  133. #[derive(Debug, Clone, Hash, PartialEq, Eq, Serialize, Deserialize)]
  134. #[repr(i32)]
  135. /// The generators for the group of [Flags].
  136. ///
  137. /// These are mostly values from libc, save for several custom values. Note that the presence of a
  138. /// flag in this enum does not guarantee it's supported.
  139. /// The standard libc `O_*` value which corresponds to each variant is given in the variant's
  140. /// comment.
  141. /// Consult your libc documentation for an explanation of what these means.
  142. pub enum FlagValue {
  143. // Standard flags.
  144. /// `O_RDONLY`
  145. ReadOnly = libc::O_RDONLY,
  146. /// `O_WRONLY`
  147. WriteOnly = libc::O_WRONLY,
  148. /// `O_RDWR`
  149. ReadWrite = libc::O_RDWR,
  150. /// `O_ACCMODE`
  151. AccMode = libc::O_ACCMODE,
  152. /// `O_CREAT`
  153. Create = libc::O_CREAT,
  154. /// `O_EXCL`
  155. Exclusive = libc::O_EXCL,
  156. /// `O_NOCTTY`
  157. NoCtty = libc::O_NOCTTY,
  158. /// `O_TRUNC`
  159. Truncate = libc::O_TRUNC,
  160. /// `O_APPEND`
  161. Append = libc::O_APPEND,
  162. /// `O_NONBLOCK`
  163. NonBlock = libc::O_NONBLOCK,
  164. /// `O_DSYNC`
  165. Dsync = libc::O_DSYNC,
  166. /// `O_ASYNC`
  167. Async = libc::O_ASYNC,
  168. /// `O_DIRECT`
  169. Direct = libc::O_DIRECT,
  170. /// `O_DIRECTORY`
  171. Directory = libc::O_DIRECTORY,
  172. /// `O_NOFOLLOW`
  173. NoFollow = libc::O_NOFOLLOW,
  174. /// `O_NOATIME`
  175. NoAtime = libc::O_NOATIME,
  176. /// `O_CLOEXEC`
  177. CloseExec = libc::O_CLOEXEC,
  178. /// `O_RSYNC`
  179. Rsync = libc::O_RSYNC,
  180. /// `O_PATH`
  181. Path = libc::O_PATH,
  182. /// `O_TMPFILE`
  183. TmpFile = libc::O_TMPFILE,
  184. // Custom flags.
  185. /// Indicates that a process block should be created.
  186. Process = 0x01000000,
  187. /// Indicates that a server block should be created.
  188. Server = 0x02000000,
  189. }
  190. impl FlagValue {
  191. /// Returns the underlying [i32] value.
  192. pub const fn value(self) -> i32 {
  193. self as i32
  194. }
  195. }
  196. impl Copy for FlagValue {}
  197. impl From<FlagValue> for i32 {
  198. fn from(flag_value: FlagValue) -> Self {
  199. flag_value.value()
  200. }
  201. }
  202. impl BitOr for FlagValue {
  203. type Output = Flags;
  204. fn bitor(self, rhs: Self) -> Self::Output {
  205. Flags::new(self.value() | rhs.value())
  206. }
  207. }
  208. #[derive(Debug, Clone, Hash, PartialEq, Eq, Serialize, Deserialize)]
  209. /// A wrapper type around [i32] with convenience methods for checking if `libc::O_*`
  210. /// flags have been set.
  211. pub struct Flags(i32);
  212. impl Copy for Flags {}
  213. impl Flags {
  214. /// Wraps the given [i32] value.
  215. pub const fn new(value: i32) -> Self {
  216. Self(value)
  217. }
  218. /// Returns the inner [i32] value.
  219. pub const fn value(self) -> i32 {
  220. self.0
  221. }
  222. /// Returns true if these flags allow the file to be written to.
  223. pub const fn writeable(self) -> bool {
  224. const MASK: i32 = FlagValue::ReadWrite.value() | FlagValue::WriteOnly.value();
  225. self.0 & MASK != 0
  226. }
  227. /// Returns true if these flags allow the file to be read from.
  228. pub const fn readable(self) -> bool {
  229. !self.write_only()
  230. }
  231. /// Returns true if the file was opened readonly.
  232. pub const fn read_only(self) -> bool {
  233. self.0 == FlagValue::ReadOnly.value()
  234. }
  235. /// Returns true if the file was opened writeonly
  236. pub const fn write_only(self) -> bool {
  237. self.0 & FlagValue::WriteOnly.value() != 0
  238. }
  239. /// Returns true if these flags are for a directory.
  240. pub const fn directory(self) -> bool {
  241. self.0 & FlagValue::Directory.value() != 0
  242. }
  243. /// Returns true if these flags are for a process.
  244. pub const fn process(self) -> bool {
  245. self.0 & FlagValue::Process.value() != 0
  246. }
  247. /// Returns true if these flags are for a server.
  248. pub const fn server(self) -> bool {
  249. self.0 & FlagValue::Server.value() != 0
  250. }
  251. /// Asserts that these flags allow a file to be read.
  252. ///
  253. /// If the assertion fails then an [io::Error] with the errno [libc::EACCES] is returned.
  254. pub fn assert_readable(self) -> Result<(), io::Error> {
  255. if !self.readable() {
  256. Err(io::Error::from_raw_os_error(libc::EACCES))
  257. } else {
  258. Ok(())
  259. }
  260. }
  261. /// Asserts that these flags allow a file to be written.
  262. ///
  263. /// If the assertion fails then an [io::Error] with the errno [libc::EACCES] is returned.
  264. pub fn assert_writeable(self) -> Result<(), io::Error> {
  265. if !self.writeable() {
  266. Err(io::Error::from_raw_os_error(libc::EACCES))
  267. } else {
  268. Ok(())
  269. }
  270. }
  271. }
  272. impl From<i32> for Flags {
  273. fn from(value: i32) -> Self {
  274. Self::new(value)
  275. }
  276. }
  277. impl From<Flags> for i32 {
  278. fn from(flags: Flags) -> Self {
  279. flags.value()
  280. }
  281. }
  282. impl From<FlagValue> for Flags {
  283. fn from(flag_value: FlagValue) -> Self {
  284. Self::new(flag_value.value())
  285. }
  286. }
  287. impl BitOr<Flags> for Flags {
  288. type Output = Flags;
  289. fn bitor(self, rhs: Flags) -> Self::Output {
  290. Self::new(self.value() | rhs.value())
  291. }
  292. }
  293. impl BitOr<FlagValue> for Flags {
  294. type Output = Flags;
  295. fn bitor(self, rhs: FlagValue) -> Self::Output {
  296. Self::new(self.value() | rhs.value())
  297. }
  298. }
  299. impl Display for Flags {
  300. fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
  301. self.value().fmt(f)
  302. }
  303. }
  304. impl Default for Flags {
  305. fn default() -> Self {
  306. Self::new(0)
  307. }
  308. }
  309. /// Attributes of a file.
  310. #[derive(Serialize, Deserialize, PartialEq, Eq, Clone, Hash, Default)]
  311. pub struct Attrs {
  312. pub mode: u32,
  313. pub uid: u32,
  314. pub gid: u32,
  315. pub atime: Epoch,
  316. pub mtime: Epoch,
  317. pub ctime: Epoch,
  318. pub tags: Vec<(String, Vec<u8>)>,
  319. }
  320. #[derive(Serialize, Deserialize, PartialEq, Eq, Clone, Hash)]
  321. /// A type for indicating which fields in [Attrs] have been set and which should be ignored.
  322. ///
  323. /// This method was chosen over using [Option] for greater efficiency on the wire.
  324. pub struct AttrsSet(u16);
  325. macro_rules! field {
  326. ($index:expr, $name:ident) => {
  327. pub const $name: AttrsSet = AttrsSet::new(1 << $index);
  328. paste! {
  329. pub fn [<$name:lower>](self) -> bool {
  330. const MASK: u16 = 1 << $index;
  331. self.0 & MASK != 0
  332. }
  333. }
  334. };
  335. }
  336. impl AttrsSet {
  337. field!(0, MODE);
  338. field!(1, UID);
  339. field!(2, GID);
  340. field!(3, ATIME);
  341. field!(4, MTIME);
  342. field!(5, CTIME);
  343. pub const ALL: Self = Self::new(
  344. Self::MODE.0 | Self::UID.0 | Self::GID.0 | Self::ATIME.0 | Self::MTIME.0 | Self::CTIME.0,
  345. );
  346. pub const fn new(value: u16) -> Self {
  347. Self(value)
  348. }
  349. pub const fn none() -> Self {
  350. Self(0)
  351. }
  352. pub const fn value(self) -> u16 {
  353. self.0
  354. }
  355. }
  356. impl Copy for AttrsSet {}
  357. impl From<u16> for AttrsSet {
  358. fn from(value: u16) -> Self {
  359. Self::new(value)
  360. }
  361. }
  362. impl From<AttrsSet> for u16 {
  363. fn from(attr: AttrsSet) -> Self {
  364. attr.value()
  365. }
  366. }
  367. impl BitOr<Self> for AttrsSet {
  368. type Output = Self;
  369. fn bitor(self, rhs: Self) -> Self::Output {
  370. AttrsSet::new(self.value() | rhs.value())
  371. }
  372. }
  373. impl BitOrAssign<Self> for AttrsSet {
  374. fn bitor_assign(&mut self, rhs: Self) {
  375. self.0 |= rhs.0
  376. }
  377. }
  378. /// A filesystem entry.
  379. ///
  380. /// This struct includes attributes of a file as well as cache control
  381. /// information for how long it may be cached.
  382. #[derive(Debug, Serialize, Deserialize)]
  383. pub struct Entry {
  384. pub attr: BlockMetaSecrets,
  385. pub attr_timeout: Duration,
  386. pub entry_timeout: Duration,
  387. }
  388. /// A request to lookup a name in a directory.
  389. #[derive(Serialize, Deserialize)]
  390. pub struct Lookup<'a> {
  391. pub parent: Inode,
  392. pub name: &'a str,
  393. }
  394. /// A reply containing the [Entry] stored under a name in a directory.
  395. #[derive(Debug, Serialize, Deserialize)]
  396. pub struct LookupReply {
  397. pub inode: Inode,
  398. pub generation: u64,
  399. pub entry: Entry,
  400. }
  401. /// A request to create a file in a directory under a given name.
  402. #[derive(Serialize, Deserialize)]
  403. pub struct Create<'a> {
  404. pub parent: Inode,
  405. pub name: &'a str,
  406. pub flags: Flags,
  407. pub mode: u32,
  408. pub umask: u32,
  409. }
  410. /// A reply containing information about a newly created file.
  411. #[derive(Serialize, Deserialize)]
  412. pub struct CreateReply {
  413. pub inode: Inode,
  414. pub handle: Handle,
  415. pub entry: Entry,
  416. }
  417. /// A request to hope a file.
  418. #[derive(Serialize, Deserialize)]
  419. pub struct Open {
  420. pub inode: Inode,
  421. pub flags: Flags,
  422. }
  423. /// A reply which contains a handle to an open file.
  424. #[derive(Serialize, Deserialize)]
  425. pub struct OpenReply {
  426. pub handle: Handle,
  427. }
  428. /// A request to read data at a particular offset from an open file.
  429. #[derive(Serialize, Deserialize)]
  430. pub struct Read {
  431. pub inode: Inode,
  432. pub handle: Handle,
  433. pub offset: u64,
  434. pub size: u64,
  435. }
  436. /// A reply containing data read from a file.
  437. #[derive(Serialize, Deserialize)]
  438. pub struct ReadReply<'a> {
  439. pub data: &'a [u8],
  440. }
  441. /// A request to write data to a particular offset in an open file.
  442. #[derive(Serialize, Deserialize)]
  443. pub struct Write<R> {
  444. pub inode: Inode,
  445. pub handle: Handle,
  446. pub offset: u64,
  447. pub data: R,
  448. }
  449. /// A reply containing the number of bytes written to a file.
  450. #[derive(Serialize, Deserialize)]
  451. pub struct WriteReply {
  452. pub written: u64,
  453. }
  454. /// A request to flush all data cached for an open file to durable storage.
  455. #[derive(Serialize, Deserialize)]
  456. pub struct Flush {
  457. pub inode: Inode,
  458. pub handle: Handle,
  459. }
  460. /// A request to read the contents of a directory.
  461. #[derive(Serialize, Deserialize)]
  462. pub struct ReadDir {
  463. pub inode: Inode,
  464. pub handle: Handle,
  465. /// The maximum number of directory entries to return in a single response. A value of 0
  466. /// indicates there is no limit. Note that the server may impose it's own limit.
  467. pub limit: u32,
  468. /// An opaque value which the server uses to keep track of the client's position in reading
  469. /// the directory. A value of 0 indicates the directory is to be iterated from the beginning.
  470. pub state: u64,
  471. }
  472. /// A reply containing the contents of a directory.
  473. #[derive(Serialize, Deserialize)]
  474. pub struct ReadDirReply {
  475. pub entries: Vec<(String, DirEntry)>,
  476. /// This is the value to pass in a subsequent [ReadDir] message to continue reading this
  477. /// directory. A value of 0 indicates that all entries have been returned.
  478. pub new_state: u64,
  479. }
  480. /// A request to create a new hard link to a file.
  481. #[derive(Serialize, Deserialize)]
  482. pub struct Link<'a> {
  483. pub inode: Inode,
  484. pub new_parent: Inode,
  485. pub name: &'a str,
  486. }
  487. /// A reply containing the [Entry] of the newly created hard link.
  488. #[derive(Serialize, Deserialize)]
  489. pub struct LinkReply {
  490. pub entry: Entry,
  491. }
  492. /// A request to remove a name referring to an inode.
  493. ///
  494. /// If the inode becomes orphaned, it is removed from durable storage.
  495. #[derive(Serialize, Deserialize)]
  496. pub struct Unlink<'a> {
  497. pub parent: Inode,
  498. pub name: &'a str,
  499. }
  500. /// A request to read a file's metadata.
  501. #[derive(Serialize, Deserialize)]
  502. pub struct ReadMeta {
  503. pub inode: Inode,
  504. pub handle: Option<Handle>,
  505. }
  506. /// A reply containing the metadata of a file.
  507. #[derive(Serialize, Deserialize)]
  508. pub struct ReadMetaReply {
  509. pub attrs: BlockMetaSecrets,
  510. pub valid_for: Duration,
  511. }
  512. /// A request to write the metadata of a file.
  513. #[derive(Serialize, Deserialize)]
  514. pub struct WriteMeta {
  515. pub inode: Inode,
  516. pub handle: Option<Handle>,
  517. pub attrs: Attrs,
  518. /// The bits in this value indicate which fields in `attrs` have been initialized.
  519. pub attrs_set: AttrsSet,
  520. }
  521. /// A reply containing the newly written file metadata.
  522. #[derive(Serialize, Deserialize)]
  523. pub struct WriteMetaReply {
  524. pub attrs: BlockMetaSecrets,
  525. pub valid_for: Duration,
  526. }
  527. /// A request to pre-allocate a given amount of space from durable storage for a file.
  528. #[derive(Serialize, Deserialize)]
  529. pub struct Allocate {
  530. pub inode: Inode,
  531. pub handle: Handle,
  532. pub offset: Option<u64>,
  533. pub size: u64,
  534. }
  535. /// A request to close an open file.
  536. #[derive(Serialize, Deserialize)]
  537. pub struct Close {
  538. pub inode: Inode,
  539. pub handle: Handle,
  540. }
  541. /// A request to forget about an inode which was previously referenced.
  542. ///
  543. /// This message must be sent
  544. /// so the server knows when it can free resources associated with the inode.
  545. /// If `N` [Entry] structs are sent in a reply to [Lookup] messages, then the caller must send one
  546. /// or more [Forget] messages such that their `count` fields add up to `N`.
  547. #[derive(Serialize, Deserialize)]
  548. pub struct Forget {
  549. pub inode: Inode,
  550. pub count: u64,
  551. }
  552. /// The description of a region in a file to lock.
  553. #[derive(Serialize, Deserialize)]
  554. pub struct LockDesc {
  555. pub offset: u64,
  556. pub size: u64,
  557. pub exclusive: bool,
  558. }
  559. /// A request to lock a region of a file.
  560. #[derive(Serialize, Deserialize)]
  561. pub struct Lock {
  562. pub inode: Inode,
  563. pub handle: Handle,
  564. pub desc: LockDesc,
  565. }
  566. /// A request to unlock a region of a file.
  567. #[derive(Serialize, Deserialize)]
  568. pub struct Unlock {
  569. pub inode: Inode,
  570. pub handle: Handle,
  571. }
  572. /// A request to add a [btlib::Readcap] to a file.
  573. #[derive(Serialize, Deserialize)]
  574. pub struct AddReadcap {
  575. pub inode: Inode,
  576. pub handle: Handle,
  577. pub pub_creds: ConcretePub,
  578. }
  579. /// A request to give a process access to an inode.
  580. #[derive(Serialize, Deserialize)]
  581. pub struct GrantAccess {
  582. pub inode: Inode,
  583. pub record: IssuedProcRec,
  584. }