├── .bazelrc ├── .gitignore ├── BUILD.bazel ├── Cargo.toml ├── LICENSE ├── MODULE.bazel ├── README.asciidoc ├── examples └── helloworld │ ├── BUILD │ ├── Cargo.toml │ └── helloworld.rs ├── fuse-libc ├── BUILD ├── Cargo.toml ├── fuse-libc.rs ├── io │ ├── iovec.rs │ └── socket.rs └── os │ ├── freebsd.rs │ └── linux.rs ├── fuse-linux ├── BUILD ├── Cargo.toml ├── fuse-linux.rs ├── socket.rs └── sys.rs ├── fuse-std ├── BUILD ├── Cargo.toml └── fuse-std.rs ├── fuse-vfs ├── BUILD ├── Cargo.toml └── fuse-vfs.rs ├── fuse ├── BUILD ├── Cargo.toml ├── client.rs ├── client │ ├── BUILD │ └── io.rs ├── cuse.rs ├── entry.rs ├── file_mode.rs ├── fuse.rs ├── internal.rs ├── internal │ ├── BUILD │ ├── bitflags.rs │ ├── compat.rs │ ├── debug.rs │ ├── dirent.rs │ ├── testing │ │ ├── BUILD │ │ ├── fuse_testutil.rs │ │ ├── interop_testutil.rs │ │ └── testing.bzl │ └── timestamp.rs ├── io.rs ├── kernel.rs ├── kernel_traits.rs ├── lock.rs ├── node_attr.rs ├── node_id.rs ├── node_name.rs ├── notify.rs ├── operations.rs ├── operations │ ├── BUILD │ ├── access.rs │ ├── access │ │ ├── BUILD │ │ ├── access_interop_test.rs │ │ └── access_test.rs │ ├── bmap.rs │ ├── bmap │ │ ├── BUILD │ │ └── bmap_interop_test.rs │ ├── copy_file_range.rs │ ├── copy_file_range │ │ ├── BUILD │ │ ├── copy_file_range_interop_test.rs │ │ └── copy_file_range_test.rs │ ├── create.rs │ ├── create │ │ ├── BUILD │ │ ├── create_interop_test.rs │ │ └── create_test.rs │ ├── cuse_init.rs │ ├── cuse_init │ │ ├── BUILD │ │ ├── cuse_init_interop_test.rs │ │ └── cuse_init_test.rs │ ├── fallocate.rs │ ├── fallocate │ │ ├── BUILD │ │ ├── fallocate_interop_test.rs │ │ └── fallocate_test.rs │ ├── flush.rs │ ├── flush │ │ ├── BUILD │ │ ├── flush_interop_test.rs │ │ └── flush_test.rs │ ├── forget.rs │ ├── forget │ │ ├── BUILD │ │ └── forget_test.rs │ ├── fsync.rs │ ├── fsync │ │ ├── BUILD │ │ ├── fsync_interop_test.rs │ │ └── fsync_test.rs │ ├── fsyncdir.rs │ ├── fsyncdir │ │ ├── BUILD │ │ ├── fsyncdir_interop_test.rs │ │ └── fsyncdir_test.rs │ ├── fuse_init.rs │ ├── fuse_init │ │ ├── BUILD │ │ └── fuse_init_test.rs │ ├── getattr.rs │ ├── getattr │ │ ├── BUILD │ │ └── getattr_test.rs │ ├── getlk.rs │ ├── getlk │ │ ├── BUILD │ │ └── getlk_interop_test.rs │ ├── getxattr.rs │ ├── getxattr │ │ ├── BUILD │ │ ├── getxattr_interop_test.rs │ │ └── getxattr_test.rs │ ├── interrupt.rs │ ├── ioctl.rs │ ├── ioctl │ │ ├── BUILD │ │ ├── ioctl_cuse_interop_test.rs │ │ └── ioctl_fuse_interop_test.rs │ ├── link.rs │ ├── link │ │ ├── BUILD │ │ ├── link_interop_test.rs │ │ └── link_test.rs │ ├── listxattr.rs │ ├── listxattr │ │ ├── BUILD │ │ ├── listxattr_interop_test.rs │ │ └── listxattr_test.rs │ ├── lookup.rs │ ├── lookup │ │ ├── BUILD │ │ └── lookup_test.rs │ ├── lseek.rs │ ├── lseek │ │ ├── BUILD │ │ ├── lseek_interop_test.rs │ │ └── lseek_test.rs │ ├── mkdir.rs │ ├── mkdir │ │ ├── BUILD │ │ └── mkdir_test.rs │ ├── mknod.rs │ ├── mknod │ │ ├── BUILD │ │ └── mknod_test.rs │ ├── open.rs │ ├── open │ │ ├── BUILD │ │ └── open_test.rs │ ├── opendir.rs │ ├── opendir │ │ ├── BUILD │ │ ├── opendir_interop_test.rs │ │ └── opendir_test.rs │ ├── poll.rs │ ├── poll │ │ ├── BUILD │ │ └── poll_interop_test.rs │ ├── read.rs │ ├── read │ │ ├── BUILD │ │ └── read_test.rs │ ├── readdir.rs │ ├── readdir │ │ ├── BUILD │ │ ├── readdir_interop_test.rs │ │ └── readdir_test.rs │ ├── readdirplus.rs │ ├── readlink.rs │ ├── readlink │ │ ├── BUILD │ │ └── readlink_interop_test.rs │ ├── release.rs │ ├── release │ │ ├── BUILD │ │ └── release_test.rs │ ├── releasedir.rs │ ├── releasedir │ │ ├── BUILD │ │ └── releasedir_test.rs │ ├── removexattr.rs │ ├── removexattr │ │ ├── BUILD │ │ ├── removexattr_interop_test.rs │ │ └── removexattr_test.rs │ ├── rename.rs │ ├── rename │ │ ├── BUILD │ │ ├── rename_interop_test.rs │ │ └── rename_test.rs │ ├── rmdir.rs │ ├── rmdir │ │ ├── BUILD │ │ └── rmdir_test.rs │ ├── setattr.rs │ ├── setattr │ │ ├── BUILD │ │ ├── setattr_interop_test.rs │ │ └── setattr_test.rs │ ├── setlk.rs │ ├── setlk │ │ ├── BUILD │ │ └── setlk_interop_test.rs │ ├── setxattr.rs │ ├── setxattr │ │ ├── BUILD │ │ ├── setxattr_interop_test.rs │ │ └── setxattr_test.rs │ ├── statfs.rs │ ├── statfs │ │ ├── BUILD │ │ └── statfs_interop_test.rs │ ├── symlink.rs │ ├── symlink │ │ ├── BUILD │ │ ├── symlink_interop_test.rs │ │ └── symlink_test.rs │ ├── unlink.rs │ ├── unlink │ │ ├── BUILD │ │ └── unlink_test.rs │ ├── write.rs │ └── write │ │ ├── BUILD │ │ └── write_test.rs ├── os.rs ├── os │ ├── BUILD │ ├── freebsd.rs │ ├── linux.rs │ └── linux_test.rs ├── server.rs ├── server │ ├── BUILD │ ├── decode.rs │ └── decode_test.rs └── unix_time.rs ├── rustfmt.toml └── third_party └── modules ├── com_github_jmillikin_rust-freebsd-errno └── 1.0.0 │ ├── MODULE.bazel │ ├── overlay │ └── MODULE.bazel │ ├── patches │ └── rust_edition.patch │ └── source.json ├── com_github_jmillikin_rust-linux-errno └── 1.0.1 │ ├── MODULE.bazel │ ├── overlay │ └── MODULE.bazel │ ├── patches │ └── rust_edition.patch │ └── source.json ├── com_github_jmillikin_rust-linux-syscall └── 1.0.0 │ ├── MODULE.bazel │ ├── overlay │ └── MODULE.bazel │ ├── patches │ └── rust_edition.patch │ └── source.json ├── com_github_jmillikin_rust-posix-errno └── 1.0.1 │ ├── MODULE.bazel │ ├── overlay │ └── MODULE.bazel │ ├── patches │ └── rust_edition.patch │ └── source.json └── com_github_rust-lang_libc └── 0.2.149 ├── MODULE.bazel ├── overlay ├── BUILD.bazel └── MODULE.bazel └── source.json /.bazelrc: -------------------------------------------------------------------------------- 1 | common --registry=https://bcr.bazel.build 2 | common --registry=file:///%workspace%/third_party 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /bazel-* 2 | /target 3 | /user.bazelrc 4 | -------------------------------------------------------------------------------- /BUILD.bazel: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jmillikin/rust-fuse/88740a5ec642ab680b4b188b4c727d598554b206/BUILD.bazel -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | members = [ 3 | "fuse", 4 | "fuse-libc", 5 | "fuse-linux", 6 | "examples/helloworld", 7 | ] 8 | -------------------------------------------------------------------------------- /MODULE.bazel: -------------------------------------------------------------------------------- 1 | module( 2 | name = "com_github_jmillikin_rust-fuse", 3 | ) 4 | 5 | bazel_dep(name = "platforms", version = "0.0.10") 6 | bazel_dep(name = "rules_rust", version = "0.52.2") 7 | 8 | bazel_dep( 9 | name = "com_github_jmillikin_rust-freebsd-errno", 10 | version = "1.0.0", 11 | ) 12 | 13 | bazel_dep( 14 | name = "com_github_jmillikin_rust-linux-errno", 15 | version = "1.0.1", 16 | ) 17 | 18 | bazel_dep( 19 | name = "com_github_jmillikin_rust-linux-syscall", 20 | version = "1.0.0", 21 | ) 22 | 23 | bazel_dep( 24 | name = "com_github_rust-lang_libc", 25 | version = "0.2.149", 26 | ) 27 | 28 | rust = use_extension("@rules_rust//rust:extensions.bzl", "rust") 29 | rust.toolchain( 30 | versions = ["1.81.0"], 31 | ) 32 | -------------------------------------------------------------------------------- /README.asciidoc: -------------------------------------------------------------------------------- 1 | = rust-fuse 2 | :url-fuse: https://en.wikipedia.org/wiki/Filesystem_in_Userspace 3 | :url-docs: https://jmillikin.github.io/rust-fuse/ 4 | 5 | image:https://img.shields.io/badge/License-Apache%202.0-blue.svg[link="http://www.apache.org/licenses/LICENSE-2.0"] 6 | image:https://img.shields.io/badge/docs-github.io-green.svg[link={url-docs}] 7 | 8 | The `fuse` crate is an implementation of the {url-fuse}[FUSE] protocol, which 9 | allows filesystems and character devices to be backed by a userspace process. 10 | It currently provides enough coverage to implement basic FUSE and CUSE servers. 11 | 12 | == Stability 13 | 14 | This is a pre-v0.1 library. Many of FUSE's more advanced capabilities do not 15 | work yet, and test coverage is incomplete. Please file issues if there is 16 | functionality you'd like to see implemented. 17 | 18 | [%header, cols="2,5"] 19 | |=== 20 | |Feature 21 | |Tracking issue 22 | 23 | |FreeBSD support 24 | |image:https://img.shields.io/github/issues/detail/state/jmillikin/rust-fuse/5[link="https://github.com/jmillikin/rust-fuse/issues/5"] 25 | 26 | |High-level API 27 | |image:https://img.shields.io/github/issues/detail/state/jmillikin/rust-fuse/10[link="https://github.com/jmillikin/rust-fuse/issues/10"] 28 | 29 | |Interrupts 30 | |image:https://img.shields.io/github/issues/detail/state/jmillikin/rust-fuse/5[link="https://github.com/jmillikin/rust-fuse/issues/5"] 31 | 32 | |macOS support 33 | |Not planned due to lack of open-source kernel drivers. 34 | 35 | |Unprivileged mounts 36 | |image:https://img.shields.io/github/issues/detail/state/jmillikin/rust-fuse/6[link="https://github.com/jmillikin/rust-fuse/issues/6"] 37 | |=== 38 | 39 | 40 | ## Contributing 41 | 42 | I am happy to accept contributions in the form of bug reports, pull requests, 43 | or emailed patches. 44 | 45 | == Usage 46 | 47 | Add a dependency in `Cargo.toml`: 48 | 49 | [source,toml] 50 | ---- 51 | [dependencies] 52 | fuse = { git = "https://github.com/jmillikin/rust-fuse" } 53 | ---- 54 | 55 | Implement the `FuseHandlers` trait for your filesystem: 56 | 57 | [source,rust] 58 | ---- 59 | extern crate fuse; 60 | use fuse::server; 61 | use fuse::server::fuse_rpc; 62 | 63 | struct HelloFS {} 64 | impl fuse_rpc::Handlers for HelloFS { 65 | // your filesystem handlers here 66 | } 67 | ---- 68 | 69 | Use `fuse-libc` (requires `libc`) or `fuse-linux` (requires a supported 70 | target architecture) to build and run your filesystem server: 71 | 72 | [source,rust] 73 | ---- 74 | fn mount(target: &OsStr) -> fuse_libc::FuseServerSocket { 75 | let mount_options = fuse::os::linux::MountOptions::new(); 76 | fuse_libc::os::linux::mount(&target_cstr, mount_options).unwrap() 77 | } 78 | 79 | fn main() { 80 | let handlers = HelloWorldFS {}; 81 | let mount_target = std::env::args_os().nth(1).unwrap(); 82 | let dev_fuse = mount(&mount_target); 83 | let conn = server::FuseServer::new().connect(dev_fuse).unwrap(); 84 | fuse_rpc::serve(&conn, &handlers); 85 | } 86 | ---- 87 | 88 | Please see {url-docs}[the documentation] for advanced options. 89 | 90 | === Feature `std` 91 | 92 | It is possible to run a minimal single-threaded FUSE server in a `no_std` 93 | binary. 94 | 95 | [source,toml] 96 | ---- 97 | [dependencies.fuse] 98 | default-features = false 99 | ---- 100 | 101 | Note that some functionality is not available in `no_std` mode. Please see 102 | {url-docs}[the documentation] for details on which parts of the API depend 103 | on `std`. 104 | -------------------------------------------------------------------------------- /examples/helloworld/BUILD: -------------------------------------------------------------------------------- 1 | load("@rules_rust//rust:defs.bzl", "rust_binary") 2 | 3 | rust_binary( 4 | name = "helloworld", 5 | srcs = ["helloworld.rs"], 6 | edition = "2021", 7 | deps = [ 8 | "//fuse", 9 | "//fuse-libc", 10 | "//fuse-std", 11 | "@com_github_rust-lang_libc//:libc", 12 | ], 13 | ) 14 | -------------------------------------------------------------------------------- /examples/helloworld/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "helloworld" 3 | version = "0.0.1" 4 | authors = ["John Millikin "] 5 | license = "Apache-2.0" 6 | edition = "2021" 7 | 8 | [[bin]] 9 | name = "helloworld" 10 | path = "helloworld.rs" 11 | 12 | [dependencies] 13 | fuse = { version = "0.0.1", path = "../../fuse" } 14 | fuse-libc = { version = "0.0.1", path = "../../fuse-libc" } 15 | libc = "0.2" 16 | -------------------------------------------------------------------------------- /fuse-libc/BUILD: -------------------------------------------------------------------------------- 1 | load( 2 | "@rules_rust//rust:defs.bzl", 3 | "rust_clippy", 4 | "rust_doc", 5 | "rust_doc_test", 6 | "rust_library", 7 | ) 8 | 9 | rust_library( 10 | name = "fuse-libc", 11 | srcs = glob([ 12 | "fuse-libc.rs", 13 | "io/*.rs", 14 | "os/*.rs", 15 | ]), 16 | edition = "2021", 17 | visibility = ["//visibility:public"], 18 | deps = [ 19 | "//fuse", 20 | "@com_github_rust-lang_libc//:libc", 21 | ], 22 | ) 23 | 24 | rust_clippy( 25 | name = "fuse-libc_clippy", 26 | deps = [":fuse-libc"], 27 | ) 28 | 29 | rust_doc( 30 | name = "fuse-libc_doc", 31 | crate = ":fuse-libc", 32 | ) 33 | 34 | rust_doc_test( 35 | name = "fuse-libc_doc_test", 36 | crate = ":fuse-libc", 37 | ) 38 | -------------------------------------------------------------------------------- /fuse-libc/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "fuse-libc" 3 | version = "0.0.1" 4 | authors = ["John Millikin "] 5 | license = "Apache-2.0" 6 | edition = "2021" 7 | 8 | [lib] 9 | name = "fuse_libc" 10 | path = "fuse-libc.rs" 11 | 12 | [dependencies] 13 | fuse = { version = "0.0.1", path = "../fuse" } 14 | libc = { version = "0.2.*" } 15 | -------------------------------------------------------------------------------- /fuse-libc/fuse-libc.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2021 John Millikin and the rust-fuse contributors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // SPDX-License-Identifier: Apache-2.0 16 | 17 | #![no_std] 18 | 19 | #![warn( 20 | // API hygiene 21 | clippy::exhaustive_enums, 22 | clippy::exhaustive_structs, 23 | clippy::must_use_candidate, 24 | 25 | // Panic hygiene 26 | clippy::expect_used, 27 | clippy::todo, 28 | clippy::unimplemented, 29 | clippy::unwrap_used, 30 | 31 | // no_std hygiene 32 | clippy::std_instead_of_core, 33 | 34 | // Explicit casts 35 | clippy::fn_to_numeric_cast_any, 36 | clippy::ptr_as_ptr, 37 | 38 | // Optimization 39 | clippy::trivially_copy_pass_by_ref, 40 | 41 | // Unused symbols 42 | clippy::let_underscore_must_use, 43 | clippy::no_effect_underscore_binding, 44 | clippy::used_underscore_binding, 45 | 46 | // Leftover debugging 47 | clippy::print_stderr, 48 | clippy::print_stdout, 49 | )] 50 | 51 | use core::ffi; 52 | 53 | mod io { 54 | pub(crate) mod iovec; 55 | pub(crate) mod socket; 56 | } 57 | 58 | pub use crate::io::socket::{ 59 | FuseServerSocket, 60 | LibcError, 61 | }; 62 | 63 | #[cfg(any(doc, not(target_os = "freebsd")))] 64 | pub use crate::io::socket::CuseServerSocket; 65 | 66 | pub mod os { 67 | #[cfg(any(doc, target_os = "freebsd"))] 68 | pub mod freebsd; 69 | 70 | #[cfg(any(doc, target_os = "linux"))] 71 | pub mod linux; 72 | } 73 | 74 | #[cfg(not(target_os = "freebsd"))] 75 | const DEV_CUSE: &ffi::CStr = c"/dev/cuse"; 76 | 77 | const DEV_FUSE: &ffi::CStr = c"/dev/fuse"; 78 | -------------------------------------------------------------------------------- /fuse-libc/io/iovec.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2021 John Millikin and the rust-fuse contributors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // SPDX-License-Identifier: Apache-2.0 16 | 17 | use core::marker::PhantomData; 18 | 19 | #[repr(C)] 20 | pub(crate) struct IoVec<'a> { 21 | iov_base: *const core::ffi::c_void, 22 | iov_len: usize, 23 | _phantom: PhantomData<&'a [u8]>, 24 | } 25 | 26 | impl IoVec<'static> { 27 | #[allow(dead_code)] 28 | pub(crate) fn null() -> Self { 29 | Self { 30 | iov_base: core::ptr::null(), 31 | iov_len: 0, 32 | _phantom: PhantomData, 33 | } 34 | } 35 | 36 | #[allow(dead_code)] 37 | pub(crate) fn global(buf: &'static [u8]) -> Self { 38 | IoVec { 39 | iov_base: buf.as_ptr().cast::(), 40 | iov_len: buf.len(), 41 | _phantom: PhantomData, 42 | } 43 | } 44 | } 45 | 46 | impl<'a> IoVec<'a> { 47 | pub(crate) fn borrow(buf: &'a [u8]) -> Self { 48 | IoVec { 49 | iov_base: buf.as_ptr().cast::(), 50 | iov_len: buf.len(), 51 | _phantom: PhantomData, 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /fuse-libc/os/freebsd.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2021 John Millikin and the rust-fuse contributors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // SPDX-License-Identifier: Apache-2.0 16 | 17 | use core::ffi; 18 | 19 | #[cfg(target_os = "freebsd")] 20 | use fuse::os::freebsd as fuse_os_freebsd; 21 | 22 | use crate::io::iovec::IoVec; 23 | use crate::io::socket::{FuseServerSocket, LibcError}; 24 | 25 | #[cfg(all(doc, not(target_os = "freebsd")))] 26 | mod fuse_os_freebsd { 27 | #[derive(Copy, Clone)] 28 | pub struct MountOptions<'a> { _p: &'a () } 29 | } 30 | 31 | const MNT_NOSUID: i32 = 0x08; 32 | 33 | const DEFAULT_FLAGS: i32 = MNT_NOSUID; 34 | 35 | #[derive(Copy, Clone)] 36 | pub struct MountOptions<'a> { 37 | opts: fuse_os_freebsd::MountOptions<'a>, 38 | flags: i32, 39 | } 40 | 41 | impl<'a> MountOptions<'a> { 42 | #[must_use] 43 | pub fn flags(&self) -> i32 { 44 | self.flags 45 | } 46 | 47 | pub fn set_flags(&mut self, flags: i32) { 48 | self.flags = flags; 49 | } 50 | } 51 | 52 | impl<'a> From> for MountOptions<'a> { 53 | fn from(opts: fuse_os_freebsd::MountOptions<'a>) -> Self { 54 | Self { 55 | opts, 56 | flags: DEFAULT_FLAGS, 57 | } 58 | } 59 | } 60 | 61 | pub fn mount<'a>( 62 | target: &ffi::CStr, 63 | options: impl Into>, 64 | ) -> Result { 65 | let options = options.into(); 66 | let opts = options.opts; 67 | let socket = FuseServerSocket::new()?; 68 | 69 | let mut fd_buf = [0u8; 32]; 70 | fmt_raw_fd(&mut fd_buf, socket.fuse_device_fd()); 71 | let mut iovecs = [ 72 | // fstype 73 | IoVec::global(b"fstype\0"), 74 | IoVec::global(b"fusefs\0"), 75 | 76 | // from 77 | IoVec::global(b"from\0"), 78 | IoVec::global(b"/dev/fuse\0"), 79 | 80 | // fspath 81 | IoVec::global(b"fspath\0"), 82 | IoVec::borrow(target.to_bytes_with_nul()), 83 | 84 | // fd 85 | IoVec::global(b"fd\0"), 86 | IoVec::borrow(&fd_buf), 87 | 88 | // placeholder: default_permissions 89 | IoVec::null(), 90 | IoVec::null(), 91 | 92 | // placeholder: subtype= 93 | IoVec::null(), 94 | IoVec::null(), 95 | ]; 96 | 97 | let mut iovecs_len: usize = 8; 98 | 99 | if opts.default_permissions() { 100 | iovecs[iovecs_len] = IoVec::global(b"default_permissions\0"); 101 | iovecs[iovecs_len + 1] = IoVec::global(b"\0"); 102 | iovecs_len += 2; 103 | } 104 | 105 | if let Some(subtype) = opts.subtype() { 106 | let subtype_bytes = subtype.as_cstr().to_bytes_with_nul(); 107 | iovecs[iovecs_len] = IoVec::global(b"subtype=\0"); 108 | iovecs[iovecs_len + 1] = IoVec::borrow(subtype_bytes); 109 | iovecs_len += 2; 110 | } 111 | 112 | let nmount_rc = unsafe { 113 | libc::nmount( 114 | iovecs.as_mut_ptr().cast::(), 115 | iovecs_len as libc::c_uint, 116 | options.flags, 117 | ) 118 | }; 119 | if nmount_rc == -1 { 120 | return Err(LibcError::last_os_error()); 121 | } 122 | 123 | Ok(socket) 124 | } 125 | 126 | fn fmt_raw_fd(buf: &mut [u8; 32], fd: u32) { 127 | let buf_ptr = buf.as_mut_ptr().cast::(); 128 | let format_ptr = b"%u\0".as_ptr().cast::(); 129 | unsafe { 130 | libc::snprintf(buf_ptr, 32, format_ptr, fd); 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /fuse-linux/BUILD: -------------------------------------------------------------------------------- 1 | load( 2 | "@rules_rust//rust:defs.bzl", 3 | "rust_clippy", 4 | "rust_doc", 5 | "rust_doc_test", 6 | "rust_library", 7 | ) 8 | 9 | rust_library( 10 | name = "fuse-linux", 11 | srcs = glob(["*.rs"]), 12 | edition = "2021", 13 | visibility = ["//visibility:public"], 14 | deps = [ 15 | "//fuse", 16 | "@com_github_jmillikin_rust-linux-errno//linux-errno", 17 | "@com_github_jmillikin_rust-linux-syscall//linux-syscall", 18 | ], 19 | ) 20 | 21 | rust_clippy( 22 | name = "fuse-linux_clippy", 23 | deps = [":fuse-linux"], 24 | ) 25 | 26 | rust_doc( 27 | name = "fuse-linux_doc", 28 | crate = ":fuse-linux", 29 | ) 30 | 31 | rust_doc_test( 32 | name = "fuse-linux_doc_test", 33 | crate = ":fuse-linux", 34 | ) 35 | -------------------------------------------------------------------------------- /fuse-linux/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "fuse-linux" 3 | version = "0.0.1" 4 | authors = ["John Millikin "] 5 | license = "Apache-2.0" 6 | edition = "2021" 7 | 8 | [lib] 9 | name = "fuse_linux" 10 | path = "fuse-linux.rs" 11 | 12 | [dependencies] 13 | fuse = { version = "0.0.1", path = "../fuse" } 14 | linux-errno = { version = "1.0" } 15 | linux-syscall = { version = "1.0" } 16 | -------------------------------------------------------------------------------- /fuse-std/BUILD: -------------------------------------------------------------------------------- 1 | load( 2 | "@rules_rust//rust:defs.bzl", 3 | "rust_clippy", 4 | "rust_doc", 5 | "rust_doc_test", 6 | "rust_library", 7 | ) 8 | 9 | rust_library( 10 | name = "fuse-std", 11 | srcs = ["fuse-std.rs"], 12 | edition = "2021", 13 | visibility = ["//visibility:public"], 14 | deps = ["//fuse"], 15 | ) 16 | 17 | rust_clippy( 18 | name = "fuse-std_clippy", 19 | deps = [":fuse-std"], 20 | ) 21 | 22 | rust_doc( 23 | name = "fuse-std_doc", 24 | crate = ":fuse-std", 25 | ) 26 | 27 | rust_doc_test( 28 | name = "fuse-std_doc_test", 29 | crate = ":fuse-std", 30 | ) 31 | -------------------------------------------------------------------------------- /fuse-std/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "fuse-std" 3 | version = "0.0.1" 4 | authors = ["John Millikin "] 5 | license = "Apache-2.0" 6 | edition = "2021" 7 | 8 | [lib] 9 | name = "fuse_std" 10 | path = "fuse-std.rs" 11 | 12 | [dependencies] 13 | fuse = { version = "0.0.1", path = "../fuse" } 14 | 15 | -------------------------------------------------------------------------------- /fuse-vfs/BUILD: -------------------------------------------------------------------------------- 1 | load( 2 | "@rules_rust//rust:defs.bzl", 3 | "rust_clippy", 4 | "rust_doc", 5 | "rust_doc_test", 6 | "rust_library", 7 | ) 8 | 9 | rust_library( 10 | name = "fuse-vfs", 11 | srcs = ["fuse-vfs.rs"], 12 | edition = "2021", 13 | visibility = ["//visibility:public"], 14 | deps = ["//fuse"], 15 | ) 16 | 17 | rust_clippy( 18 | name = "fuse-vfs_clippy", 19 | deps = [":fuse-vfs"], 20 | ) 21 | 22 | rust_doc( 23 | name = "fuse-vfs_doc", 24 | crate = ":fuse-vfs", 25 | ) 26 | 27 | rust_doc_test( 28 | name = "fuse-vfs_doc_test", 29 | size = "small", 30 | crate = ":fuse-vfs", 31 | ) 32 | -------------------------------------------------------------------------------- /fuse-vfs/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "fuse-vfs" 3 | version = "0.0.1" 4 | authors = ["John Millikin "] 5 | license = "Apache-2.0" 6 | edition = "2021" 7 | 8 | [lib] 9 | name = "fuse_vfs" 10 | path = "fuse-vfs.rs" 11 | 12 | [dependencies] 13 | fuse = { version = "0.0.1", path = "../fuse" } 14 | -------------------------------------------------------------------------------- /fuse/BUILD: -------------------------------------------------------------------------------- 1 | load( 2 | "@rules_rust//rust:defs.bzl", 3 | "rust_clippy", 4 | "rust_doc", 5 | "rust_doc_test", 6 | "rust_library", 7 | ) 8 | 9 | rust_library( 10 | name = "fuse", 11 | srcs = glob(["*.rs"]) + [ 12 | "//fuse/client:srcs", 13 | "//fuse/internal:srcs", 14 | "//fuse/operations:srcs", 15 | "//fuse/os:srcs", 16 | "//fuse/server:srcs", 17 | ], 18 | edition = "2021", 19 | visibility = ["//visibility:public"], 20 | deps = select({ 21 | "@platforms//os:freebsd": [ 22 | "@com_github_jmillikin_rust-freebsd-errno//freebsd-errno", 23 | ], 24 | "@platforms//os:linux": [ 25 | "@com_github_jmillikin_rust-linux-errno//linux-errno", 26 | ], 27 | "//conditions:default": [], 28 | }), 29 | ) 30 | 31 | rust_clippy( 32 | name = "fuse_clippy", 33 | deps = [":fuse"], 34 | ) 35 | 36 | rust_doc( 37 | name = "fuse_doc", 38 | crate = ":fuse", 39 | ) 40 | 41 | rust_doc_test( 42 | name = "fuse_doc_test", 43 | crate = ":fuse", 44 | ) 45 | -------------------------------------------------------------------------------- /fuse/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "fuse" 3 | version = "0.0.1" 4 | authors = ["John Millikin "] 5 | license = "Apache-2.0" 6 | edition = "2021" 7 | 8 | [lib] 9 | name = "fuse" 10 | path = "fuse.rs" 11 | 12 | [target.'cfg(target_os = "freebsd")'.dependencies] 13 | freebsd-errno = { version = "1.0" } 14 | 15 | [target.'cfg(target_os = "linux")'.dependencies] 16 | linux-errno = { version = "1.0" } 17 | -------------------------------------------------------------------------------- /fuse/client.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2021 John Millikin and the rust-fuse contributors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // SPDX-License-Identifier: Apache-2.0 16 | 17 | //! CUSE and FUSE clients. 18 | 19 | pub mod io; 20 | 21 | // ClientError {{{ 22 | 23 | /// Errors that may be encountered by a CUSE or FUSE client. 24 | #[non_exhaustive] 25 | #[derive(Copy, Clone, Debug, Eq, PartialEq)] 26 | pub enum ClientError { 27 | /// An invalid response was received from the server. 28 | ResponseError(ResponseError), 29 | 30 | /// The socket encountered an I/O error when receiving a response. 31 | RecvError(IoError), 32 | 33 | /// The socket encountered an I/O error when sending a request. 34 | SendError(IoError), 35 | } 36 | 37 | impl From for ClientError { 38 | fn from(err: ResponseError) -> Self { 39 | Self::ResponseError(err) 40 | } 41 | } 42 | 43 | impl From> for ClientError { 44 | fn from(err: io::RecvError) -> Self { 45 | Self::RecvError(match err { 46 | io::RecvError::Other(io_err) => io_err, 47 | }) 48 | } 49 | } 50 | 51 | impl From> for ClientError { 52 | fn from(err: io::SendError) -> Self { 53 | Self::SendError(match err { 54 | io::SendError::Other(io_err) => io_err, 55 | }) 56 | } 57 | } 58 | 59 | // }}} 60 | 61 | // ResponseError {{{ 62 | 63 | /// Errors describing why a response is invalid. 64 | #[non_exhaustive] 65 | #[derive(Copy, Clone, Debug, Eq, PartialEq)] 66 | pub enum ResponseError { 67 | } 68 | 69 | // }}} 70 | -------------------------------------------------------------------------------- /fuse/client/BUILD: -------------------------------------------------------------------------------- 1 | filegroup( 2 | name = "srcs", 3 | srcs = glob(["*.rs"]), 4 | visibility = ["//fuse:__subpackages__"], 5 | ) 6 | -------------------------------------------------------------------------------- /fuse/client/io.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2021 John Millikin and the rust-fuse contributors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // SPDX-License-Identifier: Apache-2.0 16 | 17 | //! Client-specific I/O types. 18 | 19 | /// Errors that may be encountered when receiving a response. 20 | #[non_exhaustive] 21 | #[derive(Copy, Clone, Debug, Eq, PartialEq)] 22 | pub enum RecvError { 23 | /// The socket encountered an error not otherwise specified. 24 | Other(IoError), 25 | } 26 | 27 | /// Errors that may be encountered when sending a request. 28 | #[non_exhaustive] 29 | #[derive(Copy, Clone, Debug, Eq, PartialEq)] 30 | pub enum SendError { 31 | /// The socket encountered an error not otherwise specified. 32 | Other(IoError), 33 | } 34 | -------------------------------------------------------------------------------- /fuse/internal.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 John Millikin and the rust-fuse contributors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // SPDX-License-Identifier: Apache-2.0 16 | 17 | #[macro_use] 18 | mod bitflags; 19 | 20 | pub(crate) mod compat; 21 | pub(crate) mod debug; 22 | pub(crate) mod dirent; 23 | 24 | pub(crate) mod timestamp; 25 | 26 | macro_rules! new { 27 | ($t:ty { $( $field:ident : $value:expr , )+ }) => {{ 28 | let mut value = <$t>::new(); 29 | $( 30 | value.$field = $value; 31 | )+ 32 | value 33 | }} 34 | } 35 | 36 | macro_rules! try_from_cuse_request { 37 | ($t:ty, |$request:ident| $try_from:tt) => { 38 | impl<'a> TryFrom> for $t { 39 | type Error = crate::server::RequestError; 40 | 41 | fn try_from( 42 | $request: crate::server::CuseRequest<'a>, 43 | ) -> Result { 44 | $try_from 45 | } 46 | } 47 | } 48 | } 49 | 50 | macro_rules! try_from_fuse_request { 51 | ($t:ty, |$request:ident| $try_from:tt) => { 52 | impl<'a> TryFrom> for $t { 53 | type Error = crate::server::RequestError; 54 | 55 | fn try_from( 56 | $request: crate::server::FuseRequest<'a>, 57 | ) -> Result { 58 | $try_from 59 | } 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /fuse/internal/BUILD: -------------------------------------------------------------------------------- 1 | load("@rules_rust//rust:defs.bzl", "rust_library") 2 | 3 | filegroup( 4 | name = "srcs", 5 | srcs = [ 6 | "bitflags.rs", 7 | "compat.rs", 8 | "debug.rs", 9 | "dirent.rs", 10 | "timestamp.rs", 11 | ], 12 | visibility = ["//fuse:__subpackages__"], 13 | ) 14 | -------------------------------------------------------------------------------- /fuse/internal/debug.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 John Millikin and the rust-fuse contributors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // SPDX-License-Identifier: Apache-2.0 16 | 17 | use core::ascii; 18 | use core::fmt; 19 | 20 | #[inline] 21 | #[must_use] 22 | pub(crate) fn hex_u32(value: u32) -> impl fmt::Debug { 23 | DebugHexU32(value) 24 | } 25 | 26 | struct DebugHexU32(u32); 27 | 28 | impl fmt::Debug for DebugHexU32 { 29 | #[inline] 30 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { 31 | // 8 hex digits + 2 for leading "0x". 32 | write!(fmt, "{:#010X}", self.0) 33 | } 34 | } 35 | 36 | #[inline] 37 | #[must_use] 38 | pub(crate) fn hex_u64(value: u64) -> impl fmt::Debug { 39 | DebugHexU64(value) 40 | } 41 | 42 | struct DebugHexU64(u64); 43 | 44 | impl fmt::Debug for DebugHexU64 { 45 | #[inline] 46 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { 47 | // 16 hex digits + 2 for leading "0x". 48 | write!(fmt, "{:#018X}", self.0) 49 | } 50 | } 51 | 52 | #[inline] 53 | #[must_use] 54 | pub(crate) fn bytes<'a>(value: &'a [u8]) -> impl fmt::Debug + 'a { 55 | DebugBytesAsString(value) 56 | } 57 | 58 | struct DebugBytesAsString<'a>(&'a [u8]); 59 | 60 | impl fmt::Debug for DebugBytesAsString<'_> { 61 | #[inline] 62 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { 63 | write!(fmt, "\"")?; 64 | for byte in self.0.iter().flat_map(|&b| ascii::escape_default(b)) { 65 | fmt::Write::write_char(fmt, byte as char)?; 66 | } 67 | write!(fmt, "\"") 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /fuse/internal/dirent.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2022 John Millikin and the rust-fuse contributors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // SPDX-License-Identifier: Apache-2.0 16 | 17 | use core::mem; 18 | use core::ptr; 19 | use core::slice; 20 | 21 | use crate::kernel; 22 | 23 | pub(crate) trait Dirent: Sized { 24 | fn namelen(&self) -> u32; 25 | } 26 | 27 | impl Dirent for kernel::fuse_dirent { 28 | #[inline] 29 | fn namelen(&self) -> u32 { 30 | self.namelen 31 | } 32 | } 33 | 34 | impl Dirent for kernel::fuse_direntplus { 35 | #[inline] 36 | fn namelen(&self) -> u32 { 37 | self.dirent.namelen 38 | } 39 | } 40 | 41 | #[inline] 42 | pub(crate) fn entry_size(name: &crate::NodeName) -> usize { 43 | let name_len = name.as_bytes().len(); 44 | let padding_len = (8 - (name_len % 8)) % 8; 45 | mem::size_of::() + name_len + padding_len 46 | } 47 | 48 | #[inline] 49 | pub(crate) unsafe fn read_unchecked( 50 | buf: &[u8], 51 | ) -> (T, &crate::NodeName) { 52 | let buf_ptr = buf.as_ptr(); 53 | let name_ptr = buf_ptr.add(mem::size_of::()); 54 | 55 | let mut dirent_uninit: mem::MaybeUninit = mem::MaybeUninit::uninit(); 56 | ptr::copy_nonoverlapping( 57 | buf_ptr, 58 | dirent_uninit.as_mut_ptr().cast::(), 59 | mem::size_of::(), 60 | ); 61 | let dirent = dirent_uninit.assume_init(); 62 | let name_len = dirent.namelen() as usize; 63 | let name_bytes = slice::from_raw_parts(name_ptr, name_len); 64 | let name = crate::NodeName::from_bytes_unchecked(name_bytes); 65 | (dirent, name) 66 | } 67 | 68 | #[inline] 69 | pub(crate) unsafe fn write_unchecked( 70 | dirent: T, 71 | name: &crate::NodeName, 72 | buf: &mut [u8], 73 | ) { 74 | let buf_ptr = buf.as_mut_ptr(); 75 | let dirent_dst = buf_ptr.cast::(); 76 | let name_dst = buf_ptr.add(mem::size_of::()); 77 | 78 | let name = name.as_bytes(); 79 | let padding_len = (8 - (name.len() % 8)) % 8; 80 | 81 | dirent_dst.write(dirent); 82 | ptr::copy_nonoverlapping(name.as_ptr(), name_dst, name.len()); 83 | if padding_len > 0 { 84 | let padding_dst = name_dst.add(name.len()); 85 | ptr::write_bytes(padding_dst, 0, padding_len); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /fuse/internal/testing/BUILD: -------------------------------------------------------------------------------- 1 | load("@rules_rust//rust:defs.bzl", "rust_binary", "rust_library") 2 | 3 | package( 4 | default_testonly = True, 5 | default_visibility = ["//fuse:__subpackages__"], 6 | ) 7 | 8 | rust_library( 9 | name = "fuse_testutil", 10 | srcs = ["fuse_testutil.rs"], 11 | edition = "2021", 12 | deps = ["//fuse"], 13 | ) 14 | 15 | rust_library( 16 | name = "interop_testutil", 17 | srcs = ["interop_testutil.rs"], 18 | edition = "2021", 19 | tags = ["manual"], 20 | deps = [ 21 | ":fuse_testutil", 22 | "//fuse", 23 | "@com_github_rust-lang_libc//:libc", 24 | "@com_github_utkarshkukreti_diff.rs//:diff", 25 | ] + select({ 26 | "@platforms//os:freebsd": [ 27 | "//fuse-libc", 28 | "@com_github_jmillikin_rust-freebsd-errno//freebsd-errno", 29 | ], 30 | "@platforms//os:linux": [ 31 | "//fuse-linux", 32 | "@com_github_jmillikin_rust-linux-errno//linux-errno", 33 | ], 34 | "//conditions:default": [], 35 | }), 36 | ) 37 | -------------------------------------------------------------------------------- /fuse/internal/testing/testing.bzl: -------------------------------------------------------------------------------- 1 | load("@rules_rust//rust:defs.bzl", "rust_test") 2 | 3 | def operation_tests(name, interop_test_os = None): 4 | for filename in native.glob(["*.rs"]): 5 | if not filename.startswith(name + "_"): 6 | continue 7 | if filename.endswith("_interop_test.rs"): 8 | _operation_interop_test(filename, interop_test_os) 9 | elif filename.endswith("_test.rs"): 10 | _operation_test(filename) 11 | 12 | def _operation_test(filename): 13 | target_name = filename[:-len(".rs")] 14 | if target_name in native.existing_rules(): 15 | return 16 | 17 | rust_test( 18 | name = target_name, 19 | srcs = [filename], 20 | size = "small", 21 | timeout = "short", 22 | rustc_flags = ["--deny=warnings"], 23 | deps = [ 24 | "//fuse", 25 | "//fuse/internal/testing:fuse_testutil", 26 | ] + select({ 27 | "@platforms//os:freebsd": [ 28 | "@com_github_jmillikin_rust-freebsd-errno//freebsd-errno", 29 | ], 30 | "@platforms//os:linux": [ 31 | "@com_github_jmillikin_rust-linux-errno//linux-errno", 32 | ], 33 | "//conditions:default": [], 34 | }), 35 | ) 36 | 37 | def _operation_interop_test(filename, interop_test_os): 38 | target_name = filename[:-len(".rs")] 39 | if target_name in native.existing_rules(): 40 | return 41 | 42 | rust_test( 43 | name = target_name, 44 | srcs = [filename], 45 | size = "medium", 46 | timeout = "short", 47 | rustc_flags = ["--deny=warnings"], 48 | deps = [ 49 | "//fuse", 50 | "//fuse/internal/testing:interop_testutil", 51 | "@com_github_rust-lang_libc//:libc", 52 | ] + select({ 53 | "@platforms//os:linux": [ 54 | "@com_github_jmillikin_rust-linux-errno//linux-errno", 55 | "@com_github_jmillikin_rust-linux-syscall//linux-syscall", 56 | ], 57 | "//conditions:default": [], 58 | }), 59 | tags = ["manual"], 60 | ) 61 | -------------------------------------------------------------------------------- /fuse/internal/timestamp.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2022 John Millikin and the rust-fuse contributors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // SPDX-License-Identifier: Apache-2.0 16 | 17 | use core::cmp; 18 | use core::convert::TryFrom; 19 | use core::time; 20 | 21 | pub(crate) const MAX_NANOS: u32 = 999_999_999; 22 | 23 | pub(crate) fn new_duration(raw_seconds: u64, nanos: u32) -> time::Duration { 24 | // https://github.com/rust-lang/libs-team/issues/117 25 | time::Duration::new( 26 | cmp::min(raw_seconds, i64::MAX as u64), 27 | cmp::min(nanos, MAX_NANOS), 28 | ) 29 | } 30 | 31 | pub(crate) fn split_duration(d: time::Duration) -> (u64, u32) { 32 | let (seconds, nanos) = match i64::try_from(d.as_secs()) { 33 | Ok(seconds) => (seconds, d.subsec_nanos()), 34 | Err(_) => (i64::MAX, 0), 35 | }; 36 | (seconds as u64, nanos) 37 | } 38 | -------------------------------------------------------------------------------- /fuse/kernel_traits.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2024 John Millikin and the rust-fuse contributors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // SPDX-License-Identifier: Apache-2.0 16 | 17 | use crate::kernel; 18 | use crate::server; 19 | 20 | macro_rules! cuse_reply_sized { 21 | ($t:ty) => { 22 | impl server::CuseReply for $t { 23 | fn send_to( 24 | &self, 25 | reply_sender: server::CuseReplySender<'_, S>, 26 | ) -> Result<(), server::SendError> { 27 | reply_sender.inner.send_1(self.as_bytes()) 28 | } 29 | } 30 | }; 31 | } 32 | 33 | macro_rules! fuse_reply_sized { 34 | ($t:ty) => { 35 | impl server::FuseReply for $t { 36 | fn send_to( 37 | &self, 38 | reply_sender: server::FuseReplySender<'_, S>, 39 | ) -> Result<(), server::SendError> { 40 | reply_sender.inner.send_1(self.as_bytes()) 41 | } 42 | } 43 | }; 44 | } 45 | 46 | fuse_reply_sized!(kernel::fuse_bmap_out); 47 | fuse_reply_sized!(kernel::fuse_getxattr_out); 48 | fuse_reply_sized!(kernel::fuse_lk_out); 49 | fuse_reply_sized!(kernel::fuse_lseek_out); 50 | fuse_reply_sized!(kernel::fuse_open_out); 51 | fuse_reply_sized!(kernel::fuse_poll_out); 52 | fuse_reply_sized!(kernel::fuse_write_out); 53 | 54 | cuse_reply_sized!(kernel::fuse_open_out); 55 | cuse_reply_sized!(kernel::fuse_write_out); 56 | 57 | impl server::FuseReply for kernel::fuse_attr_out { 58 | fn send_to( 59 | &self, 60 | reply_sender: server::FuseReplySender<'_, S>, 61 | ) -> Result<(), server::SendError> { 62 | let mut buf = self.as_bytes(); 63 | if reply_sender.layout.version_minor() < 9 { 64 | buf = &buf[..kernel::FUSE_COMPAT_ATTR_OUT_SIZE]; 65 | } 66 | reply_sender.inner.send_1(buf) 67 | } 68 | } 69 | 70 | impl server::FuseReply for kernel::fuse_entry_out { 71 | fn send_to( 72 | &self, 73 | reply_sender: server::FuseReplySender<'_, S>, 74 | ) -> Result<(), server::SendError> { 75 | let mut buf = self.as_bytes(); 76 | if reply_sender.layout.version_minor() < 9 { 77 | buf = &buf[..kernel::FUSE_COMPAT_ENTRY_OUT_SIZE]; 78 | } 79 | reply_sender.inner.send_1(buf) 80 | } 81 | } 82 | 83 | impl server::FuseReply for kernel::fuse_init_out { 84 | fn send_to( 85 | &self, 86 | reply_sender: server::FuseReplySender<'_, S>, 87 | ) -> Result<(), server::SendError> { 88 | let mut buf = self.as_bytes(); 89 | if self.minor < 5 { 90 | buf = &buf[..kernel::FUSE_COMPAT_INIT_OUT_SIZE]; 91 | } else if self.minor < 23 { 92 | buf = &buf[..kernel::FUSE_COMPAT_22_INIT_OUT_SIZE]; 93 | } 94 | reply_sender.inner.send_1(buf) 95 | } 96 | } 97 | 98 | impl server::FuseReply for kernel::fuse_statfs_out { 99 | fn send_to( 100 | &self, 101 | reply_sender: server::FuseReplySender<'_, S>, 102 | ) -> Result<(), server::SendError> { 103 | let mut buf = self.as_bytes(); 104 | if reply_sender.layout.version_minor() < 4 { 105 | buf = &buf[..kernel::FUSE_COMPAT_STATFS_SIZE]; 106 | } 107 | reply_sender.inner.send_1(buf) 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /fuse/node_id.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2022 John Millikin and the rust-fuse contributors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // SPDX-License-Identifier: Apache-2.0 16 | 17 | use core::fmt; 18 | use core::num::NonZeroU64; 19 | 20 | use crate::kernel; 21 | 22 | /// Node IDs are per-mount unique identifiers for filesystem nodes. 23 | #[derive(Clone, Copy, Eq, Hash, Ord, PartialEq, PartialOrd)] 24 | pub struct NodeId { 25 | bits: NonZeroU64, 26 | } 27 | 28 | impl NodeId { 29 | /// The node ID of the root directory. 30 | pub const ROOT: NodeId = unsafe { 31 | NodeId::new_unchecked(kernel::FUSE_ROOT_ID) 32 | }; 33 | 34 | /// Creates a new `NodeId` if the given value is not zero. 35 | #[inline] 36 | #[must_use] 37 | pub const fn new(id: u64) -> Option { 38 | match NonZeroU64::new(id) { 39 | Some(id) => Some(NodeId { bits: id }), 40 | None => None, 41 | } 42 | } 43 | 44 | /// Creates a new `NodeId` without checking that the given value is non-zero. 45 | /// 46 | /// # Safety 47 | /// 48 | /// The value must not be zero. 49 | /// 50 | /// The `NodeId` struct is a wrapper around [`NonZeroU64`], so passing 51 | /// zero to this function is undefined behavior. 52 | #[inline] 53 | #[must_use] 54 | pub const unsafe fn new_unchecked(id: u64) -> NodeId { 55 | Self { bits: NonZeroU64::new_unchecked(id) } 56 | } 57 | 58 | /// Returns the node ID as a primitive integer. 59 | #[inline] 60 | #[must_use] 61 | pub const fn get(&self) -> u64 { 62 | self.bits.get() 63 | } 64 | 65 | /// Returns whether the node ID is [`NodeId::ROOT`]. 66 | #[inline] 67 | #[must_use] 68 | pub const fn is_root(&self) -> bool { 69 | self.bits.get() == kernel::FUSE_ROOT_ID 70 | } 71 | } 72 | 73 | impl fmt::Debug for NodeId { 74 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { 75 | self.bits.fmt(fmt) 76 | } 77 | } 78 | 79 | impl fmt::Binary for NodeId { 80 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { 81 | self.bits.fmt(fmt) 82 | } 83 | } 84 | 85 | impl fmt::LowerHex for NodeId { 86 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { 87 | self.bits.fmt(fmt) 88 | } 89 | } 90 | 91 | impl fmt::UpperHex for NodeId { 92 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { 93 | self.bits.fmt(fmt) 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /fuse/operations.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 John Millikin and the rust-fuse contributors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // SPDX-License-Identifier: Apache-2.0 16 | 17 | #![allow(missing_docs)] // TODO 18 | 19 | pub(crate) mod access; 20 | pub(crate) mod bmap; 21 | pub(crate) mod copy_file_range; 22 | pub(crate) mod create; 23 | pub(crate) mod cuse_init; 24 | pub(crate) mod fallocate; 25 | pub(crate) mod flush; 26 | pub(crate) mod forget; 27 | pub(crate) mod fsync; 28 | pub(crate) mod fsyncdir; 29 | pub(crate) mod fuse_init; 30 | pub(crate) mod getattr; 31 | pub(crate) mod getlk; 32 | pub(crate) mod getxattr; 33 | pub(crate) mod interrupt; 34 | pub(crate) mod ioctl; 35 | pub(crate) mod link; 36 | pub(crate) mod listxattr; 37 | pub(crate) mod lookup; 38 | pub(crate) mod lseek; 39 | pub(crate) mod mkdir; 40 | pub(crate) mod mknod; 41 | pub(crate) mod open; 42 | pub(crate) mod opendir; 43 | pub(crate) mod poll; 44 | pub(crate) mod read; 45 | pub(crate) mod readdir; 46 | pub(crate) mod readdirplus; 47 | pub(crate) mod readlink; 48 | pub(crate) mod release; 49 | pub(crate) mod releasedir; 50 | pub(crate) mod removexattr; 51 | pub(crate) mod rename; 52 | pub(crate) mod rmdir; 53 | pub(crate) mod setattr; 54 | pub(crate) mod setlk; 55 | pub(crate) mod setxattr; 56 | pub(crate) mod statfs; 57 | pub(crate) mod symlink; 58 | pub(crate) mod unlink; 59 | pub(crate) mod write; 60 | -------------------------------------------------------------------------------- /fuse/operations/BUILD: -------------------------------------------------------------------------------- 1 | filegroup( 2 | name = "srcs", 3 | srcs = glob(["*.rs"]), 4 | visibility = ["//fuse:__subpackages__"], 5 | ) 6 | -------------------------------------------------------------------------------- /fuse/operations/access.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 John Millikin and the rust-fuse contributors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // SPDX-License-Identifier: Apache-2.0 16 | 17 | use core::fmt; 18 | use core::marker::PhantomData; 19 | 20 | use crate::kernel; 21 | use crate::server::decode; 22 | 23 | // AccessRequest {{{ 24 | 25 | /// Request type for `FUSE_ACCESS`. 26 | #[derive(Clone, Copy)] 27 | pub struct AccessRequest<'a> { 28 | phantom: PhantomData<&'a ()>, 29 | node_id: crate::NodeId, 30 | mask: u32, 31 | } 32 | 33 | impl AccessRequest<'_> { 34 | #[must_use] 35 | pub fn node_id(&self) -> crate::NodeId { 36 | self.node_id 37 | } 38 | 39 | #[must_use] 40 | pub fn mask(&self) -> u32 { 41 | self.mask 42 | } 43 | } 44 | 45 | try_from_fuse_request!(AccessRequest<'a>, |request| { 46 | let mut dec = request.decoder(); 47 | dec.expect_opcode(kernel::fuse_opcode::FUSE_ACCESS)?; 48 | let raw: &'a kernel::fuse_access_in = dec.next_sized()?; 49 | Ok(Self { 50 | phantom: PhantomData, 51 | node_id: decode::node_id(dec.header().nodeid)?, 52 | mask: raw.mask, 53 | }) 54 | }); 55 | 56 | impl fmt::Debug for AccessRequest<'_> { 57 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { 58 | fmt.debug_struct("AccessRequest") 59 | .field("node_id", &self.node_id) 60 | .field("mask", &self.mask) 61 | .finish() 62 | } 63 | } 64 | 65 | // }}} 66 | -------------------------------------------------------------------------------- /fuse/operations/access/BUILD: -------------------------------------------------------------------------------- 1 | load("//fuse/internal/testing:testing.bzl", "operation_tests") 2 | 3 | operation_tests("access") 4 | -------------------------------------------------------------------------------- /fuse/operations/access/access_test.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 John Millikin and the rust-fuse contributors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // SPDX-License-Identifier: Apache-2.0 16 | 17 | use fuse::kernel; 18 | use fuse::server::AccessRequest; 19 | 20 | use fuse_testutil as testutil; 21 | use fuse_testutil::{decode_request, MessageBuilder}; 22 | 23 | #[test] 24 | fn request() { 25 | let buf = MessageBuilder::new() 26 | .set_header(|h| { 27 | h.opcode = kernel::fuse_opcode::FUSE_ACCESS; 28 | h.nodeid = 123; 29 | }) 30 | .push_sized(&testutil::new!(kernel::fuse_access_in { 31 | mask: 0xFF, 32 | })) 33 | .build_aligned(); 34 | let req = decode_request!(AccessRequest, buf); 35 | 36 | assert_eq!(req.mask(), 0xFF); 37 | } 38 | 39 | #[test] 40 | fn request_impl_debug() { 41 | let buf; 42 | let request = fuse_testutil::build_request!(buf, AccessRequest, { 43 | .set_header(|h| { 44 | h.opcode = kernel::fuse_opcode::FUSE_ACCESS; 45 | h.nodeid = kernel::FUSE_ROOT_ID; 46 | }) 47 | .push_sized(&kernel::fuse_access_in::new()) 48 | }); 49 | 50 | assert_eq!( 51 | format!("{:#?}", request), 52 | concat!( 53 | "AccessRequest {\n", 54 | " node_id: 1,\n", 55 | " mask: 0,\n", 56 | "}", 57 | ), 58 | ); 59 | } 60 | -------------------------------------------------------------------------------- /fuse/operations/bmap.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 John Millikin and the rust-fuse contributors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // SPDX-License-Identifier: Apache-2.0 16 | 17 | use core::fmt; 18 | 19 | use crate::kernel; 20 | use crate::server::decode; 21 | 22 | // BmapRequest {{{ 23 | 24 | /// Request type for `FUSE_BMAP`. 25 | #[derive(Clone, Copy)] 26 | pub struct BmapRequest<'a> { 27 | header: &'a kernel::fuse_in_header, 28 | body: &'a kernel::fuse_bmap_in, 29 | } 30 | 31 | impl BmapRequest<'_> { 32 | #[must_use] 33 | pub fn node_id(&self) -> crate::NodeId { 34 | unsafe { crate::NodeId::new_unchecked(self.header.nodeid) } 35 | } 36 | 37 | #[must_use] 38 | pub fn block(&self) -> u64 { 39 | self.body.block 40 | } 41 | 42 | #[must_use] 43 | pub fn block_size(&self) -> u32 { 44 | self.body.blocksize 45 | } 46 | } 47 | 48 | try_from_fuse_request!(BmapRequest<'a>, |request| { 49 | let mut dec = request.decoder(); 50 | dec.expect_opcode(kernel::fuse_opcode::FUSE_BMAP)?; 51 | 52 | let header = dec.header(); 53 | let body = dec.next_sized()?; 54 | decode::node_id(header.nodeid)?; 55 | Ok(Self { header, body }) 56 | }); 57 | 58 | impl fmt::Debug for BmapRequest<'_> { 59 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { 60 | fmt.debug_struct("BmapRequest") 61 | .field("node_id", &self.node_id()) 62 | .field("block", &self.block()) 63 | .field("block_size", &self.block_size()) 64 | .finish() 65 | } 66 | } 67 | 68 | // }}} 69 | -------------------------------------------------------------------------------- /fuse/operations/bmap/BUILD: -------------------------------------------------------------------------------- 1 | load("//fuse/internal/testing:testing.bzl", "operation_tests") 2 | 3 | operation_tests( 4 | "bmap", 5 | interop_test_os = ["linux"], 6 | ) 7 | -------------------------------------------------------------------------------- /fuse/operations/copy_file_range.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2022 John Millikin and the rust-fuse contributors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // SPDX-License-Identifier: Apache-2.0 16 | 17 | use core::fmt; 18 | 19 | use crate::kernel; 20 | use crate::server::decode; 21 | 22 | // CopyFileRangeRequest {{{ 23 | 24 | /// Request type for `FUSE_COPY_FILE_RANGE`. 25 | #[derive(Clone, Copy)] 26 | pub struct CopyFileRangeRequest<'a> { 27 | header: &'a kernel::fuse_in_header, 28 | body: &'a kernel::fuse_copy_file_range_in, 29 | } 30 | 31 | impl CopyFileRangeRequest<'_> { 32 | #[must_use] 33 | pub fn input_node_id(&self) -> crate::NodeId { 34 | unsafe { crate::NodeId::new_unchecked(self.header.nodeid) } 35 | } 36 | 37 | #[must_use] 38 | pub fn input_handle(&self) -> u64 { 39 | self.body.fh_in 40 | } 41 | 42 | #[must_use] 43 | pub fn input_offset(&self) -> u64 { 44 | self.body.off_in 45 | } 46 | 47 | #[must_use] 48 | pub fn output_node_id(&self) -> crate::NodeId { 49 | unsafe { crate::NodeId::new_unchecked(self.body.nodeid_out) } 50 | } 51 | 52 | #[must_use] 53 | pub fn output_handle(&self) -> u64 { 54 | self.body.fh_out 55 | } 56 | 57 | #[must_use] 58 | pub fn output_offset(&self) -> u64 { 59 | self.body.off_out 60 | } 61 | 62 | #[must_use] 63 | pub fn len(&self) -> u64 { 64 | self.body.len 65 | } 66 | 67 | #[must_use] 68 | pub fn flags(&self) -> CopyFileRangeRequestFlags { 69 | CopyFileRangeRequestFlags { 70 | bits: self.body.flags, 71 | } 72 | } 73 | } 74 | 75 | try_from_fuse_request!(CopyFileRangeRequest<'a>, |request| { 76 | let mut dec = request.decoder(); 77 | dec.expect_opcode(kernel::fuse_opcode::FUSE_COPY_FILE_RANGE)?; 78 | 79 | use kernel::fuse_copy_file_range_in; 80 | 81 | let header = dec.header(); 82 | let body: &'a fuse_copy_file_range_in = dec.next_sized()?; 83 | decode::node_id(header.nodeid)?; 84 | decode::node_id(body.nodeid_out)?; 85 | 86 | Ok(Self { header, body }) 87 | }); 88 | 89 | impl fmt::Debug for CopyFileRangeRequest<'_> { 90 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { 91 | fmt.debug_struct("CopyFileRangeRequest") 92 | .field("input_node_id", &self.input_node_id()) 93 | .field("input_handle", &self.input_handle()) 94 | .field("input_offset", &self.input_offset()) 95 | .field("output_node_id", &self.output_node_id()) 96 | .field("output_handle", &self.output_handle()) 97 | .field("output_offset", &self.output_offset()) 98 | .field("len", &self.len()) 99 | .field("flags", &self.flags()) 100 | .finish() 101 | } 102 | } 103 | 104 | // }}} 105 | 106 | // CopyFileRangeRequestFlags {{{ 107 | 108 | /// Optional flags set on [`CopyFileRangeRequest`]. 109 | #[derive(Clone, Copy, Eq, Hash, Ord, PartialEq, PartialOrd)] 110 | pub struct CopyFileRangeRequestFlags { 111 | bits: u64, 112 | } 113 | 114 | #[derive(Clone, Copy, Eq, Hash, Ord, PartialEq, PartialOrd)] 115 | pub struct CopyFileRangeRequestFlag { 116 | mask: u64, 117 | } 118 | 119 | mod request_flags { 120 | bitflags!(CopyFileRangeRequestFlag, CopyFileRangeRequestFlags, u64, { 121 | }); 122 | } 123 | 124 | // }}} 125 | -------------------------------------------------------------------------------- /fuse/operations/copy_file_range/BUILD: -------------------------------------------------------------------------------- 1 | load("//fuse/internal/testing:testing.bzl", "operation_tests") 2 | 3 | operation_tests( 4 | "copy_file_range", 5 | interop_test_os = ["linux"], 6 | ) 7 | -------------------------------------------------------------------------------- /fuse/operations/copy_file_range/copy_file_range_test.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2022 John Millikin and the rust-fuse contributors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // SPDX-License-Identifier: Apache-2.0 16 | 17 | use fuse::kernel; 18 | use fuse::server::CopyFileRangeRequest; 19 | 20 | use fuse_testutil as testutil; 21 | use fuse_testutil::{decode_request, MessageBuilder}; 22 | 23 | #[test] 24 | fn request() { 25 | let buf = MessageBuilder::new() 26 | .set_header(|h| { 27 | h.opcode = kernel::fuse_opcode::FUSE_COPY_FILE_RANGE; 28 | h.nodeid = 10; 29 | }) 30 | .push_sized(&testutil::new!(kernel::fuse_copy_file_range_in { 31 | fh_in: 11, 32 | off_in: 12, 33 | nodeid_out: 13, 34 | fh_out: 14, 35 | off_out: 15, 36 | len: 16, 37 | })) 38 | .build_aligned(); 39 | 40 | let req = decode_request!(CopyFileRangeRequest, buf); 41 | 42 | assert_eq!(req.input_node_id(), fuse::NodeId::new(10).unwrap()); 43 | assert_eq!(req.input_handle(), 11); 44 | assert_eq!(req.input_offset(), 12); 45 | assert_eq!(req.output_node_id(), fuse::NodeId::new(13).unwrap()); 46 | assert_eq!(req.output_handle(), 14); 47 | assert_eq!(req.output_offset(), 15); 48 | assert_eq!(req.len(), 16); 49 | assert_eq!(req.flags(), fuse::CopyFileRangeRequestFlags::new()); 50 | } 51 | 52 | #[test] 53 | fn request_impl_debug() { 54 | let buf; 55 | let request = fuse_testutil::build_request!(buf, CopyFileRangeRequest, { 56 | .set_header(|h| { 57 | h.opcode = kernel::fuse_opcode::FUSE_COPY_FILE_RANGE; 58 | h.nodeid = 10; 59 | }) 60 | .push_sized(&testutil::new!(kernel::fuse_copy_file_range_in { 61 | fh_in: 11, 62 | off_in: 12, 63 | nodeid_out: 13, 64 | fh_out: 14, 65 | off_out: 15, 66 | len: 16, 67 | })) 68 | }); 69 | 70 | assert_eq!( 71 | format!("{:#?}", request), 72 | concat!( 73 | "CopyFileRangeRequest {\n", 74 | " input_node_id: 10,\n", 75 | " input_handle: 11,\n", 76 | " input_offset: 12,\n", 77 | " output_node_id: 13,\n", 78 | " output_handle: 14,\n", 79 | " output_offset: 15,\n", 80 | " len: 16,\n", 81 | " flags: CopyFileRangeRequestFlags {},\n", 82 | "}", 83 | ), 84 | ); 85 | } 86 | -------------------------------------------------------------------------------- /fuse/operations/create/BUILD: -------------------------------------------------------------------------------- 1 | load("//fuse/internal/testing:testing.bzl", "operation_tests") 2 | 3 | operation_tests("create") 4 | -------------------------------------------------------------------------------- /fuse/operations/create/create_test.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 John Millikin and the rust-fuse contributors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // SPDX-License-Identifier: Apache-2.0 16 | 17 | use fuse::kernel; 18 | use fuse::server::CreateRequest; 19 | 20 | use fuse_testutil as testutil; 21 | use fuse_testutil::{decode_request, MessageBuilder}; 22 | 23 | #[test] 24 | fn request_v7p1() { 25 | let buf = MessageBuilder::new() 26 | .set_header(|h| { 27 | h.opcode = kernel::fuse_opcode::FUSE_CREATE; 28 | h.nodeid = 123; 29 | }) 30 | .push_sized(&0xFFu32) // fuse_create_in::flags 31 | .push_sized(&0u32) // fuse_create_in::unused 32 | .push_bytes(b"hello.world!\x00") 33 | .build_aligned(); 34 | 35 | let req = decode_request!(CreateRequest, buf, { 36 | protocol_version: (7, 1), 37 | }); 38 | 39 | assert_eq!(req.name(), "hello.world!"); 40 | assert_eq!(req.flags(), fuse::CreateRequestFlags::new()); 41 | assert_eq!(req.open_flags(), 0xFF); 42 | assert_eq!(req.mode(), fuse::FileMode::new(0)); 43 | assert_eq!(req.umask(), 0); 44 | } 45 | 46 | #[test] 47 | fn request_v7p12() { 48 | let buf = MessageBuilder::new() 49 | .set_header(|h| { 50 | h.opcode = kernel::fuse_opcode::FUSE_CREATE; 51 | h.nodeid = 123; 52 | }) 53 | .push_sized(&testutil::new!(kernel::fuse_create_in { 54 | flags: 0xFF, 55 | mode: 0xEE, 56 | umask: 0xDD, 57 | open_flags: 0, // TODO 58 | })) 59 | .push_bytes(b"hello.world!\x00") 60 | .build_aligned(); 61 | 62 | let req = decode_request!(CreateRequest, buf, { 63 | protocol_version: (7, 12), 64 | }); 65 | 66 | assert_eq!(req.name(), "hello.world!"); 67 | assert_eq!(req.flags(), fuse::CreateRequestFlags::new()); 68 | assert_eq!(req.open_flags(), 0xFF); 69 | assert_eq!(req.mode(), fuse::FileMode::new(0xEE)); 70 | assert_eq!(req.umask(), 0xDD); 71 | } 72 | 73 | #[test] 74 | fn request_impl_debug() { 75 | let buf; 76 | let request = fuse_testutil::build_request!(buf, CreateRequest, { 77 | .set_header(|h| { 78 | h.opcode = kernel::fuse_opcode::FUSE_CREATE; 79 | h.nodeid = kernel::FUSE_ROOT_ID; 80 | }) 81 | .push_sized(&testutil::new!(kernel::fuse_create_in { 82 | flags: 123, 83 | mode: 0o100644, 84 | umask: 0o22, 85 | open_flags: 0, // TODO 86 | })) 87 | .push_bytes(b"hello.world\x00") 88 | }); 89 | 90 | assert_eq!( 91 | format!("{:#?}", request), 92 | concat!( 93 | "CreateRequest {\n", 94 | " node_id: 1,\n", 95 | " name: \"hello.world\",\n", 96 | " flags: CreateRequestFlags {},\n", 97 | " open_flags: 0x0000007B,\n", 98 | " mode: 0o100644,\n", 99 | " umask: 18,\n", 100 | "}", 101 | ), 102 | ); 103 | } 104 | -------------------------------------------------------------------------------- /fuse/operations/cuse_init/BUILD: -------------------------------------------------------------------------------- 1 | load("//fuse/internal/testing:testing.bzl", "operation_tests") 2 | 3 | operation_tests( 4 | "cuse_init", 5 | interop_test_os = ["linux"], 6 | ) 7 | -------------------------------------------------------------------------------- /fuse/operations/fallocate.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 John Millikin and the rust-fuse contributors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // SPDX-License-Identifier: Apache-2.0 16 | 17 | use core::fmt; 18 | 19 | use crate::internal::debug; 20 | use crate::kernel; 21 | use crate::server::decode; 22 | 23 | // FallocateRequest {{{ 24 | 25 | /// Request type for `FUSE_FALLOCATE`. 26 | #[derive(Clone, Copy)] 27 | pub struct FallocateRequest<'a> { 28 | header: &'a kernel::fuse_in_header, 29 | body: &'a kernel::fuse_fallocate_in, 30 | } 31 | 32 | impl FallocateRequest<'_> { 33 | #[must_use] 34 | pub fn node_id(&self) -> crate::NodeId { 35 | unsafe { crate::NodeId::new_unchecked(self.header.nodeid) } 36 | } 37 | 38 | #[must_use] 39 | pub fn handle(&self) -> u64 { 40 | self.body.fh 41 | } 42 | 43 | #[must_use] 44 | pub fn offset(&self) -> u64 { 45 | self.body.offset 46 | } 47 | 48 | #[must_use] 49 | pub fn length(&self) -> u64 { 50 | self.body.length 51 | } 52 | 53 | #[must_use] 54 | pub fn fallocate_flags(&self) -> crate::FallocateFlags { 55 | self.body.mode 56 | } 57 | } 58 | 59 | try_from_fuse_request!(FallocateRequest<'a>, |request| { 60 | let mut dec = request.decoder(); 61 | dec.expect_opcode(kernel::fuse_opcode::FUSE_FALLOCATE)?; 62 | 63 | let header = dec.header(); 64 | let body = dec.next_sized()?; 65 | decode::node_id(header.nodeid)?; 66 | Ok(Self { header, body }) 67 | }); 68 | 69 | impl fmt::Debug for FallocateRequest<'_> { 70 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { 71 | fmt.debug_struct("FallocateRequest") 72 | .field("node_id", &self.node_id()) 73 | .field("handle", &self.handle()) 74 | .field("offset", &self.offset()) 75 | .field("length", &self.length()) 76 | .field("fallocate_flags", &debug::hex_u32(self.fallocate_flags())) 77 | .finish() 78 | } 79 | } 80 | 81 | // }}} 82 | -------------------------------------------------------------------------------- /fuse/operations/fallocate/BUILD: -------------------------------------------------------------------------------- 1 | load("//fuse/internal/testing:testing.bzl", "operation_tests") 2 | 3 | operation_tests( 4 | "fallocate", 5 | interop_test_os = ["linux"], 6 | ) 7 | -------------------------------------------------------------------------------- /fuse/operations/fallocate/fallocate_test.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 John Millikin and the rust-fuse contributors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // SPDX-License-Identifier: Apache-2.0 16 | 17 | use fuse::kernel; 18 | use fuse::server::FallocateRequest; 19 | 20 | use fuse_testutil as testutil; 21 | use fuse_testutil::{decode_request, MessageBuilder}; 22 | 23 | #[test] 24 | fn request() { 25 | let buf = MessageBuilder::new() 26 | .set_header(|h| { 27 | h.opcode = kernel::fuse_opcode::FUSE_FALLOCATE; 28 | h.nodeid = 123; 29 | }) 30 | .push_sized(&testutil::new!(kernel::fuse_fallocate_in { 31 | fh: 12, 32 | offset: 34, 33 | length: 56, 34 | mode: 0b11, 35 | })) 36 | .build_aligned(); 37 | 38 | let req = decode_request!(FallocateRequest, buf); 39 | 40 | assert_eq!(req.handle(), 12); 41 | assert_eq!(req.offset(), 34); 42 | assert_eq!(req.length(), 56); 43 | assert_eq!(req.fallocate_flags(), 0b11); 44 | } 45 | 46 | #[test] 47 | fn request_impl_debug() { 48 | let buf; 49 | let request = fuse_testutil::build_request!(buf, FallocateRequest, { 50 | .set_header(|h| { 51 | h.opcode = kernel::fuse_opcode::FUSE_FALLOCATE; 52 | h.nodeid = kernel::FUSE_ROOT_ID; 53 | }) 54 | .push_sized(&testutil::new!(kernel::fuse_fallocate_in { 55 | fh: 123, 56 | offset: 1024, 57 | length: 4096, 58 | mode: 0b11, 59 | })) 60 | }); 61 | 62 | assert_eq!( 63 | format!("{:#?}", request), 64 | concat!( 65 | "FallocateRequest {\n", 66 | " node_id: 1,\n", 67 | " handle: 123,\n", 68 | " offset: 1024,\n", 69 | " length: 4096,\n", 70 | " fallocate_flags: 0x00000003,\n", 71 | "}", 72 | ), 73 | ); 74 | } 75 | -------------------------------------------------------------------------------- /fuse/operations/flush.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 John Millikin and the rust-fuse contributors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // SPDX-License-Identifier: Apache-2.0 16 | 17 | use core::fmt; 18 | use core::marker::PhantomData; 19 | 20 | use crate::kernel; 21 | use crate::server; 22 | use crate::server::decode; 23 | 24 | // FlushRequest {{{ 25 | 26 | /// Request type for `FUSE_FLUSH`. 27 | #[derive(Clone, Copy)] 28 | pub struct FlushRequest<'a> { 29 | phantom: PhantomData<&'a ()>, 30 | node_id: crate::NodeId, 31 | handle: u64, 32 | lock_owner: crate::LockOwner, 33 | } 34 | 35 | impl FlushRequest<'_> { 36 | #[must_use] 37 | pub fn node_id(&self) -> crate::NodeId { 38 | self.node_id 39 | } 40 | 41 | #[must_use] 42 | pub fn handle(&self) -> u64 { 43 | self.handle 44 | } 45 | 46 | #[must_use] 47 | pub fn lock_owner(&self) -> crate::LockOwner { 48 | self.lock_owner 49 | } 50 | } 51 | 52 | try_from_cuse_request!(FlushRequest<'a>, |request| { 53 | Self::try_from(request.inner, true) 54 | }); 55 | 56 | try_from_fuse_request!(FlushRequest<'a>, |request| { 57 | Self::try_from(request.inner, false) 58 | }); 59 | 60 | impl<'a> FlushRequest<'a> { 61 | fn try_from( 62 | request: server::Request<'a>, 63 | is_cuse: bool, 64 | ) -> Result { 65 | let mut dec = request.decoder(); 66 | dec.expect_opcode(kernel::fuse_opcode::FUSE_FLUSH)?; 67 | 68 | let node_id = if is_cuse { 69 | crate::NodeId::ROOT 70 | } else { 71 | decode::node_id(dec.header().nodeid)? 72 | }; 73 | 74 | let raw: &kernel::fuse_flush_in = dec.next_sized()?; 75 | Ok(Self { 76 | phantom: PhantomData, 77 | node_id, 78 | handle: raw.fh, 79 | lock_owner: crate::LockOwner(raw.lock_owner), 80 | }) 81 | } 82 | } 83 | 84 | impl fmt::Debug for FlushRequest<'_> { 85 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { 86 | fmt.debug_struct("FlushRequest") 87 | .field("node_id", &self.node_id) 88 | .field("handle", &self.handle) 89 | .field("lock_owner", &self.lock_owner) 90 | .finish() 91 | } 92 | } 93 | 94 | // }}} 95 | -------------------------------------------------------------------------------- /fuse/operations/flush/BUILD: -------------------------------------------------------------------------------- 1 | load("//fuse/internal/testing:testing.bzl", "operation_tests") 2 | 3 | operation_tests("flush") 4 | -------------------------------------------------------------------------------- /fuse/operations/flush/flush_test.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 John Millikin and the rust-fuse contributors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // SPDX-License-Identifier: Apache-2.0 16 | 17 | use fuse::kernel; 18 | use fuse::server::FlushRequest; 19 | 20 | use fuse_testutil as testutil; 21 | use fuse_testutil::{decode_request, MessageBuilder}; 22 | 23 | #[test] 24 | fn request() { 25 | let buf = MessageBuilder::new() 26 | .set_header(|h| { 27 | h.opcode = kernel::fuse_opcode::FUSE_FLUSH; 28 | h.nodeid = 123; 29 | }) 30 | .push_sized(&testutil::new!(kernel::fuse_flush_in { 31 | fh: 123, 32 | lock_owner: 456, 33 | })) 34 | .build_aligned(); 35 | 36 | let req = decode_request!(FlushRequest, buf); 37 | 38 | assert_eq!(req.handle(), 123); 39 | assert_eq!(req.lock_owner(), fuse::LockOwner(456)); 40 | } 41 | 42 | #[test] 43 | fn request_impl_debug() { 44 | let buf; 45 | let request = fuse_testutil::build_request!(buf, FlushRequest, { 46 | .set_header(|h| { 47 | h.opcode = kernel::fuse_opcode::FUSE_FLUSH; 48 | h.nodeid = kernel::FUSE_ROOT_ID; 49 | }) 50 | .push_sized(&testutil::new!(kernel::fuse_flush_in { 51 | fh: 12, 52 | lock_owner: 34, 53 | })) 54 | }); 55 | assert_eq!( 56 | format!("{:#?}", request), 57 | concat!( 58 | "FlushRequest {\n", 59 | " node_id: 1,\n", 60 | " handle: 12,\n", 61 | " lock_owner: 0x0000000000000022,\n", 62 | "}", 63 | ), 64 | ); 65 | } 66 | -------------------------------------------------------------------------------- /fuse/operations/forget/BUILD: -------------------------------------------------------------------------------- 1 | load("//fuse/internal/testing:testing.bzl", "operation_tests") 2 | 3 | operation_tests("forget") 4 | -------------------------------------------------------------------------------- /fuse/operations/forget/forget_test.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 John Millikin and the rust-fuse contributors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // SPDX-License-Identifier: Apache-2.0 16 | 17 | use fuse::kernel; 18 | use fuse::server::{ForgetRequest, ForgetRequestItem}; 19 | 20 | use fuse_testutil as testutil; 21 | use fuse_testutil::{decode_request, MessageBuilder}; 22 | 23 | #[test] 24 | fn request_single() { 25 | let buf = MessageBuilder::new() 26 | .set_header(|h| { 27 | h.opcode = kernel::fuse_opcode::FUSE_FORGET; 28 | h.nodeid = 123; 29 | }) 30 | .push_sized(&testutil::new!(kernel::fuse_forget_in { 31 | nlookup: 456, 32 | })) 33 | .build_aligned(); 34 | 35 | let req = decode_request!(ForgetRequest, buf); 36 | 37 | let items: Vec = req.items().collect(); 38 | assert_eq!(items.len(), 1); 39 | assert_eq!(items[0].node_id(), fuse::NodeId::new(123).unwrap()); 40 | assert_eq!(items[0].lookup_count(), 456); 41 | } 42 | 43 | #[test] 44 | fn request_batch() { 45 | let buf = MessageBuilder::new() 46 | .set_opcode(kernel::fuse_opcode::FUSE_BATCH_FORGET) 47 | .push_sized(&testutil::new!(kernel::fuse_batch_forget_in { 48 | count: 2, 49 | })) 50 | .push_sized(&testutil::new!(kernel::fuse_forget_one { 51 | nodeid: 12, 52 | nlookup: 34, 53 | })) 54 | .push_sized(&testutil::new!(kernel::fuse_forget_one { 55 | nodeid: 56, 56 | nlookup: 78, 57 | })) 58 | .build_aligned(); 59 | 60 | let req = decode_request!(ForgetRequest, buf); 61 | 62 | let items: Vec = req.items().collect(); 63 | assert_eq!(items.len(), 2); 64 | assert_eq!(items[0].node_id(), fuse::NodeId::new(12).unwrap()); 65 | assert_eq!(items[0].lookup_count(), 34); 66 | assert_eq!(items[1].node_id(), fuse::NodeId::new(56).unwrap()); 67 | assert_eq!(items[1].lookup_count(), 78); 68 | } 69 | 70 | #[test] 71 | fn request_impl_debug() { 72 | let buf = MessageBuilder::new() 73 | .set_header(|h| { 74 | h.opcode = kernel::fuse_opcode::FUSE_FORGET; 75 | h.nodeid = 123; 76 | }) 77 | .push_sized(&testutil::new!(kernel::fuse_forget_in { 78 | nlookup: 456, 79 | })) 80 | .build_aligned(); 81 | 82 | let request = decode_request!(ForgetRequest, buf); 83 | 84 | assert_eq!( 85 | format!("{:#?}", request), 86 | concat!( 87 | "ForgetRequest {\n", 88 | " items: [\n", 89 | " ForgetRequestItem {\n", 90 | " node_id: 123,\n", 91 | " lookup_count: 456,\n", 92 | " },\n", 93 | " ],\n", 94 | "}", 95 | ), 96 | ); 97 | } 98 | -------------------------------------------------------------------------------- /fuse/operations/fsync.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 John Millikin and the rust-fuse contributors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // SPDX-License-Identifier: Apache-2.0 16 | 17 | use core::fmt; 18 | 19 | use crate::kernel; 20 | use crate::server; 21 | use crate::server::decode; 22 | 23 | // FsyncRequest {{{ 24 | 25 | /// Request type for `FUSE_FSYNC`. 26 | #[derive(Clone, Copy)] 27 | pub struct FsyncRequest<'a> { 28 | header: &'a kernel::fuse_in_header, 29 | body: &'a kernel::fuse_fsync_in, 30 | } 31 | 32 | impl FsyncRequest<'_> { 33 | #[must_use] 34 | pub fn node_id(&self) -> crate::NodeId { 35 | crate::NodeId::new(self.header.nodeid).unwrap_or(crate::NodeId::ROOT) 36 | } 37 | 38 | #[must_use] 39 | pub fn handle(&self) -> u64 { 40 | self.body.fh 41 | } 42 | 43 | #[must_use] 44 | pub fn flags(&self) -> FsyncRequestFlags { 45 | FsyncRequestFlags { 46 | bits: self.body.fsync_flags, 47 | } 48 | } 49 | } 50 | 51 | try_from_cuse_request!(FsyncRequest<'a>, |request| { 52 | Self::try_from(request.inner, true) 53 | }); 54 | 55 | try_from_fuse_request!(FsyncRequest<'a>, |request| { 56 | Self::try_from(request.inner, false) 57 | }); 58 | 59 | impl<'a> FsyncRequest<'a> { 60 | fn try_from( 61 | request: server::Request<'a>, 62 | is_cuse: bool, 63 | ) -> Result { 64 | let mut dec = request.decoder(); 65 | dec.expect_opcode(kernel::fuse_opcode::FUSE_FSYNC)?; 66 | 67 | let header = dec.header(); 68 | let body = dec.next_sized()?; 69 | if !is_cuse { 70 | decode::node_id(header.nodeid)?; 71 | } 72 | Ok(Self { header, body }) 73 | } 74 | } 75 | 76 | impl fmt::Debug for FsyncRequest<'_> { 77 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { 78 | fmt.debug_struct("FsyncRequest") 79 | .field("node_id", &self.node_id()) 80 | .field("handle", &self.handle()) 81 | .field("flags", &self.flags()) 82 | .finish() 83 | } 84 | } 85 | 86 | // }}} 87 | 88 | // FsyncRequestFlags {{{ 89 | 90 | /// Optional flags set on [`FsyncRequest`]. 91 | #[derive(Clone, Copy, Eq, Hash, Ord, PartialEq, PartialOrd)] 92 | pub struct FsyncRequestFlags { 93 | bits: u32, 94 | } 95 | 96 | #[derive(Clone, Copy, Eq, Hash, Ord, PartialEq, PartialOrd)] 97 | pub struct FsyncRequestFlag { 98 | mask: u32, 99 | } 100 | 101 | mod request_flags { 102 | use crate::kernel; 103 | bitflags!(FsyncRequestFlag, FsyncRequestFlags, u32, { 104 | FDATASYNC = kernel::FUSE_FSYNC_FDATASYNC; 105 | }); 106 | } 107 | 108 | // }}} 109 | -------------------------------------------------------------------------------- /fuse/operations/fsync/BUILD: -------------------------------------------------------------------------------- 1 | load("//fuse/internal/testing:testing.bzl", "operation_tests") 2 | 3 | operation_tests("fsync") 4 | -------------------------------------------------------------------------------- /fuse/operations/fsync/fsync_test.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 John Millikin and the rust-fuse contributors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // SPDX-License-Identifier: Apache-2.0 16 | 17 | use fuse::kernel; 18 | use fuse::server::FsyncRequest; 19 | 20 | use fuse_testutil as testutil; 21 | use fuse_testutil::{decode_request, MessageBuilder}; 22 | 23 | #[test] 24 | fn request() { 25 | let buf = MessageBuilder::new() 26 | .set_header(|h| { 27 | h.opcode = kernel::fuse_opcode::FUSE_FSYNC; 28 | h.nodeid = 123; 29 | }) 30 | .push_sized(&testutil::new!(kernel::fuse_fsync_in { 31 | fh: 3, 32 | fsync_flags: 0x1, 33 | })) 34 | .build_aligned(); 35 | 36 | let req = decode_request!(FsyncRequest, buf); 37 | 38 | assert_eq!(req.handle(), 3); 39 | assert_eq!(req.flags().get(fuse::FsyncRequestFlag::FDATASYNC), true); 40 | } 41 | 42 | #[test] 43 | fn request_impl_debug() { 44 | let buf; 45 | let request = fuse_testutil::build_request!(buf, FsyncRequest, { 46 | .set_header(|h| { 47 | h.opcode = kernel::fuse_opcode::FUSE_FSYNC; 48 | h.nodeid = kernel::FUSE_ROOT_ID; 49 | }) 50 | .push_sized(&testutil::new!(kernel::fuse_fsync_in { 51 | fh: 3, 52 | fsync_flags: 0x1, 53 | })) 54 | }); 55 | 56 | assert_eq!( 57 | format!("{:#?}", request), 58 | concat!( 59 | "FsyncRequest {\n", 60 | " node_id: 1,\n", 61 | " handle: 3,\n", 62 | " flags: FsyncRequestFlags {\n", 63 | " FDATASYNC,\n", 64 | " },\n", 65 | "}", 66 | ), 67 | ); 68 | } 69 | -------------------------------------------------------------------------------- /fuse/operations/fsyncdir.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 John Millikin and the rust-fuse contributors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // SPDX-License-Identifier: Apache-2.0 16 | 17 | use core::fmt; 18 | 19 | use crate::kernel; 20 | use crate::server::decode; 21 | 22 | // FsyncdirRequest {{{ 23 | 24 | /// Request type for `FUSE_FSYNCDIR`. 25 | #[derive(Clone, Copy)] 26 | pub struct FsyncdirRequest<'a> { 27 | header: &'a kernel::fuse_in_header, 28 | body: &'a kernel::fuse_fsync_in, 29 | } 30 | 31 | impl FsyncdirRequest<'_> { 32 | #[must_use] 33 | pub fn node_id(&self) -> crate::NodeId { 34 | unsafe { crate::NodeId::new_unchecked(self.header.nodeid) } 35 | } 36 | 37 | #[must_use] 38 | pub fn handle(&self) -> u64 { 39 | self.body.fh 40 | } 41 | 42 | #[must_use] 43 | pub fn flags(&self) -> FsyncdirRequestFlags { 44 | FsyncdirRequestFlags { 45 | bits: self.body.fsync_flags, 46 | } 47 | } 48 | } 49 | 50 | try_from_fuse_request!(FsyncdirRequest<'a>, |request| { 51 | let mut dec = request.decoder(); 52 | dec.expect_opcode(kernel::fuse_opcode::FUSE_FSYNCDIR)?; 53 | 54 | let header = dec.header(); 55 | let body = dec.next_sized()?; 56 | decode::node_id(header.nodeid)?; 57 | Ok(Self { header, body }) 58 | }); 59 | 60 | impl fmt::Debug for FsyncdirRequest<'_> { 61 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { 62 | fmt.debug_struct("FsyncdirRequest") 63 | .field("node_id", &self.node_id()) 64 | .field("handle", &self.handle()) 65 | .field("flags", &self.flags()) 66 | .finish() 67 | } 68 | } 69 | 70 | // }}} 71 | 72 | // FsyncdirRequestFlags {{{ 73 | 74 | /// Optional flags set on [`FsyncdirRequest`]. 75 | #[derive(Clone, Copy, Eq, Hash, Ord, PartialEq, PartialOrd)] 76 | pub struct FsyncdirRequestFlags { 77 | bits: u32, 78 | } 79 | 80 | #[derive(Clone, Copy, Eq, Hash, Ord, PartialEq, PartialOrd)] 81 | pub struct FsyncdirRequestFlag { 82 | mask: u32, 83 | } 84 | 85 | mod request_flags { 86 | use crate::kernel; 87 | bitflags!(FsyncdirRequestFlag, FsyncdirRequestFlags, u32, { 88 | FDATASYNC = kernel::FUSE_FSYNC_FDATASYNC; 89 | }); 90 | } 91 | 92 | // }}} 93 | -------------------------------------------------------------------------------- /fuse/operations/fsyncdir/BUILD: -------------------------------------------------------------------------------- 1 | load("//fuse/internal/testing:testing.bzl", "operation_tests") 2 | 3 | operation_tests("fsyncdir") 4 | -------------------------------------------------------------------------------- /fuse/operations/fsyncdir/fsyncdir_test.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 John Millikin and the rust-fuse contributors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // SPDX-License-Identifier: Apache-2.0 16 | 17 | use fuse::kernel; 18 | use fuse::server::FsyncdirRequest; 19 | 20 | use fuse_testutil as testutil; 21 | use fuse_testutil::{decode_request, MessageBuilder}; 22 | 23 | #[test] 24 | fn request() { 25 | let buf = MessageBuilder::new() 26 | .set_header(|h| { 27 | h.opcode = kernel::fuse_opcode::FUSE_FSYNCDIR; 28 | h.nodeid = 123; 29 | }) 30 | .push_sized(&testutil::new!(kernel::fuse_fsync_in { 31 | fh: 3, 32 | fsync_flags: 0x1, 33 | })) 34 | .build_aligned(); 35 | 36 | let req = decode_request!(FsyncdirRequest, buf, { 37 | protocol_version: (7, 1), 38 | }); 39 | 40 | assert_eq!(req.handle(), 3); 41 | assert_eq!(req.flags().get(fuse::FsyncdirRequestFlag::FDATASYNC), true); 42 | } 43 | 44 | #[test] 45 | fn request_impl_debug() { 46 | let buf; 47 | let request = fuse_testutil::build_request!(buf, FsyncdirRequest, { 48 | .set_header(|h| { 49 | h.opcode = kernel::fuse_opcode::FUSE_FSYNCDIR; 50 | h.nodeid = kernel::FUSE_ROOT_ID; 51 | }) 52 | .push_sized(&testutil::new!(kernel::fuse_fsync_in { 53 | fh: 3, 54 | fsync_flags: 0x1, 55 | })) 56 | }); 57 | 58 | assert_eq!( 59 | format!("{:#?}", request), 60 | concat!( 61 | "FsyncdirRequest {\n", 62 | " node_id: 1,\n", 63 | " handle: 3,\n", 64 | " flags: FsyncdirRequestFlags {\n", 65 | " FDATASYNC,\n", 66 | " },\n", 67 | "}", 68 | ), 69 | ); 70 | } 71 | -------------------------------------------------------------------------------- /fuse/operations/fuse_init/BUILD: -------------------------------------------------------------------------------- 1 | load("//fuse/internal/testing:testing.bzl", "operation_tests") 2 | 3 | operation_tests("fuse_init") 4 | -------------------------------------------------------------------------------- /fuse/operations/getattr.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 John Millikin and the rust-fuse contributors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // SPDX-License-Identifier: Apache-2.0 16 | 17 | use core::fmt; 18 | 19 | use crate::internal::compat; 20 | use crate::kernel; 21 | use crate::server::decode; 22 | 23 | // GetattrRequest {{{ 24 | 25 | /// Request type for `FUSE_GETATTR`. 26 | #[derive(Clone, Copy)] 27 | pub struct GetattrRequest<'a> { 28 | header: &'a kernel::fuse_in_header, 29 | body: compat::Versioned>, 30 | } 31 | 32 | impl GetattrRequest<'_> { 33 | #[must_use] 34 | pub fn node_id(&self) -> crate::NodeId { 35 | unsafe { crate::NodeId::new_unchecked(self.header.nodeid) } 36 | } 37 | 38 | #[must_use] 39 | pub fn handle(&self) -> Option { 40 | let body = self.body.as_v7p9()?; 41 | if (body.getattr_flags & kernel::FUSE_GETATTR_FH) > 0 { 42 | return Some(body.fh); 43 | } 44 | None 45 | } 46 | } 47 | 48 | try_from_fuse_request!(GetattrRequest<'a>, |request| { 49 | let version_minor = request.layout.version_minor(); 50 | let mut dec = request.decoder(); 51 | dec.expect_opcode(kernel::fuse_opcode::FUSE_GETATTR)?; 52 | 53 | let header = dec.header(); 54 | decode::node_id(header.nodeid)?; 55 | 56 | let body = if version_minor >= 9 { 57 | let body_v7p9 = dec.next_sized()?; 58 | compat::Versioned::new_getattr_v7p9(version_minor, body_v7p9) 59 | } else { 60 | compat::Versioned::new_getattr_v7p1(version_minor) 61 | }; 62 | 63 | Ok(Self { header, body }) 64 | }); 65 | 66 | impl fmt::Debug for GetattrRequest<'_> { 67 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { 68 | fmt.debug_struct("GetattrRequest") 69 | .field("node_id", &self.node_id()) 70 | .field("handle", &format_args!("{:?}", &self.handle())) 71 | .finish() 72 | } 73 | } 74 | 75 | // }}} 76 | -------------------------------------------------------------------------------- /fuse/operations/getattr/BUILD: -------------------------------------------------------------------------------- 1 | load("//fuse/internal/testing:testing.bzl", "operation_tests") 2 | 3 | operation_tests("getattr") 4 | -------------------------------------------------------------------------------- /fuse/operations/getattr/getattr_test.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 John Millikin and the rust-fuse contributors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // SPDX-License-Identifier: Apache-2.0 16 | 17 | use fuse::kernel; 18 | use fuse::server::GetattrRequest; 19 | 20 | use fuse_testutil as testutil; 21 | use fuse_testutil::{decode_request, MessageBuilder}; 22 | 23 | #[test] 24 | fn request_v7p1() { 25 | let buf = MessageBuilder::new() 26 | .set_header(|h| { 27 | h.opcode = kernel::fuse_opcode::FUSE_GETATTR; 28 | h.nodeid = 123; 29 | }) 30 | .build_aligned(); 31 | 32 | let req = decode_request!(GetattrRequest, buf, { 33 | protocol_version: (7, 1), 34 | }); 35 | 36 | assert_eq!(req.handle(), None); 37 | } 38 | 39 | #[test] 40 | fn request_v7p9() { 41 | let buf = MessageBuilder::new() 42 | .set_header(|h| { 43 | h.opcode = kernel::fuse_opcode::FUSE_GETATTR; 44 | h.nodeid = 123; 45 | }) 46 | .push_sized(&kernel::fuse_getattr_in::new()) 47 | .build_aligned(); 48 | 49 | let req = decode_request!(GetattrRequest, buf, { 50 | protocol_version: (7, 9), 51 | }); 52 | 53 | assert_eq!(req.handle(), None); 54 | } 55 | 56 | #[test] 57 | fn request_v7p9_with_handle() { 58 | let buf = MessageBuilder::new() 59 | .set_header(|h| { 60 | h.opcode = kernel::fuse_opcode::FUSE_GETATTR; 61 | h.nodeid = 123; 62 | }) 63 | .push_sized(&testutil::new!(kernel::fuse_getattr_in { 64 | getattr_flags: kernel::FUSE_GETATTR_FH, 65 | fh: 123, 66 | })) 67 | .build_aligned(); 68 | 69 | let req = decode_request!(GetattrRequest, buf, { 70 | protocol_version: (7, 9), 71 | }); 72 | 73 | assert_eq!(req.handle(), Some(123)); 74 | } 75 | 76 | #[test] 77 | fn request_impl_debug() { 78 | let buf; 79 | let request = fuse_testutil::build_request!(buf, GetattrRequest, { 80 | .set_header(|h| { 81 | h.opcode = kernel::fuse_opcode::FUSE_GETATTR; 82 | h.nodeid = kernel::FUSE_ROOT_ID; 83 | }) 84 | .push_sized(&testutil::new!(kernel::fuse_getattr_in { 85 | getattr_flags: kernel::FUSE_GETATTR_FH, 86 | fh: 123, 87 | })) 88 | }); 89 | 90 | assert_eq!( 91 | format!("{:#?}", request), 92 | concat!( 93 | "GetattrRequest {\n", 94 | " node_id: 1,\n", 95 | " handle: Some(123),\n", 96 | "}", 97 | ), 98 | ); 99 | } 100 | -------------------------------------------------------------------------------- /fuse/operations/getlk.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 John Millikin and the rust-fuse contributors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // SPDX-License-Identifier: Apache-2.0 16 | 17 | use core::fmt; 18 | 19 | use crate::kernel; 20 | use crate::server::decode; 21 | 22 | // GetlkRequest {{{ 23 | 24 | /// Request type for `FUSE_GETLK`. 25 | #[derive(Clone, Copy)] 26 | pub struct GetlkRequest<'a> { 27 | header: &'a kernel::fuse_in_header, 28 | body: &'a kernel::fuse_lk_in, 29 | lock_range: crate::LockRange, 30 | } 31 | 32 | impl GetlkRequest<'_> { 33 | #[inline] 34 | #[must_use] 35 | pub fn node_id(&self) -> crate::NodeId { 36 | unsafe { crate::NodeId::new_unchecked(self.header.nodeid) } 37 | } 38 | 39 | #[inline] 40 | #[must_use] 41 | pub fn handle(&self) -> u64 { 42 | self.body.fh 43 | } 44 | 45 | #[inline] 46 | #[must_use] 47 | pub fn owner(&self) -> crate::LockOwner { 48 | crate::LockOwner(self.body.owner) 49 | } 50 | 51 | #[inline] 52 | #[must_use] 53 | pub fn lock_mode(&self) -> crate::LockMode { 54 | crate::LockMode(self.body.lk.r#type) 55 | } 56 | 57 | #[inline] 58 | #[must_use] 59 | pub fn lock_range(&self) -> crate::LockRange { 60 | self.lock_range 61 | } 62 | } 63 | 64 | try_from_fuse_request!(GetlkRequest<'a>, |request| { 65 | let mut dec = request.decoder(); 66 | dec.expect_opcode(kernel::fuse_opcode::FUSE_GETLK)?; 67 | 68 | let header = dec.header(); 69 | decode::node_id(header.nodeid)?; 70 | 71 | let body: &kernel::fuse_lk_in = dec.next_sized()?; 72 | let lock_range = crate::LockRange::decode(&body.lk)?; 73 | Ok(Self { header, body, lock_range }) 74 | }); 75 | 76 | impl fmt::Debug for GetlkRequest<'_> { 77 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { 78 | fmt.debug_struct("GetlkRequest") 79 | .field("node_id", &self.node_id()) 80 | .field("handle", &self.handle()) 81 | .field("owner", &self.owner()) 82 | .field("lock_mode", &self.lock_mode()) 83 | .field("lock_range", &self.lock_range()) 84 | .finish() 85 | } 86 | } 87 | 88 | // }}} 89 | -------------------------------------------------------------------------------- /fuse/operations/getlk/BUILD: -------------------------------------------------------------------------------- 1 | load("//fuse/internal/testing:testing.bzl", "operation_tests") 2 | 3 | operation_tests("getlk") 4 | -------------------------------------------------------------------------------- /fuse/operations/getxattr.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 John Millikin and the rust-fuse contributors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // SPDX-License-Identifier: Apache-2.0 16 | 17 | use core::fmt; 18 | use core::num; 19 | 20 | use crate::kernel; 21 | use crate::server::decode; 22 | 23 | // GetxattrRequest {{{ 24 | 25 | /// Request type for `FUSE_GETXATTR`. 26 | #[derive(Clone, Copy)] 27 | pub struct GetxattrRequest<'a> { 28 | header: &'a kernel::fuse_in_header, 29 | body: &'a kernel::fuse_getxattr_in, 30 | name: &'a core::ffi::CStr, 31 | } 32 | 33 | impl GetxattrRequest<'_> { 34 | #[inline] 35 | #[must_use] 36 | pub fn node_id(&self) -> crate::NodeId { 37 | unsafe { crate::NodeId::new_unchecked(self.header.nodeid) } 38 | } 39 | 40 | #[inline] 41 | #[must_use] 42 | pub fn size(&self) -> Option { 43 | let size = usize::try_from(self.body.size).unwrap_or(usize::MAX); 44 | num::NonZeroUsize::new(size) 45 | } 46 | 47 | #[inline] 48 | #[must_use] 49 | pub fn name(&self) -> &core::ffi::CStr { 50 | self.name 51 | } 52 | } 53 | 54 | try_from_fuse_request!(GetxattrRequest<'a>, |request| { 55 | let mut dec = request.decoder(); 56 | dec.expect_opcode(kernel::fuse_opcode::FUSE_GETXATTR)?; 57 | 58 | let header = dec.header(); 59 | decode::node_id(header.nodeid)?; 60 | 61 | let body = dec.next_sized()?; 62 | let name = dec.next_cstr()?; 63 | Ok(Self { header, body, name }) 64 | }); 65 | 66 | impl fmt::Debug for GetxattrRequest<'_> { 67 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { 68 | fmt.debug_struct("GetxattrRequest") 69 | .field("node_id", &self.node_id()) 70 | .field("size", &format_args!("{:?}", &self.size())) 71 | .field("name", &self.name()) 72 | .finish() 73 | } 74 | } 75 | 76 | // }}} 77 | -------------------------------------------------------------------------------- /fuse/operations/getxattr/BUILD: -------------------------------------------------------------------------------- 1 | load("//fuse/internal/testing:testing.bzl", "operation_tests") 2 | 3 | operation_tests("getxattr") 4 | -------------------------------------------------------------------------------- /fuse/operations/getxattr/getxattr_test.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 John Millikin and the rust-fuse contributors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // SPDX-License-Identifier: Apache-2.0 16 | 17 | use core::num; 18 | 19 | use fuse::kernel; 20 | use fuse::server::GetxattrRequest; 21 | 22 | use fuse_testutil as testutil; 23 | use fuse_testutil::{decode_request, MessageBuilder}; 24 | 25 | #[test] 26 | fn request_sized() { 27 | let buf = MessageBuilder::new() 28 | .set_header(|h| { 29 | h.opcode = kernel::fuse_opcode::FUSE_GETXATTR; 30 | h.nodeid = 123; 31 | }) 32 | .push_sized(&testutil::new!(kernel::fuse_getxattr_in { 33 | size: 10, 34 | })) 35 | .push_bytes(b"hello.world!\x00") 36 | .build_aligned(); 37 | 38 | let req = decode_request!(GetxattrRequest, buf); 39 | 40 | assert_eq!(req.size(), Some(num::NonZeroUsize::new(10).unwrap())); 41 | assert_eq!(req.name(), c"hello.world!"); 42 | } 43 | 44 | #[test] 45 | fn request_unsized() { 46 | let buf = MessageBuilder::new() 47 | .set_header(|h| { 48 | h.opcode = kernel::fuse_opcode::FUSE_GETXATTR; 49 | h.nodeid = 123; 50 | }) 51 | .push_sized(&kernel::fuse_getxattr_in::new()) 52 | .push_bytes(b"hello.world!\x00") 53 | .build_aligned(); 54 | 55 | let req = decode_request!(GetxattrRequest, buf); 56 | 57 | assert_eq!(req.size(), None); 58 | assert_eq!(req.name(), c"hello.world!"); 59 | } 60 | 61 | #[test] 62 | fn request_impl_debug() { 63 | let buf; 64 | let request = fuse_testutil::build_request!(buf, GetxattrRequest, { 65 | .set_header(|h| { 66 | h.opcode = kernel::fuse_opcode::FUSE_GETXATTR; 67 | h.nodeid = kernel::FUSE_ROOT_ID; 68 | }) 69 | .push_sized(&testutil::new!(kernel::fuse_getxattr_in { 70 | size: 11, 71 | })) 72 | .push_bytes(b"hello.world!\x00") 73 | }); 74 | 75 | assert_eq!( 76 | format!("{:#?}", request), 77 | concat!( 78 | "GetxattrRequest {\n", 79 | " node_id: 1,\n", 80 | " size: Some(11),\n", 81 | " name: \"hello.world!\",\n", 82 | "}", 83 | ), 84 | ); 85 | } 86 | -------------------------------------------------------------------------------- /fuse/operations/interrupt.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2022 John Millikin and the rust-fuse contributors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // SPDX-License-Identifier: Apache-2.0 16 | 17 | use core::fmt; 18 | use core::num; 19 | 20 | use crate::kernel; 21 | use crate::server; 22 | 23 | // InterruptRequest {{{ 24 | 25 | /// Request type for `FUSE_INTERRUPT`. 26 | #[derive(Clone, Copy)] 27 | pub struct InterruptRequest<'a> { 28 | body: &'a kernel::fuse_interrupt_in, 29 | } 30 | 31 | impl InterruptRequest<'_> { 32 | #[must_use] 33 | pub fn request_id(&self) -> num::NonZeroU64 { 34 | unsafe { num::NonZeroU64::new_unchecked(self.body.unique) } 35 | } 36 | } 37 | 38 | try_from_cuse_request!(InterruptRequest<'a>, |request| { 39 | Self::try_from(request.inner) 40 | }); 41 | 42 | try_from_fuse_request!(InterruptRequest<'a>, |request| { 43 | Self::try_from(request.inner) 44 | }); 45 | 46 | impl<'a> InterruptRequest<'a> { 47 | fn try_from( 48 | request: server::Request<'a>, 49 | ) -> Result { 50 | let mut dec = request.decoder(); 51 | dec.expect_opcode(kernel::fuse_opcode::FUSE_INTERRUPT)?; 52 | let body: &kernel::fuse_interrupt_in = dec.next_sized()?; 53 | if body.unique == 0 { 54 | return Err(server::RequestError::MissingRequestId); 55 | } 56 | Ok(Self { body }) 57 | } 58 | } 59 | 60 | impl fmt::Debug for InterruptRequest<'_> { 61 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { 62 | fmt.debug_struct("InterruptRequest") 63 | .field("request_id", &self.request_id()) 64 | .finish() 65 | } 66 | } 67 | 68 | // }}} 69 | -------------------------------------------------------------------------------- /fuse/operations/ioctl/BUILD: -------------------------------------------------------------------------------- 1 | load("//fuse/internal/testing:testing.bzl", "operation_tests") 2 | 3 | operation_tests( 4 | "ioctl", 5 | interop_test_os = ["linux"], 6 | ) 7 | -------------------------------------------------------------------------------- /fuse/operations/link.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 John Millikin and the rust-fuse contributors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // SPDX-License-Identifier: Apache-2.0 16 | 17 | use crate::kernel; 18 | use crate::server::decode; 19 | 20 | // LinkRequest {{{ 21 | 22 | /// Request type for `FUSE_LINK`. 23 | #[derive(Clone, Copy, Debug)] 24 | pub struct LinkRequest<'a> { 25 | node_id: crate::NodeId, 26 | new_parent_id: crate::NodeId, 27 | new_name: &'a crate::NodeName, 28 | } 29 | 30 | impl LinkRequest<'_> { 31 | #[must_use] 32 | pub fn node_id(&self) -> crate::NodeId { 33 | self.node_id 34 | } 35 | 36 | #[must_use] 37 | pub fn new_parent_id(&self) -> crate::NodeId { 38 | self.new_parent_id 39 | } 40 | 41 | #[must_use] 42 | pub fn new_name(&self) -> &crate::NodeName { 43 | self.new_name 44 | } 45 | } 46 | 47 | try_from_fuse_request!(LinkRequest<'a>, |request| { 48 | let mut dec = request.decoder(); 49 | dec.expect_opcode(kernel::fuse_opcode::FUSE_LINK)?; 50 | 51 | let raw: &kernel::fuse_link_in = dec.next_sized()?; 52 | let name = dec.next_node_name()?; 53 | Ok(Self { 54 | node_id: decode::node_id(raw.oldnodeid)?, 55 | new_parent_id: decode::node_id(dec.header().nodeid)?, 56 | new_name: name, 57 | }) 58 | }); 59 | 60 | // }}} 61 | -------------------------------------------------------------------------------- /fuse/operations/link/BUILD: -------------------------------------------------------------------------------- 1 | load("//fuse/internal/testing:testing.bzl", "operation_tests") 2 | 3 | operation_tests("link") 4 | -------------------------------------------------------------------------------- /fuse/operations/link/link_test.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 John Millikin and the rust-fuse contributors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // SPDX-License-Identifier: Apache-2.0 16 | 17 | use fuse::kernel; 18 | use fuse::server::LinkRequest; 19 | 20 | use fuse_testutil as testutil; 21 | use fuse_testutil::{decode_request, MessageBuilder}; 22 | 23 | #[test] 24 | fn request() { 25 | let buf = MessageBuilder::new() 26 | .set_header(|h| { 27 | h.opcode = kernel::fuse_opcode::FUSE_LINK; 28 | h.nodeid = 100; 29 | }) 30 | .push_sized(&testutil::new!(kernel::fuse_link_in { 31 | oldnodeid: 123, 32 | })) 33 | .push_bytes(b"hello.world!\x00") 34 | .build_aligned(); 35 | 36 | let req = decode_request!(LinkRequest, buf); 37 | 38 | assert_eq!(req.node_id(), fuse::NodeId::new(123).unwrap()); 39 | assert_eq!(req.new_parent_id(), fuse::NodeId::new(100).unwrap()); 40 | assert_eq!(req.new_name(), "hello.world!"); 41 | } 42 | 43 | #[test] 44 | fn request_impl_debug() { 45 | let buf = MessageBuilder::new() 46 | .set_header(|h| { 47 | h.opcode = kernel::fuse_opcode::FUSE_LINK; 48 | h.nodeid = 100; 49 | }) 50 | .push_sized(&testutil::new!(kernel::fuse_link_in { 51 | oldnodeid: 123, 52 | })) 53 | .push_bytes(b"hello.world!\x00") 54 | .build_aligned(); 55 | let request = decode_request!(LinkRequest, buf); 56 | 57 | assert_eq!( 58 | format!("{:#?}", request), 59 | concat!( 60 | "LinkRequest {\n", 61 | " node_id: 123,\n", 62 | " new_parent_id: 100,\n", 63 | " new_name: \"hello.world!\",\n", 64 | "}", 65 | ), 66 | ); 67 | } 68 | -------------------------------------------------------------------------------- /fuse/operations/listxattr/BUILD: -------------------------------------------------------------------------------- 1 | load("//fuse/internal/testing:testing.bzl", "operation_tests") 2 | 3 | operation_tests("listxattr") 4 | -------------------------------------------------------------------------------- /fuse/operations/listxattr/listxattr_test.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 John Millikin and the rust-fuse contributors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // SPDX-License-Identifier: Apache-2.0 16 | 17 | use core::num; 18 | 19 | use fuse::kernel; 20 | use fuse::server::{ 21 | ListxattrNamesWriter, 22 | ListxattrRequest, 23 | }; 24 | 25 | use fuse_testutil as testutil; 26 | use fuse_testutil::{decode_request, MessageBuilder}; 27 | 28 | #[test] 29 | fn request_sized() { 30 | let buf = MessageBuilder::new() 31 | .set_header(|h| { 32 | h.opcode = kernel::fuse_opcode::FUSE_LISTXATTR; 33 | h.nodeid = 123; 34 | }) 35 | .push_sized(&testutil::new!(kernel::fuse_getxattr_in { 36 | size: 10, 37 | })) 38 | .build_aligned(); 39 | 40 | let req = decode_request!(ListxattrRequest, buf); 41 | 42 | assert_eq!(req.size(), Some(num::NonZeroUsize::new(10).unwrap())); 43 | } 44 | 45 | #[test] 46 | fn request_unsized() { 47 | let buf = MessageBuilder::new() 48 | .set_header(|h| { 49 | h.opcode = kernel::fuse_opcode::FUSE_LISTXATTR; 50 | h.nodeid = 123; 51 | }) 52 | .push_sized(&kernel::fuse_getxattr_in::new()) 53 | .build_aligned(); 54 | 55 | let req = decode_request!(ListxattrRequest, buf); 56 | 57 | assert_eq!(req.size(), None); 58 | } 59 | 60 | #[test] 61 | fn request_impl_debug() { 62 | let buf; 63 | let request = fuse_testutil::build_request!(buf, ListxattrRequest, { 64 | .set_header(|h| { 65 | h.opcode = kernel::fuse_opcode::FUSE_LISTXATTR; 66 | h.nodeid = kernel::FUSE_ROOT_ID; 67 | }) 68 | .push_sized(&testutil::new!(kernel::fuse_getxattr_in { 69 | size: 11, 70 | })) 71 | }); 72 | 73 | assert_eq!( 74 | format!("{:#?}", request), 75 | concat!( 76 | "ListxattrRequest {\n", 77 | " node_id: 1,\n", 78 | " size: Some(11),\n", 79 | "}", 80 | ), 81 | ); 82 | } 83 | 84 | #[test] 85 | fn listxattr_names() { 86 | let mut buf = [0u8; 10]; 87 | let mut names = ListxattrNamesWriter::new(&mut buf); 88 | assert_eq!(names.capacity(), 10); 89 | 90 | // response must fit in provided buffer 91 | { 92 | assert!(names.try_push(c"12345678901").is_err()); 93 | } 94 | 95 | // xattr names are NUL-terminated, so two 3-byte names requires 8 bytes 96 | // of buffer space. 97 | names.try_push(c"123").unwrap(); 98 | names.try_push(c"456").unwrap(); 99 | assert_eq!(names.position(), 8); 100 | 101 | let names = names.into_names(); 102 | assert_eq!(names.as_bytes(), b"123\x00456\x00") 103 | } 104 | -------------------------------------------------------------------------------- /fuse/operations/lookup.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 John Millikin and the rust-fuse contributors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // SPDX-License-Identifier: Apache-2.0 16 | 17 | use crate::kernel; 18 | use crate::server::decode; 19 | 20 | // LookupRequest {{{ 21 | 22 | /// Request type for `FUSE_LOOKUP`. 23 | #[derive(Clone, Copy, Debug)] 24 | pub struct LookupRequest<'a> { 25 | parent_id: crate::NodeId, 26 | name: &'a crate::NodeName, 27 | } 28 | 29 | impl LookupRequest<'_> { 30 | #[must_use] 31 | pub fn parent_id(&self) -> crate::NodeId { 32 | self.parent_id 33 | } 34 | 35 | #[must_use] 36 | pub fn name(&self) -> &crate::NodeName { 37 | self.name 38 | } 39 | } 40 | 41 | try_from_fuse_request!(LookupRequest<'a>, |request| { 42 | let mut dec = request.decoder(); 43 | dec.expect_opcode(kernel::fuse_opcode::FUSE_LOOKUP)?; 44 | Ok(Self { 45 | parent_id: decode::node_id(dec.header().nodeid)?, 46 | name: dec.next_node_name()?, 47 | }) 48 | }); 49 | 50 | // }}} 51 | -------------------------------------------------------------------------------- /fuse/operations/lookup/BUILD: -------------------------------------------------------------------------------- 1 | load("//fuse/internal/testing:testing.bzl", "operation_tests") 2 | 3 | operation_tests("lookup") 4 | -------------------------------------------------------------------------------- /fuse/operations/lookup/lookup_test.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 John Millikin and the rust-fuse contributors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // SPDX-License-Identifier: Apache-2.0 16 | 17 | use fuse::kernel; 18 | use fuse::server::LookupRequest; 19 | 20 | use fuse_testutil::{decode_request, MessageBuilder}; 21 | 22 | #[test] 23 | fn request() { 24 | let buf = MessageBuilder::new() 25 | .set_header(|h| { 26 | h.opcode = kernel::fuse_opcode::FUSE_LOOKUP; 27 | h.nodeid = 123; 28 | }) 29 | .push_bytes(b"hello.world!\x00") 30 | .build_aligned(); 31 | let req = decode_request!(LookupRequest, buf); 32 | 33 | assert_eq!(req.name(), "hello.world!"); 34 | } 35 | 36 | #[test] 37 | fn request_impl_debug() { 38 | let buf = MessageBuilder::new() 39 | .set_header(|h| { 40 | h.opcode = kernel::fuse_opcode::FUSE_LOOKUP; 41 | h.nodeid = 123; 42 | }) 43 | .push_bytes(b"hello.world!\x00") 44 | .build_aligned(); 45 | let request = decode_request!(LookupRequest, buf); 46 | 47 | assert_eq!( 48 | format!("{:#?}", request), 49 | concat!( 50 | "LookupRequest {\n", 51 | " parent_id: 123,\n", 52 | " name: \"hello.world!\",\n", 53 | "}", 54 | ), 55 | ); 56 | } 57 | -------------------------------------------------------------------------------- /fuse/operations/lseek.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 John Millikin and the rust-fuse contributors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // SPDX-License-Identifier: Apache-2.0 16 | 17 | use core::fmt; 18 | 19 | use crate::kernel; 20 | use crate::server::decode; 21 | 22 | // LseekRequest {{{ 23 | 24 | /// Request type for `FUSE_LSEEK`. 25 | #[derive(Clone, Copy)] 26 | pub struct LseekRequest<'a> { 27 | raw: &'a kernel::fuse_lseek_in, 28 | node_id: crate::NodeId, 29 | } 30 | 31 | impl LseekRequest<'_> { 32 | #[must_use] 33 | pub fn node_id(&self) -> crate::NodeId { 34 | self.node_id 35 | } 36 | 37 | #[must_use] 38 | pub fn handle(&self) -> u64 { 39 | self.raw.fh 40 | } 41 | 42 | #[must_use] 43 | pub fn offset(&self) -> u64 { 44 | self.raw.offset 45 | } 46 | 47 | #[must_use] 48 | pub fn whence(&self) -> LseekWhence { 49 | LseekWhence(self.raw.whence) 50 | } 51 | } 52 | 53 | try_from_fuse_request!(LseekRequest<'a>, |request| { 54 | let mut dec = request.decoder(); 55 | dec.expect_opcode(kernel::fuse_opcode::FUSE_LSEEK)?; 56 | let raw = dec.next_sized()?; 57 | Ok(Self { 58 | raw, 59 | node_id: decode::node_id(dec.header().nodeid)?, 60 | }) 61 | }); 62 | 63 | impl fmt::Debug for LseekRequest<'_> { 64 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { 65 | fmt.debug_struct("LseekRequest") 66 | .field("node_id", &self.node_id) 67 | .field("handle", &self.raw.fh) 68 | .field("offset", &self.raw.offset) 69 | .field("whence", &LseekWhence(self.raw.whence)) 70 | .finish() 71 | } 72 | } 73 | 74 | #[derive(Eq, PartialEq)] 75 | pub struct LseekWhence(u32); 76 | 77 | impl LseekWhence { 78 | pub const SEEK_DATA: LseekWhence = LseekWhence(3); 79 | pub const SEEK_HOLE: LseekWhence = LseekWhence(4); 80 | } 81 | 82 | impl fmt::Debug for LseekWhence { 83 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { 84 | match self.0 { 85 | 3 => fmt.write_str("SEEK_DATA"), 86 | 4 => fmt.write_str("SEEK_HOLE"), 87 | _ => self.0.fmt(fmt), 88 | } 89 | } 90 | } 91 | 92 | // }}} 93 | -------------------------------------------------------------------------------- /fuse/operations/lseek/BUILD: -------------------------------------------------------------------------------- 1 | load("//fuse/internal/testing:testing.bzl", "operation_tests") 2 | 3 | operation_tests( 4 | "lseek", 5 | interop_test_os = ["linux"], 6 | ) 7 | -------------------------------------------------------------------------------- /fuse/operations/lseek/lseek_test.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2021 John Millikin and the rust-fuse contributors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // SPDX-License-Identifier: Apache-2.0 16 | 17 | use fuse::kernel; 18 | use fuse::server::LseekRequest; 19 | 20 | use fuse_testutil as testutil; 21 | use fuse_testutil::{decode_request, MessageBuilder}; 22 | 23 | #[test] 24 | fn request() { 25 | let buf = MessageBuilder::new() 26 | .set_header(|h| { 27 | h.opcode = kernel::fuse_opcode::FUSE_LSEEK; 28 | h.nodeid = 123; 29 | }) 30 | .push_sized(&testutil::new!(kernel::fuse_lseek_in { 31 | fh: 12, 32 | offset: 34, 33 | whence: 3, 34 | })) 35 | .build_aligned(); 36 | 37 | let req = decode_request!(LseekRequest, buf); 38 | 39 | assert_eq!(req.handle(), 12); 40 | assert_eq!(req.offset(), 34); 41 | assert_eq!(req.whence(), fuse::LseekWhence::SEEK_DATA); 42 | } 43 | 44 | #[test] 45 | fn request_impl_debug() { 46 | let buf; 47 | let request = fuse_testutil::build_request!(buf, LseekRequest, { 48 | .set_header(|h| { 49 | h.opcode = kernel::fuse_opcode::FUSE_LSEEK; 50 | h.nodeid = kernel::FUSE_ROOT_ID; 51 | }) 52 | .push_sized(&testutil::new!(kernel::fuse_lseek_in { 53 | fh: 12, 54 | offset: 34, 55 | whence: 3, 56 | })) 57 | }); 58 | 59 | assert_eq!( 60 | format!("{:#?}", request), 61 | concat!( 62 | "LseekRequest {\n", 63 | " node_id: 1,\n", 64 | " handle: 12,\n", 65 | " offset: 34,\n", 66 | " whence: SEEK_DATA,\n", 67 | "}", 68 | ), 69 | ); 70 | } 71 | -------------------------------------------------------------------------------- /fuse/operations/mkdir.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 John Millikin and the rust-fuse contributors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // SPDX-License-Identifier: Apache-2.0 16 | 17 | use core::fmt; 18 | 19 | use crate::kernel; 20 | use crate::server::decode; 21 | 22 | // MkdirRequest {{{ 23 | 24 | /// Request type for `FUSE_MKDIR`. 25 | #[derive(Clone, Copy)] 26 | pub struct MkdirRequest<'a> { 27 | parent_id: crate::NodeId, 28 | name: &'a crate::NodeName, 29 | raw: kernel::fuse_mkdir_in, 30 | } 31 | 32 | impl MkdirRequest<'_> { 33 | #[must_use] 34 | pub fn parent_id(&self) -> crate::NodeId { 35 | self.parent_id 36 | } 37 | 38 | #[must_use] 39 | pub fn name(&self) -> &crate::NodeName { 40 | self.name 41 | } 42 | 43 | #[must_use] 44 | pub fn mode(&self) -> crate::FileMode { 45 | crate::FileMode::new(self.raw.mode) 46 | } 47 | 48 | #[must_use] 49 | pub fn umask(&self) -> u32 { 50 | self.raw.umask 51 | } 52 | } 53 | 54 | try_from_fuse_request!(MkdirRequest<'a>, |request| { 55 | let mut dec = request.decoder(); 56 | dec.expect_opcode(kernel::fuse_opcode::FUSE_MKDIR)?; 57 | 58 | let raw: &kernel::fuse_mkdir_in = dec.next_sized()?; 59 | let name = dec.next_node_name()?; 60 | Ok(Self { 61 | parent_id: decode::node_id(dec.header().nodeid)?, 62 | name, 63 | raw: *raw, 64 | }) 65 | }); 66 | 67 | impl fmt::Debug for MkdirRequest<'_> { 68 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { 69 | fmt.debug_struct("MkdirRequest") 70 | .field("parent_id", &self.parent_id()) 71 | .field("name", &self.name()) 72 | .field("mode", &self.mode()) 73 | .field("umask", &format_args!("{:#o}", &self.raw.umask)) 74 | .finish() 75 | } 76 | } 77 | 78 | // }}} 79 | -------------------------------------------------------------------------------- /fuse/operations/mkdir/BUILD: -------------------------------------------------------------------------------- 1 | load("//fuse/internal/testing:testing.bzl", "operation_tests") 2 | 3 | operation_tests("mkdir") 4 | -------------------------------------------------------------------------------- /fuse/operations/mkdir/mkdir_test.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 John Millikin and the rust-fuse contributors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // SPDX-License-Identifier: Apache-2.0 16 | 17 | use fuse::kernel; 18 | use fuse::server::MkdirRequest; 19 | 20 | use fuse_testutil as testutil; 21 | use fuse_testutil::{decode_request, MessageBuilder}; 22 | 23 | #[test] 24 | fn request() { 25 | let buf = MessageBuilder::new() 26 | .set_header(|h| { 27 | h.opcode = kernel::fuse_opcode::FUSE_MKDIR; 28 | h.nodeid = 100; 29 | }) 30 | .push_sized(&testutil::new!(kernel::fuse_mkdir_in { 31 | mode: 0o755, 32 | umask: 0o111, 33 | })) 34 | .push_bytes(b"hello.world!\x00") 35 | .build_aligned(); 36 | 37 | let req = decode_request!(MkdirRequest, buf); 38 | 39 | assert_eq!(req.parent_id(), fuse::NodeId::new(100).unwrap()); 40 | assert_eq!(req.name(), "hello.world!"); 41 | assert_eq!(req.mode(), fuse::FileMode::new(0o755)); 42 | assert_eq!(req.umask(), 0o111); 43 | } 44 | 45 | #[test] 46 | fn request_impl_debug() { 47 | let buf = MessageBuilder::new() 48 | .set_header(|h| { 49 | h.opcode = kernel::fuse_opcode::FUSE_MKDIR; 50 | h.nodeid = 100; 51 | }) 52 | .push_sized(&testutil::new!(kernel::fuse_mkdir_in { 53 | mode: 0o755, 54 | umask: 0o111, 55 | })) 56 | .push_bytes(b"hello.world!\x00") 57 | .build_aligned(); 58 | let request = decode_request!(MkdirRequest, buf); 59 | 60 | assert_eq!( 61 | format!("{:#?}", request), 62 | concat!( 63 | "MkdirRequest {\n", 64 | " parent_id: 100,\n", 65 | " name: \"hello.world!\",\n", 66 | " mode: 0o755,\n", 67 | " umask: 0o111,\n", 68 | "}", 69 | ), 70 | ); 71 | } 72 | -------------------------------------------------------------------------------- /fuse/operations/mknod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 John Millikin and the rust-fuse contributors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // SPDX-License-Identifier: Apache-2.0 16 | 17 | use core::fmt; 18 | 19 | use crate::internal::compat; 20 | use crate::kernel; 21 | use crate::server::decode; 22 | 23 | // MknodRequest {{{ 24 | 25 | /// Request type for `FUSE_MKNOD`. 26 | #[derive(Clone, Copy)] 27 | pub struct MknodRequest<'a> { 28 | header: &'a kernel::fuse_in_header, 29 | body: compat::Versioned>, 30 | name: &'a crate::NodeName, 31 | } 32 | 33 | impl MknodRequest<'_> { 34 | #[must_use] 35 | pub fn parent_id(&self) -> crate::NodeId { 36 | unsafe { crate::NodeId::new_unchecked(self.header.nodeid) } 37 | } 38 | 39 | #[must_use] 40 | pub fn name(&self) -> &crate::NodeName { 41 | self.name 42 | } 43 | 44 | #[must_use] 45 | pub fn mode(&self) -> crate::FileMode { 46 | crate::FileMode::new(self.body.as_v7p1().mode) 47 | } 48 | 49 | #[must_use] 50 | pub fn umask(&self) -> u32 { 51 | if let Some(body) = self.body.as_v7p12() { 52 | return body.umask; 53 | } 54 | 0 55 | } 56 | 57 | #[must_use] 58 | pub fn device_number(&self) -> Option { 59 | use crate::FileType as T; 60 | let body = self.body.as_v7p1(); 61 | match crate::FileType::from_mode(self.mode()) { 62 | Some(T::CharacterDevice | T::BlockDevice) => Some(body.rdev), 63 | _ => None, 64 | } 65 | } 66 | } 67 | 68 | try_from_fuse_request!(MknodRequest<'a>, |request| { 69 | let version_minor = request.layout.version_minor(); 70 | let mut dec = request.decoder(); 71 | dec.expect_opcode(kernel::fuse_opcode::FUSE_MKNOD)?; 72 | 73 | let header = dec.header(); 74 | decode::node_id(dec.header().nodeid)?; 75 | 76 | let body = if version_minor >= 12 { 77 | let body_v7p12 = dec.next_sized()?; 78 | compat::Versioned::new_mknod_v7p12(version_minor, body_v7p12) 79 | } else { 80 | let body_v7p1 = dec.next_sized()?; 81 | compat::Versioned::new_mknod_v7p1(version_minor, body_v7p1) 82 | }; 83 | 84 | let name = dec.next_node_name()?; 85 | 86 | Ok(Self { header, body, name }) 87 | }); 88 | 89 | impl fmt::Debug for MknodRequest<'_> { 90 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { 91 | fmt.debug_struct("MknodRequest") 92 | .field("parent_id", &self.parent_id()) 93 | .field("name", &self.name()) 94 | .field("mode", &self.mode()) 95 | .field("umask", &format_args!("{:#o}", &self.umask())) 96 | .field("device_number", &format_args!("{:?}", self.device_number())) 97 | .finish() 98 | } 99 | } 100 | 101 | // }}} 102 | -------------------------------------------------------------------------------- /fuse/operations/mknod/BUILD: -------------------------------------------------------------------------------- 1 | load("//fuse/internal/testing:testing.bzl", "operation_tests") 2 | 3 | operation_tests("mknod") 4 | -------------------------------------------------------------------------------- /fuse/operations/mknod/mknod_test.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 John Millikin and the rust-fuse contributors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // SPDX-License-Identifier: Apache-2.0 16 | 17 | use fuse::kernel; 18 | use fuse::server::MknodRequest; 19 | 20 | use fuse_testutil as testutil; 21 | use fuse_testutil::{decode_request, MessageBuilder}; 22 | 23 | const S_IFBLK: u32 = 0o60000; 24 | 25 | #[test] 26 | fn request_v7p1() { 27 | let buf = MessageBuilder::new() 28 | .set_header(|h| { 29 | h.opcode = kernel::fuse_opcode::FUSE_MKNOD; 30 | h.nodeid = 100; 31 | }) 32 | .push_sized(&0o644u32) 33 | .push_sized(&0u32) 34 | .push_bytes(b"hello.world!\x00") 35 | .build_aligned(); 36 | 37 | let req = decode_request!(MknodRequest, buf, { 38 | protocol_version: (7, 1), 39 | }); 40 | 41 | assert_eq!(req.parent_id(), fuse::NodeId::new(100).unwrap()); 42 | assert_eq!(req.name(), "hello.world!"); 43 | assert_eq!(req.mode(), fuse::FileMode::new(0o644)); 44 | assert_eq!(req.umask(), 0); 45 | assert_eq!(req.device_number(), None); 46 | } 47 | 48 | #[test] 49 | fn request_v7p12() { 50 | let buf = MessageBuilder::new() 51 | .set_header(|h| { 52 | h.opcode = kernel::fuse_opcode::FUSE_MKNOD; 53 | h.nodeid = 100; 54 | }) 55 | .push_sized(&testutil::new!(kernel::fuse_mknod_in { 56 | mode: 0o644, 57 | umask: 0o111, 58 | })) 59 | .push_bytes(b"hello.world!\x00") 60 | .build_aligned(); 61 | 62 | let req = decode_request!(MknodRequest, buf, { 63 | protocol_version: (7, 12), 64 | }); 65 | 66 | assert_eq!(req.parent_id(), fuse::NodeId::new(100).unwrap()); 67 | assert_eq!(req.name(), "hello.world!"); 68 | assert_eq!(req.mode(), fuse::FileMode::new(0o644)); 69 | assert_eq!(req.umask(), 0o111); 70 | assert_eq!(req.device_number(), None); 71 | } 72 | 73 | #[test] 74 | fn request_device_number() { 75 | let buf = MessageBuilder::new() 76 | .set_header(|h| { 77 | h.opcode = kernel::fuse_opcode::FUSE_MKNOD; 78 | h.nodeid = 100; 79 | }) 80 | .push_sized(&testutil::new!(kernel::fuse_mknod_in { 81 | mode: S_IFBLK | 0o644, 82 | rdev: 123, 83 | umask: 0o111, 84 | })) 85 | .push_bytes(b"hello.world!\x00") 86 | .build_aligned(); 87 | 88 | let req = decode_request!(MknodRequest, buf, { 89 | protocol_version: (7, 12), 90 | }); 91 | 92 | assert_eq!( 93 | fuse::FileType::from_mode(req.mode()), 94 | Some(fuse::FileType::BlockDevice) 95 | ); 96 | assert_eq!(req.mode().permissions(), 0o644); 97 | assert_eq!(req.device_number(), Some(123)); 98 | } 99 | 100 | #[test] 101 | fn request_impl_debug() { 102 | let buf = MessageBuilder::new() 103 | .set_header(|h| { 104 | h.opcode = kernel::fuse_opcode::FUSE_MKNOD; 105 | h.nodeid = 100; 106 | }) 107 | .push_sized(&testutil::new!(kernel::fuse_mknod_in { 108 | mode: S_IFBLK | 0o644, 109 | rdev: 123, 110 | umask: 0o111, 111 | })) 112 | .push_bytes(b"hello.world!\x00") 113 | .build_aligned(); 114 | let request = decode_request!(MknodRequest, buf); 115 | 116 | assert_eq!( 117 | format!("{:#?}", request), 118 | concat!( 119 | "MknodRequest {\n", 120 | " parent_id: 100,\n", 121 | " name: \"hello.world!\",\n", 122 | " mode: 0o60644,\n", 123 | " umask: 0o111,\n", 124 | " device_number: Some(123),\n", 125 | "}", 126 | ), 127 | ); 128 | } 129 | -------------------------------------------------------------------------------- /fuse/operations/open.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 John Millikin and the rust-fuse contributors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // SPDX-License-Identifier: Apache-2.0 16 | 17 | use core::fmt; 18 | 19 | use crate::internal::debug; 20 | use crate::kernel; 21 | use crate::server; 22 | use crate::server::decode; 23 | 24 | // OpenRequest {{{ 25 | 26 | /// Request type for `FUSE_OPEN`. 27 | #[derive(Clone, Copy)] 28 | pub struct OpenRequest<'a> { 29 | header: &'a kernel::fuse_in_header, 30 | body: &'a kernel::fuse_open_in, 31 | } 32 | 33 | impl OpenRequest<'_> { 34 | #[must_use] 35 | pub fn node_id(&self) -> crate::NodeId { 36 | crate::NodeId::new(self.header.nodeid).unwrap_or(crate::NodeId::ROOT) 37 | } 38 | 39 | #[must_use] 40 | pub fn flags(&self) -> OpenRequestFlags { 41 | OpenRequestFlags { 42 | bits: self.body.open_flags, 43 | } 44 | } 45 | 46 | #[must_use] 47 | #[allow(clippy::misnamed_getters)] 48 | pub fn open_flags(&self) -> crate::OpenFlags { 49 | self.body.flags 50 | } 51 | } 52 | 53 | try_from_cuse_request!(OpenRequest<'a>, |request| { 54 | Self::try_from(request.inner, true) 55 | }); 56 | 57 | try_from_fuse_request!(OpenRequest<'a>, |request| { 58 | Self::try_from(request.inner, false) 59 | }); 60 | 61 | impl<'a> OpenRequest<'a> { 62 | fn try_from( 63 | request: server::Request<'a>, 64 | is_cuse: bool, 65 | ) -> Result { 66 | let mut dec = request.decoder(); 67 | dec.expect_opcode(kernel::fuse_opcode::FUSE_OPEN)?; 68 | 69 | let header = dec.header(); 70 | let body = dec.next_sized()?; 71 | if !is_cuse { 72 | decode::node_id(header.nodeid)?; 73 | } 74 | Ok(Self { header, body }) 75 | } 76 | } 77 | 78 | impl fmt::Debug for OpenRequest<'_> { 79 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { 80 | fmt.debug_struct("OpenRequest") 81 | .field("node_id", &self.node_id()) 82 | .field("flags", &self.flags()) 83 | .field("open_flags", &debug::hex_u32(self.open_flags())) 84 | .finish() 85 | } 86 | } 87 | 88 | // }}} 89 | 90 | // OpenRequestFlags {{{ 91 | 92 | #[derive(Clone, Copy, Eq, Hash, Ord, PartialEq, PartialOrd)] 93 | pub struct OpenRequestFlags { 94 | bits: u32, 95 | } 96 | 97 | #[derive(Clone, Copy, Eq, Hash, Ord, PartialEq, PartialOrd)] 98 | pub struct OpenRequestFlag { 99 | mask: u32, 100 | } 101 | 102 | mod request_flags { 103 | use crate::kernel; 104 | bitflags!(OpenRequestFlag, OpenRequestFlags, u32, { 105 | KILL_SUIDGID = kernel::FUSE_OPEN_KILL_SUIDGID; 106 | }); 107 | } 108 | 109 | // }}} 110 | 111 | // OpenResponseFlags {{{ 112 | 113 | #[derive(Clone, Copy, Eq, Hash, Ord, PartialEq, PartialOrd)] 114 | pub struct OpenResponseFlags { 115 | bits: u32, 116 | } 117 | 118 | #[derive(Clone, Copy, Eq, Hash, Ord, PartialEq, PartialOrd)] 119 | pub struct OpenResponseFlag { 120 | mask: u32, 121 | } 122 | 123 | mod response_flags { 124 | use crate::kernel; 125 | bitflags!(OpenResponseFlag, OpenResponseFlags, u32, { 126 | DIRECT_IO = kernel::FOPEN_DIRECT_IO; 127 | KEEP_CACHE = kernel::FOPEN_KEEP_CACHE; 128 | NONSEEKABLE = kernel::FOPEN_NONSEEKABLE; 129 | CACHE_DIR = kernel::FOPEN_CACHE_DIR; 130 | STREAM = kernel::FOPEN_STREAM; 131 | NOFLUSH = kernel::FOPEN_NOFLUSH; 132 | }); 133 | } 134 | 135 | // }}} 136 | -------------------------------------------------------------------------------- /fuse/operations/open/BUILD: -------------------------------------------------------------------------------- 1 | load("//fuse/internal/testing:testing.bzl", "operation_tests") 2 | 3 | operation_tests("open") 4 | -------------------------------------------------------------------------------- /fuse/operations/open/open_test.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 John Millikin and the rust-fuse contributors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // SPDX-License-Identifier: Apache-2.0 16 | 17 | use fuse::kernel; 18 | use fuse::server::OpenRequest; 19 | 20 | use fuse_testutil as testutil; 21 | use fuse_testutil::{decode_request, MessageBuilder}; 22 | 23 | #[test] 24 | fn request() { 25 | let buf = MessageBuilder::new() 26 | .set_header(|h| { 27 | h.opcode = kernel::fuse_opcode::FUSE_OPEN; 28 | h.nodeid = 123; 29 | }) 30 | .push_sized(&testutil::new!(kernel::fuse_open_in { 31 | flags: 0xFF, 32 | open_flags: kernel::FUSE_OPEN_KILL_SUIDGID, 33 | })) 34 | .build_aligned(); 35 | 36 | let req = decode_request!(OpenRequest, buf); 37 | 38 | assert_eq!(req.flags().get(fuse::OpenRequestFlag::KILL_SUIDGID), true); 39 | assert_eq!(req.open_flags(), 0xFF); 40 | } 41 | 42 | #[test] 43 | fn request_impl_debug() { 44 | let buf; 45 | let request = fuse_testutil::build_request!(buf, OpenRequest, { 46 | .set_header(|h| { 47 | h.opcode = kernel::fuse_opcode::FUSE_OPEN; 48 | h.nodeid = kernel::FUSE_ROOT_ID; 49 | }) 50 | .push_sized(&testutil::new!(kernel::fuse_open_in { 51 | flags: 0xFF, 52 | open_flags: kernel::FUSE_OPEN_KILL_SUIDGID, 53 | })) 54 | }); 55 | 56 | assert_eq!( 57 | format!("{:#?}", request), 58 | concat!( 59 | "OpenRequest {\n", 60 | " node_id: 1,\n", 61 | " flags: OpenRequestFlags {\n", 62 | " KILL_SUIDGID,\n", 63 | " },\n", 64 | " open_flags: 0x000000FF,\n", 65 | "}", 66 | ), 67 | ); 68 | } 69 | -------------------------------------------------------------------------------- /fuse/operations/opendir.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 John Millikin and the rust-fuse contributors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // SPDX-License-Identifier: Apache-2.0 16 | 17 | use core::fmt; 18 | 19 | use crate::internal::debug; 20 | use crate::kernel; 21 | use crate::server::decode; 22 | 23 | // OpendirRequest {{{ 24 | 25 | /// Request type for `FUSE_OPENDIR`. 26 | #[derive(Clone, Copy)] 27 | pub struct OpendirRequest<'a> { 28 | header: &'a kernel::fuse_in_header, 29 | body: &'a kernel::fuse_open_in, 30 | } 31 | 32 | impl OpendirRequest<'_> { 33 | #[must_use] 34 | pub fn node_id(&self) -> crate::NodeId { 35 | unsafe { crate::NodeId::new_unchecked(self.header.nodeid) } 36 | } 37 | 38 | #[must_use] 39 | pub fn flags(&self) -> OpendirRequestFlags { 40 | OpendirRequestFlags { 41 | bits: self.body.open_flags, 42 | } 43 | } 44 | 45 | #[must_use] 46 | #[allow(clippy::misnamed_getters)] 47 | pub fn open_flags(&self) -> crate::OpenFlags { 48 | self.body.flags 49 | } 50 | } 51 | 52 | try_from_fuse_request!(OpendirRequest<'a>, |request| { 53 | let mut dec = request.decoder(); 54 | dec.expect_opcode(kernel::fuse_opcode::FUSE_OPENDIR)?; 55 | 56 | let header = dec.header(); 57 | let body = dec.next_sized()?; 58 | decode::node_id(header.nodeid)?; 59 | Ok(Self { header, body }) 60 | }); 61 | 62 | impl fmt::Debug for OpendirRequest<'_> { 63 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { 64 | fmt.debug_struct("OpendirRequest") 65 | .field("node_id", &self.node_id()) 66 | .field("flags", &self.flags()) 67 | .field("open_flags", &debug::hex_u32(self.open_flags())) 68 | .finish() 69 | } 70 | } 71 | 72 | // }}} 73 | 74 | // OpendirRequestFlags {{{ 75 | 76 | #[derive(Clone, Copy, Eq, Hash, Ord, PartialEq, PartialOrd)] 77 | pub struct OpendirRequestFlags { 78 | bits: u32, 79 | } 80 | 81 | #[derive(Clone, Copy, Eq, Hash, Ord, PartialEq, PartialOrd)] 82 | pub struct OpendirRequestFlag { 83 | mask: u32, 84 | } 85 | 86 | mod request_flags { 87 | use crate::kernel; 88 | bitflags!(OpendirRequestFlag, OpendirRequestFlags, u32, { 89 | KILL_SUIDGID = kernel::FUSE_OPEN_KILL_SUIDGID; 90 | }); 91 | } 92 | 93 | // }}} 94 | 95 | // OpendirResponseFlags {{{ 96 | 97 | #[derive(Clone, Copy, Eq, Hash, Ord, PartialEq, PartialOrd)] 98 | pub struct OpendirResponseFlags { 99 | bits: u32, 100 | } 101 | 102 | #[derive(Clone, Copy, Eq, Hash, Ord, PartialEq, PartialOrd)] 103 | pub struct OpendirResponseFlag { 104 | mask: u32, 105 | } 106 | 107 | mod response_flags { 108 | use crate::kernel; 109 | bitflags!(OpendirResponseFlag, OpendirResponseFlags, u32, { 110 | DIRECT_IO = kernel::FOPEN_DIRECT_IO; 111 | KEEP_CACHE = kernel::FOPEN_KEEP_CACHE; 112 | NONSEEKABLE = kernel::FOPEN_NONSEEKABLE; 113 | CACHE_DIR = kernel::FOPEN_CACHE_DIR; 114 | STREAM = kernel::FOPEN_STREAM; 115 | NOFLUSH = kernel::FOPEN_NOFLUSH; 116 | }); 117 | } 118 | 119 | // }}} 120 | -------------------------------------------------------------------------------- /fuse/operations/opendir/BUILD: -------------------------------------------------------------------------------- 1 | load("//fuse/internal/testing:testing.bzl", "operation_tests") 2 | 3 | operation_tests("opendir") 4 | -------------------------------------------------------------------------------- /fuse/operations/opendir/opendir_test.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 John Millikin and the rust-fuse contributors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // SPDX-License-Identifier: Apache-2.0 16 | 17 | use fuse::kernel; 18 | use fuse::server::OpendirRequest; 19 | 20 | use fuse_testutil as testutil; 21 | use fuse_testutil::{decode_request, MessageBuilder}; 22 | 23 | #[test] 24 | fn request() { 25 | let buf = MessageBuilder::new() 26 | .set_header(|h| { 27 | h.opcode = kernel::fuse_opcode::FUSE_OPENDIR; 28 | h.nodeid = 123; 29 | }) 30 | .push_sized(&testutil::new!(kernel::fuse_open_in { 31 | flags: 0xFF, 32 | open_flags: 0, // TODO 33 | })) 34 | .build_aligned(); 35 | 36 | let req = decode_request!(OpendirRequest, buf); 37 | 38 | assert_eq!(req.open_flags(), 0xFF); 39 | } 40 | 41 | #[test] 42 | fn request_impl_debug() { 43 | let buf; 44 | let request = fuse_testutil::build_request!(buf, OpendirRequest, { 45 | .set_header(|h| { 46 | h.opcode = kernel::fuse_opcode::FUSE_OPENDIR; 47 | h.nodeid = kernel::FUSE_ROOT_ID; 48 | }) 49 | .push_sized(&testutil::new!(kernel::fuse_open_in { 50 | flags: 0x1, 51 | })) 52 | }); 53 | 54 | assert_eq!( 55 | format!("{:#?}", request), 56 | concat!( 57 | "OpendirRequest {\n", 58 | " node_id: 1,\n", 59 | " flags: OpendirRequestFlags {},\n", 60 | " open_flags: 0x00000001,\n", 61 | "}", 62 | ), 63 | ); 64 | } 65 | -------------------------------------------------------------------------------- /fuse/operations/poll/BUILD: -------------------------------------------------------------------------------- 1 | load("//fuse/internal/testing:testing.bzl", "operation_tests") 2 | 3 | operation_tests( 4 | "poll", 5 | interop_test_os = ["linux"], 6 | ) 7 | -------------------------------------------------------------------------------- /fuse/operations/read.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 John Millikin and the rust-fuse contributors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // SPDX-License-Identifier: Apache-2.0 16 | 17 | use core::fmt; 18 | 19 | use crate::internal::compat; 20 | use crate::internal::debug; 21 | use crate::kernel; 22 | use crate::server; 23 | use crate::server::decode; 24 | 25 | // ReadRequest {{{ 26 | 27 | /// Request type for `FUSE_READ`. 28 | #[derive(Clone, Copy)] 29 | pub struct ReadRequest<'a> { 30 | header: &'a kernel::fuse_in_header, 31 | body: compat::Versioned>, 32 | } 33 | 34 | impl ReadRequest<'_> { 35 | #[must_use] 36 | pub fn node_id(&self) -> crate::NodeId { 37 | crate::NodeId::new(self.header.nodeid).unwrap_or(crate::NodeId::ROOT) 38 | } 39 | 40 | #[must_use] 41 | pub fn size(&self) -> u32 { 42 | self.body.as_v7p1().size 43 | } 44 | 45 | #[must_use] 46 | pub fn offset(&self) -> u64 { 47 | self.body.as_v7p1().offset 48 | } 49 | 50 | /// The value set in [`fuse_open_out::fh`], or zero if not set. 51 | /// 52 | /// [`fuse_open_out::fh`]: crate::kernel::fuse_open_out::fh 53 | #[must_use] 54 | pub fn handle(&self) -> u64 { 55 | self.body.as_v7p1().fh 56 | } 57 | 58 | #[must_use] 59 | pub fn lock_owner(&self) -> Option { 60 | let body = self.body.as_v7p9()?; 61 | if body.read_flags & kernel::FUSE_READ_LOCKOWNER == 0 { 62 | return None; 63 | } 64 | Some(crate::LockOwner(body.lock_owner)) 65 | } 66 | 67 | #[must_use] 68 | pub fn open_flags(&self) -> crate::OpenFlags { 69 | if let Some(body) = self.body.as_v7p9() { 70 | return body.flags; 71 | } 72 | 0 73 | } 74 | } 75 | 76 | try_from_cuse_request!(ReadRequest<'a>, |request| { 77 | let version_minor = request.layout.version_minor(); 78 | Self::try_from(request.inner, version_minor, true) 79 | }); 80 | 81 | try_from_fuse_request!(ReadRequest<'a>, |request| { 82 | let version_minor = request.layout.version_minor(); 83 | Self::try_from(request.inner, version_minor, false) 84 | }); 85 | 86 | impl<'a> ReadRequest<'a> { 87 | fn try_from( 88 | request: server::Request<'a>, 89 | version_minor: u32, 90 | is_cuse: bool, 91 | ) -> Result, server::RequestError> { 92 | let mut dec = request.decoder(); 93 | dec.expect_opcode(kernel::fuse_opcode::FUSE_READ)?; 94 | let header = dec.header(); 95 | 96 | if !is_cuse { 97 | decode::node_id(header.nodeid)?; 98 | } 99 | 100 | let body = if version_minor >= 9 { 101 | let body_v7p9 = dec.next_sized()?; 102 | compat::Versioned::new_read_v7p9(version_minor, body_v7p9) 103 | } else { 104 | let body_v7p1 = dec.next_sized()?; 105 | compat::Versioned::new_read_v7p1(version_minor, body_v7p1) 106 | }; 107 | 108 | Ok(ReadRequest { header, body }) 109 | } 110 | } 111 | 112 | impl fmt::Debug for ReadRequest<'_> { 113 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { 114 | fmt.debug_struct("ReadRequest") 115 | .field("node_id", &self.node_id()) 116 | .field("size", &self.size()) 117 | .field("offset", &self.offset()) 118 | .field("handle", &self.handle()) 119 | .field("lock_owner", &format_args!("{:?}", &self.lock_owner())) 120 | .field("open_flags", &debug::hex_u32(self.open_flags())) 121 | .finish() 122 | } 123 | } 124 | 125 | // }}} 126 | -------------------------------------------------------------------------------- /fuse/operations/read/BUILD: -------------------------------------------------------------------------------- 1 | load("//fuse/internal/testing:testing.bzl", "operation_tests") 2 | 3 | operation_tests("read") 4 | -------------------------------------------------------------------------------- /fuse/operations/read/read_test.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 John Millikin and the rust-fuse contributors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // SPDX-License-Identifier: Apache-2.0 16 | 17 | use fuse::kernel; 18 | use fuse::server::ReadRequest; 19 | 20 | use fuse_testutil as testutil; 21 | use fuse_testutil::{decode_request, MessageBuilder}; 22 | 23 | const DUMMY_READ_FLAG: u32 = 0x80000000; 24 | 25 | #[test] 26 | fn request_v7p1() { 27 | let buf = MessageBuilder::new() 28 | .set_header(|h| { 29 | h.opcode = kernel::fuse_opcode::FUSE_READ; 30 | h.nodeid = 123; 31 | }) 32 | .push_sized(&123u64) // fuse_read_in:: 33 | .push_sized(&45u64) // fuse_read_in:: 34 | .push_sized(&12u32) // fuse_read_in:: 35 | .push_sized(&0u32) // fuse_read_in:: 36 | .build_aligned(); 37 | 38 | let req = decode_request!(ReadRequest, buf, { 39 | protocol_version: (7, 1), 40 | }); 41 | 42 | assert_eq!(req.handle(), 123); 43 | assert_eq!(req.offset(), 45); 44 | assert_eq!(req.size(), 12); 45 | assert_eq!(req.lock_owner(), None); 46 | assert_eq!(req.open_flags(), 0); 47 | } 48 | 49 | #[test] 50 | fn request_v7p9() { 51 | let buf = MessageBuilder::new() 52 | .set_header(|h| { 53 | h.opcode = kernel::fuse_opcode::FUSE_READ; 54 | h.nodeid = 123; 55 | }) 56 | .push_sized(&testutil::new!(kernel::fuse_read_in { 57 | fh: 123, 58 | offset: 45, 59 | size: 12, 60 | flags: 67, 61 | })) 62 | .build_aligned(); 63 | 64 | let req = decode_request!(ReadRequest, buf, { 65 | protocol_version: (7, 9), 66 | }); 67 | 68 | assert_eq!(req.handle(), 123); 69 | assert_eq!(req.offset(), 45); 70 | assert_eq!(req.size(), 12); 71 | assert_eq!(req.lock_owner(), None); 72 | assert_eq!(req.open_flags(), 67); 73 | } 74 | 75 | #[test] 76 | fn request_lock_owner() { 77 | let buf = MessageBuilder::new() 78 | .set_header(|h| { 79 | h.opcode = kernel::fuse_opcode::FUSE_READ; 80 | h.nodeid = 123; 81 | }) 82 | .push_sized(&testutil::new!(kernel::fuse_read_in { 83 | fh: 123, 84 | offset: 45, 85 | size: 12, 86 | read_flags: DUMMY_READ_FLAG | kernel::FUSE_READ_LOCKOWNER, 87 | lock_owner: 123, 88 | flags: 67, 89 | })) 90 | .build_aligned(); 91 | 92 | let req = decode_request!(ReadRequest, buf); 93 | 94 | assert_eq!(req.lock_owner(), Some(fuse::LockOwner(123))); 95 | } 96 | 97 | #[test] 98 | fn request_impl_debug() { 99 | let buf; 100 | let request = fuse_testutil::build_request!(buf, ReadRequest, { 101 | .set_header(|h| { 102 | h.opcode = kernel::fuse_opcode::FUSE_READ; 103 | h.nodeid = kernel::FUSE_ROOT_ID; 104 | }) 105 | .push_sized(&testutil::new!(kernel::fuse_read_in { 106 | fh: 3, 107 | offset: 2, 108 | size: 1, 109 | flags: 0x4, 110 | })) 111 | }); 112 | 113 | assert_eq!( 114 | format!("{:#?}", request), 115 | concat!( 116 | "ReadRequest {\n", 117 | " node_id: 1,\n", 118 | " size: 1,\n", 119 | " offset: 2,\n", 120 | " handle: 3,\n", 121 | " lock_owner: None,\n", 122 | " open_flags: 0x00000004,\n", 123 | "}", 124 | ), 125 | ); 126 | } 127 | -------------------------------------------------------------------------------- /fuse/operations/readdir/BUILD: -------------------------------------------------------------------------------- 1 | load("//fuse/internal/testing:testing.bzl", "operation_tests") 2 | 3 | operation_tests("readdir") 4 | -------------------------------------------------------------------------------- /fuse/operations/readlink.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 John Millikin and the rust-fuse contributors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // SPDX-License-Identifier: Apache-2.0 16 | 17 | use core::fmt; 18 | use core::marker::PhantomData; 19 | 20 | use crate::kernel; 21 | use crate::server::decode; 22 | 23 | // ReadlinkRequest {{{ 24 | 25 | /// Request type for `FUSE_READLINK`. 26 | #[derive(Clone, Copy)] 27 | pub struct ReadlinkRequest<'a> { 28 | phantom: PhantomData<&'a ()>, 29 | node_id: crate::NodeId, 30 | } 31 | 32 | impl ReadlinkRequest<'_> { 33 | #[must_use] 34 | pub fn node_id(&self) -> crate::NodeId { 35 | self.node_id 36 | } 37 | } 38 | 39 | try_from_fuse_request!(ReadlinkRequest<'a>, |request| { 40 | let dec = request.decoder(); 41 | dec.expect_opcode(kernel::fuse_opcode::FUSE_READLINK)?; 42 | Ok(Self { 43 | phantom: PhantomData, 44 | node_id: decode::node_id(dec.header().nodeid)?, 45 | }) 46 | }); 47 | 48 | impl fmt::Debug for ReadlinkRequest<'_> { 49 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { 50 | fmt.debug_struct("ReadlinkRequest") 51 | .field("node_id", &self.node_id) 52 | .finish() 53 | } 54 | } 55 | 56 | // }}} 57 | -------------------------------------------------------------------------------- /fuse/operations/readlink/BUILD: -------------------------------------------------------------------------------- 1 | load("//fuse/internal/testing:testing.bzl", "operation_tests") 2 | 3 | operation_tests("readlink") 4 | -------------------------------------------------------------------------------- /fuse/operations/release.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 John Millikin and the rust-fuse contributors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // SPDX-License-Identifier: Apache-2.0 16 | 17 | use core::fmt; 18 | 19 | use crate::internal::compat; 20 | use crate::internal::debug; 21 | use crate::kernel; 22 | use crate::server; 23 | use crate::server::decode; 24 | 25 | // ReleaseRequest {{{ 26 | 27 | /// Request type for `FUSE_RELEASE`. 28 | #[derive(Clone, Copy)] 29 | pub struct ReleaseRequest<'a> { 30 | header: &'a kernel::fuse_in_header, 31 | body: compat::Versioned>, 32 | } 33 | 34 | impl ReleaseRequest<'_> { 35 | #[must_use] 36 | pub fn node_id(&self) -> crate::NodeId { 37 | crate::NodeId::new(self.header.nodeid).unwrap_or(crate::NodeId::ROOT) 38 | } 39 | 40 | /// The value set in [`fuse_open_out::fh`], or zero if not set. 41 | /// 42 | /// [`fuse_open_out::fh`]: crate::kernel::fuse_open_out::fh 43 | #[must_use] 44 | pub fn handle(&self) -> u64 { 45 | self.body.as_v7p1().fh 46 | } 47 | 48 | #[must_use] 49 | pub fn lock_owner(&self) -> Option { 50 | let body = self.body.as_v7p8()?; 51 | if body.release_flags & kernel::FUSE_RELEASE_FLOCK_UNLOCK == 0 { 52 | return None; 53 | } 54 | Some(crate::LockOwner(body.lock_owner)) 55 | } 56 | 57 | #[must_use] 58 | pub fn open_flags(&self) -> crate::OpenFlags { 59 | self.body.as_v7p1().flags 60 | } 61 | } 62 | 63 | try_from_cuse_request!(ReleaseRequest<'a>, |request| { 64 | let version_minor = request.layout.version_minor(); 65 | Self::try_from(request.inner, version_minor, true) 66 | }); 67 | 68 | try_from_fuse_request!(ReleaseRequest<'a>, |request| { 69 | let version_minor = request.layout.version_minor(); 70 | Self::try_from(request.inner, version_minor, false) 71 | }); 72 | 73 | impl<'a> ReleaseRequest<'a> { 74 | fn try_from( 75 | request: server::Request<'a>, 76 | version_minor: u32, 77 | is_cuse: bool, 78 | ) -> Result { 79 | let mut dec = request.decoder(); 80 | dec.expect_opcode(kernel::fuse_opcode::FUSE_RELEASE)?; 81 | 82 | let header = dec.header(); 83 | if !is_cuse { 84 | decode::node_id(header.nodeid)?; 85 | } 86 | 87 | let body = if version_minor >= 8 { 88 | let body_v7p8 = dec.next_sized()?; 89 | compat::Versioned::new_release_v7p8(version_minor, body_v7p8) 90 | } else { 91 | let body_v7p1 = dec.next_sized()?; 92 | compat::Versioned::new_release_v7p1(version_minor, body_v7p1) 93 | }; 94 | 95 | Ok(Self { header, body }) 96 | } 97 | } 98 | 99 | impl fmt::Debug for ReleaseRequest<'_> { 100 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { 101 | fmt.debug_struct("ReleaseRequest") 102 | .field("node_id", &self.node_id()) 103 | .field("handle", &self.handle()) 104 | .field("lock_owner", &format_args!("{:?}", self.lock_owner())) 105 | .field("open_flags", &debug::hex_u32(self.open_flags())) 106 | .finish() 107 | } 108 | } 109 | 110 | // }}} 111 | -------------------------------------------------------------------------------- /fuse/operations/release/BUILD: -------------------------------------------------------------------------------- 1 | load("//fuse/internal/testing:testing.bzl", "operation_tests") 2 | 3 | operation_tests("release") 4 | -------------------------------------------------------------------------------- /fuse/operations/release/release_test.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 John Millikin and the rust-fuse contributors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // SPDX-License-Identifier: Apache-2.0 16 | 17 | use fuse::kernel; 18 | use fuse::server::ReleaseRequest; 19 | 20 | use fuse_testutil as testutil; 21 | use fuse_testutil::{decode_request, MessageBuilder}; 22 | 23 | const DUMMY_RELEASE_FLAG: u32 = 0x80000000; 24 | 25 | #[test] 26 | fn request_v7p1() { 27 | let buf = MessageBuilder::new() 28 | .set_header(|h| { 29 | h.opcode = kernel::fuse_opcode::FUSE_RELEASE; 30 | h.nodeid = 123; 31 | }) 32 | .push_sized(&123u64) // fuse_release_in::fh 33 | .push_sized(&0xFFu32) // fuse_release_in::flags 34 | .push_sized(&0u32) // fuse_release_in::padding 35 | .build_aligned(); 36 | 37 | let req = decode_request!(ReleaseRequest, buf, { 38 | protocol_version: (7, 1), 39 | }); 40 | 41 | assert_eq!(req.handle(), 123); 42 | assert_eq!(req.open_flags(), 0xFF); 43 | assert_eq!(req.lock_owner(), None); 44 | } 45 | 46 | #[test] 47 | fn request_v7p8() { 48 | let buf = MessageBuilder::new() 49 | .set_header(|h| { 50 | h.opcode = kernel::fuse_opcode::FUSE_RELEASE; 51 | h.nodeid = 123; 52 | }) 53 | .push_sized(&testutil::new!(kernel::fuse_release_in { 54 | fh: 123, 55 | flags: 0xFF, 56 | })) 57 | .build_aligned(); 58 | 59 | let req = decode_request!(ReleaseRequest, buf, { 60 | protocol_version: (7, 8), 61 | }); 62 | 63 | assert_eq!(req.handle(), 123); 64 | assert_eq!(req.open_flags(), 0xFF); 65 | assert_eq!(req.lock_owner(), None); 66 | } 67 | 68 | #[test] 69 | fn request_lock_owner() { 70 | let buf = MessageBuilder::new() 71 | .set_header(|h| { 72 | h.opcode = kernel::fuse_opcode::FUSE_RELEASE; 73 | h.nodeid = 123; 74 | }) 75 | .push_sized(&testutil::new!(kernel::fuse_release_in { 76 | fh: 123, 77 | flags: 0xFF, 78 | release_flags: DUMMY_RELEASE_FLAG 79 | | kernel::FUSE_RELEASE_FLOCK_UNLOCK, 80 | lock_owner: 123, 81 | })) 82 | .build_aligned(); 83 | 84 | let req = decode_request!(ReleaseRequest, buf, { 85 | protocol_version: (7, 8), 86 | }); 87 | 88 | assert_eq!(req.lock_owner(), Some(fuse::LockOwner(123))); 89 | } 90 | 91 | #[test] 92 | fn request_impl_debug() { 93 | let buf; 94 | let request = fuse_testutil::build_request!(buf, ReleaseRequest, { 95 | .set_header(|h| { 96 | h.opcode = kernel::fuse_opcode::FUSE_RELEASE; 97 | h.nodeid = kernel::FUSE_ROOT_ID; 98 | }) 99 | .push_sized(&testutil::new!(kernel::fuse_release_in { 100 | fh: 3, 101 | flags: 0x4, 102 | })) 103 | }); 104 | 105 | assert_eq!( 106 | format!("{:#?}", request), 107 | concat!( 108 | "ReleaseRequest {\n", 109 | " node_id: 1,\n", 110 | " handle: 3,\n", 111 | " lock_owner: None,\n", 112 | " open_flags: 0x00000004,\n", 113 | "}", 114 | ), 115 | ); 116 | } 117 | -------------------------------------------------------------------------------- /fuse/operations/releasedir.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 John Millikin and the rust-fuse contributors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // SPDX-License-Identifier: Apache-2.0 16 | 17 | use core::fmt; 18 | 19 | use crate::internal::compat; 20 | use crate::internal::debug; 21 | use crate::kernel; 22 | use crate::server::decode; 23 | 24 | // ReleasedirRequest {{{ 25 | 26 | /// Request type for `FUSE_RELEASEDIR`. 27 | #[derive(Clone, Copy)] 28 | pub struct ReleasedirRequest<'a> { 29 | header: &'a kernel::fuse_in_header, 30 | body: compat::Versioned>, 31 | } 32 | 33 | impl ReleasedirRequest<'_> { 34 | #[must_use] 35 | pub fn node_id(&self) -> crate::NodeId { 36 | unsafe { crate::NodeId::new_unchecked(self.header.nodeid) } 37 | } 38 | 39 | /// The value set in [`fuse_open_out::fh`], or zero if not set. 40 | /// 41 | /// [`fuse_open_out::fh`]: crate::kernel::fuse_open_out::fh 42 | #[must_use] 43 | pub fn handle(&self) -> u64 { 44 | self.body.as_v7p1().fh 45 | } 46 | 47 | #[must_use] 48 | pub fn lock_owner(&self) -> Option { 49 | let body = self.body.as_v7p8()?; 50 | if body.release_flags & kernel::FUSE_RELEASE_FLOCK_UNLOCK == 0 { 51 | return None; 52 | } 53 | Some(crate::LockOwner(body.lock_owner)) 54 | } 55 | 56 | #[must_use] 57 | pub fn open_flags(&self) -> crate::OpenFlags { 58 | self.body.as_v7p1().flags 59 | } 60 | } 61 | 62 | try_from_fuse_request!(ReleasedirRequest<'a>, |request| { 63 | let version_minor = request.layout.version_minor(); 64 | let mut dec = request.decoder(); 65 | dec.expect_opcode(kernel::fuse_opcode::FUSE_RELEASEDIR)?; 66 | 67 | let header = dec.header(); 68 | decode::node_id(header.nodeid)?; 69 | 70 | let body = if version_minor >= 8 { 71 | let body_v7p8 = dec.next_sized()?; 72 | compat::Versioned::new_release_v7p8(version_minor, body_v7p8) 73 | } else { 74 | let body_v7p1 = dec.next_sized()?; 75 | compat::Versioned::new_release_v7p1(version_minor, body_v7p1) 76 | }; 77 | 78 | Ok(Self { header, body }) 79 | }); 80 | 81 | impl fmt::Debug for ReleasedirRequest<'_> { 82 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { 83 | fmt.debug_struct("ReleasedirRequest") 84 | .field("node_id", &self.node_id()) 85 | .field("handle", &self.handle()) 86 | .field("lock_owner", &format_args!("{:?}", self.lock_owner())) 87 | .field("open_flags", &debug::hex_u32(self.open_flags())) 88 | .finish() 89 | } 90 | } 91 | 92 | // }}} 93 | -------------------------------------------------------------------------------- /fuse/operations/releasedir/BUILD: -------------------------------------------------------------------------------- 1 | load("//fuse/internal/testing:testing.bzl", "operation_tests") 2 | 3 | operation_tests("releasedir") 4 | -------------------------------------------------------------------------------- /fuse/operations/releasedir/releasedir_test.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 John Millikin and the rust-fuse contributors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // SPDX-License-Identifier: Apache-2.0 16 | 17 | use fuse::kernel; 18 | use fuse::server::ReleasedirRequest; 19 | 20 | use fuse_testutil as testutil; 21 | use fuse_testutil::{decode_request, MessageBuilder}; 22 | 23 | const DUMMY_RELEASE_FLAG: u32 = 0x80000000; 24 | 25 | #[test] 26 | fn request_v7p1() { 27 | let buf = MessageBuilder::new() 28 | .set_header(|h| { 29 | h.opcode = kernel::fuse_opcode::FUSE_RELEASEDIR; 30 | h.nodeid = 123; 31 | }) 32 | .push_sized(&123u64) // fuse_release_in::fh 33 | .push_sized(&0xFFu32) // fuse_release_in::flags 34 | .push_sized(&0u32) // fuse_release_in::padding 35 | .build_aligned(); 36 | 37 | let req = decode_request!(ReleasedirRequest, buf, { 38 | protocol_version: (7, 1), 39 | }); 40 | 41 | assert_eq!(req.handle(), 123); 42 | assert_eq!(req.open_flags(), 0xFF); 43 | assert_eq!(req.lock_owner(), None); 44 | } 45 | 46 | #[test] 47 | fn request_v7p8() { 48 | let buf = MessageBuilder::new() 49 | .set_header(|h| { 50 | h.opcode = kernel::fuse_opcode::FUSE_RELEASEDIR; 51 | h.nodeid = 123; 52 | }) 53 | .push_sized(&testutil::new!(kernel::fuse_release_in { 54 | fh: 123, 55 | flags: 0xFF, 56 | })) 57 | .build_aligned(); 58 | 59 | let req = decode_request!(ReleasedirRequest, buf, { 60 | protocol_version: (7, 8), 61 | }); 62 | 63 | assert_eq!(req.handle(), 123); 64 | assert_eq!(req.open_flags(), 0xFF); 65 | assert_eq!(req.lock_owner(), None); 66 | } 67 | 68 | #[test] 69 | fn request_lock_owner() { 70 | let buf = MessageBuilder::new() 71 | .set_header(|h| { 72 | h.opcode = kernel::fuse_opcode::FUSE_RELEASEDIR; 73 | h.nodeid = 123; 74 | }) 75 | .push_sized(&testutil::new!(kernel::fuse_release_in { 76 | fh: 123, 77 | flags: 0xFF, 78 | release_flags: DUMMY_RELEASE_FLAG 79 | | kernel::FUSE_RELEASE_FLOCK_UNLOCK, 80 | lock_owner: 123, 81 | })) 82 | .build_aligned(); 83 | 84 | let req = decode_request!(ReleasedirRequest, buf, { 85 | protocol_version: (7, 8), 86 | }); 87 | 88 | assert_eq!(req.lock_owner(), Some(fuse::LockOwner(123))); 89 | } 90 | 91 | #[test] 92 | fn request_impl_debug() { 93 | let buf; 94 | let request = fuse_testutil::build_request!(buf, ReleasedirRequest, { 95 | .set_header(|h| { 96 | h.opcode = kernel::fuse_opcode::FUSE_RELEASEDIR; 97 | h.nodeid = kernel::FUSE_ROOT_ID; 98 | }) 99 | .push_sized(&testutil::new!(kernel::fuse_release_in { 100 | fh: 3, 101 | flags: 0x4, 102 | })) 103 | }); 104 | 105 | assert_eq!( 106 | format!("{:#?}", request), 107 | concat!( 108 | "ReleasedirRequest {\n", 109 | " node_id: 1,\n", 110 | " handle: 3,\n", 111 | " lock_owner: None,\n", 112 | " open_flags: 0x00000004,\n", 113 | "}", 114 | ), 115 | ); 116 | } 117 | -------------------------------------------------------------------------------- /fuse/operations/removexattr.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 John Millikin and the rust-fuse contributors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // SPDX-License-Identifier: Apache-2.0 16 | 17 | use core::fmt; 18 | 19 | use crate::kernel; 20 | use crate::server::decode; 21 | 22 | // RemovexattrRequest {{{ 23 | 24 | /// Request type for `FUSE_REMOVEXATTR`. 25 | #[derive(Clone, Copy)] 26 | pub struct RemovexattrRequest<'a> { 27 | header: &'a kernel::fuse_in_header, 28 | name: &'a core::ffi::CStr, 29 | } 30 | 31 | impl RemovexattrRequest<'_> { 32 | #[inline] 33 | #[must_use] 34 | pub fn node_id(&self) -> crate::NodeId { 35 | unsafe { crate::NodeId::new_unchecked(self.header.nodeid) } 36 | } 37 | 38 | #[inline] 39 | #[must_use] 40 | pub fn name(&self) -> &core::ffi::CStr { 41 | self.name 42 | } 43 | } 44 | 45 | try_from_fuse_request!(RemovexattrRequest<'a>, |request| { 46 | let mut dec = request.decoder(); 47 | dec.expect_opcode(kernel::fuse_opcode::FUSE_REMOVEXATTR)?; 48 | 49 | let header = dec.header(); 50 | decode::node_id(header.nodeid)?; 51 | let name = dec.next_cstr()?; 52 | Ok(Self { header, name }) 53 | }); 54 | 55 | impl fmt::Debug for RemovexattrRequest<'_> { 56 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { 57 | fmt.debug_struct("RemovexattrRequest") 58 | .field("node_id", &self.node_id()) 59 | .field("name", &self.name()) 60 | .finish() 61 | } 62 | } 63 | 64 | // }}} 65 | -------------------------------------------------------------------------------- /fuse/operations/removexattr/BUILD: -------------------------------------------------------------------------------- 1 | load("//fuse/internal/testing:testing.bzl", "operation_tests") 2 | 3 | operation_tests("removexattr") 4 | -------------------------------------------------------------------------------- /fuse/operations/removexattr/removexattr_interop_test.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2021 John Millikin and the rust-fuse contributors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // SPDX-License-Identifier: Apache-2.0 16 | 17 | use std::sync::mpsc; 18 | use std::panic; 19 | 20 | use fuse::server; 21 | use fuse::server::FuseRequest; 22 | 23 | use interop_testutil::{ 24 | diff_str, 25 | fuse_interop_test, 26 | path_cstr, 27 | OsError, 28 | }; 29 | 30 | struct TestFS { 31 | requests: mpsc::Sender, 32 | } 33 | 34 | struct TestHandlers<'a, S> { 35 | fs: &'a TestFS, 36 | conn: &'a server::FuseConnection, 37 | } 38 | 39 | impl interop_testutil::TestFS for TestFS { 40 | fn dispatch_request( 41 | &self, 42 | conn: &server::FuseConnection, 43 | request: FuseRequest<'_>, 44 | ) { 45 | use fuse::server::FuseHandlers; 46 | (TestHandlers{fs: self, conn}).dispatch(request); 47 | } 48 | } 49 | 50 | impl<'a, S> server::FuseHandlers for TestHandlers<'a, S> 51 | where 52 | S: server::FuseSocket, 53 | S::Error: core::fmt::Debug, 54 | { 55 | fn unimplemented(&self, request: FuseRequest<'_>) { 56 | self.conn.reply(request.id()).err(OsError::UNIMPLEMENTED).unwrap(); 57 | } 58 | 59 | fn lookup(&self, request: FuseRequest<'_>) { 60 | let send_reply = self.conn.reply(request.id()); 61 | let request = server::LookupRequest::try_from(request).unwrap(); 62 | 63 | if !request.parent_id().is_root() { 64 | return send_reply.err(OsError::NOT_FOUND).unwrap(); 65 | } 66 | if request.name() != "xattrs.txt" { 67 | return send_reply.err(OsError::NOT_FOUND).unwrap(); 68 | } 69 | 70 | let mut attr = fuse::NodeAttr::new(fuse::NodeId::new(2).unwrap()); 71 | attr.set_mode(fuse::FileMode::S_IFREG | 0o644); 72 | attr.set_link_count(1); 73 | 74 | let mut entry = fuse::Entry::new(attr); 75 | entry.set_cache_timeout(std::time::Duration::from_secs(60)); 76 | 77 | send_reply.ok(&entry).unwrap(); 78 | } 79 | 80 | fn removexattr(&self, request: FuseRequest<'_>) { 81 | let send_reply = self.conn.reply(request.id()); 82 | let request = server::RemovexattrRequest::try_from(request).unwrap(); 83 | self.fs.requests.send(format!("{:#?}", request)).unwrap(); 84 | send_reply.ok_empty().unwrap(); 85 | } 86 | } 87 | 88 | fn removexattr_test( 89 | test_fn: impl FnOnce(&std::path::Path) + panic::UnwindSafe, 90 | ) -> Vec { 91 | let (request_send, request_recv) = mpsc::channel(); 92 | let fs = TestFS { 93 | requests: request_send, 94 | }; 95 | fuse_interop_test(fs, test_fn); 96 | request_recv.iter().collect() 97 | } 98 | 99 | #[test] 100 | fn removexattr() { 101 | let requests = removexattr_test(|root| { 102 | let path = path_cstr(root.join("xattrs.txt")); 103 | 104 | #[cfg(target_os = "linux")] 105 | let rc = unsafe { 106 | libc::removexattr( 107 | path.as_ptr(), 108 | c"user.xattr_name".as_ptr(), 109 | ) 110 | }; 111 | 112 | #[cfg(target_os = "freebsd")] 113 | let rc = unsafe { 114 | libc::extattr_delete_file( 115 | path.as_ptr(), 116 | libc::EXTATTR_NAMESPACE_USER, 117 | c"xattr_name".as_ptr(), 118 | ) 119 | }; 120 | 121 | assert_eq!(rc, 0); 122 | }); 123 | assert_eq!(requests.len(), 1); 124 | 125 | let expect = r#"RemovexattrRequest { 126 | node_id: 2, 127 | name: "user.xattr_name", 128 | }"#; 129 | if let Some(diff) = diff_str(expect, &requests[0]) { 130 | println!("{}", diff); 131 | assert!(false); 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /fuse/operations/removexattr/removexattr_test.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 John Millikin and the rust-fuse contributors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // SPDX-License-Identifier: Apache-2.0 16 | 17 | use fuse::kernel; 18 | use fuse::server::RemovexattrRequest; 19 | 20 | use fuse_testutil::{decode_request, MessageBuilder}; 21 | 22 | #[test] 23 | fn request() { 24 | let buf = MessageBuilder::new() 25 | .set_header(|h| { 26 | h.opcode = kernel::fuse_opcode::FUSE_REMOVEXATTR; 27 | h.nodeid = 123; 28 | }) 29 | .push_bytes(b"hello.world!\x00") 30 | .build_aligned(); 31 | 32 | let req = decode_request!(RemovexattrRequest, buf); 33 | assert_eq!(req.name(), c"hello.world!"); 34 | } 35 | 36 | #[test] 37 | fn request_impl_debug() { 38 | let buf; 39 | let request = fuse_testutil::build_request!(buf, RemovexattrRequest, { 40 | .set_header(|h| { 41 | h.opcode = kernel::fuse_opcode::FUSE_REMOVEXATTR; 42 | h.nodeid = kernel::FUSE_ROOT_ID; 43 | }) 44 | .push_bytes(b"hello.world!\x00") 45 | }); 46 | 47 | assert_eq!( 48 | format!("{:#?}", request), 49 | concat!( 50 | "RemovexattrRequest {\n", 51 | " node_id: 1,\n", 52 | " name: \"hello.world!\",\n", 53 | "}", 54 | ), 55 | ); 56 | } 57 | -------------------------------------------------------------------------------- /fuse/operations/rename.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 John Millikin and the rust-fuse contributors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // SPDX-License-Identifier: Apache-2.0 16 | 17 | use core::fmt; 18 | 19 | use crate::internal::debug; 20 | use crate::kernel; 21 | use crate::server::decode; 22 | 23 | // RenameRequest {{{ 24 | 25 | /// Request type for `FUSE_RENAME` and `FUSE_RENAME2`. 26 | #[derive(Clone, Copy)] 27 | pub struct RenameRequest<'a> { 28 | old_directory_id: crate::NodeId, 29 | old_name: &'a crate::NodeName, 30 | new_directory_id: crate::NodeId, 31 | new_name: &'a crate::NodeName, 32 | rename_flags: u32, 33 | } 34 | 35 | impl RenameRequest<'_> { 36 | #[must_use] 37 | pub fn old_directory_id(&self) -> crate::NodeId { 38 | self.old_directory_id 39 | } 40 | 41 | #[must_use] 42 | pub fn old_name(&self) -> &crate::NodeName { 43 | self.old_name 44 | } 45 | 46 | #[must_use] 47 | pub fn new_directory_id(&self) -> crate::NodeId { 48 | self.new_directory_id 49 | } 50 | 51 | #[must_use] 52 | pub fn new_name(&self) -> &crate::NodeName { 53 | self.new_name 54 | } 55 | 56 | #[must_use] 57 | pub fn rename_flags(&self) -> crate::RenameFlags { 58 | self.rename_flags 59 | } 60 | } 61 | 62 | try_from_fuse_request!(RenameRequest<'a>, |request| { 63 | let mut dec = request.decoder(); 64 | let header = dec.header(); 65 | 66 | let mut rename_flags = 0; 67 | let new_dir: u64; 68 | if header.opcode == kernel::fuse_opcode::FUSE_RENAME2 { 69 | let parsed: &kernel::fuse_rename2_in = dec.next_sized()?; 70 | rename_flags = parsed.flags; 71 | new_dir = parsed.newdir; 72 | } else { 73 | dec.expect_opcode(kernel::fuse_opcode::FUSE_RENAME)?; 74 | let parsed: &kernel::fuse_rename_in = dec.next_sized()?; 75 | new_dir = parsed.newdir; 76 | } 77 | let old_name = dec.next_node_name()?; 78 | let new_name = dec.next_node_name()?; 79 | Ok(Self { 80 | old_directory_id: decode::node_id(header.nodeid)?, 81 | old_name, 82 | new_directory_id: decode::node_id(new_dir)?, 83 | new_name, 84 | rename_flags, 85 | }) 86 | }); 87 | 88 | impl fmt::Debug for RenameRequest<'_> { 89 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { 90 | fmt.debug_struct("RenameRequest") 91 | .field("old_directory_id", &self.old_directory_id) 92 | .field("old_name", &self.old_name) 93 | .field("new_directory_id", &self.new_directory_id) 94 | .field("new_name", &self.new_name) 95 | .field("rename_flags", &debug::hex_u32(self.rename_flags)) 96 | .finish() 97 | } 98 | } 99 | 100 | // }}} 101 | -------------------------------------------------------------------------------- /fuse/operations/rename/BUILD: -------------------------------------------------------------------------------- 1 | load("//fuse/internal/testing:testing.bzl", "operation_tests") 2 | 3 | operation_tests("rename") 4 | -------------------------------------------------------------------------------- /fuse/operations/rename/rename_test.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 John Millikin and the rust-fuse contributors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // SPDX-License-Identifier: Apache-2.0 16 | 17 | use fuse::kernel; 18 | use fuse::server::RenameRequest; 19 | 20 | use fuse_testutil as testutil; 21 | use fuse_testutil::{decode_request, MessageBuilder}; 22 | 23 | #[test] 24 | fn request_rename() { 25 | let buf = MessageBuilder::new() 26 | .set_header(|h| { 27 | h.opcode = kernel::fuse_opcode::FUSE_RENAME; 28 | h.nodeid = 123; 29 | }) 30 | .push_sized(&testutil::new!(kernel::fuse_rename_in { 31 | newdir: 456, 32 | })) 33 | .push_bytes(b"old\x00") 34 | .push_bytes(b"new\x00") 35 | .build_aligned(); 36 | 37 | let request = decode_request!(RenameRequest, buf); 38 | 39 | assert_eq!(request.old_name(), "old"); 40 | assert_eq!(request.new_name(), "new"); 41 | assert_eq!(request.old_directory_id(), fuse::NodeId::new(123).unwrap()); 42 | assert_eq!(request.new_directory_id(), fuse::NodeId::new(456).unwrap()); 43 | assert_eq!(request.rename_flags(), 0); 44 | } 45 | 46 | #[test] 47 | fn request_rename2() { 48 | let buf = MessageBuilder::new() 49 | .set_header(|h| { 50 | h.opcode = kernel::fuse_opcode::FUSE_RENAME2; 51 | h.nodeid = 123; 52 | }) 53 | .push_sized(&testutil::new!(kernel::fuse_rename2_in { 54 | newdir: 456, 55 | flags: 0b111, 56 | })) 57 | .push_bytes(b"old\x00") 58 | .push_bytes(b"new\x00") 59 | .build_aligned(); 60 | 61 | let request = decode_request!(RenameRequest, buf); 62 | 63 | assert_eq!(request.old_name(), "old"); 64 | assert_eq!(request.new_name(), "new"); 65 | assert_eq!(request.old_directory_id(), fuse::NodeId::new(123).unwrap()); 66 | assert_eq!(request.new_directory_id(), fuse::NodeId::new(456).unwrap()); 67 | assert_eq!(request.rename_flags(), 0b111); 68 | } 69 | 70 | #[test] 71 | fn request_impl_debug() { 72 | let buf = MessageBuilder::new() 73 | .set_header(|h| { 74 | h.opcode = kernel::fuse_opcode::FUSE_RENAME2; 75 | h.nodeid = 123; 76 | }) 77 | .push_sized(&testutil::new!(kernel::fuse_rename2_in { 78 | newdir: 456, 79 | flags: 0b111, 80 | })) 81 | .push_bytes(b"old\x00") 82 | .push_bytes(b"new\x00") 83 | .build_aligned(); 84 | let request = decode_request!(RenameRequest, buf); 85 | 86 | assert_eq!( 87 | format!("{:#?}", request), 88 | concat!( 89 | "RenameRequest {\n", 90 | " old_directory_id: 123,\n", 91 | " old_name: \"old\",\n", 92 | " new_directory_id: 456,\n", 93 | " new_name: \"new\",\n", 94 | " rename_flags: 0x00000007,\n", 95 | "}", 96 | ), 97 | ); 98 | } 99 | -------------------------------------------------------------------------------- /fuse/operations/rmdir.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 John Millikin and the rust-fuse contributors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // SPDX-License-Identifier: Apache-2.0 16 | 17 | use crate::kernel; 18 | use crate::server::decode; 19 | 20 | // RmdirRequest {{{ 21 | 22 | /// Request type for `FUSE_RMDIR`. 23 | #[derive(Clone, Copy, Debug)] 24 | pub struct RmdirRequest<'a> { 25 | parent_id: crate::NodeId, 26 | name: &'a crate::NodeName, 27 | } 28 | 29 | impl RmdirRequest<'_> { 30 | #[must_use] 31 | pub fn parent_id(&self) -> crate::NodeId { 32 | self.parent_id 33 | } 34 | 35 | #[must_use] 36 | pub fn name(&self) -> &crate::NodeName { 37 | self.name 38 | } 39 | } 40 | 41 | try_from_fuse_request!(RmdirRequest<'a>, |request| { 42 | let mut dec = request.decoder(); 43 | dec.expect_opcode(kernel::fuse_opcode::FUSE_RMDIR)?; 44 | Ok(Self { 45 | parent_id: decode::node_id(dec.header().nodeid)?, 46 | name: dec.next_node_name()?, 47 | }) 48 | }); 49 | 50 | // }}} 51 | -------------------------------------------------------------------------------- /fuse/operations/rmdir/BUILD: -------------------------------------------------------------------------------- 1 | load("//fuse/internal/testing:testing.bzl", "operation_tests") 2 | 3 | operation_tests("rmdir") 4 | -------------------------------------------------------------------------------- /fuse/operations/rmdir/rmdir_test.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 John Millikin and the rust-fuse contributors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // SPDX-License-Identifier: Apache-2.0 16 | 17 | use fuse::kernel; 18 | use fuse::server::RmdirRequest; 19 | 20 | use fuse_testutil::{decode_request, MessageBuilder}; 21 | 22 | #[test] 23 | fn request() { 24 | let buf = MessageBuilder::new() 25 | .set_header(|h| { 26 | h.opcode = kernel::fuse_opcode::FUSE_RMDIR; 27 | h.nodeid = 100; 28 | }) 29 | .push_bytes(b"hello.world!\x00") 30 | .build_aligned(); 31 | let request = decode_request!(RmdirRequest, buf); 32 | 33 | assert_eq!(request.parent_id(), fuse::NodeId::new(100).unwrap()); 34 | assert_eq!(request.name(), "hello.world!"); 35 | } 36 | 37 | #[test] 38 | fn request_impl_debug() { 39 | let buf = MessageBuilder::new() 40 | .set_header(|h| { 41 | h.opcode = kernel::fuse_opcode::FUSE_RMDIR; 42 | h.nodeid = 100; 43 | }) 44 | .push_bytes(b"hello.world!\x00") 45 | .build_aligned(); 46 | let request = decode_request!(RmdirRequest, buf); 47 | 48 | assert_eq!( 49 | format!("{:#?}", request), 50 | concat!( 51 | "RmdirRequest {\n", 52 | " parent_id: 100,\n", 53 | " name: \"hello.world!\",\n", 54 | "}", 55 | ), 56 | ); 57 | } 58 | -------------------------------------------------------------------------------- /fuse/operations/setattr/BUILD: -------------------------------------------------------------------------------- 1 | load("//fuse/internal/testing:testing.bzl", "operation_tests") 2 | 3 | operation_tests("setattr") 4 | -------------------------------------------------------------------------------- /fuse/operations/setlk.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 John Millikin and the rust-fuse contributors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // SPDX-License-Identifier: Apache-2.0 16 | 17 | use core::fmt; 18 | 19 | use crate::kernel; 20 | use crate::server::decode; 21 | 22 | // SetlkRequest {{{ 23 | 24 | /// Request type for `FUSE_SETLK` and `FUSE_SETLKW`. 25 | #[derive(Clone, Copy)] 26 | pub struct SetlkRequest<'a> { 27 | header: &'a kernel::fuse_in_header, 28 | body: &'a kernel::fuse_lk_in, 29 | lock: crate::Lock, 30 | } 31 | 32 | impl SetlkRequest<'_> { 33 | #[inline] 34 | #[must_use] 35 | pub fn node_id(&self) -> crate::NodeId { 36 | unsafe { crate::NodeId::new_unchecked(self.header.nodeid) } 37 | } 38 | 39 | #[inline] 40 | #[must_use] 41 | pub fn handle(&self) -> u64 { 42 | self.body.fh 43 | } 44 | 45 | #[inline] 46 | #[must_use] 47 | pub fn may_block(&self) -> bool { 48 | self.header.opcode == kernel::fuse_opcode::FUSE_SETLKW 49 | } 50 | 51 | #[inline] 52 | #[must_use] 53 | pub fn owner(&self) -> crate::LockOwner { 54 | crate::LockOwner(self.body.owner) 55 | } 56 | 57 | #[inline] 58 | #[must_use] 59 | pub fn lock(&self) -> crate::Lock { 60 | self.lock 61 | } 62 | 63 | #[inline] 64 | #[must_use] 65 | pub fn flags(&self) -> SetlkRequestFlags { 66 | SetlkRequestFlags { 67 | bits: self.body.lk_flags, 68 | } 69 | } 70 | } 71 | 72 | try_from_fuse_request!(SetlkRequest<'a>, |request| { 73 | let mut dec = request.decoder(); 74 | 75 | let header = dec.header(); 76 | if header.opcode != kernel::fuse_opcode::FUSE_SETLKW { 77 | dec.expect_opcode(kernel::fuse_opcode::FUSE_SETLK)?; 78 | } 79 | 80 | decode::node_id(header.nodeid)?; 81 | 82 | let body: &kernel::fuse_lk_in = dec.next_sized()?; 83 | let lock = crate::Lock::decode(&body.lk)?; 84 | Ok(Self { header, body, lock }) 85 | }); 86 | 87 | /// Optional flags set on [`SetlkRequest`]. 88 | #[derive(Clone, Copy, Eq, Hash, Ord, PartialEq, PartialOrd)] 89 | pub struct SetlkRequestFlags { 90 | bits: u32, 91 | } 92 | 93 | #[derive(Clone, Copy, Eq, Hash, Ord, PartialEq, PartialOrd)] 94 | pub struct SetlkRequestFlag { 95 | mask: u32, 96 | } 97 | 98 | mod flags { 99 | use crate::kernel; 100 | bitflags!(SetlkRequestFlag, SetlkRequestFlags, u32, { 101 | LK_FLOCK = kernel::FUSE_LK_FLOCK; 102 | }); 103 | } 104 | 105 | impl fmt::Debug for SetlkRequest<'_> { 106 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { 107 | fmt.debug_struct("SetlkRequest") 108 | .field("node_id", &self.node_id()) 109 | .field("handle", &self.handle()) 110 | .field("may_block", &self.may_block()) 111 | .field("owner", &self.owner()) 112 | .field("lock", &self.lock()) 113 | .field("flags", &self.flags()) 114 | .finish() 115 | } 116 | } 117 | 118 | // }}} 119 | -------------------------------------------------------------------------------- /fuse/operations/setlk/BUILD: -------------------------------------------------------------------------------- 1 | load("//fuse/internal/testing:testing.bzl", "operation_tests") 2 | 3 | operation_tests("setlk") 4 | -------------------------------------------------------------------------------- /fuse/operations/setxattr.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 John Millikin and the rust-fuse contributors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // SPDX-License-Identifier: Apache-2.0 16 | 17 | use core::fmt; 18 | 19 | use crate::internal::compat; 20 | use crate::internal::debug; 21 | use crate::kernel; 22 | use crate::server::decode; 23 | 24 | // SetxattrRequest {{{ 25 | 26 | /// Request type for `FUSE_SETXATTR`. 27 | #[derive(Clone, Copy)] 28 | pub struct SetxattrRequest<'a> { 29 | header: &'a kernel::fuse_in_header, 30 | body: compat::Versioned>, 31 | name: &'a core::ffi::CStr, 32 | value: &'a [u8], 33 | } 34 | 35 | impl SetxattrRequest<'_> { 36 | #[inline] 37 | #[must_use] 38 | pub fn node_id(&self) -> crate::NodeId { 39 | unsafe { crate::NodeId::new_unchecked(self.header.nodeid) } 40 | } 41 | 42 | #[inline] 43 | #[must_use] 44 | pub fn name(&self) -> &core::ffi::CStr { 45 | self.name 46 | } 47 | 48 | #[inline] 49 | #[must_use] 50 | pub fn flags(&self) -> SetxattrRequestFlags { 51 | if let Some(body) = self.body.as_v7p33() { 52 | return SetxattrRequestFlags { 53 | bits: body.setxattr_flags, 54 | }; 55 | } 56 | SetxattrRequestFlags::new() 57 | } 58 | 59 | #[inline] 60 | #[must_use] 61 | pub fn setxattr_flags(&self) -> crate::SetxattrFlags { 62 | self.body.as_v7p1().flags 63 | } 64 | 65 | #[inline] 66 | #[must_use] 67 | pub fn value(&self) -> &[u8] { 68 | self.value 69 | } 70 | } 71 | 72 | try_from_fuse_request!(SetxattrRequest<'a>, |request| { 73 | let mut dec = request.decoder(); 74 | dec.expect_opcode(kernel::fuse_opcode::FUSE_SETXATTR)?; 75 | 76 | let header = dec.header(); 77 | decode::node_id(header.nodeid)?; 78 | 79 | let body = if request.layout.have_setxattr_ext() { 80 | let body_v7p33 = dec.next_sized()?; 81 | compat::Versioned::new_setxattr_v7p33(body_v7p33) 82 | } else { 83 | let body_v7p1 = dec.next_sized()?; 84 | compat::Versioned::new_setxattr_v7p1(body_v7p1) 85 | }; 86 | 87 | let name = dec.next_cstr()?; 88 | let value = dec.next_bytes(body.as_v7p1().size)?; 89 | 90 | Ok(Self { header, body, name, value }) 91 | }); 92 | 93 | impl fmt::Debug for SetxattrRequest<'_> { 94 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { 95 | fmt.debug_struct("SetxattrRequest") 96 | .field("node_id", &self.node_id()) 97 | .field("name", &self.name()) 98 | .field("flags", &self.flags()) 99 | .field("setxattr_flags", &debug::hex_u32(self.setxattr_flags())) 100 | .field("value", &debug::bytes(self.value)) 101 | .finish() 102 | } 103 | } 104 | 105 | // }}} 106 | 107 | // SetxattrRequestFlags {{{ 108 | 109 | /// Optional flags set on [`SetxattrRequest`]. 110 | #[derive(Clone, Copy, Eq, Hash, Ord, PartialEq, PartialOrd)] 111 | pub struct SetxattrRequestFlags { 112 | bits: u32, 113 | } 114 | 115 | #[derive(Clone, Copy, Eq, Hash, Ord, PartialEq, PartialOrd)] 116 | pub struct SetxattrRequestFlag { 117 | mask: u32, 118 | } 119 | 120 | mod request_flags { 121 | use crate::kernel; 122 | bitflags!(SetxattrRequestFlag, SetxattrRequestFlags, u32, { 123 | ACL_KILL_SGID = kernel::FUSE_SETXATTR_ACL_KILL_SGID; 124 | }); 125 | } 126 | 127 | // }}} 128 | -------------------------------------------------------------------------------- /fuse/operations/setxattr/BUILD: -------------------------------------------------------------------------------- 1 | load("//fuse/internal/testing:testing.bzl", "operation_tests") 2 | 3 | operation_tests("setxattr") 4 | -------------------------------------------------------------------------------- /fuse/operations/setxattr/setxattr_test.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 John Millikin and the rust-fuse contributors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // SPDX-License-Identifier: Apache-2.0 16 | 17 | use fuse::kernel; 18 | use fuse::server::SetxattrRequest; 19 | 20 | use fuse_testutil::{decode_request, MessageBuilder}; 21 | 22 | #[test] 23 | fn request() { 24 | let buf = MessageBuilder::new() 25 | .set_header(|h| { 26 | h.opcode = kernel::fuse_opcode::FUSE_SETXATTR; 27 | h.nodeid = 123; 28 | }) 29 | .push_sized(&10u32) // fuse_setxattr_in::size 30 | .push_sized(&0b11u32) // fuse_setxattr_in::flags 31 | .push_bytes(b"hello.world!\x00") 32 | .push_bytes(b"some\x00value") 33 | .build_aligned(); 34 | 35 | let req = decode_request!(SetxattrRequest, buf); 36 | 37 | assert_eq!(req.name(), c"hello.world!"); 38 | assert_eq!(req.value(), b"some\x00value"); 39 | assert_eq!(req.setxattr_flags(), 0b11); 40 | } 41 | 42 | #[test] 43 | fn request_impl_debug() { 44 | let buf; 45 | let request = fuse_testutil::build_request!(buf, SetxattrRequest, { 46 | .set_header(|h| { 47 | h.opcode = kernel::fuse_opcode::FUSE_SETXATTR; 48 | h.nodeid = kernel::FUSE_ROOT_ID; 49 | }) 50 | .push_sized(&10u32) // fuse_setxattr_in::size 51 | .push_sized(&0u32) // fuse_setxattr_in::flags 52 | .push_bytes(b"hello.world!\x00") 53 | .push_bytes(b"some\x00value") 54 | }); 55 | 56 | assert_eq!( 57 | format!("{:#?}", request), 58 | concat!( 59 | "SetxattrRequest {\n", 60 | " node_id: 1,\n", 61 | " name: \"hello.world!\",\n", 62 | " flags: SetxattrRequestFlags {},\n", 63 | " setxattr_flags: 0x00000000,\n", 64 | " value: \"some\\x00value\",\n", 65 | "}", 66 | ), 67 | ); 68 | } 69 | -------------------------------------------------------------------------------- /fuse/operations/statfs/BUILD: -------------------------------------------------------------------------------- 1 | load("//fuse/internal/testing:testing.bzl", "operation_tests") 2 | 3 | operation_tests("statfs") 4 | -------------------------------------------------------------------------------- /fuse/operations/symlink.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 John Millikin and the rust-fuse contributors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // SPDX-License-Identifier: Apache-2.0 16 | 17 | //! Implements the `FUSE_SYMLINK` operation. 18 | 19 | use core::fmt; 20 | 21 | use crate::kernel; 22 | use crate::server::decode; 23 | 24 | // SymlinkRequest {{{ 25 | 26 | /// Request type for `FUSE_SYMLINK`. 27 | #[derive(Clone, Copy)] 28 | pub struct SymlinkRequest<'a> { 29 | parent_id: crate::NodeId, 30 | name: &'a crate::NodeName, 31 | content: &'a core::ffi::CStr, 32 | } 33 | 34 | impl SymlinkRequest<'_> { 35 | #[must_use] 36 | pub fn parent_id(&self) -> crate::NodeId { 37 | self.parent_id 38 | } 39 | 40 | #[must_use] 41 | pub fn name(&self) -> &crate::NodeName { 42 | self.name 43 | } 44 | 45 | #[must_use] 46 | pub fn content(&self) -> &core::ffi::CStr { 47 | self.content 48 | } 49 | } 50 | 51 | try_from_fuse_request!(SymlinkRequest<'a>, |request| { 52 | let mut dec = request.decoder(); 53 | dec.expect_opcode(kernel::fuse_opcode::FUSE_SYMLINK)?; 54 | let content = dec.next_cstr()?; 55 | let name = dec.next_node_name()?; 56 | Ok(Self { 57 | parent_id: decode::node_id(dec.header().nodeid)?, 58 | name, 59 | content, 60 | }) 61 | }); 62 | 63 | impl fmt::Debug for SymlinkRequest<'_> { 64 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { 65 | fmt.debug_struct("SymlinkRequest") 66 | .field("parent_id", &self.parent_id) 67 | .field("name", &self.name) 68 | .field("content", &self.content) 69 | .finish() 70 | } 71 | } 72 | 73 | // }}} 74 | -------------------------------------------------------------------------------- /fuse/operations/symlink/BUILD: -------------------------------------------------------------------------------- 1 | load("//fuse/internal/testing:testing.bzl", "operation_tests") 2 | 3 | operation_tests("symlink") 4 | -------------------------------------------------------------------------------- /fuse/operations/symlink/symlink_test.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 John Millikin and the rust-fuse contributors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // SPDX-License-Identifier: Apache-2.0 16 | 17 | use fuse::kernel; 18 | use fuse::server::SymlinkRequest; 19 | 20 | use fuse_testutil::{decode_request, MessageBuilder}; 21 | 22 | #[test] 23 | fn request() { 24 | let buf = MessageBuilder::new() 25 | .set_header(|h| { 26 | h.opcode = kernel::fuse_opcode::FUSE_SYMLINK; 27 | h.nodeid = 100; 28 | }) 29 | .push_bytes(b"link content\x00") 30 | .push_bytes(b"link name\x00") 31 | .build_aligned(); 32 | let request = decode_request!(SymlinkRequest, buf); 33 | 34 | assert_eq!(request.parent_id(), fuse::NodeId::new(100).unwrap()); 35 | assert_eq!(request.name(), "link name"); 36 | assert_eq!(request.content(), c"link content"); 37 | } 38 | 39 | #[test] 40 | fn request_impl_debug() { 41 | let buf = MessageBuilder::new() 42 | .set_header(|h| { 43 | h.opcode = kernel::fuse_opcode::FUSE_SYMLINK; 44 | h.nodeid = 100; 45 | }) 46 | .push_bytes(b"link content\x00") 47 | .push_bytes(b"link name\x00") 48 | .build_aligned(); 49 | let request = decode_request!(SymlinkRequest, buf); 50 | 51 | assert_eq!( 52 | format!("{:#?}", request), 53 | concat!( 54 | "SymlinkRequest {\n", 55 | " parent_id: 100,\n", 56 | " name: \"link name\",\n", 57 | " content: \"link content\",\n", 58 | "}", 59 | ), 60 | ); 61 | } 62 | -------------------------------------------------------------------------------- /fuse/operations/unlink.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 John Millikin and the rust-fuse contributors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // SPDX-License-Identifier: Apache-2.0 16 | 17 | //! Implements the `FUSE_UNLINK` operation. 18 | 19 | use crate::kernel; 20 | use crate::server::decode; 21 | 22 | // UnlinkRequest {{{ 23 | 24 | /// Request type for `FUSE_UNLINK`. 25 | #[derive(Clone, Copy, Debug)] 26 | pub struct UnlinkRequest<'a> { 27 | parent_id: crate::NodeId, 28 | name: &'a crate::NodeName, 29 | } 30 | 31 | impl UnlinkRequest<'_> { 32 | #[must_use] 33 | pub fn parent_id(&self) -> crate::NodeId { 34 | self.parent_id 35 | } 36 | 37 | #[must_use] 38 | pub fn name(&self) -> &crate::NodeName { 39 | self.name 40 | } 41 | } 42 | 43 | try_from_fuse_request!(UnlinkRequest<'a>, |request| { 44 | let mut dec = request.decoder(); 45 | dec.expect_opcode(kernel::fuse_opcode::FUSE_UNLINK)?; 46 | Ok(Self { 47 | parent_id: decode::node_id(dec.header().nodeid)?, 48 | name: dec.next_node_name()?, 49 | }) 50 | }); 51 | 52 | // }}} 53 | -------------------------------------------------------------------------------- /fuse/operations/unlink/BUILD: -------------------------------------------------------------------------------- 1 | load("//fuse/internal/testing:testing.bzl", "operation_tests") 2 | 3 | operation_tests("unlink") 4 | -------------------------------------------------------------------------------- /fuse/operations/unlink/unlink_test.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 John Millikin and the rust-fuse contributors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // SPDX-License-Identifier: Apache-2.0 16 | 17 | use fuse::kernel; 18 | use fuse::server::UnlinkRequest; 19 | 20 | use fuse_testutil::{decode_request, MessageBuilder}; 21 | 22 | #[test] 23 | fn request() { 24 | let buf = MessageBuilder::new() 25 | .set_header(|h| { 26 | h.opcode = kernel::fuse_opcode::FUSE_UNLINK; 27 | h.nodeid = 100; 28 | }) 29 | .push_bytes(b"hello.world!\x00") 30 | .build_aligned(); 31 | let request = decode_request!(UnlinkRequest, buf); 32 | 33 | assert_eq!(request.parent_id(), fuse::NodeId::new(100).unwrap()); 34 | assert_eq!(request.name(), "hello.world!"); 35 | } 36 | 37 | #[test] 38 | fn request_impl_debug() { 39 | let buf = MessageBuilder::new() 40 | .set_header(|h| { 41 | h.opcode = kernel::fuse_opcode::FUSE_UNLINK; 42 | h.nodeid = 100; 43 | }) 44 | .push_bytes(b"hello.world!\x00") 45 | .build_aligned(); 46 | let request = decode_request!(UnlinkRequest, buf); 47 | 48 | assert_eq!( 49 | format!("{:#?}", request), 50 | concat!( 51 | "UnlinkRequest {\n", 52 | " parent_id: 100,\n", 53 | " name: \"hello.world!\",\n", 54 | "}", 55 | ), 56 | ); 57 | } 58 | -------------------------------------------------------------------------------- /fuse/operations/write/BUILD: -------------------------------------------------------------------------------- 1 | load("//fuse/internal/testing:testing.bzl", "operation_tests") 2 | 3 | operation_tests("write") 4 | -------------------------------------------------------------------------------- /fuse/operations/write/write_test.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 John Millikin and the rust-fuse contributors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // SPDX-License-Identifier: Apache-2.0 16 | 17 | use fuse::kernel; 18 | use fuse::server::WriteRequest; 19 | 20 | use fuse_testutil as testutil; 21 | use fuse_testutil::{decode_request, MessageBuilder}; 22 | 23 | const DUMMY_WRITE_FLAG: u32 = 0x80000000; 24 | 25 | #[test] 26 | fn request_v7p1() { 27 | let buf = MessageBuilder::new() 28 | .set_header(|h| { 29 | h.opcode = kernel::fuse_opcode::FUSE_WRITE; 30 | h.nodeid = 123; 31 | }) 32 | .push_sized(&123u64) // fuse_write_in::fh 33 | .push_sized(&45u64) // fuse_write_in::offset 34 | .push_sized(&12u32) // fuse_write_in::size 35 | .push_sized(&0u32) // fuse_write_in::write_flags 36 | .push_bytes(b"hello.world!") 37 | .build_aligned(); 38 | 39 | let req = decode_request!(WriteRequest, buf, { 40 | protocol_version: (7, 1), 41 | }); 42 | 43 | assert_eq!(req.handle(), 123); 44 | assert_eq!(req.offset(), 45); 45 | assert_eq!(req.lock_owner(), None); 46 | assert_eq!(req.flags().get(fuse::WriteRequestFlag::WRITE_CACHE), false); 47 | assert_eq!(req.open_flags(), 0); 48 | assert_eq!(req.value(), b"hello.world!"); 49 | } 50 | 51 | #[test] 52 | fn request_v7p9() { 53 | let buf = MessageBuilder::new() 54 | .set_header(|h| { 55 | h.opcode = kernel::fuse_opcode::FUSE_WRITE; 56 | h.nodeid = 123; 57 | }) 58 | .push_sized(&testutil::new!(kernel::fuse_write_in { 59 | fh: 123, 60 | offset: 45, 61 | size: 12, 62 | flags: 67, 63 | })) 64 | .push_bytes(b"hello.world!") 65 | .build_aligned(); 66 | 67 | let req = decode_request!(WriteRequest, buf, { 68 | protocol_version: (7, 9), 69 | }); 70 | 71 | assert_eq!(req.handle(), 123); 72 | assert_eq!(req.offset(), 45); 73 | assert_eq!(req.lock_owner(), None); 74 | assert_eq!(req.flags().get(fuse::WriteRequestFlag::WRITE_CACHE), false); 75 | assert_eq!(req.open_flags(), 67); 76 | assert_eq!(req.value(), b"hello.world!"); 77 | } 78 | 79 | #[test] 80 | fn request_lock_owner() { 81 | let buf = MessageBuilder::new() 82 | .set_header(|h| { 83 | h.opcode = kernel::fuse_opcode::FUSE_WRITE; 84 | h.nodeid = 123; 85 | }) 86 | .push_sized(&testutil::new!(kernel::fuse_write_in { 87 | write_flags: DUMMY_WRITE_FLAG | kernel::FUSE_WRITE_LOCKOWNER, 88 | lock_owner: 123, 89 | })) 90 | .build_aligned(); 91 | 92 | let req = decode_request!(WriteRequest, buf); 93 | 94 | assert_eq!(req.lock_owner(), Some(fuse::LockOwner(123))); 95 | } 96 | 97 | #[test] 98 | fn request_page_cache() { 99 | let buf = MessageBuilder::new() 100 | .set_header(|h| { 101 | h.opcode = kernel::fuse_opcode::FUSE_WRITE; 102 | h.nodeid = 123; 103 | }) 104 | .push_sized(&testutil::new!(kernel::fuse_write_in { 105 | write_flags: DUMMY_WRITE_FLAG | kernel::FUSE_WRITE_CACHE, 106 | })) 107 | .build_aligned(); 108 | 109 | let req = decode_request!(WriteRequest, buf); 110 | 111 | assert_eq!(req.flags().get(fuse::WriteRequestFlag::WRITE_CACHE), true); 112 | } 113 | -------------------------------------------------------------------------------- /fuse/os/BUILD: -------------------------------------------------------------------------------- 1 | load("@rules_rust//rust:defs.bzl", "rust_test") 2 | 3 | filegroup( 4 | name = "srcs", 5 | srcs = [ 6 | "freebsd.rs", 7 | "linux.rs", 8 | ], 9 | visibility = ["//:__subpackages__"], 10 | ) 11 | 12 | rust_test( 13 | name = "linux_test", 14 | srcs = [ 15 | "linux.rs", 16 | "linux_test.rs", 17 | ], 18 | crate = "//fuse", 19 | edition = "2021", 20 | rustc_flags = ["--deny=warnings"], 21 | target_compatible_with = [ 22 | "@platforms//os:linux", 23 | ], 24 | ) 25 | -------------------------------------------------------------------------------- /fuse/server/BUILD: -------------------------------------------------------------------------------- 1 | load("@rules_rust//rust:defs.bzl", "rust_test") 2 | 3 | filegroup( 4 | name = "srcs", 5 | srcs = [ 6 | "decode.rs", 7 | ], 8 | visibility = ["//fuse:__subpackages__"], 9 | ) 10 | 11 | rust_test( 12 | name = "decode_test", 13 | size = "small", 14 | timeout = "short", 15 | srcs = ["decode_test.rs"], 16 | crate = "//fuse", 17 | rustc_flags = [ 18 | '--cfg=rust_fuse_test="decode_test"', 19 | "--deny=warnings", 20 | ], 21 | deps = [ 22 | "//fuse", 23 | "//fuse/internal/testing:fuse_testutil", 24 | ], 25 | ) 26 | -------------------------------------------------------------------------------- /fuse/unix_time.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 John Millikin and the rust-fuse contributors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // SPDX-License-Identifier: Apache-2.0 16 | 17 | use core::fmt; 18 | 19 | /// A measurement of Unix time with nanosecond precision. 20 | /// 21 | /// Unix time is the number of Unix seconds that have elapsed since the Unix 22 | /// epoch of 1970-01-01 00:00:00 UTC. Unix seconds are exactly 1/86400 of a day. 23 | #[derive(Clone, Copy, Eq, Hash, Ord, PartialEq, PartialOrd)] 24 | pub struct UnixTime { 25 | seconds: i64, 26 | nanos: u32, 27 | } 28 | 29 | const UNIX_EPOCH: UnixTime = UnixTime { 30 | seconds: 0, 31 | nanos: 0, 32 | }; 33 | 34 | impl UnixTime { 35 | /// The Unix epoch, 1970-01-01 00:00:00 UTC. 36 | pub const EPOCH: UnixTime = UNIX_EPOCH; 37 | 38 | /// Creates a new `UnixTime` with the given offset from the epoch. 39 | /// 40 | /// Returns `None` if the nanoseconds value exceeds 999,999,999. 41 | #[inline] 42 | #[must_use] 43 | pub const fn new(seconds: i64, nanos: u32) -> Option { 44 | if nanos > crate::internal::timestamp::MAX_NANOS { 45 | return None; 46 | } 47 | Some(Self { seconds, nanos }) 48 | } 49 | 50 | /// Creates a new `UnixTime` with the given offset from the epoch. 51 | /// 52 | /// Returns `None` if the nanoseconds value exceeds 999,999,999. 53 | #[inline] 54 | #[must_use] 55 | pub const fn from_seconds(seconds: i64) -> UnixTime { 56 | Self { seconds, nanos: 0 } 57 | } 58 | 59 | /// Creates a new `UnixTime` without checking that the nanoseconds value 60 | /// is valid. 61 | /// 62 | /// # Safety 63 | /// 64 | /// The nanoseconds value must not exceed 999,999,999. 65 | #[inline] 66 | #[must_use] 67 | pub const unsafe fn new_unchecked(seconds: i64, nanos: u32) -> UnixTime { 68 | Self { seconds, nanos } 69 | } 70 | 71 | #[inline] 72 | #[must_use] 73 | pub(crate) unsafe fn from_timespec_unchecked( 74 | seconds: u64, 75 | nanos: u32, 76 | ) -> UnixTime { 77 | Self { 78 | seconds: seconds as i64, 79 | nanos, 80 | } 81 | } 82 | 83 | #[inline] 84 | #[must_use] 85 | pub(crate) fn as_timespec(&self) -> (u64, u32) { 86 | (self.seconds as u64, self.nanos) 87 | } 88 | 89 | /// Returns the number of whole seconds contained by this `UnixTime`. 90 | #[inline] 91 | #[must_use] 92 | pub const fn seconds(&self) -> i64 { 93 | self.seconds 94 | } 95 | 96 | /// Returns the fractional part of this `UnixTime`, in nanoseconds. 97 | #[inline] 98 | #[must_use] 99 | pub const fn nanos(&self) -> u32 { 100 | self.nanos 101 | } 102 | } 103 | 104 | impl fmt::Debug for UnixTime { 105 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { 106 | fmt.debug_tuple("UnixTime") 107 | .field(&format_args!("{:?}.{:09?}", self.seconds, self.nanos)) 108 | .finish() 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /rustfmt.toml: -------------------------------------------------------------------------------- 1 | edition = "2021" 2 | max_width = 80 3 | hard_tabs = true 4 | imports_layout = "HorizontalVertical" 5 | match_block_trailing_comma = true 6 | ignore = [ 7 | "src/internal/fuse_kernel.rs", 8 | "src/lib.rs", 9 | ] 10 | -------------------------------------------------------------------------------- /third_party/modules/com_github_jmillikin_rust-freebsd-errno/1.0.0/MODULE.bazel: -------------------------------------------------------------------------------- 1 | module( 2 | name = "com_github_jmillikin_rust-freebsd-errno", 3 | version = "1.0.0", 4 | compatibility_level = 1, 5 | ) 6 | 7 | bazel_dep(name = "platforms", version = "0.0.10") 8 | bazel_dep(name = "rules_rust", version = "0.52.2") 9 | 10 | bazel_dep( 11 | name = "com_github_jmillikin_rust-posix-errno", 12 | version = "1.0.1", 13 | repo_name = "rust_posix_errno", 14 | ) 15 | 16 | rust = use_extension("@rules_rust//rust:extensions.bzl", "rust") 17 | rust.toolchain( 18 | versions = ["1.63.0"], 19 | ) 20 | -------------------------------------------------------------------------------- /third_party/modules/com_github_jmillikin_rust-freebsd-errno/1.0.0/overlay/MODULE.bazel: -------------------------------------------------------------------------------- 1 | ../MODULE.bazel -------------------------------------------------------------------------------- /third_party/modules/com_github_jmillikin_rust-freebsd-errno/1.0.0/patches/rust_edition.patch: -------------------------------------------------------------------------------- 1 | --- freebsd-errno/BUILD 2 | +++ freebsd-errno/BUILD 3 | @@ -6,6 +6,7 @@ rust_library( 4 | name = "freebsd-errno", 5 | srcs = ["freebsd-errno.rs"], 6 | crate_features = ["posix-traits"], 7 | + edition = "2018", 8 | target_compatible_with = [ 9 | "@platforms//os:freebsd", 10 | ], 11 | -------------------------------------------------------------------------------- /third_party/modules/com_github_jmillikin_rust-freebsd-errno/1.0.0/source.json: -------------------------------------------------------------------------------- 1 | 2 | { 3 | "url": "https://github.com/jmillikin/rust-freebsd-errno/releases/download/v1.0.0/freebsd-errno-1.0.0.tar.xz", 4 | "integrity": "sha256-BK+kzKZbR9EJOw/WCGjzrVCosIGUz2/SpJfihZMz7vE=", 5 | "strip_prefix": "freebsd-errno-1.0.0", 6 | "overlay": { 7 | "MODULE.bazel": "sha256-1LxOmnmakzHskjhvHbgqUlA7sLritoWfqXDcp3sRLBI=" 8 | }, 9 | "patches": { 10 | "rust_edition.patch": "sha256-VjqdvnH0hYph+ui+w6OKxGgvu2wrCfJ3wbUeK2rwLws=" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /third_party/modules/com_github_jmillikin_rust-linux-errno/1.0.1/MODULE.bazel: -------------------------------------------------------------------------------- 1 | module( 2 | name = "com_github_jmillikin_rust-linux-errno", 3 | version = "1.0.1", 4 | compatibility_level = 1, 5 | ) 6 | 7 | bazel_dep(name = "platforms", version = "0.0.10") 8 | bazel_dep(name = "rules_rust", version = "0.52.2") 9 | 10 | bazel_dep( 11 | name = "com_github_jmillikin_rust-posix-errno", 12 | version = "1.0.1", 13 | repo_name = "rust_posix_errno", 14 | ) 15 | 16 | rust = use_extension("@rules_rust//rust:extensions.bzl", "rust") 17 | rust.toolchain( 18 | versions = ["1.63.0"], 19 | ) 20 | -------------------------------------------------------------------------------- /third_party/modules/com_github_jmillikin_rust-linux-errno/1.0.1/overlay/MODULE.bazel: -------------------------------------------------------------------------------- 1 | ../MODULE.bazel -------------------------------------------------------------------------------- /third_party/modules/com_github_jmillikin_rust-linux-errno/1.0.1/patches/rust_edition.patch: -------------------------------------------------------------------------------- 1 | --- linux-errno/BUILD 2 | +++ linux-errno/BUILD 3 | @@ -8,6 +8,7 @@ rust_library( 4 | "linux-errno.rs", 5 | "linux-errno_*.rs", 6 | ]), 7 | + edition = "2018", 8 | crate_features = ["posix-traits"], 9 | target_compatible_with = [ 10 | "@platforms//os:linux", 11 | -------------------------------------------------------------------------------- /third_party/modules/com_github_jmillikin_rust-linux-errno/1.0.1/source.json: -------------------------------------------------------------------------------- 1 | 2 | { 3 | "url": "https://github.com/jmillikin/rust-linux-errno/releases/download/v1.0.1/linux-errno-1.0.1.tar.xz", 4 | "integrity": "sha256-AJ1YyTyAbxeABKTNMK8hGGC8RPjOfQLrT1RIIa3Xypk=", 5 | "strip_prefix": "linux-errno-1.0.1", 6 | "overlay": { 7 | "MODULE.bazel": "sha256-Y0fI6GppyuyK9Kiy71xgJErgXKLFC3AaMNammmcMIOQ=" 8 | }, 9 | "patches": { 10 | "rust_edition.patch": "sha256-X7Mz/XhwlbKe8l/rOsVK+ihS2eNY7lhKs4BTROSoXG4=" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /third_party/modules/com_github_jmillikin_rust-linux-syscall/1.0.0/MODULE.bazel: -------------------------------------------------------------------------------- 1 | module( 2 | name = "com_github_jmillikin_rust-linux-syscall", 3 | version = "1.0.0", 4 | compatibility_level = 1, 5 | ) 6 | 7 | bazel_dep(name = "platforms", version = "0.0.10") 8 | bazel_dep(name = "rules_rust", version = "0.52.2") 9 | 10 | bazel_dep( 11 | name = "com_github_jmillikin_rust-linux-errno", 12 | version = "1.0.1", 13 | repo_name = "rust_linux_errno", 14 | ) 15 | 16 | rust = use_extension("@rules_rust//rust:extensions.bzl", "rust") 17 | rust.toolchain( 18 | versions = ["1.63.0"], 19 | ) 20 | -------------------------------------------------------------------------------- /third_party/modules/com_github_jmillikin_rust-linux-syscall/1.0.0/overlay/MODULE.bazel: -------------------------------------------------------------------------------- 1 | ../MODULE.bazel -------------------------------------------------------------------------------- /third_party/modules/com_github_jmillikin_rust-linux-syscall/1.0.0/patches/rust_edition.patch: -------------------------------------------------------------------------------- 1 | --- linux-syscall/BUILD 2 | +++ linux-syscall/BUILD 3 | @@ -8,6 +8,7 @@ rust_library( 4 | "linux-syscall.rs", 5 | "arch/**/*.rs", 6 | ]), 7 | + edition = "2018", 8 | target_compatible_with = [ 9 | "@platforms//os:linux", 10 | ], 11 | -------------------------------------------------------------------------------- /third_party/modules/com_github_jmillikin_rust-linux-syscall/1.0.0/source.json: -------------------------------------------------------------------------------- 1 | 2 | { 3 | "url": "https://github.com/jmillikin/rust-linux-syscall/releases/download/v1.0.0/linux-syscall-1.0.0.tar.xz", 4 | "integrity": "sha256-bia54g2HlRALkDXGmPSXetFTvtHq/p+dy1TxT70rEgo=", 5 | "strip_prefix": "linux-syscall-1.0.0", 6 | "overlay": { 7 | "MODULE.bazel": "sha256-ZSlMN+v6fHu2pY8O/OIZo+7cocDYmhHsdZhijN5FVeI=" 8 | }, 9 | "patches": { 10 | "rust_edition.patch": "sha256-v/nAU6LiqZB6ZENwaQOt7m67vEOw3xsmtQxz0nI/PCE=" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /third_party/modules/com_github_jmillikin_rust-posix-errno/1.0.1/MODULE.bazel: -------------------------------------------------------------------------------- 1 | module( 2 | name = "com_github_jmillikin_rust-posix-errno", 3 | version = "1.0.1", 4 | compatibility_level = 1, 5 | ) 6 | 7 | bazel_dep(name = "platforms", version = "0.0.10") 8 | bazel_dep(name = "rules_rust", version = "0.52.2") 9 | 10 | rust = use_extension("@rules_rust//rust:extensions.bzl", "rust") 11 | rust.toolchain( 12 | versions = ["1.63.0"], 13 | ) 14 | -------------------------------------------------------------------------------- /third_party/modules/com_github_jmillikin_rust-posix-errno/1.0.1/overlay/MODULE.bazel: -------------------------------------------------------------------------------- 1 | ../MODULE.bazel -------------------------------------------------------------------------------- /third_party/modules/com_github_jmillikin_rust-posix-errno/1.0.1/patches/rust_edition.patch: -------------------------------------------------------------------------------- 1 | --- posix-errno/BUILD 2 | +++ posix-errno/BUILD 3 | @@ -5,6 +5,7 @@ package(default_visibility = ["//visibility:public"]) 4 | rust_library( 5 | name = "posix-errno", 6 | srcs = ["posix-errno.rs"], 7 | + edition = "2015", 8 | ) 9 | 10 | rust_doc( 11 | -------------------------------------------------------------------------------- /third_party/modules/com_github_jmillikin_rust-posix-errno/1.0.1/source.json: -------------------------------------------------------------------------------- 1 | 2 | { 3 | "url": "https://github.com/jmillikin/rust-posix-errno/releases/download/v1.0.1/posix-errno-1.0.1.tar.xz", 4 | "integrity": "sha256-DIbISf9nM3L+ZBXUAEojNWW1eyiE6knTtyXdEpbMJSk=", 5 | "strip_prefix": "posix-errno-1.0.1", 6 | "overlay": { 7 | "MODULE.bazel": "sha256-vtls4Ss3RUfsRScZPTXRXgn0C6Uv6HixtDBgF6uTcPA=" 8 | }, 9 | "patches": { 10 | "rust_edition.patch": "sha256-zvLtnKD96AUHPrU4d679GUd1Evb5AJkiJeZamLEpGts=" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /third_party/modules/com_github_rust-lang_libc/0.2.149/MODULE.bazel: -------------------------------------------------------------------------------- 1 | module( 2 | name = "com_github_rust-lang_libc", 3 | version = "0.2.149", 4 | compatibility_level = 1, 5 | ) 6 | 7 | bazel_dep(name = "bazel_skylib", version = "1.7.1") 8 | bazel_dep(name = "platforms", version = "0.0.10") 9 | bazel_dep(name = "rules_rust", version = "0.52.2") 10 | 11 | rust = use_extension("@rules_rust//rust:extensions.bzl", "rust") 12 | rust.toolchain( 13 | versions = ["1.63.0"], 14 | ) 15 | -------------------------------------------------------------------------------- /third_party/modules/com_github_rust-lang_libc/0.2.149/overlay/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@bazel_skylib//rules:common_settings.bzl", "string_flag") 2 | load("@rules_rust//rust:defs.bzl", "rust_library") 3 | 4 | string_flag( 5 | name = "freebsd_abi", 6 | build_setting_default = "14", 7 | make_variable = "FREEBSD_ABI", 8 | ) 9 | 10 | rust_library( 11 | name = "libc", 12 | srcs = glob(["src/**/*.rs"]), 13 | edition = "2015", 14 | rustc_flags = [ 15 | "--cfg=libc_const_extern_fn", 16 | "--cfg=libc_core_cvoid", 17 | "--cfg=libc_priv_mod_use", 18 | ] + select({ 19 | "@platforms//os:freebsd": ["--cfg=freebsd$(FREEBSD_ABI)"], 20 | "//conditions:default": [], 21 | }), 22 | toolchains = [":freebsd_abi"], 23 | visibility = ["//visibility:public"], 24 | ) 25 | -------------------------------------------------------------------------------- /third_party/modules/com_github_rust-lang_libc/0.2.149/overlay/MODULE.bazel: -------------------------------------------------------------------------------- 1 | ../MODULE.bazel -------------------------------------------------------------------------------- /third_party/modules/com_github_rust-lang_libc/0.2.149/source.json: -------------------------------------------------------------------------------- 1 | { 2 | "url": "https://crates.io/api/v1/crates/libc/0.2.149/download", 3 | "integrity": "sha256-oIFzvIi3lV0bMUWqVhU5CWxCGsjevejLw2EuxjX+4ps=", 4 | "strip_prefix": "libc-0.2.149", 5 | "archive_type": "tar.gz", 6 | "overlay": { 7 | "BUILD.bazel": "sha256-pD7Ws3ZXg6kJQ2XmKiR0OE4YdFwg3RZejsCuU7alCRY=", 8 | "MODULE.bazel": "sha256-6SoYPBR/9IWcd2M9T2gjs0fYuk+5jihnVu29ETZEVh8=" 9 | } 10 | } 11 | --------------------------------------------------------------------------------