sftp_server/
backend.rs

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