Skip to main content

abi_definitions/file_system/
directory.rs

1use crate::{
2    XilaFileSystemAccess, XilaFileSystemStatistics, XilaTaskIdentifier, abi_unsafe_function,
3    parse_c_str,
4};
5use alloc::ffi::CString;
6use core::{ffi::c_char, ptr::null_mut};
7use log::debug;
8use shared::generate_shadow_type;
9use task::{TaskIdentifier, block_on};
10use virtual_file_system::{SynchronousDirectory, get_instance as get_file_system_instance};
11
12use super::{XilaFileKind, XilaFileSystemInode, XilaFileSystemSize};
13
14generate_shadow_type!(XilaFileSystemDirectory, SynchronousDirectory);
15
16abi_unsafe_function! {
17    /// This function is used to open a directory.
18    ///
19    /// # Safety
20    ///
21    /// This function is unsafe because it dereferences raw pointers.
22    fn xila_file_system_directory_open(
23        task: XilaTaskIdentifier,
24        path: *const c_char,
25        out_directory: *mut XilaFileSystemDirectory,
26    ) -> XilaFileSystemResult {
27        let path = parse_c_str(path)?;
28        let task = TaskIdentifier::from(task);
29
30        debug!("Opening directory {path:?} for task {task:?}");
31
32        let synchronous_directory =
33            SynchronousDirectory::open(get_file_system_instance(), task, path)?;
34
35        unsafe {
36            // Cast the destination slot and overwrite it without reading/dropping garbage first
37            let target_slot = out_directory as *mut SynchronousDirectory;
38            ::core::ptr::write(target_slot, synchronous_directory);
39        }
40
41        Ok(())
42    }
43}
44
45abi_unsafe_function! {
46    /// This function is used to read a directory.
47    ///
48    /// # Safety
49    ///
50    /// This function is unsafe because it dereferences raw pointers.
51    fn xila_file_system_directory_read(
52        directory: *mut XilaFileSystemDirectory,
53        entry_name: *mut *const c_char,
54        entry_type: *mut XilaFileKind,
55        entry_size: *mut XilaFileSystemSize,
56        entry_inode: *mut XilaFileSystemInode,
57    ) -> XilaFileSystemResult {
58        debug!("Reading directory {directory:?}");
59
60        let entry = (*directory).read()?;
61
62        if let Some(entry) = entry {
63            *entry_name = CString::new(entry.name.as_str()).unwrap().into_raw();
64            *entry_type = entry.kind.into();
65            *entry_size = entry.size;
66            *entry_inode = entry.inode;
67        } else {
68            *entry_name = null_mut();
69        }
70
71        Ok(())
72    }
73}
74
75abi_unsafe_function! {
76    /// This function is used to close a directory.
77    ///
78    /// # Safety
79    /// The caller must ensure that the provided pointer is valid and points to a properly initialized `XilaFile
80    fn xila_file_system_directory_close(
81        directory: *mut XilaFileSystemDirectory,
82    ) -> XilaFileSystemResult {
83        (*directory).close_internal(get_file_system_instance())
84    }
85}
86
87abi_unsafe_function! {
88    /// This function is used to rewind a directory.
89    ///
90    /// # Safety
91    /// The caller must ensure that the provided pointer is valid and points to a properly initialized `XilaFileSystemItem` that is a directory.
92    fn xila_file_system_directory_rewind(
93        directory: *mut XilaFileSystemDirectory,
94    ) -> XilaFileSystemResult {
95        debug!("Rewinding directory {directory:?} ");
96
97        (*directory).rewind()
98    }
99}
100
101abi_unsafe_function! {
102    /// This function is used to set the position in a directory.
103    ///
104    /// # Safety
105    /// The caller must ensure that the provided pointer is valid and points to a properly initialized `XilaFileSystemItem` that is a directory.
106    fn xila_file_system_directory_set_position(
107        directory: *mut XilaFileSystemDirectory,
108        offset: XilaFileSystemSize,
109    ) -> XilaFileSystemResult {
110        debug!("Setting position in directory {directory:?} to offset {offset}");
111
112        (*directory).set_position(offset)?;
113
114        Ok(())
115    }
116}
117
118abi_unsafe_function! {
119    /// This function is used to get the statistics of a directory.
120    ///
121    /// # Safety
122    /// The caller must ensure that the provided pointer is valid and points to a properly initialized `XilaFileSystemItem` that is a directory.
123    fn xila_file_system_directory_get_statistics(
124        directory: *mut XilaFileSystemDirectory,
125        statistics: *mut XilaFileSystemStatistics,
126    ) -> XilaFileSystemResult {
127        debug!("Getting statistics for directory {directory:?}");
128
129        let result = (*directory).get_statistics()?;
130
131        *statistics = XilaFileSystemStatistics::from_statistics(result);
132
133        Ok(())
134    }
135}
136
137abi_unsafe_function! {
138    /// This function is used to get the access flags of a directory.
139    ///
140    /// # Safety
141    /// The caller must ensure that the provided pointer is valid and points to a properly initialized `XilaFileSystemItem` that is a directory.
142    fn xila_file_system_directory_get_access(
143        directory: *mut XilaFileSystemDirectory,
144        access: *mut XilaFileSystemAccess,
145    ) -> XilaFileSystemResult {
146        debug!("Getting access flags for directory {directory:?}");
147
148        let result = (*directory).get_access()?;
149
150        log::information!("Access flags for directory {directory:?}: {result:?}");
151
152        access.write(result.bits());
153
154        Ok(())
155    }
156}
157
158abi_unsafe_function! {
159    /// This function is used to get the state flags of a directory.
160    ///
161    /// # Safety
162    /// The caller must ensure that the provided pointer is valid and points to a properly initialized `XilaFileSystemItem` that is a directory.
163    fn xila_file_system_directory_get_state(
164        directory: *mut XilaFileSystemDirectory,
165        state: *mut u8,
166    ) -> XilaFileSystemResult {
167        debug!("Getting state flags for directory {directory:?}");
168
169        let result = (*directory).get_state()?;
170
171        state.write(result.bits());
172
173        Ok(())
174    }
175}
176
177abi_unsafe_function! {
178    /// This function is used to get the position in a file.
179    ///
180    /// # Safety
181    ///
182    /// This function is unsafe because it dereferences raw pointers.
183    fn xila_file_system_directory_create(
184        task: XilaTaskIdentifier,
185        path: *const c_char,
186    ) -> XilaFileSystemResult {
187        let path = parse_c_str(path)?;
188
189        block_on(get_file_system_instance().create_directory(task.into(), &path))?;
190
191        Ok(())
192    }
193}