Skip to main content

capsec_std/
fs.rs

1//! Capability-gated filesystem operations.
2//!
3//! Drop-in replacements for `std::fs` functions that require a capability token
4//! proving the caller has filesystem permission.
5//!
6//! # Example
7//!
8//! ```no_run
9//! # use capsec_core::root::test_root;
10//! # use capsec_core::permission::FsRead;
11//! # use capsec_core::has::Has;
12//! let root = test_root();
13//! let cap = root.grant::<FsRead>();
14//! let data = capsec_std::fs::read("/tmp/data.bin", &cap).unwrap();
15//! ```
16
17use crate::file::{ReadFile, WriteFile};
18use capsec_core::cap::Cap;
19use capsec_core::error::CapSecError;
20use capsec_core::has::Has;
21use capsec_core::permission::{FsRead, FsWrite};
22use std::path::Path;
23
24/// Reads the entire contents of a file into a byte vector.
25/// Requires [`FsRead`] permission.
26pub fn read(path: impl AsRef<Path>, cap: &impl Has<FsRead>) -> Result<Vec<u8>, CapSecError> {
27    let _proof: Cap<FsRead> = cap.cap_ref();
28    Ok(std::fs::read(path)?)
29}
30
31/// Reads the entire contents of a file into a string.
32/// Requires [`FsRead`] permission.
33pub fn read_to_string(
34    path: impl AsRef<Path>,
35    cap: &impl Has<FsRead>,
36) -> Result<String, CapSecError> {
37    let _proof: Cap<FsRead> = cap.cap_ref();
38    Ok(std::fs::read_to_string(path)?)
39}
40
41/// Returns an iterator over the entries within a directory.
42/// Requires [`FsRead`] permission.
43pub fn read_dir(
44    path: impl AsRef<Path>,
45    cap: &impl Has<FsRead>,
46) -> Result<std::fs::ReadDir, CapSecError> {
47    let _proof: Cap<FsRead> = cap.cap_ref();
48    Ok(std::fs::read_dir(path)?)
49}
50
51/// Returns metadata about a file or directory.
52/// Requires [`FsRead`] permission.
53pub fn metadata(
54    path: impl AsRef<Path>,
55    cap: &impl Has<FsRead>,
56) -> Result<std::fs::Metadata, CapSecError> {
57    let _proof: Cap<FsRead> = cap.cap_ref();
58    Ok(std::fs::metadata(path)?)
59}
60
61/// Writes bytes to a file, creating it if it doesn't exist, truncating if it does.
62/// Requires [`FsWrite`] permission.
63pub fn write(
64    path: impl AsRef<Path>,
65    contents: impl AsRef<[u8]>,
66    cap: &impl Has<FsWrite>,
67) -> Result<(), CapSecError> {
68    let _proof: Cap<FsWrite> = cap.cap_ref();
69    Ok(std::fs::write(path, contents)?)
70}
71
72/// Creates all directories in the given path if they don't exist.
73/// Requires [`FsWrite`] permission.
74pub fn create_dir_all(path: impl AsRef<Path>, cap: &impl Has<FsWrite>) -> Result<(), CapSecError> {
75    let _proof: Cap<FsWrite> = cap.cap_ref();
76    Ok(std::fs::create_dir_all(path)?)
77}
78
79/// Deletes a file.
80/// Requires [`FsWrite`] permission.
81pub fn remove_file(path: impl AsRef<Path>, cap: &impl Has<FsWrite>) -> Result<(), CapSecError> {
82    let _proof: Cap<FsWrite> = cap.cap_ref();
83    Ok(std::fs::remove_file(path)?)
84}
85
86/// Recursively deletes a directory and all its contents.
87/// Requires [`FsWrite`] permission.
88pub fn remove_dir_all(path: impl AsRef<Path>, cap: &impl Has<FsWrite>) -> Result<(), CapSecError> {
89    let _proof: Cap<FsWrite> = cap.cap_ref();
90    Ok(std::fs::remove_dir_all(path)?)
91}
92
93/// Renames a file or directory.
94/// Requires [`FsWrite`] permission.
95pub fn rename(
96    from: impl AsRef<Path>,
97    to: impl AsRef<Path>,
98    cap: &impl Has<FsWrite>,
99) -> Result<(), CapSecError> {
100    let _proof: Cap<FsWrite> = cap.cap_ref();
101    Ok(std::fs::rename(from, to)?)
102}
103
104/// Copies a file. Requires both [`FsRead`] and [`FsWrite`] permissions
105/// (passed as separate capability tokens).
106pub fn copy(
107    from: impl AsRef<Path>,
108    to: impl AsRef<Path>,
109    read_cap: &impl Has<FsRead>,
110    write_cap: &impl Has<FsWrite>,
111) -> Result<u64, CapSecError> {
112    let _read_proof: Cap<FsRead> = read_cap.cap_ref();
113    let _write_proof: Cap<FsWrite> = write_cap.cap_ref();
114    Ok(std::fs::copy(from, to)?)
115}
116
117/// Opens a file for reading. Returns a [`ReadFile`] that implements `Read` + `Seek`
118/// but NOT `Write`, enforcing the capability boundary beyond the function call.
119/// Requires [`FsRead`] permission.
120pub fn open(path: impl AsRef<Path>, cap: &impl Has<FsRead>) -> Result<ReadFile, CapSecError> {
121    let _proof: Cap<FsRead> = cap.cap_ref();
122    Ok(ReadFile::new(std::fs::File::open(path)?))
123}
124
125/// Creates or truncates a file for writing. Returns a [`WriteFile`] that implements
126/// `Write` + `Seek` but NOT `Read`, enforcing the capability boundary beyond the function call.
127/// Requires [`FsWrite`] permission.
128pub fn create(path: impl AsRef<Path>, cap: &impl Has<FsWrite>) -> Result<WriteFile, CapSecError> {
129    let _proof: Cap<FsWrite> = cap.cap_ref();
130    Ok(WriteFile::new(std::fs::File::create(path)?))
131}