Skip to main content

vfsi_sync/backend/
mod.rs

1//! Native synchronous backend contracts.
2//! `HandleBackend` supports owned handles; `VectorBackend` adds native vector engines
3//! and overridable workflows. Shared algorithms live in [`crate::backend::helpers`].
4//!
5//! These are execution hooks, not application traits. Use [`crate::Vfsi`] and
6//! [`crate::VfsiExt`] on a client for portable filesystem operations.
7//! The old root traits and scalar/vector namespace aliases are removed:
8//!
9//! ```compile_fail,E0432
10//! use vfsi_sync::FileSystem;
11//! ```
12//! ```compile_fail,E0432
13//! use vfsi_sync::Backend;
14//! ```
15//! ```compile_fail,E0432
16//! use vfsi_sync::HandleBackend;
17//! ```
18//! ```compile_fail,E0432
19//! use vfsi_sync::VectorBackend;
20//! ```
21//! ```compile_fail,E0432
22//! use vfsi_sync::sfsi;
23//! ```
24//! ```compile_fail,E0432
25//! use vfsi_sync::vfsi;
26//! ```
27//! ```compile_fail,E0432
28//! use vfsi_sync::backend_helpers;
29//! ```
30
31/// Shared execution defaults for backend implementers.
32#[doc(hidden)]
33pub mod helpers;
34
35use crate::*;
36use std::path::{Path, PathBuf};
37use vfsi_core::internal::ManyResults;
38
39/// Object reference borrowed from a backend while grouping writes. Scoped to
40/// that backend; opaque references must establish object grouping, never OPEN
41/// state. Unequal noncanonical references do not prove distinct objects.
42#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
43pub enum OpenObjectRef<'a> {
44    Id(FsObjId),
45    Opaque(&'a [u8]),
46}
47
48/// Minimum contract for owned handles and descriptor lifecycle.
49/// This includes handle-level metadata/statistics hooks, but does not require
50/// namespace operations, directory enumeration, or native vector I/O.
51pub trait HandleBackend {
52    /// Prepare object references in one backend batch when metadata is needed.
53    /// Inputs retain request order so failure indices remain attributable.
54    /// References returned for the batch must use a consistent, canonical
55    /// representation. Return `None` when potentially aliased objects cannot
56    /// be compared safely; unequal noncanonical filehandles are insufficient.
57    fn prepare_object_refs(&mut self, _files: &[&FileOperand]) -> VfResult<()> {
58        Ok(())
59    }
60
61    /// Reference to the object pinned by a live File Descriptor, if available.
62    /// Completion scheduling conservatively assumes aliasing when unknown.
63    /// Saved paths and OPEN stateids must never be used as object references.
64    fn open_object_ref(&self, _file: &FileOperand) -> VfResult<Option<OpenObjectRef<'_>>> {
65        Ok(None)
66    }
67
68    fn vstatfs_impl(&mut self, files: &[FileOperand]) -> VfResult<Vec<FilesystemStats>> {
69        if files.is_empty() {
70            Ok(Vec::new())
71        } else {
72            Err(VfError::unsupported(0))
73        }
74    }
75
76    fn close_deferred(&mut self, file: &FileOperand) -> VfResult<()> {
77        self.close_impl(file)
78    }
79
80    fn take_notifications(&mut self) -> Vec<Box<dyn FnOnce() + Send>> {
81        Vec::new()
82    }
83
84    fn capabilities(&self) -> Capabilities {
85        Capabilities::empty()
86    }
87
88    fn abs_path(&self, path: &Path) -> PathBuf {
89        path.to_path_buf()
90    }
91
92    fn open_path_impl(
93        &mut self,
94        _base: VfPathBase,
95        _pathname: &Path,
96        _flags: i32,
97        _mode: u32,
98    ) -> VfResult<FileOperand> {
99        Err(VfError::unsupported(0))
100    }
101
102    /// One backend synchronization vector. POSIX backends may loop under one
103    /// lock because fsync has no vector syscall; protocol backends may batch.
104    fn vfsync_impl(&mut self, files: &[FileOperand], mode: vfsi_core::api::SyncMode) -> VfRes {
105        for (index, file) in files.iter().enumerate() {
106            match mode {
107                vfsi_core::api::SyncMode::Data => self.sync_data(file),
108                vfsi_core::api::SyncMode::All => self.sync_all(file),
109            }
110            .map_err(|error| error.map_index(|_| index))?;
111        }
112        Ok(())
113    }
114
115    fn sync_data(&mut self, tcf: &FileOperand) -> VfResult<()>;
116
117    fn sync_all(&mut self, tcf: &FileOperand) -> VfResult<()> {
118        self.sync_data(tcf)
119    }
120
121    fn chdir(&mut self, _path: &Path) -> VfResult<()> {
122        Err(VfError::unsupported(0))
123    }
124
125    fn getcwd(&self) -> PathBuf {
126        PathBuf::from("/")
127    }
128
129    fn seek_raw_impl(
130        &mut self,
131        _tcf: &FileOperand,
132        _offset: i64,
133        _whence: SeekFrom,
134    ) -> VfResult<i64> {
135        Err(VfError::unsupported(0))
136    }
137
138    fn vf_path(&self, file: &FileOperand) -> VfResult<PathBuf> {
139        crate::backend::helpers::vf_path_default(self, file)
140    }
141
142    fn open_raw_impl(&mut self, pathname: &Path, flags: i32, mode: u32) -> VfResult<FileOperand> {
143        crate::backend::helpers::open_raw_impl_default(self, pathname, flags, mode)
144    }
145
146    fn read_raw_impl(
147        &mut self,
148        file: &FileOperand,
149        offset: u64,
150        length: usize,
151    ) -> VfResult<Vec<u8>> {
152        crate::backend::helpers::read_raw_impl_default(self, file, offset, length)
153    }
154
155    fn write_raw_impl(&mut self, file: &FileOperand, offset: u64, data: &[u8]) -> VfResult<usize> {
156        crate::backend::helpers::write_raw_impl_default(self, file, offset, data)
157    }
158
159    fn read_file_impl(&mut self, file: &FileOperand, max_bytes: usize) -> VfResult<Vec<u8>> {
160        crate::backend::helpers::read_file_impl_default(self, file, max_bytes)
161    }
162
163    fn open_impl(&mut self, request: &OpenOp) -> VfResult<FileOperand>;
164
165    fn close_impl(&mut self, file: &FileOperand) -> VfResult<()>;
166
167    fn read_impl(&mut self, request: &ReadOp) -> VfResult<ReadResult>;
168
169    fn read_into_impl(&mut self, request: &ReadOp, buffer: &mut [u8]) -> VfResult<ReadIntoResult> {
170        crate::backend::helpers::read_into_impl_default(self, request, buffer)
171    }
172
173    fn write_impl(&mut self, request: WriteOp<&FileOperand, &[u8]>) -> VfResult<WriteResult>;
174
175    fn seek_impl(&mut self, file: &FileOperand, position: std::io::SeekFrom) -> VfResult<u64>;
176
177    /// Query a raw backend target with the same field/symlink options used by
178    /// the application interface. Returned attributes retain target identity.
179    fn metadata_impl(
180        &mut self,
181        target: Target<'_, FileOperand>,
182        options: vfsi_core::api::AttrsOptions,
183    ) -> VfResult<VfAttrs>;
184
185    /// Apply one shared attribute operation. Raw timestamps and masks are
186    /// converted by the backend, not exposed through a second mutation type.
187    fn set_attributes_impl(&mut self, update: &SetAttrsOp<Target<'_, FileOperand>>)
188    -> VfResult<()>;
189
190    /// Borrow an ordered batch without transferring request ownership.
191    /// Each operation carries its own final-symlink policy; native backends
192    /// batch contiguous equal-policy runs and validate all inputs before I/O.
193    fn vsetattrs_impl(&mut self, updates: &[SetAttrsOp<Target<'_, FileOperand>>]) -> VfResult<()> {
194        crate::backend::helpers::vsetattrs_impl_default(self, updates)
195    }
196}
197
198/// Native vector engines and backend workflow overrides.
199///
200/// Vector replies preserve input order and cardinality. Indexed failures may
201/// follow partial effects; mutations do not promise rollback or safe replay.
202/// Optional operations report `Unsupported` and capability bits conservatively.
203/// Default workflows call shared helpers; native overrides retain batching,
204/// retained identity, resource limits, and protocol recovery behavior.
205///
206/// This trait is object-safe for C/Python dispatch. No blanket implementation
207/// synthesizes a complete backend from scalar methods.
208pub trait VectorBackend: HandleBackend {
209    // Vector I/O and strict opens.
210    fn vread_impl(&mut self, reads: &[ReadOp]) -> VfResult<Vec<ReadResult>>;
211
212    fn vread_into_impl(
213        &mut self,
214        reads: &[ReadOp],
215        buffers: &mut [&mut [u8]],
216    ) -> VfResult<Vec<ReadIntoResult>> {
217        crate::backend::helpers::vread_into_impl_default(self, reads, buffers)
218    }
219    /// Execute a borrowed ordered vector. Payloads and target storage remain
220    /// with the caller; implementations must not retain them after returning.
221    fn vwrite_impl(
222        &mut self,
223        writes: &[WriteOp<&FileOperand, &[u8]>],
224    ) -> VfResult<Vec<WriteResult>> {
225        let _ = writes;
226        Err(VfError::unsupported(0))
227    }
228
229    /// Validate a strict-open request before dispatch. An error guarantees
230    /// that no operation in the batch has been attempted; FFI adapters use
231    /// this to preserve NOT_ATTEMPTED results for the remaining requests.
232    #[doc(hidden)]
233    fn vopen_preflight_impl(&mut self, paths: &[&Path], flags: &[i32], modes: &[u32]) -> VfRes {
234        if paths.len() != flags.len() || paths.len() != modes.len() {
235            return Err(VfError::failure(0, ERR_INVAL));
236        }
237        Ok(())
238    }
239
240    /// Indexed partial outcomes for strict-open collection and cleanup.
241    /// This internal ownership seam is distinct from the strict typed boundary.
242    #[doc(hidden)]
243    fn vopen_outcomes_impl(
244        &mut self,
245        paths: &[&Path],
246        flags: &[i32],
247        modes: &[u32],
248    ) -> VfResult<ManyResults<FileOperand>> {
249        crate::backend::helpers::vopen_outcomes_impl_default(self, paths, flags, modes)
250    }
251
252    fn before_open_cleanup(&mut self, _index: usize, _file: &FileOperand) -> VfResult<()> {
253        crate::backend::helpers::before_open_cleanup_default(self, _index, _file)
254    }
255
256    fn vopen_raw_impl(
257        &mut self,
258        paths: &[&Path],
259        flags: &[i32],
260        modes: &[u32],
261    ) -> VfResult<Vec<FileOperand>> {
262        crate::backend::helpers::vopen_raw_impl_default(self, paths, flags, modes)
263    }
264
265    fn vopen_raw_simple_impl(
266        &mut self,
267        paths: &[&Path],
268        flags: i32,
269        mode: u32,
270    ) -> VfResult<Vec<FileOperand>> {
271        crate::backend::helpers::vopen_raw_simple_impl_default(self, paths, flags, mode)
272    }
273
274    fn vclose_impl(&mut self, files: &[FileOperand]) -> VfRes {
275        crate::backend::helpers::vclose_impl_default(self, files)
276    }
277
278    /// Open every typed request or return an error, cleaning confirmed handles.
279    /// Creation and truncation effects are not rolled back.
280    fn vopen_impl(&mut self, requests: &[OpenOp]) -> VfResult<Vec<FileOperand>> {
281        crate::backend::helpers::vopen_typed_default(self, requests)
282    }
283
284    // Path metadata and vector attribute engines.
285    fn vgetattrs_impl(&mut self, attrs: &mut [VfAttrs]) -> VfRes {
286        let _ = (attrs,);
287        Err(VfError::unsupported(0))
288    }
289
290    fn vgetattrs_nofollow_impl(&mut self, attrs: &mut [VfAttrs]) -> VfRes {
291        let _ = (attrs,);
292        Err(VfError::unsupported(0))
293    }
294
295    fn vsetattrs_raw_impl(&mut self, attrs: &[VfAttrs]) -> VfRes {
296        let _ = (attrs,);
297        Err(VfError::unsupported(0))
298    }
299
300    fn vsetattrs_raw_nofollow_impl(&mut self, attrs: &[VfAttrs]) -> VfRes {
301        let _ = (attrs,);
302        Err(VfError::unsupported(0))
303    }
304
305    fn stat_impl(&mut self, path: &Path) -> VfResult<VfAttrs> {
306        crate::backend::helpers::stat_impl_default(self, path)
307    }
308
309    fn lstat_impl(&mut self, path: &Path) -> VfResult<VfAttrs> {
310        crate::backend::helpers::lstat_impl_default(self, path)
311    }
312
313    fn fstat_impl(&mut self, tcf: &FileOperand) -> VfResult<VfAttrs> {
314        crate::backend::helpers::fstat_impl_default(self, tcf)
315    }
316
317    fn exists_impl(&mut self, path: &Path) -> VfResult<bool> {
318        crate::backend::helpers::exists_impl_default(self, path)
319    }
320
321    fn file_type_impl(&mut self, path: &Path) -> VfResult<VfType> {
322        crate::backend::helpers::file_type_impl_default(self, path)
323    }
324
325    fn metadata_path_impl(&mut self, path: &std::path::Path, follow: bool) -> VfResult<Attrs> {
326        crate::backend::helpers::native_metadata_path_impl_default(self, path, follow)
327    }
328
329    fn set_metadata_path_impl(&mut self, op: &SetAttrsOp<&std::path::Path>) -> VfResult<()> {
330        crate::backend::helpers::native_set_metadata_path_impl_default(self, op)
331    }
332
333    // Paged directory enumeration.
334    fn listdir_impl(
335        &mut self,
336        dir: &Path,
337        masks: AttrMask,
338        max_count: usize,
339        recursive: bool,
340    ) -> VfResult<Vec<VfAttrs>> {
341        let _ = (dir, masks, max_count, recursive);
342        Err(VfError::unsupported(0))
343    }
344
345    /// False requires resolving every component without following symlinks;
346    /// validate-and-then-follow is not sufficient. Continuations retain the
347    /// originally opened directory. Unsupported guarantees must fail closed.
348    fn listdir_page_impl(
349        &mut self,
350        dir: &Path,
351        masks: AttrMask,
352        cursor: Option<DirPageCursor>,
353        page_size: usize,
354        max_entries: usize,
355        follow_symlinks: bool,
356    ) -> VfResult<(Vec<VfAttrs>, Option<DirPageCursor>)> {
357        crate::backend::helpers::listdir_page_impl_default(
358            self,
359            dir,
360            masks,
361            cursor,
362            page_size,
363            max_entries,
364            follow_symlinks,
365        )
366    }
367
368    fn directory_page_batch_size(&self) -> usize {
369        crate::backend::helpers::directory_page_batch_size_default(self)
370    }
371
372    fn vlistdir_pages_impl(
373        &mut self,
374        dirs: &[&Path],
375        masks: AttrMask,
376        cursors: Vec<Option<DirPageCursor>>,
377        page_size: usize,
378        max_entries: usize,
379        follow_symlinks: bool,
380    ) -> VfResult<Vec<BackendDirectoryPage>> {
381        crate::backend::helpers::vlistdir_pages_impl_default(
382            self,
383            dirs,
384            masks,
385            cursors,
386            page_size,
387            max_entries,
388            follow_symlinks,
389        )
390    }
391
392    fn create_dir_impl(&mut self, path: &std::path::Path, mode: u32) -> VfResult<()> {
393        crate::backend::helpers::native_create_dir_impl_default(self, path, mode)
394    }
395
396    fn read_dir_impl(
397        &mut self,
398        path: &std::path::Path,
399        options: ListDirOptions,
400    ) -> VfResult<Vec<DirEntry>> {
401        crate::backend::helpers::native_read_dir_impl_default(self, path, options)
402    }
403
404    /// Adapt full-metadata paging through the field-aware hook below.
405    fn read_dir_page_impl(
406        &mut self,
407        path: &std::path::Path,
408        cursor: Option<DirPageCursor>,
409        page_size: usize,
410        max_entries: usize,
411    ) -> VfResult<(Vec<DirEntry>, Option<DirPageCursor>)> {
412        crate::backend::helpers::native_read_dir_page_impl_default(
413            self,
414            path,
415            cursor,
416            page_size,
417            max_entries,
418        )
419    }
420
421    /// Adapt native attribute pages without materializing a full listing.
422    /// Specialized owned-page implementations should override this hook;
423    /// `read_dir_page_impl` forwards here with the full metadata mask.
424    fn read_dir_page_with_fields_impl(
425        &mut self,
426        path: &std::path::Path,
427        fields: AttrMask,
428        cursor: Option<DirPageCursor>,
429        page_size: usize,
430        max_entries: usize,
431    ) -> VfResult<(Vec<DirEntry>, Option<DirPageCursor>)> {
432        crate::backend::helpers::native_read_dir_page_with_fields_impl_default(
433            self,
434            path,
435            fields,
436            cursor,
437            page_size,
438            max_entries,
439        )
440    }
441
442    // Traversal workflows; overrides retain native batches and anchored seeds.
443    fn walk_impl(
444        &mut self,
445        root: &Path,
446        masks: AttrMask,
447        sort: &mut dyn FnMut(&Path, &mut Vec<VfAttrs>),
448    ) -> VfResult<Vec<WalkEntry>> {
449        crate::backend::helpers::walk_impl_default(self, root, masks, sort)
450    }
451
452    fn walk_with_options_impl(
453        &mut self,
454        root: &Path,
455        masks: AttrMask,
456        options: ListDirOptions,
457        sort: &mut dyn FnMut(&Path, &mut Vec<VfAttrs>),
458    ) -> VfResult<Vec<WalkEntry>> {
459        crate::backend::helpers::walk_with_options_impl_default(self, root, masks, options, sort)
460    }
461
462    fn vlistdirs_impl(
463        &mut self,
464        dirs: &[&Path],
465        masks: AttrMask,
466        max_entries: usize,
467        recursive: bool,
468        cb: &mut dyn FnMut(&VfAttrs, &Path) -> bool,
469    ) -> VfRes {
470        crate::backend::helpers::vlistdirs_impl_default(
471            self,
472            dirs,
473            masks,
474            max_entries,
475            recursive,
476            cb,
477        )
478    }
479
480    fn visit_dir_impl(
481        &mut self,
482        dir: &Path,
483        masks: AttrMask,
484        max_entries: usize,
485        cb: &mut dyn FnMut(&VfAttrs) -> bool,
486    ) -> VfRes {
487        crate::backend::helpers::visit_dir_impl_default(self, dir, masks, max_entries, cb)
488    }
489
490    // Namespace mutations and scalar adapters.
491    fn vrename_impl(&mut self, pairs: &[(FileOperand, FileOperand)]) -> VfRes {
492        let _ = (pairs,);
493        Err(VfError::unsupported(0))
494    }
495
496    /// Native atomic rename policy; never emulate no-replace with an existence check.
497    fn vrename_with_options_impl(
498        &mut self,
499        pairs: &[(FileOperand, FileOperand)],
500        options: vfsi_core::api::RenameMode,
501    ) -> VfRes {
502        match options {
503            vfsi_core::api::RenameMode::Replace => self.vrename_impl(pairs),
504            vfsi_core::api::RenameMode::NoReplace | vfsi_core::api::RenameMode::Exchange
505                if pairs.is_empty() =>
506            {
507                Ok(())
508            }
509            vfsi_core::api::RenameMode::NoReplace | vfsi_core::api::RenameMode::Exchange => {
510                Err(VfError::client(0, vfsi_core::VF_ERR_UNSUPPORTED))
511            }
512        }
513    }
514
515    fn vremove_impl(&mut self, files: &[FileOperand]) -> VfRes {
516        let _ = (files,);
517        Err(VfError::unsupported(0))
518    }
519
520    fn vmkdir_impl(&mut self, dirs: &[VfAttrs]) -> VfRes {
521        let _ = (dirs,);
522        Err(VfError::unsupported(0))
523    }
524
525    fn unlink_impl(&mut self, pathname: &Path) -> VfResult<()> {
526        crate::backend::helpers::unlink_impl_default(self, pathname)
527    }
528
529    fn vunlink_impl(&mut self, pathnames: &[&Path]) -> VfRes {
530        crate::backend::helpers::vunlink_impl_default(self, pathnames)
531    }
532
533    fn mkdir_raw_impl(&mut self, path: &Path, mode: u32) -> VfResult<()> {
534        crate::backend::helpers::mkdir_raw_impl_default(self, path, mode)
535    }
536
537    fn ensure_dir_impl(&mut self, dir: &Path, mode: u32) -> VfResult<()> {
538        crate::backend::helpers::ensure_dir_impl_default(self, dir, mode)
539    }
540
541    fn remove_impl(&mut self, path: &std::path::Path, recursive: bool) -> VfResult<()> {
542        crate::backend::helpers::native_remove_impl_default(self, path, recursive)
543    }
544
545    fn remove_dir_contents_impl(&mut self, path: &std::path::Path) -> VfResult<()> {
546        crate::backend::helpers::native_remove_dir_contents_impl_default(self, path)
547    }
548
549    fn rename_impl(&mut self, from: &std::path::Path, to: &std::path::Path) -> VfResult<()> {
550        crate::backend::helpers::native_rename_impl_default(self, from, to)
551    }
552
553    // Links.
554    fn vsymlink_impl(&mut self, oldpaths: &[&Path], newpaths: &[&Path]) -> VfRes {
555        let _ = (oldpaths, newpaths);
556        Err(VfError::unsupported(0))
557    }
558
559    fn vreadlink_impl(&mut self, paths: &[&Path]) -> VfResult<Vec<Vec<u8>>> {
560        let _ = (paths,);
561        Err(VfError::unsupported(0))
562    }
563
564    fn vhardlink_impl(&mut self, oldpaths: &[&Path], newpaths: &[&Path]) -> VfRes {
565        let _ = (oldpaths, newpaths);
566        Err(VfError::unsupported(0))
567    }
568
569    fn symlink_raw_impl(&mut self, oldpath: &Path, newpath: &Path) -> VfResult<()> {
570        crate::backend::helpers::symlink_raw_impl_default(self, oldpath, newpath)
571    }
572
573    fn readlink_raw_impl(&mut self, path: &Path) -> VfResult<Vec<u8>> {
574        crate::backend::helpers::readlink_raw_impl_default(self, path)
575    }
576
577    fn symlink_impl(&mut self, target: &std::path::Path, link: &std::path::Path) -> VfResult<()> {
578        crate::backend::helpers::native_symlink_impl_default(self, target, link)
579    }
580
581    fn hard_link_impl(&mut self, source: &std::path::Path, link: &std::path::Path) -> VfResult<()> {
582        crate::backend::helpers::native_hard_link_impl_default(self, source, link)
583    }
584
585    fn read_link_impl(&mut self, path: &std::path::Path) -> VfResult<std::path::PathBuf> {
586        crate::backend::helpers::native_read_link_impl_default(self, path)
587    }
588
589    // Extent and tree copy.
590    fn vcopy_data_impl(&mut self, pairs: &[ExtentPair]) -> VfRes {
591        let _ = (pairs,);
592        Err(VfError::unsupported(0))
593    }
594
595    fn vcopy_impl(&mut self, pairs: &[ExtentPair], options: CopyOptions) -> VfRes {
596        crate::backend::helpers::vcopy_impl_default(self, pairs, options)
597    }
598
599    fn copy_tree_impl(
600        &mut self,
601        src_dir: &Path,
602        dst: &Path,
603        symlinks: bool,
604        use_server_side_copy: bool,
605    ) -> VfRes {
606        let _ = (src_dir, dst, symlinks, use_server_side_copy);
607        Err(VfError::unsupported(0))
608    }
609
610    // Bounded whole-file reads and streams.
611    fn vread_all_impl(&mut self, files: &[FileOperand]) -> VfResult<Vec<Vec<u8>>> {
612        crate::backend::helpers::vread_all_impl_default(self, files)
613    }
614
615    fn vread_all_with_options_impl(
616        &mut self,
617        files: &[FileOperand],
618        options: ReadAllOptions,
619    ) -> VfResult<Vec<Vec<u8>>> {
620        crate::backend::helpers::vread_all_with_options_impl_default(self, files, options)
621    }
622
623    fn vstream_impl(
624        &mut self,
625        files: &[FileOperand],
626        chunk_size: usize,
627        memory_limit: usize,
628        cb: &mut ReadStreamCallback<'_>,
629    ) -> VfRes {
630        crate::backend::helpers::vstream_impl_default(self, files, chunk_size, memory_limit, cb)
631    }
632
633    // Recursive removal and retained directory lifecycle.
634    fn before_remove_type(&mut self, _index: usize) -> VfResult<()> {
635        crate::backend::helpers::before_remove_type_default(self, _index)
636    }
637
638    fn remove_paths_impl(&mut self, objs: &[&Path], recursive: bool) -> VfRes {
639        crate::backend::helpers::remove_paths_impl_default(self, objs, recursive)
640    }
641
642    fn remove_paths_with_options_impl(
643        &mut self,
644        objs: &[&Path],
645        recursive: bool,
646        options: RemoveOptions,
647    ) -> VfRes {
648        crate::backend::helpers::remove_paths_with_options_impl_default(
649            self, objs, recursive, options,
650        )
651    }
652
653    fn open_dir_impl(&mut self, path: &Path) -> VfResult<VfDir> {
654        crate::backend::helpers::open_dir_impl_default(self, path)
655    }
656
657    fn remove_dir_contents_handle_impl(&mut self, dir: &VfDir) -> VfRes {
658        crate::backend::helpers::remove_dir_contents_handle_impl_default(self, dir)
659    }
660
661    fn remove_dir_contents_handle_with_options_impl(
662        &mut self,
663        dir: &VfDir,
664        options: RemoveOptions,
665    ) -> VfRes {
666        crate::backend::helpers::remove_dir_contents_handle_with_options_impl_default(
667            self, dir, options,
668        )
669    }
670
671    fn close_dir_impl(&mut self, _dir: &VfDir) -> VfResult<()> {
672        crate::backend::helpers::close_dir_impl_default(self, _dir)
673    }
674
675    fn remove_dir_contents_path_impl(&mut self, dir: &Path) -> VfRes {
676        crate::backend::helpers::remove_dir_contents_path_impl_default(self, dir)
677    }
678
679    fn remove_dir_contents_path_with_options_impl(
680        &mut self,
681        dir: &Path,
682        options: RemoveOptions,
683    ) -> VfRes {
684        crate::backend::helpers::remove_dir_contents_path_with_options_impl_default(
685            self, dir, options,
686        )
687    }
688
689    fn ensure_empty_dir_impl(&mut self, dir: &Path) -> VfRes {
690        crate::backend::helpers::ensure_empty_dir_impl_default(self, dir)
691    }
692
693    // Optional application-data-block writes.
694    fn vwrite_adb_impl(&mut self, patterns: &[Adb]) -> VfResult<Vec<usize>> {
695        let _ = (patterns,);
696        Err(VfError::unsupported(0))
697    }
698}
699pub(crate) fn metadata_mask() -> AttrMask {
700    AttrMask::MODE
701        | AttrMask::SIZE
702        | AttrMask::NLINK
703        | AttrMask::FILEID
704        | AttrMask::FS_ID
705        | AttrMask::UID
706        | AttrMask::GID
707        | AttrMask::ATIME
708        | AttrMask::MTIME
709        | AttrMask::CTIME
710        | AttrMask::CHANGE
711}
712
713#[cfg(unix)]
714pub(crate) fn bytes_to_path(bytes: Vec<u8>) -> PathBuf {
715    use std::os::unix::ffi::OsStringExt;
716    std::ffi::OsString::from_vec(bytes).into()
717}
718#[cfg(not(unix))]
719pub(crate) fn bytes_to_path(bytes: Vec<u8>) -> PathBuf {
720    String::from_utf8_lossy(&bytes).into_owned().into()
721}
722pub(crate) fn translate_open_flags(requests: &[OpenOp]) -> VfResult<Vec<i32>> {
723    requests
724        .iter()
725        .enumerate()
726        .map(|(index, request)| {
727            vfsi_core::open_flags_to_libc(request.flags()).map_err(|error| error.with_index(index))
728        })
729        .collect()
730}