1 // Copyright 2019 The Chromium OS Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 use std::convert::TryInto; 6 use std::ffi::CStr; 7 use std::fs::File; 8 use std::io; 9 use std::mem; 10 use std::time::Duration; 11 12 use crate::sys; 13 14 use crate::server::Mapper; 15 pub use crate::sys::{ 16 FsOptions, IoctlFlags, IoctlIovec, OpenOptions, RemoveMappingOne, SetattrValid, ROOT_ID, 17 }; 18 19 const MAX_BUFFER_SIZE: u32 = 1 << 20; 20 21 /// Information about a path in the filesystem. 22 pub struct Entry { 23 /// An `Inode` that uniquely identifies this path. During `lookup`, setting this to `0` means a 24 /// negative entry. Returning `ENOENT` also means a negative entry but setting this to `0` 25 /// allows the kernel to cache the negative result for `entry_timeout`. The value should be 26 /// produced by converting a `FileSystem::Inode` into a `u64`. 27 pub inode: u64, 28 29 /// The generation number for this `Entry`. Typically used for network file systems. An `inode` 30 /// / `generation` pair must be unique over the lifetime of the file system (rather than just 31 /// the lifetime of the mount). In other words, if a `FileSystem` implementation re-uses an 32 /// `Inode` after it has been deleted then it must assign a new, previously unused generation 33 /// number to the `Inode` at the same time. 34 pub generation: u64, 35 36 /// Inode attributes. Even if `attr_timeout` is zero, `attr` must be correct. For example, for 37 /// `open()`, FUSE uses `attr.st_size` from `lookup()` to determine how many bytes to request. 38 /// If this value is not correct, incorrect data will be returned. 39 pub attr: libc::stat64, 40 41 /// How long the values in `attr` should be considered valid. If the attributes of the `Entry` 42 /// are only modified by the FUSE client, then this should be set to a very large value. 43 pub attr_timeout: Duration, 44 45 /// How long the name associated with this `Entry` should be considered valid. If directory 46 /// entries are only changed or deleted by the FUSE client, then this should be set to a very 47 /// large value. 48 pub entry_timeout: Duration, 49 } 50 51 impl From<Entry> for sys::EntryOut { from(entry: Entry) -> sys::EntryOut52 fn from(entry: Entry) -> sys::EntryOut { 53 sys::EntryOut { 54 nodeid: entry.inode, 55 generation: entry.generation, 56 entry_valid: entry.entry_timeout.as_secs(), 57 attr_valid: entry.attr_timeout.as_secs(), 58 entry_valid_nsec: entry.entry_timeout.subsec_nanos(), 59 attr_valid_nsec: entry.attr_timeout.subsec_nanos(), 60 attr: entry.attr.into(), 61 } 62 } 63 } 64 65 /// Represents information about an entry in a directory. 66 pub struct DirEntry<'a> { 67 /// The inode number for this entry. This does NOT have to be the same as the `Inode` for this 68 /// directory entry. However, it must be the same as the `attr.st_ino` field of the `Entry` that 69 /// would be returned by a `lookup` request in the parent directory for `name`. 70 pub ino: libc::ino64_t, 71 72 /// Any non-zero value that the kernel can use to identify the current point in the directory 73 /// entry stream. It does not need to be the actual physical position. A value of `0` is 74 /// reserved to mean "from the beginning" and should never be used. The `offset` value of the 75 /// first entry in a stream should point to the beginning of the second entry and so on. 76 pub offset: u64, 77 78 /// The type of this directory entry. Valid values are any of the `libc::DT_*` constants. 79 pub type_: u32, 80 81 /// The name of this directory entry. There are no requirements for the contents of this field 82 /// and any sequence of bytes is considered valid. 83 pub name: &'a CStr, 84 } 85 86 /// A reply to a `getxattr` method call. 87 pub enum GetxattrReply { 88 /// The value of the requested extended attribute. This can be arbitrary textual or binary data 89 /// and does not need to be nul-terminated. 90 Value(Vec<u8>), 91 92 /// The size of the buffer needed to hold the value of the requested extended attribute. Should 93 /// be returned when the `size` parameter is 0. Callers should note that it is still possible 94 /// for the size of the value to change in between `getxattr` calls and should not assume that a 95 /// subsequent call to `getxattr` with the returned count will always succeed. 96 Count(u32), 97 } 98 99 /// A reply to a `listxattr` method call. 100 pub enum ListxattrReply { 101 /// A buffer containing a nul-separated list of the names of all the extended attributes 102 /// associated with this `Inode`. This list of names may be unordered and includes a namespace 103 /// prefix. There may be several disjoint namespaces associated with a single `Inode`. 104 Names(Vec<u8>), 105 106 /// This size of the buffer needed to hold the full list of extended attribute names associated 107 /// with this `Inode`. Should be returned when the `size` parameter is 0. Callers should note 108 /// that it is still possible for the set of extended attributes to change between `listxattr` 109 /// calls and so should not assume that a subsequent call to `listxattr` with the returned count 110 /// will always succeed. 111 Count(u32), 112 } 113 114 /// A reply to an `ioctl` method call. 115 pub enum IoctlReply { 116 /// Indicates that the ioctl should be retried. This is only a valid reply when the `flags` 117 /// field of the ioctl request contains `IoctlFlags::UNRESTRICTED`. The kernel will read in data 118 /// and prepare output buffers as specified in the `input` and `output` fields before re-sending 119 /// the ioctl message. 120 Retry { 121 /// Data that should be read by the kernel module and sent to the server when the ioctl is 122 /// retried. 123 input: Vec<IoctlIovec>, 124 125 /// Buffer space that should be prepared so that the server can send back the response to 126 /// the ioctl. 127 output: Vec<IoctlIovec>, 128 }, 129 130 /// Indicates that the ioctl was processed. 131 Done(io::Result<Vec<u8>>), 132 } 133 134 /// A trait for directly copying data from the fuse transport into a `File` without first storing it 135 /// in an intermediate buffer. 136 pub trait ZeroCopyReader { 137 /// Copies at most `count` bytes from `self` directly into `f` at offset `off` without storing 138 /// it in any intermediate buffers. If the return value is `Ok(n)` then it must be guaranteed 139 /// that `0 <= n <= count`. If `n` is `0`, then it can indicate one of 3 possibilities: 140 /// 141 /// 1. There is no more data left in `self`. 142 /// 2. There is no more space in `f`. 143 /// 3. `count` was `0`. 144 /// 145 /// # Errors 146 /// 147 /// If any error is returned then the implementation must guarantee that no bytes were copied 148 /// from `self`. If the underlying write to `f` returns `0` then the implementation must return 149 /// an error of the kind `io::ErrorKind::WriteZero`. read_to(&mut self, f: &mut File, count: usize, off: u64) -> io::Result<usize>150 fn read_to(&mut self, f: &mut File, count: usize, off: u64) -> io::Result<usize>; 151 152 /// Copies exactly `count` bytes of data from `self` into `f` at offset `off`. `off + count` 153 /// must be less than `u64::MAX`. 154 /// 155 /// # Errors 156 /// 157 /// If an error is returned then the number of bytes copied from `self` is unspecified but it 158 /// will never be more than `count`. read_exact_to(&mut self, f: &mut File, mut count: usize, mut off: u64) -> io::Result<()>159 fn read_exact_to(&mut self, f: &mut File, mut count: usize, mut off: u64) -> io::Result<()> { 160 let c = count 161 .try_into() 162 .map_err(|e| io::Error::new(io::ErrorKind::InvalidInput, e))?; 163 if off.checked_add(c).is_none() { 164 return Err(io::Error::new( 165 io::ErrorKind::InvalidInput, 166 "`off` + `count` must be less than u64::MAX", 167 )); 168 } 169 170 while count > 0 { 171 match self.read_to(f, count, off) { 172 Ok(0) => { 173 return Err(io::Error::new( 174 io::ErrorKind::WriteZero, 175 "failed to fill whole buffer", 176 )) 177 } 178 Ok(n) => { 179 count -= n; 180 off += n as u64; 181 } 182 Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {} 183 Err(e) => return Err(e), 184 } 185 } 186 187 Ok(()) 188 } 189 190 /// Copies all remaining bytes from `self` into `f` at offset `off`. Equivalent to repeatedly 191 /// calling `read_to` until it returns either `Ok(0)` or a non-`ErrorKind::Interrupted` error. 192 /// 193 /// # Errors 194 /// 195 /// If an error is returned then the number of bytes copied from `self` is unspecified. copy_to_end(&mut self, f: &mut File, mut off: u64) -> io::Result<usize>196 fn copy_to_end(&mut self, f: &mut File, mut off: u64) -> io::Result<usize> { 197 let mut out = 0; 198 loop { 199 match self.read_to(f, ::std::usize::MAX, off) { 200 Ok(0) => return Ok(out), 201 Ok(n) => { 202 off = off.saturating_add(n as u64); 203 out += n; 204 } 205 Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {} 206 Err(e) => return Err(e), 207 } 208 } 209 } 210 } 211 212 impl<'a, R: ZeroCopyReader> ZeroCopyReader for &'a mut R { read_to(&mut self, f: &mut File, count: usize, off: u64) -> io::Result<usize>213 fn read_to(&mut self, f: &mut File, count: usize, off: u64) -> io::Result<usize> { 214 (**self).read_to(f, count, off) 215 } read_exact_to(&mut self, f: &mut File, count: usize, off: u64) -> io::Result<()>216 fn read_exact_to(&mut self, f: &mut File, count: usize, off: u64) -> io::Result<()> { 217 (**self).read_exact_to(f, count, off) 218 } copy_to_end(&mut self, f: &mut File, off: u64) -> io::Result<usize>219 fn copy_to_end(&mut self, f: &mut File, off: u64) -> io::Result<usize> { 220 (**self).copy_to_end(f, off) 221 } 222 } 223 224 /// A trait for directly copying data from a `File` into the fuse transport without first storing 225 /// it in an intermediate buffer. 226 pub trait ZeroCopyWriter { 227 /// Copies at most `count` bytes from `f` at offset `off` directly into `self` without storing 228 /// it in any intermediate buffers. If the return value is `Ok(n)` then it must be guaranteed 229 /// that `0 <= n <= count`. If `n` is `0`, then it can indicate one of 3 possibilities: 230 /// 231 /// 1. There is no more data left in `f`. 232 /// 2. There is no more space in `self`. 233 /// 3. `count` was `0`. 234 /// 235 /// # Errors 236 /// 237 /// If any error is returned then the implementation must guarantee that no bytes were copied 238 /// from `f`. If the underlying read from `f` returns `0` then the implementation must return an 239 /// error of the kind `io::ErrorKind::UnexpectedEof`. write_from(&mut self, f: &mut File, count: usize, off: u64) -> io::Result<usize>240 fn write_from(&mut self, f: &mut File, count: usize, off: u64) -> io::Result<usize>; 241 242 /// Copies exactly `count` bytes of data from `f` at offset `off` into `self`. `off + count` 243 /// must be less than `u64::MAX`. 244 /// 245 /// # Errors 246 /// 247 /// If an error is returned then the number of bytes copied from `self` is unspecified but it 248 /// well never be more than `count`. write_all_from(&mut self, f: &mut File, mut count: usize, mut off: u64) -> io::Result<()>249 fn write_all_from(&mut self, f: &mut File, mut count: usize, mut off: u64) -> io::Result<()> { 250 let c = count 251 .try_into() 252 .map_err(|e| io::Error::new(io::ErrorKind::InvalidInput, e))?; 253 if off.checked_add(c).is_none() { 254 return Err(io::Error::new( 255 io::ErrorKind::InvalidInput, 256 "`off` + `count` must be less than u64::MAX", 257 )); 258 } 259 260 while count > 0 { 261 match self.write_from(f, count, off) { 262 Ok(0) => { 263 return Err(io::Error::new( 264 io::ErrorKind::UnexpectedEof, 265 "failed to write whole buffer", 266 )) 267 } 268 Ok(n) => { 269 // No need for checked math here because we verified that `off + count` will not 270 // overflow and `n` must be <= `count`. 271 count -= n; 272 off += n as u64; 273 } 274 Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {} 275 Err(e) => return Err(e), 276 } 277 } 278 279 Ok(()) 280 } 281 282 /// Copies all remaining bytes from `f` at offset `off` into `self`. Equivalent to repeatedly 283 /// calling `write_from` until it returns either `Ok(0)` or a non-`ErrorKind::Interrupted` 284 /// error. 285 /// 286 /// # Errors 287 /// 288 /// If an error is returned then the number of bytes copied from `f` is unspecified. copy_to_end(&mut self, f: &mut File, mut off: u64) -> io::Result<usize>289 fn copy_to_end(&mut self, f: &mut File, mut off: u64) -> io::Result<usize> { 290 let mut out = 0; 291 loop { 292 match self.write_from(f, ::std::usize::MAX, off) { 293 Ok(0) => return Ok(out), 294 Ok(n) => { 295 off = off.saturating_add(n as u64); 296 out += n; 297 } 298 Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {} 299 Err(e) => return Err(e), 300 } 301 } 302 } 303 } 304 305 impl<'a, W: ZeroCopyWriter> ZeroCopyWriter for &'a mut W { write_from(&mut self, f: &mut File, count: usize, off: u64) -> io::Result<usize>306 fn write_from(&mut self, f: &mut File, count: usize, off: u64) -> io::Result<usize> { 307 (**self).write_from(f, count, off) 308 } write_all_from(&mut self, f: &mut File, count: usize, off: u64) -> io::Result<()>309 fn write_all_from(&mut self, f: &mut File, count: usize, off: u64) -> io::Result<()> { 310 (**self).write_all_from(f, count, off) 311 } copy_to_end(&mut self, f: &mut File, off: u64) -> io::Result<usize>312 fn copy_to_end(&mut self, f: &mut File, off: u64) -> io::Result<usize> { 313 (**self).copy_to_end(f, off) 314 } 315 } 316 317 /// Additional context associated with requests. 318 #[derive(Clone, Copy, Debug)] 319 pub struct Context { 320 /// The user ID of the calling process. 321 pub uid: libc::uid_t, 322 323 /// The group ID of the calling process. 324 pub gid: libc::gid_t, 325 326 /// The thread group ID of the calling process. 327 pub pid: libc::pid_t, 328 } 329 330 impl From<sys::InHeader> for Context { from(source: sys::InHeader) -> Self331 fn from(source: sys::InHeader) -> Self { 332 Context { 333 uid: source.uid, 334 gid: source.gid, 335 pid: source.pid as i32, 336 } 337 } 338 } 339 340 /// A trait for iterating over the contents of a directory. This trait is needed because rust 341 /// doesn't support generic associated types, which means that it's not possible to implement a 342 /// regular iterator that yields a `DirEntry` due to its generic lifetime parameter. 343 pub trait DirectoryIterator { 344 /// Returns the next entry in the directory or `None` if there are no more. next(&mut self) -> Option<DirEntry>345 fn next(&mut self) -> Option<DirEntry>; 346 } 347 348 /// The main trait that connects a file system with a transport. 349 #[allow(unused_variables)] 350 pub trait FileSystem { 351 /// Represents a location in the filesystem tree and can be used to perform operations that act 352 /// on the metadata of a file/directory (e.g., `getattr` and `setattr`). Can also be used as the 353 /// starting point for looking up paths in the filesystem tree. An `Inode` may support operating 354 /// directly on the content of the path that to which it points. `FileSystem` implementations 355 /// that support this should set the `FsOptions::ZERO_MESSAGE_OPEN` option in the return value 356 /// of the `init` function. On linux based systems, an `Inode` is equivalent to opening a file 357 /// or directory with the `libc::O_PATH` flag. 358 /// 359 /// # Lookup Count 360 /// 361 /// The `FileSystem` implementation is required to keep a "lookup count" for every `Inode`. 362 /// Every time an `Entry` is returned by a `FileSystem` trait method, this lookup count should 363 /// increase by 1. The lookup count for an `Inode` decreases when the kernel sends a `forget` 364 /// request. `Inode`s with a non-zero lookup count may receive requests from the kernel even 365 /// after calls to `unlink`, `rmdir` or (when overwriting an existing file) `rename`. 366 /// `FileSystem` implementations must handle such requests properly and it is recommended to 367 /// defer removal of the `Inode` until the lookup count reaches zero. Calls to `unlink`, `rmdir` 368 /// or `rename` will be followed closely by `forget` unless the file or directory is open, in 369 /// which case the kernel issues `forget` only after the `release` or `releasedir` calls. 370 /// 371 /// Note that if a file system will be exported over NFS the `Inode`'s lifetime must extend even 372 /// beyond `forget`. See the `generation` field in `Entry`. 373 type Inode: From<u64> + Into<u64>; 374 375 /// Represents a file or directory that is open for reading/writing. 376 type Handle: From<u64> + Into<u64>; 377 378 /// An iterator over the entries of a directory. See the documentation for `readdir` for more 379 /// details. 380 type DirIter: DirectoryIterator; 381 382 /// Maximum size of the buffer that the filesystem can generate data to, including the header. 383 /// This corresponds to max_write in the initialization. max_buffer_size(&self) -> u32384 fn max_buffer_size(&self) -> u32 { 385 MAX_BUFFER_SIZE 386 } 387 388 /// Initialize the file system. 389 /// 390 /// This method is called when a connection to the FUSE kernel module is first established. The 391 /// `capable` parameter indicates the features that are supported by the kernel module. The 392 /// implementation should return the options that it supports. Any options set in the returned 393 /// `FsOptions` that are not also set in `capable` are silently dropped. init(&self, capable: FsOptions) -> io::Result<FsOptions>394 fn init(&self, capable: FsOptions) -> io::Result<FsOptions> { 395 Ok(FsOptions::empty()) 396 } 397 398 /// Clean up the file system. 399 /// 400 /// Called when the filesystem exits. All open `Handle`s should be closed and the lookup count 401 /// for all open `Inode`s implicitly goes to zero. At this point the connection to the FUSE 402 /// kernel module may already be gone so implementations should not rely on being able to 403 /// communicate with the kernel. destroy(&self)404 fn destroy(&self) {} 405 406 /// Look up a directory entry by name and get its attributes. 407 /// 408 /// If this call is successful then the lookup count of the `Inode` associated with the returned 409 /// `Entry` must be increased by 1. lookup(&self, ctx: Context, parent: Self::Inode, name: &CStr) -> io::Result<Entry>410 fn lookup(&self, ctx: Context, parent: Self::Inode, name: &CStr) -> io::Result<Entry> { 411 Err(io::Error::from_raw_os_error(libc::ENOSYS)) 412 } 413 414 /// Forget about an inode. 415 /// 416 /// Called when the kernel removes an inode from its internal caches. `count` indicates the 417 /// amount by which the lookup count for the inode should be decreased. If reducing the lookup 418 /// count by `count` causes it to go to zero, then the implementation may delete the `Inode`. forget(&self, ctx: Context, inode: Self::Inode, count: u64)419 fn forget(&self, ctx: Context, inode: Self::Inode, count: u64) {} 420 421 /// Forget about multiple inodes. 422 /// 423 /// `requests` is a vector of `(inode, count)` pairs. See the documentation for `forget` for 424 /// more information. batch_forget(&self, ctx: Context, requests: Vec<(Self::Inode, u64)>)425 fn batch_forget(&self, ctx: Context, requests: Vec<(Self::Inode, u64)>) { 426 for (inode, count) in requests { 427 self.forget(ctx, inode, count) 428 } 429 } 430 431 /// Get attributes for a file / directory. 432 /// 433 /// If `handle` is not `None`, then it contains the handle previously returned by the 434 /// implementation after a call to `open` or `opendir`. However, implementations should still 435 /// take care to verify the handle if they do not trust the client (e.g., virtio-fs). 436 /// 437 /// If writeback caching is enabled (`FsOptions::WRITEBACK_CACHE`), then the kernel module 438 /// likely has a better idea of the length of the file than the file system (for 439 /// example, if there was a write that extended the size of the file but has not yet been 440 /// flushed). In this case, the `st_size` field of the returned struct is ignored. 441 /// 442 /// The returned `Duration` indicates how long the returned attributes should be considered 443 /// valid by the client. If the attributes are only changed via the FUSE kernel module (i.e., 444 /// the kernel module has exclusive access), then this should be a very large value. getattr( &self, ctx: Context, inode: Self::Inode, handle: Option<Self::Handle>, ) -> io::Result<(libc::stat64, Duration)>445 fn getattr( 446 &self, 447 ctx: Context, 448 inode: Self::Inode, 449 handle: Option<Self::Handle>, 450 ) -> io::Result<(libc::stat64, Duration)> { 451 Err(io::Error::from_raw_os_error(libc::ENOSYS)) 452 } 453 454 /// Set attributes for a file / directory. 455 /// 456 /// If `handle` is not `None`, then it contains the handle previously returned by the 457 /// implementation after a call to `open` or `opendir`. However, implementations should still 458 /// take care to verify the handle if they do not trust the client (e.g., virtio-fs). 459 /// 460 /// The `valid` parameter indicates the fields of `attr` that may be considered valid and should 461 /// be set by the file system. The content of all other fields in `attr` is undefined. 462 /// 463 /// If the `FsOptions::HANDLE_KILLPRIV` was set during `init`, then the implementation is 464 /// expected to reset the setuid and setgid bits if the file size or owner is being changed. 465 /// 466 /// This method returns the new attributes after making the modifications requested by the 467 /// client. The returned `Duration` indicates how long the returned attributes should be 468 /// considered valid by the client. If the attributes are only changed via the FUSE kernel 469 /// module (i.e., the kernel module has exclusive access), then this should be a very large 470 /// value. setattr( &self, ctx: Context, inode: Self::Inode, attr: libc::stat64, handle: Option<Self::Handle>, valid: SetattrValid, ) -> io::Result<(libc::stat64, Duration)>471 fn setattr( 472 &self, 473 ctx: Context, 474 inode: Self::Inode, 475 attr: libc::stat64, 476 handle: Option<Self::Handle>, 477 valid: SetattrValid, 478 ) -> io::Result<(libc::stat64, Duration)> { 479 Err(io::Error::from_raw_os_error(libc::ENOSYS)) 480 } 481 482 /// Read a symbolic link. readlink(&self, ctx: Context, inode: Self::Inode) -> io::Result<Vec<u8>>483 fn readlink(&self, ctx: Context, inode: Self::Inode) -> io::Result<Vec<u8>> { 484 Err(io::Error::from_raw_os_error(libc::ENOSYS)) 485 } 486 487 /// Create a symbolic link. 488 /// 489 /// The file system must create a symbolic link named `name` in the directory represented by 490 /// `parent`, which contains the string `linkname`. Returns an `Entry` for the newly created 491 /// symlink. 492 /// 493 /// If this call is successful then the lookup count of the `Inode` associated with the returned 494 /// `Entry` must be increased by 1. symlink( &self, ctx: Context, linkname: &CStr, parent: Self::Inode, name: &CStr, ) -> io::Result<Entry>495 fn symlink( 496 &self, 497 ctx: Context, 498 linkname: &CStr, 499 parent: Self::Inode, 500 name: &CStr, 501 ) -> io::Result<Entry> { 502 Err(io::Error::from_raw_os_error(libc::ENOSYS)) 503 } 504 505 /// Create a file node. 506 /// 507 /// Create a regular file, character device, block device, fifo, or socket node named `name` in 508 /// the directory represented by `inode`. Valid values for `mode` and `rdev` are the same as 509 /// those accepted by the `mknod(2)` system call. Returns an `Entry` for the newly created node. 510 /// 511 /// When the `FsOptions::DONT_MASK` feature is set, the file system is responsible for setting 512 /// the permissions of the created node to `mode & !umask`. 513 /// 514 /// If this call is successful then the lookup count of the `Inode` associated with the returned 515 /// `Entry` must be increased by 1. mknod( &self, ctx: Context, inode: Self::Inode, name: &CStr, mode: u32, rdev: u32, umask: u32, ) -> io::Result<Entry>516 fn mknod( 517 &self, 518 ctx: Context, 519 inode: Self::Inode, 520 name: &CStr, 521 mode: u32, 522 rdev: u32, 523 umask: u32, 524 ) -> io::Result<Entry> { 525 Err(io::Error::from_raw_os_error(libc::ENOSYS)) 526 } 527 528 /// Create a directory. 529 /// 530 /// When the `FsOptions::DONT_MASK` feature is set, the file system is responsible for setting 531 /// the permissions of the created directory to `mode & !umask`. Returns an `Entry` for the 532 /// newly created directory. 533 /// 534 /// If this call is successful then the lookup count of the `Inode` associated with the returned 535 /// `Entry` must be increased by 1. mkdir( &self, ctx: Context, parent: Self::Inode, name: &CStr, mode: u32, umask: u32, ) -> io::Result<Entry>536 fn mkdir( 537 &self, 538 ctx: Context, 539 parent: Self::Inode, 540 name: &CStr, 541 mode: u32, 542 umask: u32, 543 ) -> io::Result<Entry> { 544 Err(io::Error::from_raw_os_error(libc::ENOSYS)) 545 } 546 547 /// Create an unnamed temporary file. chromeos_tmpfile( &self, ctx: Context, parent: Self::Inode, mode: u32, umask: u32, ) -> io::Result<Entry>548 fn chromeos_tmpfile( 549 &self, 550 ctx: Context, 551 parent: Self::Inode, 552 mode: u32, 553 umask: u32, 554 ) -> io::Result<Entry> { 555 Err(io::Error::from_raw_os_error(libc::ENOSYS)) 556 } 557 558 /// Remove a file. 559 /// 560 /// If the file's inode lookup count is non-zero, then the file system is expected to delay 561 /// removal of the inode until the lookup count goes to zero. See the documentation of the 562 /// `forget` function for more information. unlink(&self, ctx: Context, parent: Self::Inode, name: &CStr) -> io::Result<()>563 fn unlink(&self, ctx: Context, parent: Self::Inode, name: &CStr) -> io::Result<()> { 564 Err(io::Error::from_raw_os_error(libc::ENOSYS)) 565 } 566 567 /// Remove a directory. 568 /// 569 /// If the directory's inode lookup count is non-zero, then the file system is expected to delay 570 /// removal of the inode until the lookup count goes to zero. See the documentation of the 571 /// `forget` function for more information. rmdir(&self, ctx: Context, parent: Self::Inode, name: &CStr) -> io::Result<()>572 fn rmdir(&self, ctx: Context, parent: Self::Inode, name: &CStr) -> io::Result<()> { 573 Err(io::Error::from_raw_os_error(libc::ENOSYS)) 574 } 575 576 /// Rename a file / directory. 577 /// 578 /// If the destination exists, it should be atomically replaced. If the destination's inode 579 /// lookup count is non-zero, then the file system is expected to delay removal of the inode 580 /// until the lookup count goes to zero. See the documentation of the `forget` function for more 581 /// information. 582 /// 583 /// `flags` may be `libc::RENAME_EXCHANGE` or `libc::RENAME_NOREPLACE`. If 584 /// `libc::RENAME_NOREPLACE` is specified, the implementation must not overwrite `newname` if it 585 /// exists and must return an error instead. If `libc::RENAME_EXCHANGE` is specified, the 586 /// implementation must atomically exchange the two files, i.e., both must exist and neither may 587 /// be deleted. rename( &self, ctx: Context, olddir: Self::Inode, oldname: &CStr, newdir: Self::Inode, newname: &CStr, flags: u32, ) -> io::Result<()>588 fn rename( 589 &self, 590 ctx: Context, 591 olddir: Self::Inode, 592 oldname: &CStr, 593 newdir: Self::Inode, 594 newname: &CStr, 595 flags: u32, 596 ) -> io::Result<()> { 597 Err(io::Error::from_raw_os_error(libc::ENOSYS)) 598 } 599 600 /// Create a hard link. 601 /// 602 /// Create a hard link from `inode` to `newname` in the directory represented by `newparent`. 603 /// 604 /// If this call is successful then the lookup count of the `Inode` associated with the returned 605 /// `Entry` must be increased by 1. link( &self, ctx: Context, inode: Self::Inode, newparent: Self::Inode, newname: &CStr, ) -> io::Result<Entry>606 fn link( 607 &self, 608 ctx: Context, 609 inode: Self::Inode, 610 newparent: Self::Inode, 611 newname: &CStr, 612 ) -> io::Result<Entry> { 613 Err(io::Error::from_raw_os_error(libc::ENOSYS)) 614 } 615 616 /// Open a file. 617 /// 618 /// Open the file associated with `inode` for reading / writing. All values accepted by the 619 /// `open(2)` system call are valid values for `flags` and must be handled by the file system. 620 /// However, there are some additional rules: 621 /// 622 /// * Creation flags (`libc::O_CREAT`, `libc::O_EXCL`, `libc::O_NOCTTY`) will be filtered out 623 /// and handled by the kernel. 624 /// 625 /// * The file system should check the access modes (`libc::O_RDONLY`, `libc::O_WRONLY`, 626 /// `libc::O_RDWR`) to determine if the operation is permitted. If the file system was mounted 627 /// with the `-o default_permissions` mount option, then this check will also be carried out 628 /// by the kernel before sending the open request. 629 /// 630 /// * When writeback caching is enabled (`FsOptions::WRITEBACK_CACHE`) the kernel may send read 631 /// requests even for files opened with `libc::O_WRONLY`. The file system should be prepared 632 /// to handle this. 633 /// 634 /// * When writeback caching is enabled, the kernel will handle the `libc::O_APPEND` flag. 635 /// However, this will not work reliably unless the kernel has exclusive access to the file. 636 /// In this case the file system may either ignore the `libc::O_APPEND` flag or return an 637 /// error to indicate that reliable `libc::O_APPEND` handling is not available. 638 /// 639 /// * When writeback caching is disabled, the file system is expected to properly handle 640 /// `libc::O_APPEND` and ensure that each write is appended to the end of the file. 641 /// 642 /// The file system may choose to return a `Handle` to refer to the newly opened file. The 643 /// kernel will then use this `Handle` for all operations on the content of the file (`read`, 644 /// `write`, `flush`, `release`, `fsync`). If the file system does not return a 645 /// `Handle` then the kernel will use the `Inode` for the file to operate on its contents. In 646 /// this case the file system may wish to enable the `FsOptions::ZERO_MESSAGE_OPEN` feature if 647 /// it is supported by the kernel (see below). 648 /// 649 /// The returned `OpenOptions` allow the file system to change the way the opened file is 650 /// handled by the kernel. See the documentation of `OpenOptions` for more information. 651 /// 652 /// If the `FsOptions::ZERO_MESSAGE_OPEN` feature is enabled by both the file system 653 /// implementation and the kernel, then the file system may return an error of `ENOSYS`. This 654 /// will be interpreted by the kernel as success and future calls to `open` and `release` will 655 /// be handled by the kernel without being passed on to the file system. open( &self, ctx: Context, inode: Self::Inode, flags: u32, ) -> io::Result<(Option<Self::Handle>, OpenOptions)>656 fn open( 657 &self, 658 ctx: Context, 659 inode: Self::Inode, 660 flags: u32, 661 ) -> io::Result<(Option<Self::Handle>, OpenOptions)> { 662 // Matches the behavior of libfuse. 663 Ok((None, OpenOptions::empty())) 664 } 665 666 /// Create and open a file. 667 /// 668 /// If the file does not already exist, the file system should create it with the specified 669 /// `mode`. When the `FsOptions::DONT_MASK` feature is set, the file system is responsible for 670 /// setting the permissions of the created file to `mode & !umask`. 671 /// 672 /// If the file system returns an `ENOSYS` error, then the kernel will treat this method as 673 /// unimplemented and all future calls to `create` will be handled by calling the `mknod` and 674 /// `open` methods instead. 675 /// 676 /// See the documentation for the `open` method for more information about opening the file. In 677 /// addition to the optional `Handle` and the `OpenOptions`, the file system must also return an 678 /// `Entry` for the file. This increases the lookup count for the `Inode` associated with the 679 /// file by 1. create( &self, ctx: Context, parent: Self::Inode, name: &CStr, mode: u32, flags: u32, umask: u32, ) -> io::Result<(Entry, Option<Self::Handle>, OpenOptions)>680 fn create( 681 &self, 682 ctx: Context, 683 parent: Self::Inode, 684 name: &CStr, 685 mode: u32, 686 flags: u32, 687 umask: u32, 688 ) -> io::Result<(Entry, Option<Self::Handle>, OpenOptions)> { 689 Err(io::Error::from_raw_os_error(libc::ENOSYS)) 690 } 691 692 /// Read data from a file. 693 /// 694 /// Returns `size` bytes of data starting from offset `off` from the file associated with 695 /// `inode` or `handle`. 696 /// 697 /// `flags` contains the flags used to open the file. Similarly, `handle` is the `Handle` 698 /// returned by the file system from the `open` method, if any. If the file system 699 /// implementation did not return a `Handle` from `open` then the contents of `handle` are 700 /// undefined. 701 /// 702 /// This method should return exactly the number of bytes requested by the kernel, except in the 703 /// case of error or EOF. Otherwise, the kernel will substitute the rest of the data with 704 /// zeroes. An exception to this rule is if the file was opened with the "direct I/O" option 705 /// (`libc::O_DIRECT`), in which case the kernel will forward the return code from this method 706 /// to the userspace application that made the system call. read<W: io::Write + ZeroCopyWriter>( &self, ctx: Context, inode: Self::Inode, handle: Self::Handle, w: W, size: u32, offset: u64, lock_owner: Option<u64>, flags: u32, ) -> io::Result<usize>707 fn read<W: io::Write + ZeroCopyWriter>( 708 &self, 709 ctx: Context, 710 inode: Self::Inode, 711 handle: Self::Handle, 712 w: W, 713 size: u32, 714 offset: u64, 715 lock_owner: Option<u64>, 716 flags: u32, 717 ) -> io::Result<usize> { 718 Err(io::Error::from_raw_os_error(libc::ENOSYS)) 719 } 720 721 /// Write data to a file. 722 /// 723 /// Writes `size` bytes of data starting from offset `off` to the file associated with `inode` 724 /// or `handle`. 725 /// 726 /// `flags` contains the flags used to open the file. Similarly, `handle` is the `Handle` 727 /// returned by the file system from the `open` method, if any. If the file system 728 /// implementation did not return a `Handle` from `open` then the contents of `handle` are 729 /// undefined. 730 /// 731 /// If the `FsOptions::HANDLE_KILLPRIV` feature is not enabled then then the file system is 732 /// expected to clear the setuid and setgid bits. 733 /// 734 /// If `delayed_write` is true then it indicates that this is a write for buffered data. 735 /// 736 /// This method should return exactly the number of bytes requested by the kernel, except in the 737 /// case of error. An exception to this rule is if the file was opened with the "direct I/O" 738 /// option (`libc::O_DIRECT`), in which case the kernel will forward the return code from this 739 /// method to the userspace application that made the system call. write<R: io::Read + ZeroCopyReader>( &self, ctx: Context, inode: Self::Inode, handle: Self::Handle, r: R, size: u32, offset: u64, lock_owner: Option<u64>, delayed_write: bool, flags: u32, ) -> io::Result<usize>740 fn write<R: io::Read + ZeroCopyReader>( 741 &self, 742 ctx: Context, 743 inode: Self::Inode, 744 handle: Self::Handle, 745 r: R, 746 size: u32, 747 offset: u64, 748 lock_owner: Option<u64>, 749 delayed_write: bool, 750 flags: u32, 751 ) -> io::Result<usize> { 752 Err(io::Error::from_raw_os_error(libc::ENOSYS)) 753 } 754 755 /// Flush the contents of a file. 756 /// 757 /// This method is called on every `close()` of a file descriptor. Since it is possible to 758 /// duplicate file descriptors there may be many `flush` calls for one call to `open`. 759 /// 760 /// File systems should not make any assumptions about when `flush` will be 761 /// called or even if it will be called at all. 762 /// 763 /// `handle` is the `Handle` returned by the file system from the `open` method, if any. If the 764 /// file system did not return a `Handle` from `open` then the contents of `handle` are 765 /// undefined. 766 /// 767 /// Unlike `fsync`, the file system is not required to flush pending writes. One reason to flush 768 /// data is if the file system wants to return write errors during close. However, this is not 769 /// portable because POSIX does not require `close` to wait for delayed I/O to complete. 770 /// 771 /// If the `FsOptions::POSIX_LOCKS` feature is enabled, then the file system must remove all 772 /// locks belonging to `lock_owner`. 773 /// 774 /// If this method returns an `ENOSYS` error then the kernel will treat it as success and all 775 /// subsequent calls to `flush` will be handled by the kernel without being forwarded to the 776 /// file system. flush( &self, ctx: Context, inode: Self::Inode, handle: Self::Handle, lock_owner: u64, ) -> io::Result<()>777 fn flush( 778 &self, 779 ctx: Context, 780 inode: Self::Inode, 781 handle: Self::Handle, 782 lock_owner: u64, 783 ) -> io::Result<()> { 784 Err(io::Error::from_raw_os_error(libc::ENOSYS)) 785 } 786 787 /// Synchronize file contents. 788 /// 789 /// File systems must ensure that the file contents have been flushed to disk before returning 790 /// from this method. If `datasync` is true then only the file data (but not the metadata) needs 791 /// to be flushed. 792 /// 793 /// `handle` is the `Handle` returned by the file system from the `open` method, if any. If the 794 /// file system did not return a `Handle` from `open` then the contents of 795 /// `handle` are undefined. 796 /// 797 /// If this method returns an `ENOSYS` error then the kernel will treat it as success and all 798 /// subsequent calls to `fsync` will be handled by the kernel without being forwarded to the 799 /// file system. fsync( &self, ctx: Context, inode: Self::Inode, datasync: bool, handle: Self::Handle, ) -> io::Result<()>800 fn fsync( 801 &self, 802 ctx: Context, 803 inode: Self::Inode, 804 datasync: bool, 805 handle: Self::Handle, 806 ) -> io::Result<()> { 807 Err(io::Error::from_raw_os_error(libc::ENOSYS)) 808 } 809 810 /// Allocate requested space for file data. 811 /// 812 /// If this function returns success, then the file sytem must guarantee that it is possible to 813 /// write up to `length` bytes of data starting at `offset` without failing due to a lack of 814 /// free space on the disk. 815 /// 816 /// `handle` is the `Handle` returned by the file system from the `open` method, if any. If the 817 /// file system did not return a `Handle` from `open` then the contents of `handle` are 818 /// undefined. 819 /// 820 /// If this method returns an `ENOSYS` error then the kernel will treat that as a permanent 821 /// failure: all future calls to `fallocate` will fail with `EOPNOTSUPP` without being forwarded 822 /// to the file system. fallocate( &self, ctx: Context, inode: Self::Inode, handle: Self::Handle, mode: u32, offset: u64, length: u64, ) -> io::Result<()>823 fn fallocate( 824 &self, 825 ctx: Context, 826 inode: Self::Inode, 827 handle: Self::Handle, 828 mode: u32, 829 offset: u64, 830 length: u64, 831 ) -> io::Result<()> { 832 Err(io::Error::from_raw_os_error(libc::ENOSYS)) 833 } 834 835 /// Release an open file. 836 /// 837 /// This method is called when there are no more references to an open file: all file 838 /// descriptors are closed and all memory mappings are unmapped. 839 /// 840 /// For every `open` call there will be exactly one `release` call (unless the file system is 841 /// force-unmounted). 842 /// 843 /// The file system may reply with an error, but error values are not returned to the `close()` 844 /// or `munmap()` which triggered the release. 845 /// 846 /// `handle` is the `Handle` returned by the file system from the `open` method, if any. If the 847 /// file system did not return a `Handle` from `open` then the contents of 848 /// `handle` are undefined. 849 /// 850 /// If `flush` is `true` then the contents of the file should also be flushed to disk. release( &self, ctx: Context, inode: Self::Inode, flags: u32, handle: Self::Handle, flush: bool, flock_release: bool, lock_owner: Option<u64>, ) -> io::Result<()>851 fn release( 852 &self, 853 ctx: Context, 854 inode: Self::Inode, 855 flags: u32, 856 handle: Self::Handle, 857 flush: bool, 858 flock_release: bool, 859 lock_owner: Option<u64>, 860 ) -> io::Result<()> { 861 Err(io::Error::from_raw_os_error(libc::ENOSYS)) 862 } 863 864 /// Get information about the file system. statfs(&self, ctx: Context, inode: Self::Inode) -> io::Result<libc::statvfs64>865 fn statfs(&self, ctx: Context, inode: Self::Inode) -> io::Result<libc::statvfs64> { 866 // Safe because we are zero-initializing a struct with only POD fields. 867 let mut st: libc::statvfs64 = unsafe { mem::zeroed() }; 868 869 // This matches the behavior of libfuse as it returns these values if the 870 // filesystem doesn't implement this method. 871 st.f_namemax = 255; 872 st.f_bsize = 512; 873 874 Ok(st) 875 } 876 877 /// Set an extended attribute. 878 /// 879 /// If this method fails with an `ENOSYS` error, then the kernel will treat that as a permanent 880 /// failure. The kernel will return `EOPNOTSUPP` for all future calls to `setxattr` without 881 /// forwarding them to the file system. 882 /// 883 /// Valid values for flags are the same as those accepted by the `setxattr(2)` system call and 884 /// have the same behavior. setxattr( &self, ctx: Context, inode: Self::Inode, name: &CStr, value: &[u8], flags: u32, ) -> io::Result<()>885 fn setxattr( 886 &self, 887 ctx: Context, 888 inode: Self::Inode, 889 name: &CStr, 890 value: &[u8], 891 flags: u32, 892 ) -> io::Result<()> { 893 Err(io::Error::from_raw_os_error(libc::ENOSYS)) 894 } 895 896 /// Get an extended attribute. 897 /// 898 /// If `size` is 0, then the file system should respond with `GetxattrReply::Count` and the 899 /// number of bytes needed to hold the value. If `size` is large enough to hold the value, then 900 /// the file system should reply with `GetxattrReply::Value` and the value of the extended 901 /// attribute. If `size` is not 0 but is also not large enough to hold the value, then the file 902 /// system should reply with an `ERANGE` error. 903 /// 904 /// If this method fails with an `ENOSYS` error, then the kernel will treat that as a permanent 905 /// failure. The kernel will return `EOPNOTSUPP` for all future calls to `getxattr` without 906 /// forwarding them to the file system. getxattr( &self, ctx: Context, inode: Self::Inode, name: &CStr, size: u32, ) -> io::Result<GetxattrReply>907 fn getxattr( 908 &self, 909 ctx: Context, 910 inode: Self::Inode, 911 name: &CStr, 912 size: u32, 913 ) -> io::Result<GetxattrReply> { 914 Err(io::Error::from_raw_os_error(libc::ENOSYS)) 915 } 916 917 /// List extended attribute names. 918 /// 919 /// If `size` is 0, then the file system should respond with `ListxattrReply::Count` and the 920 /// number of bytes needed to hold a `\0` byte separated list of the names of all the extended 921 /// attributes. If `size` is large enough to hold the `\0` byte separated list of the attribute 922 /// names, then the file system should reply with `ListxattrReply::Names` and the list. If 923 /// `size` is not 0 but is also not large enough to hold the list, then the file system should 924 /// reply with an `ERANGE` error. 925 /// 926 /// If this method fails with an `ENOSYS` error, then the kernel will treat that as a permanent 927 /// failure. The kernel will return `EOPNOTSUPP` for all future calls to `listxattr` without 928 /// forwarding them to the file system. listxattr(&self, ctx: Context, inode: Self::Inode, size: u32) -> io::Result<ListxattrReply>929 fn listxattr(&self, ctx: Context, inode: Self::Inode, size: u32) -> io::Result<ListxattrReply> { 930 Err(io::Error::from_raw_os_error(libc::ENOSYS)) 931 } 932 933 /// Remove an extended attribute. 934 /// 935 /// If this method fails with an `ENOSYS` error, then the kernel will treat that as a permanent 936 /// failure. The kernel will return `EOPNOTSUPP` for all future calls to `removexattr` without 937 /// forwarding them to the file system. removexattr(&self, ctx: Context, inode: Self::Inode, name: &CStr) -> io::Result<()>938 fn removexattr(&self, ctx: Context, inode: Self::Inode, name: &CStr) -> io::Result<()> { 939 Err(io::Error::from_raw_os_error(libc::ENOSYS)) 940 } 941 942 /// Open a directory for reading. 943 /// 944 /// The file system may choose to return a `Handle` to refer to the newly opened directory. The 945 /// kernel will then use this `Handle` for all operations on the content of the directory 946 /// (`readdir`, `readdirplus`, `fsyncdir`, `releasedir`). If the file system does not return a 947 /// `Handle` then the kernel will use the `Inode` for the directory to operate on its contents. 948 /// In this case the file system may wish to enable the `FsOptions::ZERO_MESSAGE_OPENDIR` 949 /// feature if it is supported by the kernel (see below). 950 /// 951 /// The returned `OpenOptions` allow the file system to change the way the opened directory is 952 /// handled by the kernel. See the documentation of `OpenOptions` for more information. 953 /// 954 /// If the `FsOptions::ZERO_MESSAGE_OPENDIR` feature is enabled by both the file system 955 /// implementation and the kernel, then the file system may return an error of `ENOSYS`. This 956 /// will be interpreted by the kernel as success and future calls to `opendir` and `releasedir` 957 /// will be handled by the kernel without being passed on to the file system. opendir( &self, ctx: Context, inode: Self::Inode, flags: u32, ) -> io::Result<(Option<Self::Handle>, OpenOptions)>958 fn opendir( 959 &self, 960 ctx: Context, 961 inode: Self::Inode, 962 flags: u32, 963 ) -> io::Result<(Option<Self::Handle>, OpenOptions)> { 964 // Matches the behavior of libfuse. 965 Ok((None, OpenOptions::empty())) 966 } 967 968 /// Read a directory. 969 /// 970 /// `handle` is the `Handle` returned by the file system from the `opendir` method, if any. If 971 /// the file system did not return a `Handle` from `opendir` then the contents of `handle` are 972 /// undefined. 973 /// 974 /// `size` indicates the maximum number of bytes that should be returned by this method. 975 /// 976 /// If `offset` is non-zero then it corresponds to one of the `offset` values from a `DirEntry` 977 /// that was previously returned by a call to `readdir` for the same handle. In this case the 978 /// file system should skip over the entries before the position defined by the `offset` value. 979 /// If entries were added or removed while the `Handle` is open then the file system may still 980 /// include removed entries or skip newly created entries. However, adding or removing entries 981 /// should never cause the file system to skip over unrelated entries or include an entry more 982 /// than once. This means that `offset` cannot be a simple index and must include sufficient 983 /// information to uniquely determine the next entry in the list even when the set of entries is 984 /// being changed. 985 /// 986 /// The file system may return entries for the current directory (".") and parent directory 987 /// ("..") but is not required to do so. If the file system does not return these entries, then 988 /// they are implicitly added by the kernel. 989 /// 990 /// The lookup count for `Inode`s associated with the returned directory entries is **NOT** 991 /// affected by this method. 992 /// readdir( &self, ctx: Context, inode: Self::Inode, handle: Self::Handle, size: u32, offset: u64, ) -> io::Result<Self::DirIter>993 fn readdir( 994 &self, 995 ctx: Context, 996 inode: Self::Inode, 997 handle: Self::Handle, 998 size: u32, 999 offset: u64, 1000 ) -> io::Result<Self::DirIter> { 1001 Err(io::Error::from_raw_os_error(libc::ENOSYS)) 1002 } 1003 1004 /// Synchronize the contents of a directory. 1005 /// 1006 /// File systems must ensure that the directory contents have been flushed to disk before 1007 /// returning from this method. If `datasync` is true then only the directory data (but not the 1008 /// metadata) needs to be flushed. 1009 /// 1010 /// `handle` is the `Handle` returned by the file system from the `opendir` method, if any. If 1011 /// the file system did not return a `Handle` from `opendir` then the contents of 1012 /// `handle` are undefined. 1013 /// 1014 /// If this method returns an `ENOSYS` error then the kernel will treat it as success and all 1015 /// subsequent calls to `fsyncdir` will be handled by the kernel without being forwarded to the 1016 /// file system. fsyncdir( &self, ctx: Context, inode: Self::Inode, datasync: bool, handle: Self::Handle, ) -> io::Result<()>1017 fn fsyncdir( 1018 &self, 1019 ctx: Context, 1020 inode: Self::Inode, 1021 datasync: bool, 1022 handle: Self::Handle, 1023 ) -> io::Result<()> { 1024 Err(io::Error::from_raw_os_error(libc::ENOSYS)) 1025 } 1026 1027 /// Release an open directory. 1028 /// 1029 /// For every `opendir` call there will be exactly one `releasedir` call (unless the file system 1030 /// is force-unmounted). 1031 /// 1032 /// `handle` is the `Handle` returned by the file system from the `opendir` method, if any. If 1033 /// the file system did not return a `Handle` from `opendir` then the contents of `handle` are 1034 /// undefined. 1035 /// 1036 /// `flags` contains used the flags used to open the directory in `opendir`. releasedir( &self, ctx: Context, inode: Self::Inode, flags: u32, handle: Self::Handle, ) -> io::Result<()>1037 fn releasedir( 1038 &self, 1039 ctx: Context, 1040 inode: Self::Inode, 1041 flags: u32, 1042 handle: Self::Handle, 1043 ) -> io::Result<()> { 1044 Err(io::Error::from_raw_os_error(libc::ENOSYS)) 1045 } 1046 1047 /// Check file access permissions. 1048 /// 1049 /// This method is called when a userspace process in the client makes an `access()` or 1050 /// `chdir()` system call. If the file system was mounted with the `-o default_permissions` 1051 /// mount option, then the kernel will perform these checks itself and this method will not be 1052 /// called. 1053 /// 1054 /// If this method returns an `ENOSYS` error, then the kernel will treat it as a permanent 1055 /// success: all future calls to `access` will return success without being forwarded to the 1056 /// file system. access(&self, ctx: Context, inode: Self::Inode, mask: u32) -> io::Result<()>1057 fn access(&self, ctx: Context, inode: Self::Inode, mask: u32) -> io::Result<()> { 1058 Err(io::Error::from_raw_os_error(libc::ENOSYS)) 1059 } 1060 1061 /// Perform an ioctl on a file or directory. 1062 /// 1063 /// `handle` is the `Handle` returned by the file system from the `open` or `opendir` methods, 1064 /// if any. If the file system did not return a `Handle` from then the contents of `handle` are 1065 /// undefined. 1066 /// 1067 /// If `flags` contains `IoctlFlags::UNRESTRICTED` then the file system may retry the ioctl 1068 /// after informing the kernel about the input and output areas. If `flags` does not contain 1069 /// `IoctlFlags::UNRESTRICTED` then the kernel will prepare the input and output areas according 1070 /// to the encoding in the ioctl command. In that case the ioctl cannot be retried. 1071 /// 1072 /// `cmd` is the ioctl request made by the calling process, truncated to 32 bits. 1073 /// 1074 /// `arg` is the argument provided by the calling process. 1075 /// 1076 /// `in_size` is the length of the additional data that accompanies the request. The file system 1077 /// may fetch this data from `reader`. 1078 /// 1079 /// `out_size` is the length of the output area prepared by the kernel to hold the response to 1080 /// the ioctl. ioctl<R: io::Read>( &self, ctx: Context, inode: Self::Inode, handle: Self::Handle, flags: IoctlFlags, cmd: u32, arg: u64, in_size: u32, out_size: u32, reader: R, ) -> io::Result<IoctlReply>1081 fn ioctl<R: io::Read>( 1082 &self, 1083 ctx: Context, 1084 inode: Self::Inode, 1085 handle: Self::Handle, 1086 flags: IoctlFlags, 1087 cmd: u32, 1088 arg: u64, 1089 in_size: u32, 1090 out_size: u32, 1091 reader: R, 1092 ) -> io::Result<IoctlReply> { 1093 Err(io::Error::from_raw_os_error(libc::ENOSYS)) 1094 } 1095 1096 /// TODO: support this getlk(&self) -> io::Result<()>1097 fn getlk(&self) -> io::Result<()> { 1098 Err(io::Error::from_raw_os_error(libc::ENOSYS)) 1099 } 1100 1101 /// TODO: support this setlk(&self) -> io::Result<()>1102 fn setlk(&self) -> io::Result<()> { 1103 Err(io::Error::from_raw_os_error(libc::ENOSYS)) 1104 } 1105 1106 /// TODO: support this setlkw(&self) -> io::Result<()>1107 fn setlkw(&self) -> io::Result<()> { 1108 Err(io::Error::from_raw_os_error(libc::ENOSYS)) 1109 } 1110 1111 /// TODO: support this bmap(&self) -> io::Result<()>1112 fn bmap(&self) -> io::Result<()> { 1113 Err(io::Error::from_raw_os_error(libc::ENOSYS)) 1114 } 1115 1116 /// TODO: support this poll(&self) -> io::Result<()>1117 fn poll(&self) -> io::Result<()> { 1118 Err(io::Error::from_raw_os_error(libc::ENOSYS)) 1119 } 1120 1121 /// TODO: support this notify_reply(&self) -> io::Result<()>1122 fn notify_reply(&self) -> io::Result<()> { 1123 Err(io::Error::from_raw_os_error(libc::ENOSYS)) 1124 } 1125 1126 /// TODO: support this lseek(&self) -> io::Result<()>1127 fn lseek(&self) -> io::Result<()> { 1128 Err(io::Error::from_raw_os_error(libc::ENOSYS)) 1129 } 1130 1131 /// Copy a range of data from one file to another 1132 /// 1133 /// Performs an optimized copy between two file descriptors without the additional cost of 1134 /// transferring data through the kernel module to user space (glibc) and then back into 1135 /// the file system again. 1136 /// 1137 /// In case this method is not implemented, glibc falls back to reading data from the source and 1138 /// writing to the destination. 1139 /// 1140 /// If this method fails with an `ENOSYS` error, then the kernel will treat that as a permanent 1141 /// failure. The kernel will return `EOPNOTSUPP` for all future calls to `copy_file_range` 1142 /// without forwarding them to the file system. 1143 /// 1144 /// All values accepted by the `copy_file_range(2)` system call are valid values for `flags` and 1145 /// must be handled by the file system. copy_file_range( &self, ctx: Context, inode_src: Self::Inode, handle_src: Self::Handle, offset_src: u64, inode_dst: Self::Inode, handle_dst: Self::Handle, offset_dst: u64, length: u64, flags: u64, ) -> io::Result<usize>1146 fn copy_file_range( 1147 &self, 1148 ctx: Context, 1149 inode_src: Self::Inode, 1150 handle_src: Self::Handle, 1151 offset_src: u64, 1152 inode_dst: Self::Inode, 1153 handle_dst: Self::Handle, 1154 offset_dst: u64, 1155 length: u64, 1156 flags: u64, 1157 ) -> io::Result<usize> { 1158 Err(io::Error::from_raw_os_error(libc::ENOSYS)) 1159 } 1160 1161 /// Set up memory mappings. 1162 /// 1163 /// Used to set up file mappings in DAX window. 1164 /// 1165 /// # Arguments 1166 /// 1167 /// * `file_offset` - Offset into the file to start the mapping. 1168 /// * `mem_offset` - Offset in Memory Window. 1169 /// * `size` - Length of mapping required. 1170 /// * `flags` - Bit field of `FUSE_SETUPMAPPING_FLAGS_*`. 1171 /// * `mapper` - Mapper object which performs the mapping. set_up_mapping<M: Mapper>( &self, ctx: Context, inode: Self::Inode, handle: Self::Handle, file_offset: u64, mem_offset: u64, size: usize, flags: u32, mapper: M, ) -> io::Result<()>1172 fn set_up_mapping<M: Mapper>( 1173 &self, 1174 ctx: Context, 1175 inode: Self::Inode, 1176 handle: Self::Handle, 1177 file_offset: u64, 1178 mem_offset: u64, 1179 size: usize, 1180 flags: u32, 1181 mapper: M, 1182 ) -> io::Result<()> { 1183 Err(io::Error::from_raw_os_error(libc::ENOSYS)) 1184 } 1185 1186 /// Remove memory mappings. 1187 /// 1188 /// Used to tear down file mappings in DAX window. This method must be supported when 1189 /// `set_up_mapping` is supported. remove_mapping<M: Mapper>(&self, msgs: &[RemoveMappingOne], mapper: M) -> io::Result<()>1190 fn remove_mapping<M: Mapper>(&self, msgs: &[RemoveMappingOne], mapper: M) -> io::Result<()> { 1191 Err(io::Error::from_raw_os_error(libc::ENOSYS)) 1192 } 1193 } 1194