1use std::borrow::Cow;
2use std::collections::VecDeque;
3
4use camino::Utf8Path;
5use camino::Utf8PathBuf;
6use lexiclean_cow::Lexiclean;
7
8use sftp_protocol::common::Metadata;
9use crate::Error;
10use super::file::OpenFile;
11
12pub type Result<T> = std::result::Result<T, Error>;
13pub trait PathRef: AsRef<Utf8Path> + Send + Sync {}
14impl<T> PathRef for T where T: AsRef<Utf8Path> + Send + Sync {}
15
16#[async_trait]
17pub trait Backend : Clone + Send + Sync {
18 async fn metadata(&self, path: impl PathRef + 'async_trait) -> Result<Metadata>;
19 async fn list(&self, path: impl PathRef + 'async_trait) -> Result<VecDeque<Metadata>>;
20 #[allow(clippy::too_many_arguments)]
21 async fn open(&self, path: impl PathRef + 'async_trait, read: bool, write: bool, append: bool, create: bool, truncate: bool, create_new: bool) -> Result<OpenFile>;
22 async fn set_metadata(&self, path: impl PathRef + 'async_trait, uid_and_gid: Option<(u32, u32)>, permissions: Option<u32>, atime_and_mtime: Option<(u32, u32)>) -> Result<()>;
23 async fn delete_file(&self, path: impl PathRef + 'async_trait) -> Result<()>;
24 async fn mkdir(&self, path: impl PathRef + 'async_trait) -> Result<()>;
25 async fn rmdir(&self, path: impl PathRef + 'async_trait) -> Result<()>;
26 async fn rename(&self, from: impl PathRef + 'async_trait, to: impl PathRef + 'async_trait) -> Result<()>;
27 async fn readlink(&self, path: impl PathRef + 'async_trait) -> Result<Option<Utf8PathBuf>>;
28 async fn mklink(&self, link_path: impl PathRef + 'async_trait, target_path: impl PathRef + 'async_trait, link_type: crate::LinkType) -> Result<()>;
29
30 fn normalize_path<'a, 'path>(&'a self, path: &'path Utf8Path) -> Result<Cow<'path, Utf8Path>> {
31 let path = path.lexiclean();
32 if let Some(first) = path.ancestors().next() {
33 if(first == "..") {
34 return Err(Error::InvalidPath);
35 }
36 }
37 Ok(path)
38 }
39}
40