Skip to main content
KeyOS API Reference

fs/
messages.rs

1// SPDX-FileCopyrightText: 2025 Foundation Devices, Inc. <hello@foundation.xyz>
2// SPDX-License-Identifier: GPL-3.0-or-later
3
4use num_traits::{FromPrimitive, ToPrimitive};
5use server::{SimpleMemoryMessage, WithAppId};
6use xous::{AppId, MemoryRange};
7
8use crate::{
9    DirEntry, DirHandle, Error, FileHandle, FileSystemEvent, Location, MappedFileInTheirSpace, Metadata,
10    OpenFlags, SeekFrom,
11};
12
13#[derive(Debug, server::Message, rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)]
14#[response(Result<FileHandle, Error>)]
15pub struct OpenFileMessage {
16    pub path: String,
17    pub location: Location,
18    pub flags: OpenFlags,
19}
20
21#[derive(Debug, server::Message, rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)]
22#[response(Result<DirHandle, Error>)]
23pub struct OpenDirMessage {
24    pub path: String,
25    pub location: Location,
26}
27
28#[derive(Debug, server::Message, rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)]
29#[response(Result<DirHandle, Error>)]
30pub struct CreateDirMessage {
31    pub path: String,
32    pub location: Location,
33}
34
35#[derive(Debug, server::Message)]
36#[response(Result<(), Error>)]
37pub struct CloseFile(pub FileHandle);
38
39#[derive(Debug, server::Message)]
40#[response(Result<(), Error>)]
41pub struct CloseDir(pub DirHandle);
42
43#[derive(Debug, server::Message, rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)]
44#[event(FileSystemEvent)]
45pub struct SubscribeFilesystemEvent(pub Location);
46
47#[derive(Debug, server::Message)]
48#[response(())]
49pub struct FormatEncryptedVolume;
50
51#[derive(Debug, server::Message)]
52#[response(Result<(), Error>)]
53pub struct Flush(pub FileHandle);
54
55#[derive(Debug, server::Message)]
56#[response(Result<(), Error>)]
57pub struct FlushFs(pub Location);
58
59#[derive(Debug, server::Message, rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)]
60#[response(Result<MappedFileInTheirSpace, Error>)]
61pub struct MapFileMessage {
62    pub path: String,
63    pub location: Location,
64}
65
66#[derive(Debug, Clone, Copy, PartialEq, Eq, rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)]
67pub enum AppResourcesRoot {
68    BuiltIn,
69    Sideloaded,
70}
71
72#[derive(Debug, server::Message, rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)]
73#[response(Result<(), Error>)]
74pub struct RegisterAppResources {
75    #[rkyv(with = WithAppId)]
76    pub app_id: AppId,
77    pub root: AppResourcesRoot,
78    pub app_dir: String,
79}
80
81#[derive(Debug, server::Message, rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)]
82#[response(Result<Metadata, Error>)]
83pub enum GetMetadata {
84    Path { path: String, location: Location },
85    Handle { handle: FileHandle },
86}
87
88#[derive(Debug, server::Message, rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)]
89#[response(Result<Option<DirEntry>, Error>)]
90pub struct NextEntry(pub DirHandle);
91
92#[derive(Debug, server::Message)]
93#[response(Result<usize, Error>)]
94pub struct ReadBlocks {
95    pub buf: MemoryRange,
96    pub block_index: u32,
97    pub block_count: usize,
98    pub location: Location,
99}
100
101#[derive(Debug, server::Message)]
102#[response(Result<usize, Error>)]
103pub struct WriteBlocks {
104    pub buf: MemoryRange,
105    pub block_index: u32,
106    pub block_count: usize,
107    pub location: Location,
108}
109
110#[derive(Debug, server::Message)]
111#[response(Result<usize, Error>)]
112pub struct BlockCount(pub Location);
113
114#[derive(Debug, server::Message)]
115#[response(Result<usize, Error>)]
116pub struct ReadFile {
117    pub buf: MemoryRange,
118    pub handle: FileHandle,
119    pub read_len: usize,
120}
121
122#[derive(Debug, server::Message)]
123#[response(Result<usize, Error>)]
124pub struct WriteFile {
125    pub buf: MemoryRange,
126    pub handle: FileHandle,
127    pub write_len: usize,
128}
129
130#[derive(Debug, server::Message, rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)]
131#[response(Result<u64, Error>)]
132pub struct SeekFile {
133    pub file: FileHandle,
134    pub pos: SeekFrom,
135}
136
137#[derive(Debug, server::Message, rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)]
138#[response(Result<(), Error>)]
139pub struct Remove {
140    pub path: String,
141    pub location: Location,
142}
143
144/// Remove all AppData for `app_id`, not just the caller's own (unlike `Remove`,
145/// which is scoped to the calling app). Wipes the app's persisted data, including
146/// any stored seed.
147#[derive(Debug, server::Message, rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)]
148#[response(Result<(), Error>)]
149pub struct RemoveAppData {
150    #[rkyv(with = WithAppId)]
151    pub app_id: AppId,
152}
153
154#[derive(Debug, server::Message, rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)]
155#[response(Result<(), Error>)]
156pub struct AtomicCopy {
157    pub src: String,
158    pub dest_dir: String,
159    pub rename: Option<String>,
160    pub location: Location,
161}
162
163#[derive(Debug, server::Message, rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)]
164#[response(Result<(), Error>)]
165pub struct Rename {
166    pub location: Location,
167    pub from: String,
168    pub to: String,
169}
170
171#[derive(Debug, server::Message, rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)]
172#[response(Result<(), Error>)]
173pub struct SetLen {
174    pub handle: FileHandle,
175    pub len: u64,
176}
177
178#[derive(Debug, server::Message, rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)]
179#[response(Result<(), Error>)]
180pub struct TruncateFile(pub FileHandle);
181
182#[derive(Debug, server::Message, rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)]
183#[response(Result<(), Error>)]
184pub struct SetMtime {
185    pub handle: FileHandle,
186    pub datetime: crate::DateTime,
187}
188
189#[derive(Debug, server::Message, rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)]
190#[response(Result<Vec<u8>, Error>)]
191pub struct AsyncRead {
192    pub handle: FileHandle,
193    pub read_len: usize,
194}
195
196#[derive(Debug, server::Message, rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)]
197#[response(Result<usize, Error>)]
198pub struct AsyncWrite {
199    pub handle: FileHandle,
200    pub buffer: Vec<u8>,
201}
202
203#[derive(Debug, server::Message)]
204#[response(Result<usize, Error>)]
205pub struct AsyncCopyBlock {
206    pub from: FileHandle,
207    pub to: FileHandle,
208    pub len: usize,
209}
210
211#[derive(Debug, server::Message)]
212#[response(Result<(), Error>)]
213pub struct MountAirlock(pub bool);
214
215#[derive(Debug, server::Message)]
216#[response(Result<(), Error>)]
217pub struct FormatAirlock;
218
219#[derive(Debug, server::Message)]
220#[response(Result<(), Error>)]
221pub struct FormatUsb;
222
223macro_rules! declare_msg {
224    ($name:ident) => {
225        #[derive(Debug, server::Message)]
226        #[response(())]
227        pub struct $name;
228    };
229}
230
231declare_msg!(GetUsbReadAccess);
232declare_msg!(GetUsbWriteAccess);
233declare_msg!(GetBootReadAccess);
234declare_msg!(GetBootWriteAccess);
235declare_msg!(GetUserReadAccess);
236declare_msg!(GetUserWriteAccess);
237declare_msg!(GetSystemReadAccess);
238declare_msg!(GetSystemWriteAccess);
239declare_msg!(GetSystemAppDataReadAccess);
240declare_msg!(GetSystemAppDataWriteAccess);
241declare_msg!(GetEncryptedRootReadAccess);
242declare_msg!(GetEncryptedRootWriteAccess);
243declare_msg!(GetAirlockReadAccess);
244declare_msg!(GetAirlockWriteAccess);
245
246impl From<SimpleMemoryMessage> for ReadBlocks {
247    fn from(msg: SimpleMemoryMessage) -> Self {
248        Self {
249            buf: msg.buf,
250            block_index: msg.arg1 as u32,
251            block_count: (msg.arg2 & 0xFFFFFF),
252            location: Location::from_usize(msg.arg2 >> 24).unwrap_or(Location::EncryptedRoot),
253        }
254    }
255}
256
257impl From<ReadBlocks> for SimpleMemoryMessage {
258    fn from(read: ReadBlocks) -> Self {
259        Self {
260            buf: read.buf,
261            arg1: read.block_index as usize,
262            arg2: (read.block_count & 0xFFFFFF) | (read.location.to_usize().unwrap() << 24),
263        }
264    }
265}
266
267impl From<SimpleMemoryMessage> for WriteBlocks {
268    fn from(msg: SimpleMemoryMessage) -> Self {
269        Self {
270            buf: msg.buf,
271            block_index: msg.arg1 as u32,
272            block_count: (msg.arg2 & 0xFFFFFF),
273            location: Location::from_usize(msg.arg2 >> 24).unwrap_or(Location::EncryptedRoot),
274        }
275    }
276}
277
278impl From<WriteBlocks> for SimpleMemoryMessage {
279    fn from(write: WriteBlocks) -> Self {
280        Self {
281            buf: write.buf,
282            arg1: write.block_index as usize,
283            arg2: (write.block_count & 0xFFFFFF) | (write.location.to_usize().unwrap() << 24),
284        }
285    }
286}
287
288impl From<SimpleMemoryMessage> for ReadFile {
289    fn from(msg: SimpleMemoryMessage) -> Self {
290        Self { buf: msg.buf, handle: FileHandle(msg.arg1 as u32), read_len: msg.arg2 }
291    }
292}
293
294impl From<ReadFile> for SimpleMemoryMessage {
295    fn from(read: ReadFile) -> Self {
296        Self { buf: read.buf, arg1: read.handle.0 as usize, arg2: read.read_len }
297    }
298}
299
300impl From<SimpleMemoryMessage> for WriteFile {
301    fn from(msg: SimpleMemoryMessage) -> Self {
302        Self { buf: msg.buf, handle: FileHandle(msg.arg1 as u32), write_len: msg.arg2 }
303    }
304}
305
306impl From<WriteFile> for SimpleMemoryMessage {
307    fn from(write: WriteFile) -> Self {
308        Self { buf: write.buf, arg1: write.handle.0 as usize, arg2: write.write_len }
309    }
310}
311
312// AsScalar/FromScalar implementations for blockingScalar messages
313impl server::AsScalar<4> for AsyncCopyBlock {
314    fn as_scalar(&self) -> [u32; 4] { [self.from.0, self.to.0, self.len as u32, 0] }
315}
316
317impl server::FromScalar<4> for AsyncCopyBlock {
318    fn from_scalar([from, to, len, _]: [u32; 4]) -> Self {
319        Self { from: FileHandle(from), to: FileHandle(to), len: len as usize }
320    }
321}