blocktree.rs 66 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971
  1. pub use private::{Blocktree, ModeAuthorizer};
  2. mod private {
  3. use btserde::{read_from, write_to};
  4. use fuse_backend_rs::{
  5. abi::fuse_abi::{stat64, statvfs64, CreateIn},
  6. api::filesystem::{
  7. Context, DirEntry as FuseDirEntry, Entry, FileSystem, FsOptions, OpenOptions,
  8. },
  9. };
  10. use log::{debug, error, warn};
  11. use serde::{Deserialize, Serialize};
  12. use std::{
  13. collections::hash_map::{self, HashMap},
  14. ffi::CStr,
  15. fs::File,
  16. io::{self, SeekFrom, Write},
  17. path::{Path, PathBuf},
  18. sync::{
  19. atomic::{AtomicU64, Ordering},
  20. RwLock,
  21. },
  22. time::Duration,
  23. };
  24. use crate::{
  25. crypto::Creds, Block, BlockMeta, BlockOpenOptions, BlockPath, BoxInIoErr, DirEntry,
  26. Directory, Epoch, Error, Result, ToStringInIoErr,
  27. };
  28. type Inode = u64;
  29. type Handle = u64;
  30. #[repr(u64)]
  31. pub enum SpecInodes {
  32. RootDir = 1,
  33. Sb = 2,
  34. FirstFree = 11,
  35. }
  36. impl From<SpecInodes> for Inode {
  37. fn from(special: SpecInodes) -> Self {
  38. special as Inode
  39. }
  40. }
  41. #[derive(Debug, Clone, Hash, PartialEq, Eq, Serialize, Deserialize)]
  42. #[repr(u32)] // This type needs to match `libc::mode_t`.
  43. /// The type of a file (regular, directory, etc).
  44. enum FileType {
  45. /// Directory.
  46. Dir = libc::S_IFDIR,
  47. /// Regular file.
  48. Reg = libc::S_IFREG,
  49. }
  50. impl FileType {
  51. /// Returns the underlying mode bits for this file type.
  52. fn value(self) -> libc::mode_t {
  53. self as libc::mode_t
  54. }
  55. /// Attempts to convert the given mode bits into a `FileType` enum value.
  56. fn from_value(value: libc::mode_t) -> Result<Self> {
  57. if (value & libc::S_IFDIR) != 0 {
  58. return Ok(FileType::Dir);
  59. }
  60. if (value & libc::S_IFREG) != 0 {
  61. return Ok(FileType::Reg);
  62. }
  63. Err(Error::custom(format!("unknown file type: 0o{value:0o}")))
  64. }
  65. }
  66. impl From<FileType> for libc::mode_t {
  67. fn from(file_type: FileType) -> Self {
  68. file_type.value()
  69. }
  70. }
  71. impl TryFrom<libc::mode_t> for FileType {
  72. type Error = crate::Error;
  73. fn try_from(value: libc::mode_t) -> Result<Self> {
  74. Self::from_value(value)
  75. }
  76. }
  77. trait SeekFromExt {
  78. /// Converts a C-style `(whence, offset)` pair into a [SeekFrom] enum value.
  79. /// See the POSIX man page of `lseek` for more details.
  80. fn whence_offset(whence: u32, offset: u64) -> io::Result<SeekFrom> {
  81. let whence = whence as i32;
  82. match whence {
  83. libc::SEEK_SET => Ok(SeekFrom::Start(offset)),
  84. libc::SEEK_CUR => Ok(SeekFrom::Current(offset as i64)),
  85. libc::SEEK_END => Ok(SeekFrom::End(offset as i64)),
  86. _ => Err(io::Error::new(
  87. io::ErrorKind::InvalidInput,
  88. "`whence` was not one of `libc::{SEEK_SET, SEEK_CUR, SEEK_END}`",
  89. )),
  90. }
  91. }
  92. }
  93. impl SeekFromExt for SeekFrom {}
  94. /// This type provides context for an authorization decision as to whether a given process will
  95. /// be allowed to access a block.
  96. pub struct AuthzContext<'a> {
  97. /// The user ID of the process being authorized.
  98. pub uid: u32,
  99. /// The group ID of the process being authorized.
  100. pub gid: u32,
  101. /// The process ID of the process being authorized.
  102. pub pid: libc::pid_t,
  103. /// A reference to the metadata of a block, the access to which is being authorized.
  104. pub meta: &'a BlockMeta,
  105. }
  106. impl<'a> AuthzContext<'a> {
  107. pub fn new(ctx: &Context, meta: &'a BlockMeta) -> AuthzContext<'a> {
  108. AuthzContext {
  109. uid: ctx.uid,
  110. gid: ctx.gid,
  111. pid: ctx.pid,
  112. meta,
  113. }
  114. }
  115. }
  116. /// A trait for types which can render authorization decisions.
  117. pub trait Authorizer {
  118. /// Returns [Ok] if read authorization is granted, and [Err] otherwise.
  119. fn can_read<'a>(&self, ctx: &AuthzContext<'a>) -> io::Result<()>;
  120. /// Returns [Ok] if write authorization is granted, and [Err] otherwise.
  121. fn can_write<'a>(&self, ctx: &AuthzContext<'a>) -> io::Result<()>;
  122. /// Returns [Ok] if execute authorization is granted, and [Err] otherwise.
  123. fn can_exec<'a>(&self, ctx: &AuthzContext<'a>) -> io::Result<()>;
  124. }
  125. /// A particularly simple authorizer that just looks at the mode bits in the block metadata
  126. /// to make authorization decisions.
  127. pub struct ModeAuthorizer {}
  128. impl ModeAuthorizer {
  129. fn authorize(mode: u32, mask: u32, denied_msg: &str) -> io::Result<()> {
  130. if (mode & mask) != 0 {
  131. Ok(())
  132. } else {
  133. Err(io::Error::new(io::ErrorKind::PermissionDenied, denied_msg))
  134. }
  135. }
  136. }
  137. impl Authorizer for ModeAuthorizer {
  138. fn can_read<'a>(&self, ctx: &AuthzContext<'a>) -> io::Result<()> {
  139. let secrets = ctx.meta.body.secrets()?;
  140. let mask = (libc::S_IRUSR * (secrets.uid == ctx.uid) as u32)
  141. | (libc::S_IRGRP * (secrets.gid == ctx.gid) as u32)
  142. | libc::S_IROTH;
  143. Self::authorize(secrets.mode, mask, "read access denied")
  144. }
  145. fn can_write<'a>(&self, ctx: &AuthzContext<'a>) -> io::Result<()> {
  146. let secrets = ctx.meta.body.secrets()?;
  147. let mask = (libc::S_IWUSR * (secrets.uid == ctx.uid) as u32)
  148. | (libc::S_IWGRP * (secrets.gid == ctx.gid) as u32)
  149. | libc::S_IWOTH;
  150. Self::authorize(secrets.mode, mask, "write access denied")
  151. }
  152. fn can_exec<'a>(&self, ctx: &AuthzContext<'a>) -> io::Result<()> {
  153. let secrets = ctx.meta.body.secrets()?;
  154. let mask = (libc::S_IXUSR * (secrets.uid == ctx.uid) as u32)
  155. | (libc::S_IXGRP * (secrets.gid == ctx.gid) as u32)
  156. | libc::S_IXOTH;
  157. Self::authorize(secrets.mode, mask, "exec access denied")
  158. }
  159. }
  160. enum HandleValue {
  161. File {
  162. block: RwLock<Box<dyn Block>>,
  163. },
  164. Directory {
  165. dir: Directory,
  166. block: RwLock<Box<dyn Block>>,
  167. },
  168. }
  169. impl HandleValue {
  170. fn new(block: Box<dyn Block>) -> HandleValue {
  171. HandleValue::File {
  172. block: RwLock::new(block),
  173. }
  174. }
  175. fn convert_to_dir(self) -> io::Result<HandleValue> {
  176. let lock = self.take_block();
  177. let dir = {
  178. let mut guard = lock.write().err_to_string()?;
  179. guard.seek(SeekFrom::Start(0))?;
  180. read_from(&mut *guard)?
  181. };
  182. Ok(HandleValue::Directory { dir, block: lock })
  183. }
  184. fn take_block(self) -> RwLock<Box<dyn Block>> {
  185. match self {
  186. Self::File { block, .. } => block,
  187. Self::Directory { block, .. } => block,
  188. }
  189. }
  190. fn block(&self) -> &RwLock<Box<dyn Block>> {
  191. match self {
  192. Self::File { block, .. } => block,
  193. Self::Directory { block, .. } => block,
  194. }
  195. }
  196. fn block_mut(&mut self) -> io::Result<&mut Box<dyn Block>> {
  197. let lock = match self {
  198. Self::File { block, .. } => block,
  199. Self::Directory { block, .. } => block,
  200. };
  201. lock.get_mut().err_to_string()
  202. }
  203. fn access_block<T, F: FnOnce(&Box<dyn Block>) -> io::Result<T>>(
  204. &self,
  205. cb: F,
  206. ) -> io::Result<T> {
  207. let guard = self.block().read().err_to_string()?;
  208. cb(&guard)
  209. }
  210. fn access_block_mut<T, F: FnOnce(&mut Box<dyn Block>) -> io::Result<T>>(
  211. &self,
  212. cb: F,
  213. ) -> io::Result<T> {
  214. let mut guard = self.block().write().err_to_string()?;
  215. cb(&mut guard)
  216. }
  217. fn directory(&self) -> io::Result<&Directory> {
  218. match self {
  219. Self::Directory { dir, .. } => Ok(dir),
  220. _ => Err(io::Error::new(
  221. io::ErrorKind::Other,
  222. "handle is not for a directory",
  223. )),
  224. }
  225. }
  226. }
  227. struct InodeTableValue {
  228. handle_values: HashMap<Handle, HandleValue>,
  229. next_handle: Handle,
  230. unclaimed_handles: Vec<Handle>,
  231. lookup_count: u64,
  232. delete: bool,
  233. }
  234. impl InodeTableValue {
  235. /// If more than this number of unclaimed blocks are open, then blocks are closed until
  236. /// only this number remain open.
  237. const UNCLAIMED_HANDLE_LIMIT: usize = 3;
  238. fn new(block: Box<dyn Block>) -> InodeTableValue {
  239. const FIRST_HANDLE: Handle = 1;
  240. let mut handles = HashMap::with_capacity(1);
  241. handles.insert(FIRST_HANDLE, HandleValue::new(block));
  242. Self {
  243. handle_values: handles,
  244. next_handle: FIRST_HANDLE + 1,
  245. lookup_count: 1,
  246. unclaimed_handles: vec![FIRST_HANDLE],
  247. delete: false,
  248. }
  249. }
  250. fn invalid_handle_err(handle: Handle) -> io::Error {
  251. io::Error::new(io::ErrorKind::Other, format!("invalid handle {handle}"))
  252. }
  253. fn value(&self, handle: Handle) -> io::Result<&HandleValue> {
  254. self.handle_values
  255. .get(&handle)
  256. .ok_or_else(|| Self::invalid_handle_err(handle))
  257. }
  258. fn value_mut(&mut self, handle: Handle) -> io::Result<&mut HandleValue> {
  259. self.handle_values
  260. .get_mut(&handle)
  261. .ok_or_else(|| Self::invalid_handle_err(handle))
  262. }
  263. fn block_mut(&mut self, handle: Handle) -> io::Result<&mut Box<dyn Block>> {
  264. self.value_mut(handle)?.block_mut()
  265. }
  266. fn convert_to_dir(&mut self, handle: Handle) -> io::Result<()> {
  267. let value = self
  268. .handle_values
  269. .remove(&handle)
  270. .ok_or_else(|| Self::invalid_handle_err(handle))?;
  271. let value = value.convert_to_dir()?;
  272. self.handle_values.insert(handle, value);
  273. Ok(())
  274. }
  275. fn access_block_mut<T, F: FnOnce(&mut Box<dyn Block>) -> io::Result<T>>(
  276. &self,
  277. handle: Handle,
  278. cb: F,
  279. ) -> io::Result<T> {
  280. self.value(handle)?.access_block_mut(cb)
  281. }
  282. fn try_borrow_block<T, F: FnOnce(&mut Box<dyn Block>) -> io::Result<T>>(
  283. &mut self,
  284. cb: F,
  285. ) -> io::Result<T> {
  286. let handle = self
  287. .unclaimed_handles
  288. .last()
  289. .ok_or_else(|| Error::custom("no handles available"))?;
  290. let value = self.value_mut(*handle)?;
  291. let block = value.block_mut()?;
  292. cb(block)
  293. }
  294. fn insert(&mut self, block: Box<dyn Block>) {
  295. let handle = self.next_handle;
  296. self.next_handle += 1;
  297. self.handle_values.insert(handle, HandleValue::new(block));
  298. self.unclaimed_handles.push(handle);
  299. }
  300. fn insert_then_get_mut(&mut self, block: Box<dyn Block>) -> &mut Box<dyn Block> {
  301. self.insert(block);
  302. let handle = self.unclaimed_handles.last().unwrap();
  303. self.block_mut(*handle).unwrap()
  304. }
  305. fn take_handle(&mut self) -> io::Result<Handle> {
  306. self.unclaimed_handles
  307. .pop()
  308. .ok_or_else(|| io::Error::new(io::ErrorKind::Other, "no unclaimed handles"))
  309. }
  310. fn give_handle(&mut self, handle: Handle) {
  311. self.unclaimed_handles.push(handle);
  312. while self.unclaimed_handles.len() > Self::UNCLAIMED_HANDLE_LIMIT {
  313. let handle = self.unclaimed_handles.pop().unwrap();
  314. self.handle_values.remove(&handle);
  315. }
  316. }
  317. /// Increments `lookup_count` by 1 and returns its current value.
  318. fn incr_lookup_count(&mut self) -> u64 {
  319. self.lookup_count += 1;
  320. self.lookup_count
  321. }
  322. /// Decrements `lookup_count` by `count` and returns its current value.
  323. fn decr_lookup_count(&mut self, count: u64) -> u64 {
  324. self.lookup_count -= count;
  325. self.lookup_count
  326. }
  327. }
  328. type InodeTable = HashMap<Inode, RwLock<InodeTableValue>>;
  329. type InodeTableEntry<'a> = hash_map::Entry<'a, Inode, RwLock<InodeTableValue>>;
  330. /// Structure for metadata about a blocktree.
  331. #[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
  332. struct Superblock {
  333. /// The generation number of the cluster this part of the blocktree is stored on.
  334. generation: u64,
  335. /// The next free inode available to the cluster.
  336. next_inode: u64,
  337. }
  338. /// Structure for managing the part of a blocktree which is stored in the local filesystem.
  339. pub struct Blocktree<C, A> {
  340. /// The path to the directory in the local filesystem where this blocktree is located.
  341. path: PathBuf,
  342. /// A map from inode numbers to their reference counts.
  343. inodes: RwLock<InodeTable>,
  344. /// The next inode that will be assigned to a new block.
  345. next_inode: AtomicU64,
  346. /// The generation number of this filesystem. This is the same for every other server in
  347. /// the same cluster.
  348. generation: u64,
  349. /// The credentials this blocktree instance will use for all cryptographic operations.
  350. creds: C,
  351. authorizer: A,
  352. }
  353. impl<C: Creds + 'static, A> Blocktree<C, A> {
  354. /// Creates a new empty blocktree at the given path.
  355. pub fn new_empty(
  356. btdir: PathBuf,
  357. generation: u64,
  358. creds: C,
  359. authorizer: A,
  360. ) -> Result<Blocktree<C, A>> {
  361. let root_block_path = creds
  362. .writecap()
  363. .ok_or(Error::MissingWritecap)?
  364. .root_block_path();
  365. // Initialize the superblock.
  366. let mut sb_block = Self::open_block(
  367. &btdir,
  368. SpecInodes::Sb.into(),
  369. creds.clone(),
  370. root_block_path.to_owned(),
  371. )?;
  372. let sb = Superblock {
  373. generation,
  374. next_inode: SpecInodes::FirstFree.into(),
  375. };
  376. write_to(&sb, &mut sb_block)?;
  377. sb_block.mut_meta_body().access_secrets(|secrets| {
  378. secrets.inode = SpecInodes::Sb.into();
  379. secrets.mode = Self::default_file_mode();
  380. secrets.uid = Self::uid();
  381. secrets.gid = Self::gid();
  382. secrets.nlink = 1;
  383. Ok(())
  384. })?;
  385. sb_block.flush()?;
  386. // Initialize the root directory.
  387. let mut root_block = Self::open_block(
  388. &btdir,
  389. SpecInodes::RootDir.into(),
  390. creds.clone(),
  391. root_block_path,
  392. )?;
  393. write_to(&Directory::new(), &mut root_block)?;
  394. root_block.mut_meta_body().access_secrets(|secrets| {
  395. secrets.inode = SpecInodes::RootDir.into();
  396. secrets.mode = Self::default_dir_mode();
  397. secrets.uid = Self::uid();
  398. secrets.gid = Self::gid();
  399. secrets.nlink = 1;
  400. Ok(())
  401. })?;
  402. root_block.flush()?;
  403. Self::new(btdir, sb, sb_block, root_block, creds, authorizer)
  404. }
  405. /// Opens an existing blocktree stored at the given path.
  406. pub fn new_existing(btdir: PathBuf, creds: C, authorizer: A) -> Result<Blocktree<C, A>> {
  407. let root_block_path = creds
  408. .writecap()
  409. .ok_or(Error::MissingWritecap)?
  410. .root_block_path();
  411. let mut sb_block = Self::open_block(
  412. &btdir,
  413. SpecInodes::Sb.into(),
  414. creds.clone(),
  415. root_block_path.to_owned(),
  416. )?;
  417. let sb = read_from(&mut sb_block)?;
  418. let root_block = Self::open_block(
  419. &btdir,
  420. SpecInodes::RootDir.into(),
  421. creds.clone(),
  422. root_block_path,
  423. )?;
  424. Self::new(btdir, sb, sb_block, root_block, creds, authorizer)
  425. }
  426. fn new(
  427. btdir: PathBuf,
  428. sb: Superblock,
  429. sb_block: Box<dyn Block>,
  430. root_block: Box<dyn Block>,
  431. creds: C,
  432. authorizer: A,
  433. ) -> Result<Blocktree<C, A>> {
  434. let mut inodes = HashMap::with_capacity(1);
  435. inodes.insert(
  436. SpecInodes::Sb.into(),
  437. RwLock::new(InodeTableValue::new(sb_block)),
  438. );
  439. inodes.insert(
  440. SpecInodes::RootDir.into(),
  441. RwLock::new(InodeTableValue::new(root_block)),
  442. );
  443. Ok(Blocktree {
  444. path: btdir,
  445. inodes: RwLock::new(inodes),
  446. next_inode: AtomicU64::new(sb.next_inode),
  447. generation: sb.generation,
  448. creds,
  449. authorizer,
  450. })
  451. }
  452. /// Returns the path to the file storing the given inode's data.
  453. fn block_path<P: AsRef<Path>>(parent: P, inode: Inode) -> PathBuf {
  454. let group = inode / 0xFF;
  455. let mut path = PathBuf::new();
  456. path.push(parent);
  457. path.push(format!("{group:02x}"));
  458. path.push(format!("{inode:x}.blk"));
  459. path
  460. }
  461. fn open_block<P: AsRef<Path>>(
  462. btdir: P,
  463. inode: Inode,
  464. creds: C,
  465. block_path: BlockPath,
  466. ) -> Result<Box<dyn Block>> {
  467. let path = Self::block_path(&btdir, inode);
  468. let dir = path.ancestors().nth(1).unwrap();
  469. if let Err(err) = std::fs::create_dir(dir) {
  470. match err.kind() {
  471. io::ErrorKind::AlreadyExists => (),
  472. _ => return Err(err.into()),
  473. }
  474. }
  475. let file = std::fs::OpenOptions::new()
  476. .read(true)
  477. .write(true)
  478. .create(true)
  479. .open(path)?;
  480. Self::open_block_file(file, creds, block_path)
  481. }
  482. fn open_block_file(file: File, creds: C, block_path: BlockPath) -> Result<Box<dyn Block>> {
  483. BlockOpenOptions::new()
  484. .with_creds(creds)
  485. .with_compress(false)
  486. .with_encrypt(true)
  487. .with_inner(file)
  488. .with_block_path(block_path)
  489. .open()
  490. }
  491. fn default_dir_mode() -> u32 {
  492. FileType::Dir.value() | 0o755
  493. }
  494. fn default_file_mode() -> u32 {
  495. FileType::Reg.value() | 0o644
  496. }
  497. fn uid() -> u32 {
  498. unsafe { libc::getuid() }
  499. }
  500. fn gid() -> u32 {
  501. unsafe { libc::getgid() }
  502. }
  503. /// Returns the [Err] variant containing the [io::Error] corresponding to [libc::ENOSYS].
  504. fn not_supported<T>() -> io::Result<T> {
  505. let err = io::Error::from_raw_os_error(libc::ENOSYS);
  506. debug!("{err}");
  507. Err(err)
  508. }
  509. fn access_entry<T, F: FnOnce(InodeTableEntry) -> io::Result<T>>(
  510. &self,
  511. inode: Inode,
  512. cb: F,
  513. ) -> io::Result<T> {
  514. let mut inodes = self.inodes.write().err_to_string()?;
  515. let entry = inodes.entry(inode);
  516. cb(entry)
  517. }
  518. fn access_value<T, F: FnOnce(&InodeTableValue) -> io::Result<T>>(
  519. &self,
  520. inode: Inode,
  521. cb: F,
  522. ) -> io::Result<T> {
  523. let inodes = self.inodes.read().err_to_string()?;
  524. let guard = inodes
  525. .get(&inode)
  526. .ok_or_else(|| Error::NotOpen(inode))?
  527. .read()
  528. .err_to_string()?;
  529. cb(&guard)
  530. }
  531. fn access_value_mut<T, F: FnOnce(&mut InodeTableValue) -> io::Result<T>>(
  532. &self,
  533. inode: Inode,
  534. cb: F,
  535. ) -> io::Result<T> {
  536. let inodes = self.inodes.read().err_to_string()?;
  537. let mut guard = inodes
  538. .get(&inode)
  539. .ok_or_else(|| Error::NotOpen(inode))?
  540. .write()
  541. .err_to_string()?;
  542. cb(&mut guard)
  543. }
  544. fn access_block_mut<T, F: FnOnce(&mut Box<dyn Block>) -> io::Result<T>>(
  545. &self,
  546. inode: Inode,
  547. handle: Handle,
  548. cb: F,
  549. ) -> io::Result<T> {
  550. self.access_value(inode, |value| value.access_block_mut(handle, cb))
  551. }
  552. fn access_meta<T, F: FnOnce(&BlockMeta) -> io::Result<T>>(
  553. &self,
  554. inode: Inode,
  555. cb: F,
  556. ) -> io::Result<T> {
  557. self.access_value(inode, |value| {
  558. let handle_value = value
  559. .handle_values
  560. .values()
  561. .next()
  562. .ok_or_else(|| Error::NotOpen(inode))?;
  563. // Because we're using any of the meta data structs we need to ensure that any
  564. // modification of meta data is performed on all open blocks.
  565. handle_value.access_block(|block| cb(block.meta()))
  566. })
  567. }
  568. fn borrow_block<T, F: FnOnce(&mut Box<dyn Block>) -> io::Result<T>>(
  569. &self,
  570. inode: Inode,
  571. cb: F,
  572. ) -> io::Result<T> {
  573. self.access_value_mut(inode, |value| {
  574. let block = match value.unclaimed_handles.last() {
  575. Some(handle) => value.handle_values.get_mut(handle).unwrap().block_mut()?,
  576. None => {
  577. let block_path = value
  578. .handle_values
  579. .values()
  580. .next()
  581. .ok_or_else(|| Error::NotOpen(inode))?
  582. .access_block(|block| Ok(block.meta_body().path.clone()))?;
  583. let block =
  584. Self::open_block(&self.path, inode, self.creds.clone(), block_path)?;
  585. value.insert_then_get_mut(block)
  586. }
  587. };
  588. cb(block)
  589. })
  590. }
  591. fn take_handle_if_ok<T, F: FnOnce(Handle, &mut Box<dyn Block>) -> io::Result<T>>(
  592. &self,
  593. inode: Inode,
  594. cb: F,
  595. ) -> io::Result<T> {
  596. self.access_value_mut(inode, |value| {
  597. let handle = value
  598. .take_handle()
  599. .map_err(|_| Error::NoHandlesAvailable(inode))?;
  600. let block = value.block_mut(handle)?;
  601. let result = cb(handle, block);
  602. if result.is_err() {
  603. value.give_handle(handle);
  604. }
  605. result
  606. })
  607. }
  608. fn give_handle(&self, inode: Inode, handle: Handle) -> io::Result<()> {
  609. self.access_value_mut(inode, |value| {
  610. let block = value.block_mut(handle)?;
  611. // Be kind, rewind.
  612. block.seek(SeekFrom::Start(0))?;
  613. value.give_handle(handle);
  614. Ok(())
  615. })
  616. }
  617. fn open_value<T, F: FnOnce(&mut InodeTableValue) -> io::Result<T>>(
  618. &self,
  619. inode: Inode,
  620. block_path: BlockPath,
  621. cb: F,
  622. ) -> io::Result<T> {
  623. self.access_entry(inode, |entry| match entry {
  624. InodeTableEntry::Vacant(entry) => {
  625. let block =
  626. Self::open_block(&self.path, inode, self.creds.clone(), block_path)?;
  627. let mut value = InodeTableValue::new(block);
  628. let result = cb(&mut value);
  629. entry.insert(RwLock::new(value));
  630. result
  631. }
  632. InodeTableEntry::Occupied(mut entry) => {
  633. let value = entry.get_mut().get_mut().err_to_string()?;
  634. if value.unclaimed_handles.is_empty() {
  635. let block =
  636. Self::open_block(&self.path, inode, self.creds.clone(), block_path)?;
  637. value.insert(block);
  638. }
  639. cb(value)
  640. }
  641. })
  642. }
  643. fn open_then_take_handle<T, F: FnOnce(Handle, &mut InodeTableValue) -> io::Result<T>>(
  644. &self,
  645. inode: Inode,
  646. block_path: BlockPath,
  647. cb: F,
  648. ) -> io::Result<T> {
  649. self.open_value(inode, block_path, |value| {
  650. let handle = value.take_handle().unwrap();
  651. cb(handle, value)
  652. })
  653. }
  654. fn inode_forget(&self, inode: Inode, count: u64) -> io::Result<()> {
  655. let mut inodes = self.inodes.write().err_to_string()?;
  656. let lookup_count = {
  657. let inode_lock = match inodes.get_mut(&inode) {
  658. Some(inode_lock) => inode_lock,
  659. None => {
  660. warn!("an attempt was made to forget non-existent inode {inode}");
  661. return Ok(());
  662. }
  663. };
  664. let mut value = inode_lock.write().err_to_string()?;
  665. value.decr_lookup_count(count)
  666. };
  667. if 0 == lookup_count {
  668. let delete = inodes
  669. .remove(&inode)
  670. .unwrap()
  671. .into_inner()
  672. .err_to_string()?
  673. .delete;
  674. if delete {
  675. let path = Self::block_path(&self.path, inode);
  676. std::fs::remove_file(path)?;
  677. }
  678. }
  679. Ok(())
  680. }
  681. /// Returns the next available inode and updates the superblock in one atomic operation.
  682. /// TODO: Obviously this strategy won't work when there are multiple servers in this
  683. /// generation.
  684. fn next_inode(&self) -> io::Result<Inode> {
  685. self.borrow_block(SpecInodes::Sb.into(), |block| {
  686. // We don't need strict ordering because the lock the inode table is already
  687. // serializing access.
  688. let inode = self.next_inode.fetch_add(1, Ordering::Relaxed);
  689. let sb = Superblock {
  690. generation: self.generation,
  691. next_inode: inode + 1,
  692. };
  693. block.seek(SeekFrom::Start(0))?;
  694. write_to(&sb, block)?;
  695. Ok(inode)
  696. })
  697. }
  698. fn attr_timeout(&self) -> Duration {
  699. Duration::from_secs(5)
  700. }
  701. fn entry_timeout(&self) -> Duration {
  702. Duration::from_secs(5)
  703. }
  704. fn unsupported_flag<T>(flag: &str) -> io::Result<T> {
  705. Err(io::Error::new(
  706. io::ErrorKind::Unsupported,
  707. format!("unsupported flag: {flag}"),
  708. ))
  709. }
  710. }
  711. unsafe impl<C: Sync, A: Sync> Sync for Blocktree<C, A> {}
  712. impl<C: Creds + Clone + 'static, A: Authorizer> FileSystem for Blocktree<C, A> {
  713. type Inode = Inode;
  714. type Handle = u64;
  715. fn init(&self, _capable: FsOptions) -> io::Result<FsOptions> {
  716. debug!("Blocktree::init called");
  717. Ok(FsOptions::empty())
  718. }
  719. fn destroy(&self) {
  720. debug!("Blocktree::destroy called");
  721. }
  722. fn lookup(&self, ctx: &Context, parent: Self::Inode, name: &CStr) -> io::Result<Entry> {
  723. debug!("Blocktree::lookup called on parent {parent}");
  724. let name = name.to_str().box_err()?;
  725. let (dir, block_path) = self.borrow_block(parent, |block| {
  726. self.authorizer
  727. .can_exec(&AuthzContext::new(ctx, block.meta()))?;
  728. block.seek(SeekFrom::Start(0))?;
  729. let dir: Directory = read_from(block)?;
  730. let path = block.meta_body().path.to_owned();
  731. Ok((dir, path))
  732. })?;
  733. let entry = dir
  734. .entries
  735. .get(name)
  736. .ok_or_else(|| io::Error::from_raw_os_error(libc::ENOENT))?;
  737. let inode = match entry {
  738. DirEntry::File(entry) => entry.inode,
  739. DirEntry::Directory(entry) => entry.inode,
  740. DirEntry::Server(_) => {
  741. return Err(io::Error::new(
  742. io::ErrorKind::Unsupported,
  743. "can't lookup server entry",
  744. ))
  745. }
  746. };
  747. let stat = self.open_value(inode, block_path, |value| {
  748. let stat =
  749. value.try_borrow_block(|block| Ok(block.meta_body().secrets()?.stat()))?;
  750. value.incr_lookup_count();
  751. Ok(stat)
  752. })?;
  753. Ok(Entry {
  754. inode,
  755. generation: self.generation,
  756. attr: stat,
  757. attr_flags: 0,
  758. attr_timeout: self.attr_timeout(),
  759. entry_timeout: self.entry_timeout(),
  760. })
  761. }
  762. fn open(
  763. &self,
  764. ctx: &Context,
  765. inode: Self::Inode,
  766. flags: u32,
  767. // This is the second field of the `fuse_open_in` struct, which is currently unused
  768. // by the kernel. (https://man7.org/linux/man-pages/man4/fuse.4.html)
  769. _fuse_flags: u32,
  770. ) -> io::Result<(Option<Self::Handle>, OpenOptions)> {
  771. debug!("Blocktree::open called on inode {inode}");
  772. let flags: i32 = flags.try_into().box_err()?;
  773. if flags & libc::O_APPEND != 0 {
  774. return Self::unsupported_flag("O_APPEND");
  775. }
  776. if flags & libc::O_CLOEXEC != 0 {
  777. return Self::unsupported_flag("O_CLOEXEC");
  778. }
  779. if flags & libc::O_DIRECTORY != 0 {
  780. return Self::unsupported_flag("O_DIRECTORY");
  781. }
  782. let handle = self.take_handle_if_ok(inode, |handle, block| {
  783. let ctx = AuthzContext::new(ctx, block.meta());
  784. if flags == libc::O_RDONLY || (flags & libc::O_RDWR) != 0 {
  785. self.authorizer.can_read(&ctx)?;
  786. }
  787. let write_mask = libc::O_WRONLY | libc::O_RDWR;
  788. if write_mask & flags != 0 {
  789. self.authorizer.can_write(&ctx)?;
  790. }
  791. Ok(handle)
  792. })?;
  793. Ok((Some(handle), OpenOptions::empty()))
  794. }
  795. fn release(
  796. &self,
  797. _ctx: &Context,
  798. inode: Self::Inode,
  799. _flags: u32,
  800. handle: Self::Handle,
  801. flush: bool,
  802. _flock_release: bool,
  803. _lock_owner: Option<u64>,
  804. ) -> io::Result<()> {
  805. debug!("Blocktree::release called on inode {inode}");
  806. if flush {
  807. self.access_block_mut(inode, handle, |block| block.flush())?;
  808. };
  809. self.give_handle(inode, handle)
  810. }
  811. fn opendir(
  812. &self,
  813. ctx: &Context,
  814. inode: Self::Inode,
  815. _flags: u32,
  816. ) -> io::Result<(Option<Self::Handle>, OpenOptions)> {
  817. debug!("Blocktree::opendir called on inode {inode}");
  818. let handle = self.access_value_mut(inode, |value| {
  819. value.try_borrow_block(|block| {
  820. let ctx = AuthzContext::new(ctx, block.meta());
  821. self.authorizer.can_exec(&ctx)?;
  822. Ok(())
  823. })?;
  824. let handle = value.take_handle()?;
  825. value.convert_to_dir(handle)?;
  826. Ok(handle)
  827. })?;
  828. Ok((Some(handle), OpenOptions::empty()))
  829. }
  830. fn releasedir(
  831. &self,
  832. _ctx: &Context,
  833. inode: Self::Inode,
  834. _flags: u32,
  835. handle: Self::Handle,
  836. ) -> io::Result<()> {
  837. debug!("Blocktree::releasedir called for inode {inode}");
  838. self.access_value_mut(inode, |value| {
  839. value.give_handle(handle);
  840. Ok(())
  841. })
  842. }
  843. fn create(
  844. &self,
  845. ctx: &Context,
  846. parent: Self::Inode,
  847. name: &CStr,
  848. args: CreateIn,
  849. ) -> std::io::Result<(Entry, Option<Self::Handle>, OpenOptions)> {
  850. debug!("Blocktree::create called on parent {parent}");
  851. let name = name
  852. .to_str()
  853. .map_err(|err| io::Error::new(io::ErrorKind::InvalidInput, err))?
  854. .to_owned();
  855. // Reserve a free inode.
  856. let inode = self.next_inode()?;
  857. // Add a directory entry to the parent for the new inode.
  858. let mut block_path = self.borrow_block(parent, |block| {
  859. let ctx = AuthzContext::new(ctx, block.meta());
  860. self.authorizer.can_write(&ctx)?;
  861. block.seek(SeekFrom::Start(0))?;
  862. let mut dir: Directory = read_from(block).box_err()?;
  863. dir.add_file(name.clone(), inode)?;
  864. block.seek(SeekFrom::Start(0))?;
  865. write_to(&dir, block).box_err()?;
  866. block.flush()?;
  867. Ok(block.meta_body().path.clone())
  868. })?;
  869. block_path.push_component(name);
  870. let (handle, attr) =
  871. self.open_then_take_handle(inode, block_path, |handle, value| {
  872. let block = value.block_mut(handle)?;
  873. Ok(block.mut_meta_body().access_secrets(|secrets| {
  874. secrets.inode = inode;
  875. secrets.mode = args.mode;
  876. secrets.uid = ctx.uid;
  877. secrets.gid = ctx.gid;
  878. let now = Epoch::now();
  879. secrets.atime = now;
  880. secrets.ctime = now;
  881. secrets.mtime = now;
  882. secrets.nlink = 1;
  883. Ok((handle, secrets.attr()))
  884. })?)
  885. })?;
  886. let entry = Entry {
  887. inode,
  888. generation: self.generation,
  889. attr: attr.into(),
  890. attr_flags: 0,
  891. attr_timeout: self.attr_timeout(),
  892. entry_timeout: self.entry_timeout(),
  893. };
  894. Ok((entry, Some(handle), OpenOptions::empty()))
  895. }
  896. fn write(
  897. &self,
  898. _ctx: &Context,
  899. inode: Self::Inode,
  900. handle: Self::Handle,
  901. r: &mut dyn fuse_backend_rs::api::filesystem::ZeroCopyReader,
  902. size: u32,
  903. _offset: u64,
  904. _lock_owner: Option<u64>,
  905. _delayed_write: bool,
  906. // `flags` and `fuse_flags` are the arguments that were passed to `open` when this
  907. // handle was returned.
  908. flags: u32,
  909. _fuse_flags: u32,
  910. ) -> io::Result<usize> {
  911. debug!("Blocktree::write called called on inode {inode}");
  912. if flags as libc::c_int == libc::O_RDONLY {
  913. return Err(io::Error::new(
  914. io::ErrorKind::PermissionDenied,
  915. "file is readonly",
  916. ));
  917. }
  918. let mut size: usize = size.try_into().box_err()?;
  919. self.access_block_mut(inode, handle, |block| {
  920. let mut buf = [0u8; crate::SECTOR_SZ_DEFAULT];
  921. let mut written = 0;
  922. while size > 0 {
  923. let read = match r.read(&mut buf) {
  924. Ok(size) => size,
  925. Err(err) => {
  926. if written > 0 {
  927. error!("error while reading: {err}");
  928. return Ok(written);
  929. } else {
  930. return Err(err);
  931. }
  932. }
  933. };
  934. if 0 == read {
  935. break;
  936. }
  937. let filled = &buf[..read];
  938. size -= read;
  939. if let Err(err) = block.write_all(filled) {
  940. if written > 0 {
  941. error!("error while writing: {err}");
  942. return Ok(written);
  943. } else {
  944. return Err(err);
  945. }
  946. }
  947. written += filled.len();
  948. }
  949. Ok(written)
  950. })
  951. }
  952. fn flush(
  953. &self,
  954. _ctx: &Context,
  955. inode: Self::Inode,
  956. handle: Self::Handle,
  957. _lock_owner: u64,
  958. ) -> io::Result<()> {
  959. debug!("Blocktree::flush called for inode {inode}");
  960. self.access_block_mut(inode, handle, |block| block.flush())
  961. }
  962. fn read(
  963. &self,
  964. _ctx: &Context,
  965. inode: Self::Inode,
  966. handle: Self::Handle,
  967. w: &mut dyn fuse_backend_rs::api::filesystem::ZeroCopyWriter,
  968. size: u32,
  969. _offset: u64,
  970. _lock_owner: Option<u64>,
  971. flags: u32,
  972. ) -> io::Result<usize> {
  973. debug!("Blocktree::read called on inode {inode}");
  974. if (flags as libc::c_int & libc::O_WRONLY) != 0 {
  975. return Err(io::Error::new(
  976. io::ErrorKind::PermissionDenied,
  977. "file is write only",
  978. ));
  979. }
  980. let mut size: usize = size.try_into().box_err()?;
  981. self.access_block_mut(inode, handle, |block| {
  982. let mut buf = [0u8; crate::SECTOR_SZ_DEFAULT];
  983. let mut read = 0;
  984. while size > 0 {
  985. let just_read = match block.read(&mut buf) {
  986. Ok(just_read) => just_read,
  987. Err(err) => {
  988. if read > 0 {
  989. error!("error while reading from block: {err}");
  990. return Ok(read);
  991. } else {
  992. return Err(err);
  993. }
  994. }
  995. };
  996. if 0 == just_read {
  997. break;
  998. }
  999. read += just_read;
  1000. let filled = &buf[..just_read];
  1001. if let Err(err) = w.write_all(filled) {
  1002. if read > 0 {
  1003. error!("error while writing: {err}");
  1004. return Ok(read);
  1005. } else {
  1006. return Err(err);
  1007. }
  1008. }
  1009. size -= filled.len();
  1010. }
  1011. Ok(read)
  1012. })
  1013. }
  1014. fn readdir(
  1015. &self,
  1016. _ctx: &Context,
  1017. inode: Self::Inode,
  1018. handle: Self::Handle,
  1019. size: u32,
  1020. offset: u64,
  1021. add_entry: &mut dyn FnMut(
  1022. fuse_backend_rs::api::filesystem::DirEntry,
  1023. ) -> io::Result<usize>,
  1024. ) -> io::Result<()> {
  1025. debug!("Blocktree::readdir called on inode {inode}");
  1026. let mut size: usize = size.try_into().box_err()?;
  1027. self.access_value(inode, |value| {
  1028. let dir = value
  1029. .value(handle)
  1030. .map_err(|_| Error::InvalidHandle { handle, inode })?
  1031. .directory()?;
  1032. let mut index: u64 = 0;
  1033. for (name, entry) in dir.entries() {
  1034. index += 1;
  1035. if index <= offset {
  1036. continue;
  1037. }
  1038. let inode = match entry.inode() {
  1039. Some(inode) => inode,
  1040. None => continue,
  1041. };
  1042. let dir_entry = FuseDirEntry {
  1043. ino: inode,
  1044. offset: index,
  1045. type_: entry.kind() as u32,
  1046. name: name.as_bytes(),
  1047. };
  1048. size = size.saturating_sub(add_entry(dir_entry)?);
  1049. if size == 0 {
  1050. break;
  1051. }
  1052. }
  1053. Ok(())
  1054. })
  1055. }
  1056. fn getattr(
  1057. &self,
  1058. _ctx: &Context,
  1059. inode: Self::Inode,
  1060. _handle: Option<Self::Handle>,
  1061. ) -> io::Result<(stat64, Duration)> {
  1062. debug!("Blocktree::getattr called for inode {inode}");
  1063. let mut stat = self.access_meta(inode, |meta| Ok(meta.body.secrets()?.stat()))?;
  1064. stat.st_ino = inode;
  1065. Ok((stat, self.attr_timeout()))
  1066. }
  1067. fn forget(&self, _ctx: &Context, inode: Self::Inode, count: u64) {
  1068. debug!("Blocktree::forget called for inode {inode}");
  1069. if let Err(err) = self.inode_forget(inode, count) {
  1070. error!("Blocktree::forget failed for inode {inode}: {err}");
  1071. }
  1072. }
  1073. fn lseek(
  1074. &self,
  1075. _ctx: &Context,
  1076. inode: Self::Inode,
  1077. handle: Self::Handle,
  1078. offset: u64,
  1079. whence: u32,
  1080. ) -> io::Result<u64> {
  1081. debug!("Blocktree::lseek called for inode {inode}");
  1082. let seek_from = SeekFrom::whence_offset(whence, offset)?;
  1083. self.access_block_mut(inode, handle, |block| block.seek(seek_from))
  1084. }
  1085. fn unlink(&self, ctx: &Context, parent: Self::Inode, name: &CStr) -> io::Result<()> {
  1086. debug!("Blocktree::unlink called on parent {parent}");
  1087. let name = name.to_str().box_err()?;
  1088. let (block_path, inode) = self.borrow_block(parent, |block| {
  1089. let ctx = AuthzContext::new(ctx, block.meta());
  1090. self.authorizer.can_write(&ctx)?;
  1091. block.seek(SeekFrom::Start(0))?;
  1092. let mut dir: Directory = read_from(block)?;
  1093. let inode = match dir.entries.remove(name) {
  1094. None => return Err(io::Error::from_raw_os_error(libc::ENOENT)),
  1095. Some(entry) => entry.inode().ok_or_else(|| {
  1096. io::Error::new(
  1097. io::ErrorKind::InvalidInput,
  1098. format!("name {name} does not refer to a file or directory"),
  1099. )
  1100. })?,
  1101. };
  1102. block.seek(SeekFrom::Start(0))?;
  1103. write_to(&dir, block)?;
  1104. let mut block_path = block.meta_body().path.clone();
  1105. block_path.push_component(name.to_owned());
  1106. Ok((block_path, inode))
  1107. })?;
  1108. self.open_value(inode, block_path, |value| {
  1109. // We mark the block for deletion if `nlink` drops to zero.
  1110. value.delete = value.try_borrow_block(|block| {
  1111. let nlink = block.mut_meta_body().access_secrets(|secrets| {
  1112. secrets.nlink -= 1;
  1113. Ok(secrets.nlink)
  1114. })?;
  1115. block.flush_meta()?;
  1116. Ok(0 == nlink)
  1117. })?;
  1118. Ok(())
  1119. })
  1120. }
  1121. //////////////////////////////////
  1122. // METHODS WHICH ARE NOT SUPPORTED
  1123. //////////////////////////////////
  1124. fn getxattr(
  1125. &self,
  1126. _ctx: &Context,
  1127. inode: Self::Inode,
  1128. _name: &CStr,
  1129. _size: u32,
  1130. ) -> io::Result<fuse_backend_rs::api::filesystem::GetxattrReply> {
  1131. debug!("Blocktree::getxattr called for inode {inode}");
  1132. Self::not_supported()
  1133. }
  1134. fn ioctl(
  1135. &self,
  1136. _ctx: &Context,
  1137. inode: Self::Inode,
  1138. _handle: Self::Handle,
  1139. _flags: u32,
  1140. _cmd: u32,
  1141. _data: fuse_backend_rs::api::filesystem::IoctlData,
  1142. _out_size: u32,
  1143. ) -> io::Result<fuse_backend_rs::api::filesystem::IoctlData> {
  1144. debug!("Blocktree::ioctl called for inode {inode}");
  1145. Self::not_supported()
  1146. }
  1147. fn access(&self, _ctx: &Context, inode: Self::Inode, _mask: u32) -> io::Result<()> {
  1148. debug!("Blocktree::access called for inode {inode}");
  1149. Self::not_supported()
  1150. }
  1151. fn batch_forget(&self, _ctx: &Context, _requests: Vec<(Self::Inode, u64)>) {
  1152. debug!("Blocktree::batch_forget called");
  1153. Self::not_supported().unwrap()
  1154. }
  1155. fn bmap(
  1156. &self,
  1157. _ctx: &Context,
  1158. inode: Self::Inode,
  1159. _block: u64,
  1160. _blocksize: u32,
  1161. ) -> io::Result<u64> {
  1162. debug!("Blocktree::bmap called for inode {inode}");
  1163. Self::not_supported()
  1164. }
  1165. fn fallocate(
  1166. &self,
  1167. _ctx: &Context,
  1168. inode: Self::Inode,
  1169. _handle: Self::Handle,
  1170. _mode: u32,
  1171. _offset: u64,
  1172. _length: u64,
  1173. ) -> io::Result<()> {
  1174. debug!("Blocktree::fallocate called for inode {inode}");
  1175. Self::not_supported()
  1176. }
  1177. fn fsync(
  1178. &self,
  1179. _ctx: &Context,
  1180. inode: Self::Inode,
  1181. _datasync: bool,
  1182. _handle: Self::Handle,
  1183. ) -> io::Result<()> {
  1184. debug!("Blocktree::fsync called for inode {inode}");
  1185. Self::not_supported()
  1186. }
  1187. fn fsyncdir(
  1188. &self,
  1189. _ctx: &Context,
  1190. inode: Self::Inode,
  1191. _datasync: bool,
  1192. _handle: Self::Handle,
  1193. ) -> io::Result<()> {
  1194. debug!("Blocktree::fsyncdir called for inode {inode}");
  1195. Self::not_supported()
  1196. }
  1197. fn getlk(
  1198. &self,
  1199. _ctx: &Context,
  1200. inode: Self::Inode,
  1201. _handle: Self::Handle,
  1202. _owner: u64,
  1203. _lock: fuse_backend_rs::api::filesystem::FileLock,
  1204. _flags: u32,
  1205. ) -> io::Result<fuse_backend_rs::api::filesystem::FileLock> {
  1206. debug!("Blocktree::getlk called for inode {inode}");
  1207. Self::not_supported()
  1208. }
  1209. fn link(
  1210. &self,
  1211. _ctx: &Context,
  1212. inode: Self::Inode,
  1213. _newparent: Self::Inode,
  1214. _newname: &CStr,
  1215. ) -> io::Result<Entry> {
  1216. debug!("Blocktree::link called for inode {inode}");
  1217. Self::not_supported()
  1218. }
  1219. fn listxattr(
  1220. &self,
  1221. _ctx: &Context,
  1222. inode: Self::Inode,
  1223. _size: u32,
  1224. ) -> io::Result<fuse_backend_rs::api::filesystem::ListxattrReply> {
  1225. debug!("Blocktree::listxattr called for inode {inode}");
  1226. Self::not_supported()
  1227. }
  1228. fn mkdir(
  1229. &self,
  1230. _ctx: &Context,
  1231. _parent: Self::Inode,
  1232. _name: &CStr,
  1233. _mode: u32,
  1234. _umask: u32,
  1235. ) -> io::Result<Entry> {
  1236. debug!("Blocktree::mkdir called");
  1237. Self::not_supported()
  1238. }
  1239. fn mknod(
  1240. &self,
  1241. _ctx: &Context,
  1242. inode: Self::Inode,
  1243. _name: &CStr,
  1244. _mode: u32,
  1245. _rdev: u32,
  1246. _umask: u32,
  1247. ) -> io::Result<Entry> {
  1248. debug!("Blocktree::mknod called for inode {inode}");
  1249. Self::not_supported()
  1250. }
  1251. fn notify_reply(&self) -> io::Result<()> {
  1252. debug!("Blocktree::notify_reply called");
  1253. Self::not_supported()
  1254. }
  1255. fn poll(
  1256. &self,
  1257. _ctx: &Context,
  1258. inode: Self::Inode,
  1259. _handle: Self::Handle,
  1260. _khandle: Self::Handle,
  1261. _flags: u32,
  1262. _events: u32,
  1263. ) -> io::Result<u32> {
  1264. debug!("Blocktree::poll called for inode {inode}");
  1265. Self::not_supported()
  1266. }
  1267. fn readdirplus(
  1268. &self,
  1269. _ctx: &Context,
  1270. _inode: Self::Inode,
  1271. _handle: Self::Handle,
  1272. _size: u32,
  1273. _offset: u64,
  1274. _add_entry: &mut dyn FnMut(
  1275. fuse_backend_rs::api::filesystem::DirEntry,
  1276. Entry,
  1277. ) -> io::Result<usize>,
  1278. ) -> io::Result<()> {
  1279. debug!("Blocktree::readdirplus called");
  1280. Self::not_supported()
  1281. }
  1282. fn readlink(&self, _ctx: &Context, inode: Self::Inode) -> io::Result<Vec<u8>> {
  1283. debug!("Blocktree::readlink called for inode {inode}");
  1284. Self::not_supported()
  1285. }
  1286. fn removexattr(&self, _ctx: &Context, inode: Self::Inode, _name: &CStr) -> io::Result<()> {
  1287. debug!("Blocktree::removexattr called for inode {inode}");
  1288. Self::not_supported()
  1289. }
  1290. fn rename(
  1291. &self,
  1292. _ctx: &Context,
  1293. _olddir: Self::Inode,
  1294. _oldname: &CStr,
  1295. _newdir: Self::Inode,
  1296. _newname: &CStr,
  1297. _flags: u32,
  1298. ) -> io::Result<()> {
  1299. debug!("Blocktree::rename called");
  1300. Self::not_supported()
  1301. }
  1302. fn rmdir(&self, _ctx: &Context, parent: Self::Inode, _name: &CStr) -> io::Result<()> {
  1303. debug!("Blocktree::rmdir called on parent {parent}");
  1304. Self::not_supported()
  1305. }
  1306. fn setattr(
  1307. &self,
  1308. _ctx: &Context,
  1309. inode: Self::Inode,
  1310. _attr: stat64,
  1311. _handle: Option<Self::Handle>,
  1312. _valid: fuse_backend_rs::api::filesystem::SetattrValid,
  1313. ) -> io::Result<(stat64, Duration)> {
  1314. debug!("Blocktree::setattr called for inode {inode}");
  1315. Self::not_supported()
  1316. }
  1317. fn setlk(
  1318. &self,
  1319. _ctx: &Context,
  1320. inode: Self::Inode,
  1321. _handle: Self::Handle,
  1322. _owner: u64,
  1323. _lock: fuse_backend_rs::api::filesystem::FileLock,
  1324. _flags: u32,
  1325. ) -> io::Result<()> {
  1326. debug!("Blocktree::setlk called for inode {inode}");
  1327. Self::not_supported()
  1328. }
  1329. fn setlkw(
  1330. &self,
  1331. _ctx: &Context,
  1332. inode: Self::Inode,
  1333. _handle: Self::Handle,
  1334. _owner: u64,
  1335. _lock: fuse_backend_rs::api::filesystem::FileLock,
  1336. _flags: u32,
  1337. ) -> io::Result<()> {
  1338. debug!("Blocktree::setlkw called for inode {inode}");
  1339. Self::not_supported()
  1340. }
  1341. fn setxattr(
  1342. &self,
  1343. _ctx: &Context,
  1344. inode: Self::Inode,
  1345. _name: &CStr,
  1346. _value: &[u8],
  1347. _flags: u32,
  1348. ) -> io::Result<()> {
  1349. debug!("Blocktree::setxattr called for inode {inode}");
  1350. Self::not_supported()
  1351. }
  1352. fn statfs(&self, _ctx: &Context, inode: Self::Inode) -> io::Result<statvfs64> {
  1353. debug!("Blocktree::statfs called for inode {inode}");
  1354. Self::not_supported()
  1355. }
  1356. fn symlink(
  1357. &self,
  1358. _ctx: &Context,
  1359. _linkname: &CStr,
  1360. _parent: Self::Inode,
  1361. _name: &CStr,
  1362. ) -> io::Result<Entry> {
  1363. debug!("Blocktree::symlink called");
  1364. Self::not_supported()
  1365. }
  1366. }
  1367. }
  1368. #[cfg(test)]
  1369. mod tests {
  1370. use fuse_backend_rs::{
  1371. abi::fuse_abi::CreateIn,
  1372. api::filesystem::{Context, FileSystem, FsOptions},
  1373. };
  1374. use std::{ffi::CString, io};
  1375. use tempdir::TempDir;
  1376. use test_helpers::*;
  1377. use crate::{crypto::ConcreteCreds, test_helpers, BlockMeta, Decompose};
  1378. use super::{private::SpecInodes, *};
  1379. /// Tests for the [ModeAuthorizer] struct.
  1380. mod mode_authorizer_tests {
  1381. use super::{
  1382. super::private::{Authorizer, AuthzContext},
  1383. *,
  1384. };
  1385. struct TestCase {
  1386. ctx_uid: u32,
  1387. ctx_gid: u32,
  1388. meta: BlockMeta,
  1389. }
  1390. impl TestCase {
  1391. const BLOCK_UID: u32 = 1000;
  1392. const BLOCK_GID: u32 = 1000;
  1393. const CTX_PID: libc::pid_t = 100;
  1394. fn new(ctx_uid: u32, ctx_gid: u32, mode: u32) -> TestCase {
  1395. let mut meta = BlockMeta::new(&*test_helpers::NODE_CREDS)
  1396. .expect("failed to create block metadata");
  1397. meta.body
  1398. .access_secrets(|secrets| {
  1399. secrets.uid = Self::BLOCK_UID;
  1400. secrets.gid = Self::BLOCK_GID;
  1401. secrets.mode = mode;
  1402. Ok(())
  1403. })
  1404. .expect("failed to update secrets");
  1405. TestCase {
  1406. ctx_uid,
  1407. ctx_gid,
  1408. meta,
  1409. }
  1410. }
  1411. fn context(&self) -> AuthzContext<'_> {
  1412. AuthzContext {
  1413. uid: self.ctx_uid,
  1414. gid: self.ctx_gid,
  1415. pid: Self::CTX_PID,
  1416. meta: &self.meta,
  1417. }
  1418. }
  1419. }
  1420. #[test]
  1421. fn cant_read_when_no_bits_set() {
  1422. let case = TestCase::new(TestCase::BLOCK_UID, TestCase::BLOCK_GID, 0);
  1423. let result = ModeAuthorizer {}.can_read(&case.context());
  1424. assert!(result.is_err())
  1425. }
  1426. #[test]
  1427. fn cant_write_when_no_bits_set() {
  1428. let case = TestCase::new(TestCase::BLOCK_UID, TestCase::BLOCK_GID, 0);
  1429. let result = ModeAuthorizer {}.can_write(&case.context());
  1430. assert!(result.is_err())
  1431. }
  1432. #[test]
  1433. fn cant_exec_when_no_bits_set() {
  1434. let case = TestCase::new(TestCase::BLOCK_UID, TestCase::BLOCK_GID, 0);
  1435. let result = ModeAuthorizer {}.can_exec(&case.context());
  1436. assert!(result.is_err())
  1437. }
  1438. #[test]
  1439. fn user_can_read_when_bit_set() {
  1440. let case = TestCase::new(TestCase::BLOCK_UID, TestCase::BLOCK_GID, libc::S_IRUSR);
  1441. let result = ModeAuthorizer {}.can_read(&case.context());
  1442. assert!(result.is_ok())
  1443. }
  1444. #[test]
  1445. fn user_can_write_when_bit_set() {
  1446. let case = TestCase::new(TestCase::BLOCK_UID, TestCase::BLOCK_GID, libc::S_IWUSR);
  1447. let result = ModeAuthorizer {}.can_write(&case.context());
  1448. assert!(result.is_ok())
  1449. }
  1450. #[test]
  1451. fn user_can_exec_when_bit_set() {
  1452. let case = TestCase::new(TestCase::BLOCK_UID, TestCase::BLOCK_GID, libc::S_IXUSR);
  1453. let result = ModeAuthorizer {}.can_exec(&case.context());
  1454. assert!(result.is_ok())
  1455. }
  1456. #[test]
  1457. fn group_can_read_when_bit_set() {
  1458. let case = TestCase::new(TestCase::BLOCK_UID, TestCase::BLOCK_GID, libc::S_IRGRP);
  1459. let result = ModeAuthorizer {}.can_read(&case.context());
  1460. assert!(result.is_ok())
  1461. }
  1462. #[test]
  1463. fn group_can_write_when_bit_set() {
  1464. let case = TestCase::new(TestCase::BLOCK_UID, TestCase::BLOCK_GID, libc::S_IWGRP);
  1465. let result = ModeAuthorizer {}.can_write(&case.context());
  1466. assert!(result.is_ok())
  1467. }
  1468. #[test]
  1469. fn group_can_exec_when_bit_set() {
  1470. let case = TestCase::new(TestCase::BLOCK_UID, TestCase::BLOCK_GID, libc::S_IXGRP);
  1471. let result = ModeAuthorizer {}.can_exec(&case.context());
  1472. assert!(result.is_ok())
  1473. }
  1474. #[test]
  1475. fn other_can_read_when_bit_set() {
  1476. let case = TestCase::new(TestCase::BLOCK_UID, TestCase::BLOCK_GID, libc::S_IROTH);
  1477. let result = ModeAuthorizer {}.can_read(&case.context());
  1478. assert!(result.is_ok())
  1479. }
  1480. #[test]
  1481. fn other_can_write_when_bit_set() {
  1482. let case = TestCase::new(TestCase::BLOCK_UID, TestCase::BLOCK_GID, libc::S_IWOTH);
  1483. let result = ModeAuthorizer {}.can_write(&case.context());
  1484. assert!(result.is_ok())
  1485. }
  1486. #[test]
  1487. fn other_can_exec_when_bit_set() {
  1488. let case = TestCase::new(TestCase::BLOCK_UID, TestCase::BLOCK_GID, libc::S_IXOTH);
  1489. let result = ModeAuthorizer {}.can_exec(&case.context());
  1490. assert!(result.is_ok())
  1491. }
  1492. #[test]
  1493. fn other_cant_write_even_if_user_can() {
  1494. let case = TestCase::new(
  1495. TestCase::BLOCK_UID + 1,
  1496. TestCase::BLOCK_GID + 1,
  1497. libc::S_IWUSR,
  1498. );
  1499. let result = ModeAuthorizer {}.can_write(&case.context());
  1500. assert!(result.is_err())
  1501. }
  1502. #[test]
  1503. fn other_cant_write_even_if_group_can() {
  1504. let case = TestCase::new(
  1505. TestCase::BLOCK_UID + 1,
  1506. TestCase::BLOCK_GID + 1,
  1507. libc::S_IWGRP,
  1508. );
  1509. let result = ModeAuthorizer {}.can_write(&case.context());
  1510. assert!(result.is_err())
  1511. }
  1512. #[test]
  1513. fn user_allowed_read_when_only_other_bit_set() {
  1514. let case = TestCase::new(TestCase::BLOCK_UID, TestCase::BLOCK_GID, libc::S_IROTH);
  1515. let result = ModeAuthorizer {}.can_read(&case.context());
  1516. assert!(result.is_ok())
  1517. }
  1518. }
  1519. struct BtTestCase {
  1520. dir: TempDir,
  1521. bt: Blocktree<ConcreteCreds, ModeAuthorizer>,
  1522. }
  1523. impl BtTestCase {
  1524. fn new_empty() -> BtTestCase {
  1525. let dir = TempDir::new("fuse").expect("failed to create temp dir");
  1526. let bt =
  1527. Blocktree::new_empty(dir.path().to_owned(), 0, Self::creds(), ModeAuthorizer {})
  1528. .expect("failed to create empty blocktree");
  1529. bt.init(FsOptions::empty()).expect("init failed");
  1530. BtTestCase { dir, bt }
  1531. }
  1532. fn new_existing(dir: TempDir) -> BtTestCase {
  1533. let bt =
  1534. Blocktree::new_existing(dir.path().to_owned(), Self::creds(), ModeAuthorizer {})
  1535. .expect("failed to create blocktree from existing directory");
  1536. bt.init(FsOptions::empty()).expect("init failed");
  1537. BtTestCase { dir, bt }
  1538. }
  1539. fn creds() -> ConcreteCreds {
  1540. test_helpers::NODE_CREDS.clone()
  1541. }
  1542. fn context(&self) -> Context {
  1543. let (stat, ..) = self
  1544. .bt
  1545. .getattr(&Default::default(), SpecInodes::RootDir.into(), None)
  1546. .expect("getattr failed");
  1547. Context {
  1548. uid: stat.st_uid,
  1549. gid: stat.st_gid,
  1550. pid: 1,
  1551. }
  1552. }
  1553. }
  1554. /// Tests that a new file can be created, written to and the written data can be read from it.
  1555. #[test]
  1556. fn create_write_lseek_read() {
  1557. let case = BtTestCase::new_empty();
  1558. let bt = &case.bt;
  1559. let ctx = case.context();
  1560. let name = CString::new("README.md").unwrap();
  1561. let flags = libc::O_RDWR as u32;
  1562. let (entry, handle, ..) = bt
  1563. .create(
  1564. &ctx,
  1565. SpecInodes::RootDir.into(),
  1566. name.as_c_str(),
  1567. CreateIn {
  1568. mode: libc::S_IFREG | 0o644,
  1569. umask: 0,
  1570. flags,
  1571. fuse_flags: 0,
  1572. },
  1573. )
  1574. .expect("failed to create file");
  1575. let inode = entry.inode;
  1576. let handle = handle.unwrap();
  1577. const LEN: usize = 32;
  1578. let mut expected = BtCursor::new([1u8; LEN]);
  1579. let written = bt
  1580. .write(
  1581. &ctx,
  1582. inode,
  1583. handle,
  1584. &mut expected,
  1585. LEN as u32,
  1586. 0,
  1587. None,
  1588. false,
  1589. flags,
  1590. 0,
  1591. )
  1592. .expect("write failed");
  1593. assert_eq!(LEN, written);
  1594. bt.lseek(&ctx, inode, handle, 0, 0).expect("lseek failed");
  1595. let mut actual = BtCursor::new([0u8; LEN]);
  1596. let read = bt
  1597. .read(&ctx, inode, handle, &mut actual, LEN as u32, 0, None, flags)
  1598. .expect("failed to read");
  1599. assert_eq!(LEN, read);
  1600. assert_eq!(expected, actual)
  1601. }
  1602. #[test]
  1603. fn lookup() {
  1604. let case = BtTestCase::new_empty();
  1605. let bt = &case.bt;
  1606. let ctx = case.context();
  1607. let name = CString::new("README.md").unwrap();
  1608. let (expected, ..) = bt
  1609. .create(
  1610. &ctx,
  1611. SpecInodes::RootDir.into(),
  1612. name.as_c_str(),
  1613. Default::default(),
  1614. )
  1615. .expect("failed to create file");
  1616. let actual = bt
  1617. .lookup(&Default::default(), SpecInodes::RootDir.into(), &name)
  1618. .expect("lookup failed");
  1619. assert_eq!(expected.generation, actual.generation);
  1620. assert_eq!(expected.inode, actual.inode);
  1621. }
  1622. /// Tests that data written by one instance of [Blocktree] can be read by a subsequent
  1623. /// instance.
  1624. #[test]
  1625. fn new_existing() {
  1626. const EXPECTED: &[u8] = b"cool as cucumbers";
  1627. let name = CString::new("RESIGNATION.docx").unwrap();
  1628. let case = BtTestCase::new_empty();
  1629. let bt = &case.bt;
  1630. let ctx = case.context();
  1631. let flags = libc::O_RDWR as u32;
  1632. {
  1633. let (entry, handle, ..) = bt
  1634. .create(
  1635. &ctx,
  1636. SpecInodes::RootDir.into(),
  1637. name.as_c_str(),
  1638. CreateIn {
  1639. mode: libc::S_IFREG | 0o644,
  1640. umask: 0,
  1641. flags,
  1642. fuse_flags: 0,
  1643. },
  1644. )
  1645. .expect("failed to create file");
  1646. let inode = entry.inode;
  1647. let handle = handle.unwrap();
  1648. let mut vec = Vec::with_capacity(EXPECTED.len());
  1649. vec.extend_from_slice(EXPECTED);
  1650. let mut cursor = BtCursor::new(vec);
  1651. let written = bt
  1652. .write(
  1653. &Default::default(),
  1654. inode,
  1655. handle,
  1656. &mut cursor,
  1657. EXPECTED.len() as u32,
  1658. 0,
  1659. None,
  1660. false,
  1661. flags,
  1662. 0,
  1663. )
  1664. .expect("write failed");
  1665. assert_eq!(EXPECTED.len(), written);
  1666. bt.flush(&Default::default(), inode, handle, 0)
  1667. .expect("flush failed");
  1668. }
  1669. let case = BtTestCase::new_existing(case.dir);
  1670. let bt = &case.bt;
  1671. let entry = bt
  1672. .lookup(&Default::default(), SpecInodes::RootDir.into(), &name)
  1673. .expect("lookup failed");
  1674. let inode = entry.inode;
  1675. let (handle, ..) = bt
  1676. .open(&Default::default(), entry.inode, 0, 0)
  1677. .expect("open failed");
  1678. let handle = handle.unwrap();
  1679. let mut actual = BtCursor::new([0u8; EXPECTED.len()]);
  1680. let _ = bt
  1681. .read(
  1682. &Default::default(),
  1683. inode,
  1684. handle,
  1685. &mut actual,
  1686. EXPECTED.len() as u32,
  1687. 0,
  1688. None,
  1689. flags,
  1690. )
  1691. .expect("read failed");
  1692. assert_eq!(EXPECTED, actual.into_inner().as_slice())
  1693. }
  1694. /// Tests that an error is returned by the `Blocktree::write` method if the file was opened
  1695. /// read-only.
  1696. #[test]
  1697. fn open_read_only_write_is_error() {
  1698. let name = CString::new("books.ods").unwrap();
  1699. let case = BtTestCase::new_empty();
  1700. let bt = &case.bt;
  1701. let ctx = case.context();
  1702. let (entry, handle, ..) = bt
  1703. .create(
  1704. &ctx,
  1705. SpecInodes::RootDir.into(),
  1706. name.as_c_str(),
  1707. CreateIn {
  1708. mode: libc::S_IFREG | 0o644,
  1709. umask: 0,
  1710. flags: 0,
  1711. fuse_flags: 0,
  1712. },
  1713. )
  1714. .expect("failed to create file");
  1715. let inode = entry.inode;
  1716. let handle = handle.unwrap();
  1717. bt.release(&ctx, inode, 0, handle, false, false, None)
  1718. .expect("release failed");
  1719. let flags = libc::O_RDONLY as u32;
  1720. let (handle, ..) = bt.open(&ctx, inode, flags, 0).expect("open failed");
  1721. let handle = handle.unwrap();
  1722. const LEN: usize = 32;
  1723. let mut reader = BtCursor::new([1u8; LEN]);
  1724. let result = bt.write(
  1725. &ctx,
  1726. inode,
  1727. handle,
  1728. &mut reader,
  1729. LEN.try_into().unwrap(),
  1730. 0,
  1731. None,
  1732. false,
  1733. flags,
  1734. 0,
  1735. );
  1736. let err = result.err().unwrap();
  1737. assert_eq!(io::ErrorKind::PermissionDenied, err.kind());
  1738. }
  1739. /// Tests that a call to `read` fails when a file is opened write only.
  1740. #[test]
  1741. fn open_write_only_read_is_error() {
  1742. let name = CString::new("books.ods").unwrap();
  1743. let case = BtTestCase::new_empty();
  1744. let bt = &case.bt;
  1745. let ctx = case.context();
  1746. let (entry, handle, ..) = bt
  1747. .create(
  1748. &ctx,
  1749. SpecInodes::RootDir.into(),
  1750. name.as_c_str(),
  1751. CreateIn {
  1752. mode: libc::S_IFREG | 0o644,
  1753. umask: 0,
  1754. flags: 0,
  1755. fuse_flags: 0,
  1756. },
  1757. )
  1758. .expect("failed to create file");
  1759. let inode = entry.inode;
  1760. let handle = handle.unwrap();
  1761. bt.release(&ctx, inode, 0, handle, false, false, None)
  1762. .expect("release failed");
  1763. let flags = libc::O_WRONLY as u32;
  1764. let (handle, ..) = bt.open(&ctx, inode, flags, 0).expect("open failed");
  1765. let handle = handle.unwrap();
  1766. const LEN: usize = 32;
  1767. let mut reader = BtCursor::new([1u8; LEN]);
  1768. let result = bt.read(
  1769. &ctx,
  1770. inode,
  1771. handle,
  1772. &mut reader,
  1773. LEN.try_into().unwrap(),
  1774. 0,
  1775. None,
  1776. flags,
  1777. );
  1778. let err = result.err().unwrap();
  1779. assert_eq!(io::ErrorKind::PermissionDenied, err.kind());
  1780. }
  1781. }