1use crate::directory::FatDirectory;
8use crate::filesystem::FatFilesystemInner;
9use crate::node::Node;
10use crate::types::{Dir, File};
11use scopeguard::defer;
12use std::cell::{Ref, RefMut};
13use std::ops::{Deref, DerefMut};
14use std::sync::Arc;
15use zx::Status;
16
17pub trait Wrapper<'a> {
18 type Target: 'a;
19
20 fn get(&self, fs: &'a FatFilesystemInner) -> Option<&Self::Target>;
22
23 fn get_mut(&mut self, fs: &'a FatFilesystemInner) -> Option<&mut Self::Target>;
25}
26
27pub struct FatfsDirRef {
28 inner: Option<Dir<'static>>,
29 open_count: usize,
30}
31
32impl FatfsDirRef {
33 pub unsafe fn from(dir: Dir<'_>) -> Self {
36 FatfsDirRef { inner: Some(std::mem::transmute(dir)), open_count: 1 }
37 }
38
39 pub fn empty() -> Self {
40 FatfsDirRef { inner: None, open_count: 0 }
41 }
42
43 pub unsafe fn maybe_reopen(
45 &mut self,
46 fs: &FatFilesystemInner,
47 parent: Option<&Arc<FatDirectory>>,
48 name: &str,
49 ) -> Result<(), Status> {
50 if self.open_count == 0 {
51 Ok(())
52 } else {
53 self.reopen(fs, parent, name)
54 }
55 }
56
57 unsafe fn reopen(
58 &mut self,
59 fs: &FatFilesystemInner,
60 parent: Option<&Arc<FatDirectory>>,
61 name: &str,
62 ) -> Result<(), Status> {
63 let dir = if let Some(parent) = parent {
64 parent.open_ref(fs)?;
65 defer! { parent.close_ref(fs) }
66 parent.find_child(fs, name)?.ok_or(Status::NOT_FOUND)?.to_dir()
67 } else {
68 fs.root_dir()
69 };
70 self.inner.replace(std::mem::transmute(dir));
71 Ok(())
72 }
73
74 pub unsafe fn open(
76 &mut self,
77 fs: &FatFilesystemInner,
78 parent: Option<&Arc<FatDirectory>>,
79 name: &str,
80 ) -> Result<(), Status> {
81 if self.open_count == std::usize::MAX {
82 Err(Status::UNAVAILABLE)
83 } else {
84 if self.open_count == 0 {
85 self.reopen(fs, parent, name)?;
86 }
87 self.open_count += 1;
88 Ok(())
89 }
90 }
91
92 pub fn close(&mut self, fs: &FatFilesystemInner) {
94 assert!(self.open_count > 0);
95 self.open_count -= 1;
96 if self.open_count == 0 {
97 self.take(&fs);
98 }
99 }
100
101 pub fn take<'a>(&mut self, _fs: &'a FatFilesystemInner) -> Option<Dir<'a>> {
104 unsafe { std::mem::transmute(self.inner.take()) }
105 }
106}
107
108impl<'a> Wrapper<'a> for FatfsDirRef {
109 type Target = Dir<'a>;
110
111 fn get(&self, _fs: &'a FatFilesystemInner) -> Option<&Dir<'a>> {
112 unsafe { std::mem::transmute(self.inner.as_ref()) }
113 }
114
115 fn get_mut(&mut self, _fs: &'a FatFilesystemInner) -> Option<&mut Dir<'a>> {
116 unsafe { std::mem::transmute(self.inner.as_mut()) }
121 }
122}
123
124unsafe impl Sync for FatfsDirRef {}
126unsafe impl Send for FatfsDirRef {}
127
128impl Drop for FatfsDirRef {
129 fn drop(&mut self) {
130 assert_eq!(self.open_count, 0);
131 assert!(self.inner.is_none());
133 }
134}
135
136pub struct FatfsFileRef {
137 inner: Option<File<'static>>,
138 open_count: usize,
139}
140
141impl FatfsFileRef {
142 pub unsafe fn from(file: File<'_>) -> Self {
145 FatfsFileRef { inner: Some(std::mem::transmute(file)), open_count: 1 }
146 }
147
148 pub unsafe fn maybe_reopen(
150 &mut self,
151 fs: &FatFilesystemInner,
152 parent: &FatDirectory,
153 name: &str,
154 ) -> Result<(), Status> {
155 if self.open_count == 0 {
156 Ok(())
157 } else {
158 self.reopen(fs, parent, name)
159 }
160 }
161
162 unsafe fn reopen(
163 &mut self,
164 fs: &FatFilesystemInner,
165 parent: &FatDirectory,
166 name: &str,
167 ) -> Result<(), Status> {
168 let file = parent.find_child(fs, name)?.ok_or(Status::NOT_FOUND)?.to_file();
169 self.inner.replace(std::mem::transmute(file));
170 Ok(())
171 }
172
173 pub unsafe fn open(
174 &mut self,
175 fs: &FatFilesystemInner,
176 parent: Option<&FatDirectory>,
177 name: &str,
178 ) -> Result<(), Status> {
179 if self.open_count == std::usize::MAX {
180 Err(Status::UNAVAILABLE)
181 } else {
182 if self.open_count == 0 {
183 self.reopen(fs, parent.ok_or(Status::BAD_HANDLE)?, name)?;
184 }
185 self.open_count += 1;
186 Ok(())
187 }
188 }
189
190 pub fn close(&mut self, fs: &FatFilesystemInner) {
191 assert!(self.open_count > 0);
192 self.open_count -= 1;
193 if self.open_count == 0 {
194 self.take(&fs);
195 }
196 }
197
198 pub fn take<'a>(&mut self, _fs: &'a FatFilesystemInner) -> Option<File<'a>> {
201 self.inner.take()
202 }
203}
204
205impl<'a> Wrapper<'a> for FatfsFileRef {
206 type Target = File<'a>;
207
208 fn get(&self, _fs: &'a FatFilesystemInner) -> Option<&File<'a>> {
209 self.inner.as_ref()
210 }
211
212 fn get_mut(&mut self, _fs: &'a FatFilesystemInner) -> Option<&mut File<'a>> {
213 unsafe { std::mem::transmute(self.inner.as_mut()) }
218 }
219}
220
221unsafe impl Sync for FatfsFileRef {}
223unsafe impl Send for FatfsFileRef {}
224
225impl Drop for FatfsFileRef {
226 fn drop(&mut self) {
227 assert_eq!(self.open_count, 0);
229 assert!(self.inner.is_none());
230 }
231}
232
233pub struct Guard<'a, T>(&'a FatFilesystemInner, Ref<'a, T>);
234
235impl<'a, T> Guard<'a, T> {
236 pub fn new(fs: &'a FatFilesystemInner, inner: Ref<'a, T>) -> Self {
237 Self(fs, inner)
238 }
239}
240
241impl<'a, T: Wrapper<'a>> Deref for Guard<'a, T> {
242 type Target = T::Target;
243 fn deref(&self) -> &T::Target {
244 self.1.get(self.0).unwrap()
245 }
246}
247
248pub(crate) struct GuardMut<'a, T>(&'a FatFilesystemInner, RefMut<'a, T>);
249
250impl<'a, T> GuardMut<'a, T> {
251 pub fn new(fs: &'a FatFilesystemInner, inner: RefMut<'a, T>) -> Self {
252 Self(fs, inner)
253 }
254}
255
256impl<'a, T: Wrapper<'a>> Deref for GuardMut<'a, T> {
257 type Target = T::Target;
258 fn deref(&self) -> &T::Target {
259 self.1.get(self.0).unwrap()
260 }
261}
262
263impl<'a, T: Wrapper<'a>> DerefMut for GuardMut<'a, T> {
264 fn deref_mut(&mut self) -> &mut T::Target {
265 self.1.get_mut(self.0).unwrap()
266 }
267}