vfsi_sync/client/
handles.rs1use super::*;
4
5pub struct FsDir<F: VectorBackend> {
8 pub(super) inner: Arc<SharedBackend<F>>,
9 pub(super) dir: Option<VfDir>,
10 pub(super) path: PathBuf,
11}
12
13impl<F: VectorBackend> fmt::Debug for FsDir<F> {
14 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
15 formatter
16 .debug_struct("FsDir")
17 .field("path", &self.path)
18 .finish_non_exhaustive()
19 }
20}
21
22impl<F: VectorBackend> FsDir<F> {
23 pub fn is_closed(&self) -> bool {
24 self.dir.is_none()
25 }
26 pub fn path(&self) -> &Path {
28 &self.path
29 }
30
31 pub fn close(mut self) -> VfResult<()> {
32 self.try_close()
33 }
34
35 pub fn try_close(&mut self) -> VfResult<()> {
37 let Some(dir) = self.dir.as_ref() else {
38 return Ok(());
39 };
40 self.inner
41 .lock()
42 .map_err(|_| poisoned())?
43 .close_dir_impl(dir)?;
44 self.dir = None;
45 Ok(())
46 }
47}
48
49impl<F: VectorBackend> Drop for FsDir<F> {
50 fn drop(&mut self) {
51 if let Some(dir) = self.dir.take() {
52 self.inner.defer(
53 CleanupTarget::Directory(dir, std::mem::take(&mut self.path)),
54 |backend, target| {
55 let CleanupTarget::Directory(dir, path) = target else {
56 unreachable!()
57 };
58 backend
59 .close_dir_impl(dir)
60 .map_err(|error| error.with_context("close_dir", path))
61 },
62 );
63 }
64 }
65}
66
67pub struct OpenFile<F: HandleBackend> {
77 pub(super) inner: Arc<SharedBackend<F>>,
78 pub(super) file: Option<FileOperand>,
79 pub(super) append: bool,
81 pub(super) path: PathBuf,
82}
83
84impl<F: HandleBackend> fmt::Debug for OpenFile<F> {
85 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
86 formatter
87 .debug_struct("OpenFile")
88 .field("path", &self.path)
89 .field("is_open", &self.file.is_some())
90 .finish()
91 }
92}
93
94impl<F: HandleBackend> OpenFile<F> {
95 pub fn is_closed(&self) -> bool {
97 self.file.is_none()
98 }
99 pub(super) fn raw(&self) -> VfResult<&FileOperand> {
100 self.file
101 .as_ref()
102 .ok_or_else(|| VfError::client(0, crate::ERR_EBADF))
103 }
104
105 pub fn read_request_at(&self, offset: u64, length: usize) -> FsRead<'_, F> {
106 FsRead {
107 file: self,
108 offset: VfOffset::At(offset),
109 length,
110 }
111 }
112
113 pub fn path(&self) -> &Path {
117 &self.path
118 }
119
120 pub fn write_request_at<'a>(&'a self, offset: u64, data: &'a [u8]) -> FsWrite<'a, F> {
121 FsWrite::new(self, VfOffset::At(offset), data)
122 }
123
124 pub fn read_request_at_into<'a>(
125 &'a self,
126 offset: u64,
127 buffer: &'a mut [u8],
128 ) -> FsReadInto<'a, F> {
129 FsReadInto {
130 file: self,
131 offset: VfOffset::At(offset),
132 buffer,
133 }
134 }
135
136 pub fn try_close(&mut self) -> VfResult<()> {
142 let Some(file) = self.file.as_ref() else {
143 return Ok(());
144 };
145 self.inner
146 .lock()
147 .map_err(|_| poisoned())?
148 .close_impl(file)
149 .map_err(|error| error.with_context("close", &self.path))?;
150 self.file = None;
151 Ok(())
152 }
153
154 pub fn close(mut self) -> VfResult<()> {
158 self.try_close()
159 }
160}
161
162pub struct FsRead<'a, F: HandleBackend> {
164 pub(super) file: &'a OpenFile<F>,
165 pub(super) offset: VfOffset,
166 pub(super) length: usize,
167}
168
169pub type FsWrite<'a, F> =
171 vfsi_core::internal::WriteRequest<&'a OpenFile<F>, &'a [u8], VfOffset, ()>;
172
173pub struct FsReadInto<'a, F: HandleBackend> {
175 pub(super) file: &'a OpenFile<F>,
176 pub(super) offset: VfOffset,
177 pub(super) buffer: &'a mut [u8],
178}
179
180impl<F: HandleBackend> Drop for OpenFile<F> {
181 fn drop(&mut self) {
182 if let Some(file) = self.file.take() {
183 self.inner.defer(
184 CleanupTarget::File(file, std::mem::take(&mut self.path)),
185 |backend, target| {
186 let CleanupTarget::File(file, path) = target else {
187 unreachable!()
188 };
189 backend
190 .close_deferred(file)
191 .map_err(|error| error.with_context("close", path))
192 },
193 );
194 }
195 }
196}