1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172
//! Contains the [`StorageBackend`](crate::storage::StorageBackend) trait that can be implemented to
//! create virtual file systems for libunftp.
//!
//! Pre-made implementations exists on crates.io (search for `unftp-sbe-`) and you can define your
//! own implementation to integrate your FTP(S) server with whatever storage mechanism you prefer.
//!
//! To create a new storage back-end:
//!
//! 1. Declare a dependency on the async-trait crate
//!
//! ```toml
//! async-trait = "0.1.50"
//! ```
//!
//! 2. Implement the [`StorageBackend`](crate::storage::StorageBackend) trait and optionally the [`Metadata`](crate::storage::Metadata) trait:
//!
//! ```no_run
//! use async_trait::async_trait;
//! use libunftp::storage::{Fileinfo, Metadata, Result, StorageBackend};
//! use std::fmt::Debug;
//! use std::path::{Path, PathBuf};
//! use libunftp::auth::DefaultUser;
//! use std::time::SystemTime;
//!
//! #[derive(Debug)]
//! pub struct Vfs {}
//!
//! #[derive(Debug)]
//! pub struct Meta {
//! inner: std::fs::Metadata,
//! }
//!
//! impl Vfs {
//! fn new() -> Vfs { Vfs{} }
//! }
//!
//! #[async_trait]
//! impl libunftp::storage::StorageBackend<DefaultUser> for Vfs {
//! type Metadata = Meta;
//!
//! async fn metadata<P: AsRef<Path> + Send + Debug>(
//! &self,
//! user: &DefaultUser,
//! path: P,
//! ) -> Result<Self::Metadata> {
//! unimplemented!()
//! }
//!
//! async fn list<P: AsRef<Path> + Send + Debug>(
//! &self,
//! user: &DefaultUser,
//! path: P,
//! ) -> Result<Vec<Fileinfo<PathBuf, Self::Metadata>>>
//! where
//! <Self as StorageBackend<DefaultUser>>::Metadata: Metadata,
//! {
//! unimplemented!()
//! }
//!
//! async fn get<P: AsRef<Path> + Send + Debug>(
//! &self,
//! user: &DefaultUser,
//! path: P,
//! start_pos: u64,
//! ) -> Result<Box<dyn tokio::io::AsyncRead + Send + Sync + Unpin>> {
//! unimplemented!()
//! }
//!
//! async fn put<
//! P: AsRef<Path> + Send + Debug,
//! R: tokio::io::AsyncRead + Send + Sync + Unpin + 'static,
//! >(
//! &self,
//! user: &DefaultUser,
//! input: R,
//! path: P,
//! start_pos: u64,
//! ) -> Result<u64> {
//! unimplemented!()
//! }
//!
//! async fn del<P: AsRef<Path> + Send + Debug>(
//! &self,
//! user: &DefaultUser,
//! path: P,
//! ) -> Result<()> {
//! unimplemented!()
//! }
//!
//! async fn mkd<P: AsRef<Path> + Send + Debug>(
//! &self,
//! user: &DefaultUser,
//! path: P,
//! ) -> Result<()> {
//! unimplemented!()
//! }
//!
//! async fn rename<P: AsRef<Path> + Send + Debug>(
//! &self,
//! user: &DefaultUser,
//! from: P,
//! to: P,
//! ) -> Result<()> {
//! unimplemented!()
//! }
//!
//! async fn rmd<P: AsRef<Path> + Send + Debug>(
//! &self,
//! user: &DefaultUser,
//! path: P,
//! ) -> Result<()> {
//! unimplemented!()
//! }
//!
//! async fn cwd<P: AsRef<Path> + Send + Debug>(
//! &self,
//! user: &DefaultUser,
//! path: P,
//! ) -> Result<()> {
//! unimplemented!()
//! }
//! }
//!
//! impl Metadata for Meta {
//! fn len(&self) -> u64 {
//! self.inner.len()
//! }
//!
//! fn is_dir(&self) -> bool {
//! self.inner.is_dir()
//! }
//!
//! fn is_file(&self) -> bool {
//! self.inner.is_file()
//! }
//!
//! fn is_symlink(&self) -> bool {
//! self.inner.file_type().is_symlink()
//! }
//!
//! fn modified(&self) -> Result<SystemTime> {
//! self.inner.modified().map_err(|e| e.into())
//! }
//!
//! fn gid(&self) -> u32 {
//! 0
//! }
//!
//! fn uid(&self) -> u32 {
//! 0
//! }
//! }
//! ```
//!
//! 3. Initialize it with the [`Server`](crate::Server):
//!
//! ```no_run
//! # use unftp_sbe_fs::Filesystem;
//! # struct Vfs{};
//! # impl Vfs { fn new() -> Filesystem { Filesystem::new("/") } }
//! let vfs_provider = Box::new(|| Vfs::new());
//! let server = libunftp::Server::new(vfs_provider);
//! ```
//!
//! [`Server`]: ../struct.Server.html
#![deny(missing_docs)]
pub(crate) mod error;
pub use error::{Error, ErrorKind};
pub(crate) mod storage_backend;
pub use storage_backend::{Fileinfo, Metadata, Permissions, Result, StorageBackend, FEATURE_RESTART, FEATURE_SITEMD5};