1use std::fmt;
4use std::io::{self, Read, Seek, SeekFrom as IoSeekFrom, Write};
5use std::path::{Component, Path, PathBuf};
6use std::sync::{Arc, Mutex};
7use std::time::SystemTime;
8
9use crate::traits::{validate_read_results, validate_write_results};
10use crate::{
11 AttrMask, Capabilities, CopyFileSystem, DEFAULT_READ_MAX_BYTES, DirEntry, DirectoryFileSystem,
12 FileSystem, LinkFileSystem, Metadata, MetadataFileSystem, MetadataQuery, MetadataUpdate,
13 NamespaceFileSystem, OpenFlags, OpenRequest, Permissions, ReadDirOptions, ReadOp, ReadResult,
14 SetAttributes, VectorFileSystem, VfError, VfFile, VfOffset, VfResult, WriteOpRef, WriteResult,
15};
16
17fn io_error(error: VfError) -> io::Error {
18 error.into()
19}
20
21fn poisoned() -> VfError {
22 VfError::client(0, crate::ERR_IO)
23}
24
25fn wrong_result_count(operation: &str, expected: usize, actual: usize) -> VfError {
26 VfError::transport(
27 None,
28 format!("{operation} backend returned {actual} results for {expected} requests"),
29 )
30}
31
32pub struct FsClient<F> {
34 inner: Arc<Mutex<F>>,
35}
36
37impl<F> Clone for FsClient<F> {
38 fn clone(&self) -> Self {
39 Self {
40 inner: Arc::clone(&self.inner),
41 }
42 }
43}
44
45impl<F> fmt::Debug for FsClient<F> {
46 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
47 formatter.debug_struct("FsClient").finish_non_exhaustive()
48 }
49}
50
51impl<F> FsClient<F> {
52 pub fn new(filesystem: F) -> Self {
53 Self {
54 inner: Arc::new(Mutex::new(filesystem)),
55 }
56 }
57
58 fn lock(&self) -> VfResult<std::sync::MutexGuard<'_, F>> {
59 self.inner.lock().map_err(|_| poisoned())
60 }
61
62 pub fn into_inner(self) -> Result<F, Self> {
63 match Arc::try_unwrap(self.inner) {
64 Ok(mutex) => match mutex.into_inner() {
65 Ok(filesystem) => Ok(filesystem),
66 Err(poisoned) => Ok(poisoned.into_inner()),
67 },
68 Err(inner) => Err(Self { inner }),
69 }
70 }
71}
72
73impl<F: FileSystem> FsClient<F> {
74 pub fn open(&self, path: impl AsRef<Path>) -> VfResult<FsFile<F>> {
76 self.open_with(OpenRequest::new(path.as_ref(), OpenFlags::READ))
77 }
78
79 pub fn open_with(&self, request: OpenRequest) -> VfResult<FsFile<F>> {
80 let file = self.lock()?.open_one(&request)?;
81 Ok(FsFile {
82 inner: Arc::clone(&self.inner),
83 file: Some(file),
84 path: request.path,
85 })
86 }
87
88 pub fn open_options(&self) -> OpenOptions<'_, F> {
89 OpenOptions::new(self)
90 }
91
92 pub fn create(&self, path: impl AsRef<Path>) -> VfResult<FsFile<F>> {
93 self.open_with(OpenRequest::new(
94 path.as_ref(),
95 OpenFlags::WRITE | OpenFlags::CREATE | OpenFlags::TRUNCATE,
96 ))
97 }
98
99 pub fn read(&self, path: impl AsRef<Path>) -> VfResult<Vec<u8>> {
100 self.read_with_limit(path, DEFAULT_READ_MAX_BYTES)
101 }
102
103 pub fn read_with_limit(&self, path: impl AsRef<Path>, max_bytes: usize) -> VfResult<Vec<u8>> {
108 let path = path.as_ref();
109 let mut file = self.open(path)?;
110 let mut output = Vec::new();
111 let mut chunk = vec![0; 64 * 1024];
112 loop {
113 let remaining = max_bytes.saturating_sub(output.len());
114 let request = if remaining == 0 {
115 1
116 } else {
117 remaining.min(chunk.len())
118 };
119 let read = file.read_native(&mut chunk[..request])?;
120 if read == 0 {
121 break;
122 }
123 if read > remaining {
124 return Err(VfError::failure(0, libc::EFBIG as u32).with_context("read", path));
125 }
126 output.extend_from_slice(&chunk[..read]);
127 }
128 file.close()?;
129 Ok(output)
130 }
131
132 pub fn read_to_string(&self, path: impl AsRef<Path>) -> VfResult<String> {
133 self.read_to_string_with_limit(path, DEFAULT_READ_MAX_BYTES)
134 }
135
136 pub fn read_to_string_with_limit(
138 &self,
139 path: impl AsRef<Path>,
140 max_bytes: usize,
141 ) -> VfResult<String> {
142 let path = path.as_ref();
143 String::from_utf8(self.read_with_limit(path, max_bytes)?)
144 .map_err(|_| VfError::client(0, crate::ERR_INVAL).with_context("read_to_string", path))
145 }
146
147 pub fn write(&self, path: impl AsRef<Path>, data: &[u8]) -> VfResult<()> {
148 let path = path.as_ref();
149 let mut file = self.create(path)?;
150 let mut written = 0;
151 while written < data.len() {
152 let count = file.write_native(&data[written..])?;
153 if count == 0 {
154 return Err(VfError::client(0, crate::ERR_IO).with_context("write", path));
155 }
156 written += count;
157 }
158 file.close()
159 }
160}
161
162impl<F: MetadataFileSystem> FsClient<F> {
163 pub fn metadata(&self, path: impl AsRef<Path>) -> VfResult<Metadata> {
164 self.lock()?.metadata_path(path.as_ref(), true)
165 }
166
167 pub fn symlink_metadata(&self, path: impl AsRef<Path>) -> VfResult<Metadata> {
168 self.lock()?.metadata_path(path.as_ref(), false)
169 }
170
171 pub fn set_metadata(&self, path: impl AsRef<Path>) -> SetMetadata<'_, F> {
172 SetMetadata {
173 client: self,
174 path: path.as_ref().to_path_buf(),
175 update: MetadataUpdate::new(),
176 follow: true,
177 }
178 }
179}
180
181impl<F: DirectoryFileSystem> FsClient<F> {
182 pub fn create_dir(&self, path: impl AsRef<Path>) -> VfResult<()> {
183 self.create_dir_with_mode(path, 0o777)
184 }
185
186 pub fn create_dir_with_mode(&self, path: impl AsRef<Path>, mode: u32) -> VfResult<()> {
187 self.lock()?.create_dir_one(path.as_ref(), mode)
188 }
189
190 pub fn read_dir(&self, path: impl AsRef<Path>) -> VfResult<Vec<DirEntry>> {
191 self.read_dir_with_options(path, ReadDirOptions::default())
192 }
193
194 pub fn read_dir_with_options(
196 &self,
197 path: impl AsRef<Path>,
198 options: ReadDirOptions,
199 ) -> VfResult<Vec<DirEntry>> {
200 self.lock()?.read_dir_one(path.as_ref(), options)
201 }
202}
203
204impl<F: DirectoryFileSystem + MetadataFileSystem> FsClient<F> {
205 pub fn create_dir_all(&self, path: impl AsRef<Path>) -> VfResult<()> {
206 let path = path.as_ref();
207 let mut current = PathBuf::new();
208 for component in path.components() {
209 match component {
210 Component::RootDir => {
211 current.push(Path::new("/"));
212 continue;
213 }
214 Component::Normal(part) => current.push(part),
215 Component::CurDir => continue,
216 Component::ParentDir => {
217 current.push("..");
222 continue;
223 }
224 Component::Prefix(_) => return Err(VfError::client(0, crate::ERR_INVAL)),
225 }
226 match self.create_dir(¤t) {
227 Ok(()) => {}
228 Err(error) if error.err_no() == crate::ERR_EXIST => {
229 if !self.metadata(¤t)?.is_dir() {
230 return Err(VfError::client(0, crate::ERR_NOTDIR)
231 .with_context("create_dir_all", ¤t));
232 }
233 }
234 Err(error) => return Err(error),
235 }
236 }
237 Ok(())
238 }
239}
240
241impl<F: NamespaceFileSystem + MetadataFileSystem> FsClient<F> {
242 fn removal_metadata(&self, path: &Path, operation: &'static str) -> VfResult<Metadata> {
243 let mut filesystem = self.lock()?;
244 let follow = !filesystem.capabilities().contains(Capabilities::LSTAT);
245 filesystem
246 .metadata_path(path, follow)
247 .map_err(|error| error.with_context(operation, path))
248 }
249
250 pub fn remove_file(&self, path: impl AsRef<Path>) -> VfResult<()> {
251 let path = path.as_ref();
252 if self.removal_metadata(path, "remove_file")?.is_dir() {
253 return Err(VfError::client(0, crate::ERR_ISDIR).with_context("remove_file", path));
254 }
255 self.lock()?.remove_one(path, false)
256 }
257
258 pub fn remove_dir(&self, path: impl AsRef<Path>) -> VfResult<()> {
259 let path = path.as_ref();
260 if !self.removal_metadata(path, "remove_dir")?.is_dir() {
261 return Err(VfError::client(0, crate::ERR_NOTDIR).with_context("remove_dir", path));
262 }
263 self.lock()?.remove_one(path, false)
264 }
265
266 pub fn remove_dir_all(&self, path: impl AsRef<Path>) -> VfResult<()> {
267 let path = path.as_ref();
268 if !self.removal_metadata(path, "remove_dir_all")?.is_dir() {
269 return Err(VfError::client(0, crate::ERR_NOTDIR).with_context("remove_dir_all", path));
270 }
271 self.lock()?.remove_one(path, true)
272 }
273
274 pub fn rename(&self, from: impl AsRef<Path>, to: impl AsRef<Path>) -> VfResult<()> {
275 self.lock()?.rename_one(from.as_ref(), to.as_ref())
276 }
277}
278
279impl<F: LinkFileSystem> FsClient<F> {
280 pub fn symlink(&self, target: impl AsRef<Path>, link: impl AsRef<Path>) -> VfResult<()> {
281 self.lock()?.symlink_one(target.as_ref(), link.as_ref())
282 }
283
284 pub fn hard_link(&self, source: impl AsRef<Path>, link: impl AsRef<Path>) -> VfResult<()> {
285 self.lock()?.hard_link_one(source.as_ref(), link.as_ref())
286 }
287
288 pub fn read_link(&self, path: impl AsRef<Path>) -> VfResult<PathBuf> {
289 self.lock()?.read_link_one(path.as_ref())
290 }
291}
292
293impl<F: CopyFileSystem> FsClient<F> {
294 pub fn copy(&self, source: impl AsRef<Path>, destination: impl AsRef<Path>) -> VfResult<()> {
295 self.lock()?.copy_one(source.as_ref(), destination.as_ref())
296 }
297}
298
299impl<F: VectorFileSystem> FsClient<F> {
300 pub fn openv(&self, requests: &[OpenRequest]) -> VfResult<Vec<FsFile<F>>> {
306 let mut filesystem = self.lock()?;
307 let files = filesystem.open_many(requests).map_err(|error| {
308 error
309 .index_opt()
310 .and_then(|index| requests.get(index))
311 .map_or(error.clone(), |request| {
312 error.with_context("openv", &request.path)
313 })
314 })?;
315 if files.len() != requests.len() {
316 let error = wrong_result_count("openv", requests.len(), files.len());
317 for file in &files {
318 let _ = filesystem.close_one(file);
319 }
320 return Err(error);
321 }
322 drop(filesystem);
323 Ok(files
324 .into_iter()
325 .zip(requests)
326 .map(|(file, request)| FsFile {
327 inner: Arc::clone(&self.inner),
328 file: Some(file),
329 path: request.path.clone(),
330 })
331 .collect())
332 }
333
334 pub fn closev(&self, mut files: Vec<FsFile<F>>) -> VfResult<()> {
340 for (index, file) in files.iter().enumerate() {
341 self.validate_owner(file, index)?;
342 }
343 let descriptors: Vec<VfFile> = files.iter().map(|file| file.raw().clone()).collect();
344 self.lock()?.close_many(&descriptors).map_err(|error| {
345 error
346 .index_opt()
347 .and_then(|index| files.get(index))
348 .map_or(error.clone(), |file| {
349 error.with_context("closev", file.path())
350 })
351 })?;
352 for file in &mut files {
353 file.file = None;
354 }
355 Ok(())
356 }
357
358 pub fn readv(&self, requests: &[FsRead<'_, F>]) -> VfResult<Vec<ReadResult>> {
359 let reads = self.read_ops(requests)?;
360 let results = self.lock()?.read_many(&reads).map_err(|error| {
361 error
362 .index_opt()
363 .and_then(|index| requests.get(index))
364 .map_or(error.clone(), |request| {
365 error.with_context("readv", request.file.path())
366 })
367 })?;
368 if results.len() != requests.len() {
369 return Err(wrong_result_count("readv", requests.len(), results.len()));
370 }
371 validate_read_results("readv", &reads, &results).map_err(|error| {
372 error
373 .index_opt()
374 .and_then(|index| requests.get(index))
375 .map_or(error.clone(), |request| {
376 error.with_context("readv", request.file.path())
377 })
378 })?;
379 Ok(results)
380 }
381
382 fn read_ops(&self, requests: &[FsRead<'_, F>]) -> VfResult<Vec<ReadOp>> {
383 let mut reads = Vec::with_capacity(requests.len());
384 for (index, request) in requests.iter().enumerate() {
385 self.validate_owner(request.file, index)?;
386 reads.push(ReadOp::new(
387 request.file.raw().clone(),
388 request.offset,
389 request.length,
390 ));
391 }
392 Ok(reads)
393 }
394
395 pub fn readv_into(&self, requests: &mut [FsReadInto<'_, F>]) -> VfResult<Vec<usize>> {
396 let mut reads = Vec::with_capacity(requests.len());
397 for (index, request) in requests.iter().enumerate() {
398 self.validate_owner(request.file, index)?;
399 reads.push(ReadOp::new(
400 request.file.raw().clone(),
401 request.offset,
402 request.buffer.len(),
403 ));
404 }
405 let results = self.lock()?.read_many(&reads).map_err(|error| {
406 error
407 .index_opt()
408 .and_then(|index| requests.get(index))
409 .map_or(error.clone(), |request| {
410 error.with_context("readv_into", request.file.path())
411 })
412 })?;
413 validate_read_results("readv_into", &reads, &results).map_err(|error| {
414 error
415 .index_opt()
416 .and_then(|index| requests.get(index))
417 .map_or(error.clone(), |request| {
418 error.with_context("readv_into", request.file.path())
419 })
420 })?;
421 let mut lengths = Vec::with_capacity(results.len());
422 for (index, (request, result)) in requests.iter_mut().zip(results).enumerate() {
423 if result.data.len() > request.buffer.len() {
424 return Err(VfError::client(index, crate::ERR_IO)
425 .with_context("readv_into", request.file.path()));
426 }
427 request.buffer[..result.data.len()].copy_from_slice(&result.data);
428 lengths.push(result.data.len());
429 }
430 Ok(lengths)
431 }
432
433 pub fn writev(&self, requests: &[FsWrite<'_, F>]) -> VfResult<Vec<WriteResult>> {
434 let writes = self.write_ops(requests)?;
435 let results = self.lock()?.write_many(&writes).map_err(|error| {
436 error
437 .index_opt()
438 .and_then(|index| requests.get(index))
439 .map_or(error.clone(), |request| {
440 error.with_context("writev", request.file.path())
441 })
442 })?;
443 if results.len() != requests.len() {
444 return Err(wrong_result_count("writev", requests.len(), results.len()));
445 }
446 validate_write_results("writev", &writes, &results).map_err(|error| {
447 error
448 .index_opt()
449 .and_then(|index| requests.get(index))
450 .map_or(error.clone(), |request| {
451 error.with_context("writev", request.file.path())
452 })
453 })?;
454 Ok(results)
455 }
456
457 fn write_ops<'a>(&self, requests: &'a [FsWrite<'a, F>]) -> VfResult<Vec<WriteOpRef<'a>>> {
458 let mut writes = Vec::with_capacity(requests.len());
459 for (index, request) in requests.iter().enumerate() {
460 self.validate_owner(request.file, index)?;
461 writes.push(WriteOpRef::new(
462 request.file.raw(),
463 request.offset,
464 request.data,
465 ));
466 }
467 Ok(writes)
468 }
469
470 fn validate_owner(&self, file: &FsFile<F>, index: usize) -> VfResult<()> {
471 if Arc::ptr_eq(&self.inner, &file.inner) {
472 Ok(())
473 } else {
474 Err(VfError::client(index, crate::ERR_INVAL))
475 }
476 }
477}
478
479pub struct OpenOptions<'a, F: FileSystem> {
481 client: &'a FsClient<F>,
482 flags: OpenFlags,
483 mode: u32,
484}
485
486impl<F: FileSystem> Clone for OpenOptions<'_, F> {
487 fn clone(&self) -> Self {
488 Self {
489 client: self.client,
490 flags: self.flags,
491 mode: self.mode,
492 }
493 }
494}
495
496impl<F: FileSystem> fmt::Debug for OpenOptions<'_, F> {
497 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
498 formatter
499 .debug_struct("OpenOptions")
500 .field("flags", &self.flags)
501 .field("mode", &format_args!("{:#o}", self.mode))
502 .finish()
503 }
504}
505
506impl<'a, F: FileSystem> OpenOptions<'a, F> {
507 fn new(client: &'a FsClient<F>) -> Self {
508 Self {
509 client,
510 flags: OpenFlags::empty(),
511 mode: 0o666,
512 }
513 }
514
515 pub fn read(&mut self, enabled: bool) -> &mut Self {
516 self.flags.set(OpenFlags::READ, enabled);
517 self
518 }
519
520 pub fn write(&mut self, enabled: bool) -> &mut Self {
521 self.flags.set(OpenFlags::WRITE, enabled);
522 self
523 }
524
525 pub fn append(&mut self, enabled: bool) -> &mut Self {
526 self.flags.set(OpenFlags::APPEND, enabled);
527 self
528 }
529
530 pub fn truncate(&mut self, enabled: bool) -> &mut Self {
531 self.flags.set(OpenFlags::TRUNCATE, enabled);
532 self
533 }
534
535 pub fn create(&mut self, enabled: bool) -> &mut Self {
536 self.flags.set(OpenFlags::CREATE, enabled);
537 self
538 }
539
540 pub fn create_new(&mut self, enabled: bool) -> &mut Self {
541 self.flags.set(OpenFlags::CREATE_NEW, enabled);
542 self
543 }
544
545 pub fn mode(&mut self, mode: u32) -> &mut Self {
546 self.mode = mode;
547 self
548 }
549
550 pub fn open(&self, path: impl AsRef<Path>) -> VfResult<FsFile<F>> {
551 self.client
552 .open_with(OpenRequest::new(path.as_ref(), self.flags).mode(self.mode))
553 }
554}
555
556impl<F: VectorFileSystem> OpenOptions<'_, F> {
557 pub fn openv<P: AsRef<Path>>(&self, paths: &[P]) -> VfResult<Vec<FsFile<F>>> {
558 let requests: Vec<OpenRequest> = paths
559 .iter()
560 .map(|path| OpenRequest::new(path.as_ref(), self.flags).mode(self.mode))
561 .collect();
562 self.client.openv(&requests)
563 }
564}
565
566pub struct SetMetadata<'a, F: MetadataFileSystem> {
568 client: &'a FsClient<F>,
569 path: PathBuf,
570 update: MetadataUpdate,
571 follow: bool,
572}
573
574impl<F: MetadataFileSystem> Clone for SetMetadata<'_, F> {
575 fn clone(&self) -> Self {
576 Self {
577 client: self.client,
578 path: self.path.clone(),
579 update: self.update.clone(),
580 follow: self.follow,
581 }
582 }
583}
584
585impl<F: MetadataFileSystem> fmt::Debug for SetMetadata<'_, F> {
586 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
587 formatter
588 .debug_struct("SetMetadata")
589 .field("path", &self.path)
590 .field("update", &self.update)
591 .field("follow", &self.follow)
592 .finish_non_exhaustive()
593 }
594}
595
596impl<F: MetadataFileSystem> SetMetadata<'_, F> {
597 pub fn permissions(&mut self, permissions: Permissions) -> &mut Self {
598 self.update.permissions = Some(permissions);
599 self
600 }
601
602 pub fn len(&mut self, len: u64) -> &mut Self {
603 self.update.len = Some(len);
604 self
605 }
606
607 pub fn accessed(&mut self, accessed: SystemTime) -> &mut Self {
608 self.update.accessed = Some(accessed);
609 self
610 }
611
612 pub fn modified(&mut self, modified: SystemTime) -> &mut Self {
613 self.update.modified = Some(modified);
614 self
615 }
616
617 pub fn follow_symlinks(&mut self, follow: bool) -> &mut Self {
618 self.follow = follow;
619 self
620 }
621
622 pub fn apply(&self) -> VfResult<()> {
623 self.client
624 .lock()?
625 .set_metadata_path(&self.path, self.update.clone(), self.follow)
626 }
627}
628
629pub struct FsFile<F: FileSystem> {
631 inner: Arc<Mutex<F>>,
632 file: Option<VfFile>,
633 path: PathBuf,
634}
635
636impl<F: FileSystem> fmt::Debug for FsFile<F> {
637 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
638 formatter
639 .debug_struct("FsFile")
640 .field("path", &self.path)
641 .field("is_open", &self.file.is_some())
642 .finish()
643 }
644}
645
646impl<F: FileSystem> FsFile<F> {
647 fn raw(&self) -> &VfFile {
648 self.file.as_ref().expect("open file")
649 }
650
651 pub fn read_at(&self, buffer: &mut [u8], offset: u64) -> VfResult<usize> {
653 self.read_into(buffer, VfOffset::At(offset))
654 }
655
656 pub fn write_at(&self, buffer: &[u8], offset: u64) -> VfResult<usize> {
658 self.write_from(buffer, VfOffset::At(offset))
659 }
660
661 pub fn read_request_at(&self, offset: u64, length: usize) -> FsRead<'_, F> {
662 FsRead {
663 file: self,
664 offset: VfOffset::At(offset),
665 length,
666 }
667 }
668
669 pub fn path(&self) -> &Path {
670 &self.path
671 }
672
673 pub fn metadata(&self) -> VfResult<Metadata> {
675 let attributes = AttrMask::MODE
676 | AttrMask::SIZE
677 | AttrMask::NLINK
678 | AttrMask::FILEID
679 | AttrMask::UID
680 | AttrMask::GID
681 | AttrMask::ATIME
682 | AttrMask::MTIME
683 | AttrMask::CTIME
684 | AttrMask::CHANGE;
685 self.inner
686 .lock()
687 .map_err(|_| poisoned())?
688 .metadata(MetadataQuery::new(self.raw().clone(), attributes))
689 .map(Metadata::from)
690 .map_err(|error| error.with_context("metadata", &self.path))
691 }
692
693 pub fn set_len(&self, len: u64) -> VfResult<()> {
695 let mut update = SetAttributes::new(self.raw().clone());
696 update.size = Some(len);
697 self.inner
698 .lock()
699 .map_err(|_| poisoned())?
700 .set_attributes(update)
701 .map_err(|error| error.with_context("set_len", &self.path))
702 }
703
704 pub fn set_permissions(&self, permissions: Permissions) -> VfResult<()> {
706 let mut update = SetAttributes::new(self.raw().clone());
707 update.mode = Some(permissions.mode());
708 self.inner
709 .lock()
710 .map_err(|_| poisoned())?
711 .set_attributes(update)
712 .map_err(|error| error.with_context("set_permissions", &self.path))
713 }
714
715 pub fn write_request_at<'a>(&'a self, offset: u64, data: &'a [u8]) -> FsWrite<'a, F> {
716 FsWrite {
717 file: self,
718 offset: VfOffset::At(offset),
719 data,
720 }
721 }
722
723 pub fn read_request_at_into<'a>(
724 &'a self,
725 offset: u64,
726 buffer: &'a mut [u8],
727 ) -> FsReadInto<'a, F> {
728 FsReadInto {
729 file: self,
730 offset: VfOffset::At(offset),
731 buffer,
732 }
733 }
734
735 pub fn read_native(&mut self, buffer: &mut [u8]) -> VfResult<usize> {
736 self.read_into(buffer, VfOffset::Cur)
737 }
738
739 pub fn write_native(&mut self, buffer: &[u8]) -> VfResult<usize> {
740 self.write_from(buffer, VfOffset::Cur)
741 }
742
743 fn read_into(&self, buffer: &mut [u8], offset: VfOffset) -> VfResult<usize> {
744 if buffer.is_empty() {
745 return Ok(0);
746 }
747 let result = self
748 .inner
749 .lock()
750 .map_err(|_| poisoned())?
751 .read_one(&ReadOp::new(self.raw().clone(), offset, buffer.len()))
752 .map_err(|error| error.with_context("read", &self.path))?;
753 if result.data.len() > buffer.len() {
754 return Err(VfError::client(0, crate::ERR_IO).with_context("read", &self.path));
755 }
756 buffer[..result.data.len()].copy_from_slice(&result.data);
757 Ok(result.data.len())
758 }
759
760 fn write_from(&self, buffer: &[u8], offset: VfOffset) -> VfResult<usize> {
761 if buffer.is_empty() {
762 return Ok(0);
763 }
764 let file = self.raw().clone();
765 let result = self
766 .inner
767 .lock()
768 .map_err(|_| poisoned())?
769 .write_one(WriteOpRef::new(&file, offset, buffer))
770 .map_err(|error| error.with_context("write", &self.path))?;
771 if result.written > buffer.len() {
772 return Err(VfError::client(0, crate::ERR_IO).with_context("write", &self.path));
773 }
774 Ok(result.written)
775 }
776
777 pub fn sync_data(&self) -> VfResult<()> {
778 self.inner
779 .lock()
780 .map_err(|_| poisoned())?
781 .sync_data(self.raw())
782 .map_err(|error| error.with_context("sync_data", &self.path))
783 }
784
785 pub fn sync_all(&self) -> VfResult<()> {
786 self.inner
787 .lock()
788 .map_err(|_| poisoned())?
789 .sync_all(self.raw())
790 .map_err(|error| error.with_context("sync_all", &self.path))
791 }
792
793 pub fn close(mut self) -> VfResult<()> {
794 let file = self.file.as_ref().expect("open file");
795 self.inner
796 .lock()
797 .map_err(|_| poisoned())?
798 .close_one(file)
799 .map_err(|error| error.with_context("close", &self.path))?;
800 self.file = None;
801 Ok(())
802 }
803
804 pub fn seek_native(&mut self, position: IoSeekFrom) -> VfResult<u64> {
806 self.inner
807 .lock()
808 .map_err(|_| poisoned())?
809 .seek_one(self.raw(), position)
810 .map_err(|error| error.with_context("seek", &self.path))
811 }
812}
813
814impl<F: FileSystem> Read for FsFile<F> {
815 fn read(&mut self, buffer: &mut [u8]) -> io::Result<usize> {
816 self.read_native(buffer).map_err(io_error)
817 }
818}
819
820impl<F: FileSystem> Write for FsFile<F> {
821 fn write(&mut self, buffer: &[u8]) -> io::Result<usize> {
822 self.write_native(buffer).map_err(io_error)
823 }
824
825 fn flush(&mut self) -> io::Result<()> {
826 self.sync_data().map_err(io_error)
827 }
828}
829
830impl<F: FileSystem> Seek for FsFile<F> {
831 fn seek(&mut self, position: IoSeekFrom) -> io::Result<u64> {
832 self.seek_native(position).map_err(io_error)
833 }
834}
835
836pub struct FsRead<'a, F: FileSystem> {
838 file: &'a FsFile<F>,
839 offset: VfOffset,
840 length: usize,
841}
842
843pub struct FsWrite<'a, F: FileSystem> {
845 file: &'a FsFile<F>,
846 offset: VfOffset,
847 data: &'a [u8],
848}
849
850pub struct FsReadInto<'a, F: FileSystem> {
852 file: &'a FsFile<F>,
853 offset: VfOffset,
854 buffer: &'a mut [u8],
855}
856
857impl<F: FileSystem> Drop for FsFile<F> {
858 fn drop(&mut self) {
859 if let Some(file) = self.file.take()
860 && let Ok(mut filesystem) = self.inner.lock()
861 {
862 let _ = filesystem.close_one(&file);
863 }
864 }
865}