1use crate::directory::FatDirectory;
8use crate::filesystem::FatFilesystemInner;
9use crate::node::Node;
10use crate::types::{Dir, File};
11use scopeguard::defer;
12use std::sync::Arc;
13use zx::Status;
14
15pub struct FatfsDirRef {
16 inner: Option<Dir<'static>>,
17 open_count: usize,
18}
19
20impl FatfsDirRef {
21 pub unsafe fn from(dir: Dir<'_>) -> Self {
24 FatfsDirRef { inner: Some(std::mem::transmute(dir)), open_count: 1 }
25 }
26
27 pub fn empty() -> Self {
28 FatfsDirRef { inner: None, open_count: 0 }
29 }
30
31 pub fn borrow<'a>(&'a self, _fs: &'a FatFilesystemInner) -> Option<&'a Dir<'a>> {
34 unsafe { std::mem::transmute(self.inner.as_ref()) }
35 }
36
37 pub fn borrow_mut<'a>(&'a mut self, _fs: &'a FatFilesystemInner) -> Option<&'a mut Dir<'a>> {
40 unsafe { std::mem::transmute(self.inner.as_mut()) }
45 }
46
47 pub unsafe fn maybe_reopen(
49 &mut self,
50 fs: &FatFilesystemInner,
51 parent: Option<&Arc<FatDirectory>>,
52 name: &str,
53 ) -> Result<(), Status> {
54 if self.open_count == 0 {
55 Ok(())
56 } else {
57 self.reopen(fs, parent, name)
58 }
59 }
60
61 unsafe fn reopen(
62 &mut self,
63 fs: &FatFilesystemInner,
64 parent: Option<&Arc<FatDirectory>>,
65 name: &str,
66 ) -> Result<(), Status> {
67 let dir = if let Some(parent) = parent {
68 parent.open_ref(fs)?;
69 defer! { parent.close_ref(fs) }
70 parent.find_child(fs, name)?.ok_or(Status::NOT_FOUND)?.to_dir()
71 } else {
72 fs.root_dir()
73 };
74 self.inner.replace(std::mem::transmute(dir));
75 Ok(())
76 }
77
78 pub unsafe fn open(
80 &mut self,
81 fs: &FatFilesystemInner,
82 parent: Option<&Arc<FatDirectory>>,
83 name: &str,
84 ) -> Result<(), Status> {
85 if self.open_count == std::usize::MAX {
86 Err(Status::UNAVAILABLE)
87 } else {
88 if self.open_count == 0 {
89 self.reopen(fs, parent, name)?;
90 }
91 self.open_count += 1;
92 Ok(())
93 }
94 }
95
96 pub fn close(&mut self, fs: &FatFilesystemInner) {
98 assert!(self.open_count > 0);
99 self.open_count -= 1;
100 if self.open_count == 0 {
101 self.take(&fs);
102 }
103 }
104
105 pub fn take<'a>(&mut self, _fs: &'a FatFilesystemInner) -> Option<Dir<'a>> {
108 unsafe { std::mem::transmute(self.inner.take()) }
109 }
110}
111
112unsafe impl Sync for FatfsDirRef {}
114unsafe impl Send for FatfsDirRef {}
115
116impl Drop for FatfsDirRef {
117 fn drop(&mut self) {
118 assert_eq!(self.open_count, 0);
119 assert!(self.inner.is_none());
121 }
122}
123
124pub struct FatfsFileRef {
125 inner: Option<File<'static>>,
126 open_count: usize,
127}
128
129impl FatfsFileRef {
130 pub unsafe fn from(file: File<'_>) -> Self {
133 FatfsFileRef { inner: Some(std::mem::transmute(file)), open_count: 1 }
134 }
135
136 pub fn borrow_mut<'a>(&'a mut self, _fs: &'a FatFilesystemInner) -> Option<&'a mut File<'a>> {
139 unsafe { std::mem::transmute(self.inner.as_mut()) }
144 }
145
146 pub fn borrow<'a>(&'a self, _fs: &'a FatFilesystemInner) -> Option<&'a File<'a>> {
149 self.inner.as_ref()
150 }
151
152 pub unsafe fn maybe_reopen(
154 &mut self,
155 fs: &FatFilesystemInner,
156 parent: &FatDirectory,
157 name: &str,
158 ) -> Result<(), Status> {
159 if self.open_count == 0 {
160 Ok(())
161 } else {
162 self.reopen(fs, parent, name)
163 }
164 }
165
166 unsafe fn reopen(
167 &mut self,
168 fs: &FatFilesystemInner,
169 parent: &FatDirectory,
170 name: &str,
171 ) -> Result<(), Status> {
172 let file = parent.find_child(fs, name)?.ok_or(Status::NOT_FOUND)?.to_file();
173 self.inner.replace(std::mem::transmute(file));
174 Ok(())
175 }
176
177 pub unsafe fn open(
178 &mut self,
179 fs: &FatFilesystemInner,
180 parent: Option<&FatDirectory>,
181 name: &str,
182 ) -> Result<(), Status> {
183 if self.open_count == std::usize::MAX {
184 Err(Status::UNAVAILABLE)
185 } else {
186 if self.open_count == 0 {
187 self.reopen(fs, parent.ok_or(Status::BAD_HANDLE)?, name)?;
188 }
189 self.open_count += 1;
190 Ok(())
191 }
192 }
193
194 pub fn close(&mut self, fs: &FatFilesystemInner) {
195 assert!(self.open_count > 0);
196 self.open_count -= 1;
197 if self.open_count == 0 {
198 self.take(&fs);
199 }
200 }
201
202 pub fn take<'a>(&mut self, _fs: &'a FatFilesystemInner) -> Option<File<'a>> {
205 self.inner.take()
206 }
207}
208
209unsafe impl Sync for FatfsFileRef {}
211unsafe impl Send for FatfsFileRef {}
212
213impl Drop for FatfsFileRef {
214 fn drop(&mut self) {
215 assert_eq!(self.open_count, 0);
217 assert!(self.inner.is_none());
218 }
219}