From 4a6847613f1d2449276e9efbf647a65303350366 Mon Sep 17 00:00:00 2001 From: AB Date: Fri, 5 Jun 2020 20:52:24 +0300 Subject: [PATCH] Linting. --- .gitignore | 1 + Cargo.lock | 106 +------- Cargo.toml | 18 +- README.md | 0 src/{http.rs => client.rs} | 16 +- src/filesystem.rs | 545 +++---------------------------------- src/main.rs | 17 +- 7 files changed, 66 insertions(+), 637 deletions(-) create mode 100644 README.md rename src/{http.rs => client.rs} (87%) diff --git a/.gitignore b/.gitignore index ea8c4bf..8516b6f 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ /target +/mus-fuse.yml diff --git a/Cargo.lock b/Cargo.lock index 4e888ac..bdcd694 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -168,16 +168,6 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b3a71ab494c0b5b860bdc8407ae08978052417070c2ced38573a9157ad75b8ac" -[[package]] -name = "ctrlc" -version = "3.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a4ba686dff9fa4c1c9636ce1010b0cf98ceb421361b0bb3d6faeec43bd217a7" -dependencies = [ - "nix", - "winapi 0.3.8", -] - [[package]] name = "dtoa" version = "0.4.5" @@ -251,29 +241,26 @@ checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" [[package]] name = "furumi" -version = "0.1.0" +version = "1.0.0" dependencies = [ "anyhow", "base64", "chrono", "clap", "config", - "ctrlc", "env_logger", "futures", "futures-intrusive", + "http", "itertools", "libc", "log", - "percent-encoding", "polyfuse", "polyfuse-tokio", "reqwest", "serde 1.0.106", "serde_json", - "size_format", "slab", - "time", "tokio", "tracing", "tracing-futures", @@ -382,15 +369,6 @@ dependencies = [ "slab", ] -[[package]] -name = "generic-array" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec" -dependencies = [ - "typenum", -] - [[package]] name = "getrandom" version = "0.1.14" @@ -763,19 +741,6 @@ dependencies = [ "winapi 0.3.8", ] -[[package]] -name = "nix" -version = "0.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50e4785f2c3b7589a0d0c1dd60285e1188adac4006e8abd6dd578e1567027363" -dependencies = [ - "bitflags", - "cc", - "cfg-if", - "libc", - "void", -] - [[package]] name = "nom" version = "4.2.3" @@ -786,29 +751,6 @@ dependencies = [ "version_check 0.1.5", ] -[[package]] -name = "num" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8536030f9fea7127f841b45bb6243b27255787fb4eb83958aa1ef9d2fdc0c36" -dependencies = [ - "num-complex", - "num-integer", - "num-iter", - "num-rational", - "num-traits 0.2.11", -] - -[[package]] -name = "num-complex" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6b19411a9719e753aff12e5187b74d60d3dc449ec3f4dc21e3989c3f554bc95" -dependencies = [ - "autocfg", - "num-traits 0.2.11", -] - [[package]] name = "num-integer" version = "0.1.42" @@ -819,28 +761,6 @@ dependencies = [ "num-traits 0.2.11", ] -[[package]] -name = "num-iter" -version = "0.1.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfb0800a0291891dd9f4fe7bd9c19384f98f7fbe0cd0f39a2c6b88b9868bbc00" -dependencies = [ - "autocfg", - "num-integer", - "num-traits 0.2.11", -] - -[[package]] -name = "num-rational" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c000134b5dbf44adc5cb772486d335293351644b801551abe8f75c84cfa4aef" -dependencies = [ - "autocfg", - "num-integer", - "num-traits 0.2.11", -] - [[package]] name = "num-traits" version = "0.1.43" @@ -1331,16 +1251,6 @@ dependencies = [ "libc", ] -[[package]] -name = "size_format" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ed5f6ab2122c6dec69dca18c72fa4590a27e581ad20d44960fe74c032a0b23b" -dependencies = [ - "generic-array", - "num", -] - [[package]] name = "slab" version = "0.4.2" @@ -1603,12 +1513,6 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e604eb7b43c06650e854be16a2a03155743d3752dd1c943f6829e26b7a36e382" -[[package]] -name = "typenum" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33" - [[package]] name = "unicase" version = "2.6.0" @@ -1683,12 +1587,6 @@ version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed" -[[package]] -name = "void" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" - [[package]] name = "want" version = "0.3.0" diff --git a/Cargo.toml b/Cargo.toml index 47eee99..f8467ba 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,8 +1,13 @@ [package] name = "furumi" -version = "0.1.0" +version = "1.0.0" authors = ["AB "] edition = "2018" +license = "WTFPL" +readme = "README.md" +description = """\ +Written safely in Rust, read-only FUSE FS on top of \ +NGINX JSON autoindex.""" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -24,16 +29,17 @@ tokio = { version = "0.2", features = ["full"] } serde = { version = "1.0", features = ["derive"] } clap = {version = "2.33", features = ["yaml"]} serde_json = "1.0" -percent-encoding = "2.1" -time = "0.1" +#percent-encoding = "2.1" +#time = "0.1" chrono = "0.4" env_logger = "0.7" log = { version = "^0.4.5", features = ["std"] } -size_format = "1.0" +#size_format = "1.0" base64 = "0.12" -ctrlc = "3.1" +#ctrlc = "3.1" config = "0.9" -itertools = "*" +itertools = "0.9" +http = "0.2" [dev-dependencies.tokio] version = "0.2" diff --git a/README.md b/README.md new file mode 100644 index 0000000..e69de29 diff --git a/src/http.rs b/src/client.rs similarity index 87% rename from src/http.rs rename to src/client.rs index b229aab..33596e4 100644 --- a/src/http.rs +++ b/src/client.rs @@ -5,9 +5,7 @@ use reqwest::{header, Client, Error}; use serde::Deserialize; use std::{ path::PathBuf, - process, - thread::sleep, - time::{Duration, SystemTime}, + time::SystemTime, }; static APP_USER_AGENT: &str = concat!(env!("CARGO_PKG_NAME"), "/", env!("CARGO_PKG_VERSION"),); @@ -59,7 +57,7 @@ impl HTTP { } pub async fn list(&self, path: PathBuf) -> Result, Error> { debug!("Fetching path '{}/{}'", self.server, path.display()); - let mut client = &self.client; + let client = &self.client; let resp = client .get(format!("{}/{}", self.server, path.display()).as_str()) .send() @@ -71,16 +69,14 @@ impl HTTP { } pub async fn read(&self, path: PathBuf, size: usize, offset: usize) -> Result, Error> { - debug!("Reading path '{}/{}'", self.server, path.display()); let mut headers = header::HeaderMap::new(); - let range = format!("bytes={}-{}", offset, { offset + size - 1 }); - info!("range = {:?}", range); + let range = format!("bytes={}-{}", offset, {offset + size - 1}); + debug!("Reading path '{}' range {} ({} bytes)", path.display(), range, size); headers.insert( header::RANGE, header::HeaderValue::from_str(range.as_str()).unwrap(), ); - - let mut client = &self.client; + let client = &self.client; let resp = client .get(format!("{}/{}", self.server, path.display()).as_str()) .headers(headers) @@ -88,7 +84,7 @@ impl HTTP { .await? .bytes() .await?; - info!("Found {} entries into '{}'", resp.len(), path.display()); + debug!("Received {} bytes of '{}'", resp.len(), path.display()); Ok(resp.to_vec()) } } diff --git a/src/filesystem.rs b/src/filesystem.rs index 2382a00..3813458 100644 --- a/src/filesystem.rs +++ b/src/filesystem.rs @@ -2,18 +2,18 @@ #![deny(clippy::unimplemented)] use crate::config; -use crate::http; +use crate::client; use polyfuse::{ io::{Reader, Writer}, op, - reply::{Collector, Reply, ReplyAttr, ReplyEntry, ReplyOpen, ReplyWrite, ReplyXattr}, - Context, DirEntry, FileAttr, Filesystem, Forget, Operation, + reply::{Reply, ReplyAttr, ReplyEntry, ReplyOpen}, + Context, DirEntry, FileAttr, Filesystem, Operation, }; use slab::Slab; -use crate::http::HTTP; -use std::path::{Path, PathBuf}; +use crate::client::HTTP; +use std::path::PathBuf; use std::{ collections::hash_map::{Entry, HashMap}, ffi::{OsStr, OsString}, @@ -24,7 +24,7 @@ use std::{ }; use tokio::sync::Mutex; use tracing_futures::Instrument; - +use std::io::{Error, ErrorKind}; type Ino = u64; //noinspection RsUnresolvedReference @@ -51,11 +51,6 @@ impl INodeTable { fn get(&self, ino: Ino) -> Option>> { self.map.get(&ino).cloned() } - - //noinspection RsUnresolvedReference - fn remove(&mut self, ino: Ino) -> Option>> { - self.map.remove(&ino) - } } #[derive(Debug)] @@ -90,7 +85,6 @@ struct INode { enum INodeKind { RegularFile(Vec), Directory(Directory), - Symlink(Arc), } #[derive(Debug, Clone)] @@ -140,7 +134,7 @@ struct FileInodeMap { //noinspection RsUnresolvedReference #[derive(Debug)] pub struct MemFS { - http: http::HTTP, + http: client::HTTP, inodes: Mutex, f_ino_map: Mutex>, ttl: Duration, @@ -243,128 +237,6 @@ impl MemFS { } } - async fn link_node(&self, ino: u64, newparent: Ino, newname: &OsStr) -> io::Result { - { - let inodes = self.inodes.lock().await; - - let inode = inodes.get(ino).ok_or_else(no_entry)?; - - let newparent = inodes.get(newparent).ok_or_else(no_entry)?; - let mut newparent = newparent.lock().await; - let newparent = match newparent.kind { - INodeKind::Directory(ref mut dir) => dir, - _ => return Err(io::Error::from_raw_os_error(libc::ENOTDIR)), - }; - - match newparent.children.entry(newname.into()) { - Entry::Occupied(..) => return Err(io::Error::from_raw_os_error(libc::EEXIST)), - Entry::Vacant(entry) => { - entry.insert(ino); - let mut inode = inode.lock().await; - let inode = &mut *inode; - inode.links += 1; - inode.attr.set_nlink(inode.attr.nlink() + 1); - } - } - } - - self.lookup_inode(newparent, newname).await - } - - async fn unlink_node(&self, parent: Ino, name: &OsStr) -> io::Result<()> { - let inodes = self.inodes.lock().await; - - let parent = inodes.get(parent).ok_or_else(no_entry)?; - let mut parent = parent.lock().await; - let parent = match parent.kind { - INodeKind::Directory(ref mut dir) => dir, - _ => return Err(io::Error::from_raw_os_error(libc::ENOTDIR)), - }; - - let &ino = parent.children.get(name).ok_or_else(no_entry)?; - - let inode = inodes.get(ino).unwrap_or_else(|| unreachable!()); - let mut inode = inode.lock().await; - let inode = &mut *inode; - - match inode.kind { - INodeKind::Directory(ref dir) if !dir.children.is_empty() => { - return Err(io::Error::from_raw_os_error(libc::ENOTEMPTY)); - } - _ => (), - } - - parent - .children - .remove(name) - .unwrap_or_else(|| unreachable!()); - - inode.links = inode.links.saturating_sub(1); - inode.attr.set_nlink(inode.attr.nlink().saturating_sub(1)); - - Ok(()) - } - - async fn rename_node(&self, parent: Ino, name: &OsStr, newname: &OsStr) -> io::Result<()> { - let inodes = self.inodes.lock().await; - - let parent = inodes.get(parent).ok_or_else(no_entry)?; - let mut parent = parent.lock().await; - let parent = match parent.kind { - INodeKind::Directory(ref mut dir) => dir, - _ => return Err(io::Error::from_raw_os_error(libc::ENOTDIR)), - }; - - let &ino = parent.children.get(name).ok_or_else(no_entry)?; - - match parent.children.entry(newname.into()) { - Entry::Occupied(..) => Err(io::Error::from_raw_os_error(libc::EEXIST)), - Entry::Vacant(entry) => { - entry.insert(ino); - parent - .children - .remove(name) - .unwrap_or_else(|| unreachable!()); - Ok(()) - } - } - } - - async fn graft_node( - &self, - parent: Ino, - name: &OsStr, - newparent: Ino, - newname: &OsStr, - ) -> io::Result<()> { - debug_assert_ne!(parent, newparent); - - let inodes = self.inodes.lock().await; - - let parent = inodes.get(parent).ok_or_else(no_entry)?; - let mut parent = parent.lock().await; - let parent = match parent.kind { - INodeKind::Directory(ref mut dir) => dir, - _ => return Err(io::Error::from_raw_os_error(libc::ENOTDIR)), - }; - - let newparent = inodes.get(newparent).ok_or_else(no_entry)?; - let mut newparent = newparent.lock().await; - let newparent = match newparent.kind { - INodeKind::Directory(ref mut dir) => dir, - _ => return Err(io::Error::from_raw_os_error(libc::ENOTDIR)), - }; - - match newparent.children.entry(newname.into()) { - Entry::Occupied(..) => Err(io::Error::from_raw_os_error(libc::EEXIST)), - Entry::Vacant(entry) => { - let ino = parent.children.remove(name).ok_or_else(no_entry)?; - entry.insert(ino); - Ok(()) - } - } - } - async fn full_path(&self, parent_ino: u64) -> io::Result { let mut full_uri: PathBuf = PathBuf::new(); if parent_ino == 1 { @@ -396,7 +268,7 @@ impl MemFS { match inodes.get(p_inode).ok_or_else(no_entry) { Ok(inode) => { let inode = inode.lock().await; - warn!("name_to_inode p_inode - {:?} name - {:?}", p_inode, name); + debug!("name_to_inode: p_inode - '{:?}' name - '{:?}'", p_inode, name); match &inode.kind { INodeKind::Directory(ref dir) => match dir.children.get(name) { @@ -411,24 +283,23 @@ impl MemFS { } async fn do_lookup(&self, op: &op::Lookup<'_>) -> io::Result { - warn!("do_lookup {:?}", op); - - //warn!("do_lookup f_inode {:?}", f_inode); - + debug!("do_lookup: {:?}", op); match self.name_to_inode(op.parent(), op.name()).await { Some(f_inode) => { - warn!("do_lookup f_inode {:?}", f_inode); let inodes = self.inodes.lock().await; let inode = inodes.get(f_inode).ok_or_else(no_entry)?; let inode = inode.lock().await; - warn!("do_lookup inode {:?}", inode); match &inode.kind { INodeKind::Directory(_) => { drop(inode); drop(inodes); let mut file_path = self.full_path(op.parent()).await.unwrap(); file_path.push(op.name()); - self.fetch_remote(file_path, f_inode).await; + // self.fetch_remote(file_path, f_inode).await.unwrap(); + match self.fetch_remote(file_path, f_inode).await { + Err(_) => return Err(io::Error::from_raw_os_error(libc::ENODATA)), + _ => {} + } } _ => { drop(inode); @@ -436,28 +307,14 @@ impl MemFS { } }; } - None => warn!("Cant find inode for {:?}", op.name()), + None => warn!("do_lookup: Cant find inode for {:?}", op.name()), } self.lookup_inode(op.parent(), op.name()).await } - async fn do_forget(&self, forgets: &[Forget]) { - let mut inodes = self.inodes.lock().await; - - for forget in forgets { - if let Some(inode) = inodes.get(forget.ino()) { - let mut inode = inode.lock().await; - inode.refcount = inode.refcount.saturating_sub(forget.nlookup()); - if inode.refcount == 0 && inode.links == 0 { - inodes.remove(forget.ino()); - } - } - } - } - async fn do_getattr(&self, op: &op::Getattr<'_>) -> io::Result { - // warn!("do_getattr: op: {:?}", op); + // debug!("do_getattr: op: {:?}", op); let inodes = self.inodes.lock().await; let inode = inodes.get(op.ino()).ok_or_else(no_entry)?; @@ -469,54 +326,11 @@ impl MemFS { Ok(reply) } - async fn do_setattr(&self, op: &op::Setattr<'_>) -> io::Result { - let inodes = self.inodes.lock().await; - - let inode = inodes.get(op.ino()).ok_or_else(no_entry)?; - let mut inode = inode.lock().await; - - if let Some(mode) = op.mode() { - inode.attr.set_mode(mode); - } - if let Some(uid) = op.uid() { - inode.attr.set_uid(uid); - } - if let Some(gid) = op.gid() { - inode.attr.set_gid(gid); - } - if let Some(size) = op.size() { - inode.attr.set_size(size); - } - if let Some(atime) = op.atime() { - inode.attr.set_atime(atime); - } - if let Some(mtime) = op.mtime() { - inode.attr.set_mtime(mtime); - } - if let Some(ctime) = op.ctime() { - inode.attr.set_ctime(ctime); - } - - let mut reply = ReplyAttr::new(inode.attr); - reply.ttl_attr(self.ttl); - - Ok(reply) - } - - async fn do_readlink(&self, op: &op::Readlink<'_>) -> io::Result> { - let inodes = self.inodes.lock().await; - - let inode = inodes.get(op.ino()).ok_or_else(no_entry)?; - let inode = inode.lock().await; - - match inode.kind { - INodeKind::Symlink(ref link) => Ok(link.clone()), - _ => Err(io::Error::from_raw_os_error(libc::EINVAL)), - } - } - pub async fn fetch_remote(&self, path: PathBuf, parent: u64) -> io::Result<()> { - let remote_entries = self.http.list(path).await.unwrap(); + let remote_entries = match self.http.list(path).await { + Ok(remote_entries) => remote_entries, + Err (e) => return Err(Error::new(ErrorKind::Other, format!("HTTP {:?}: {}", e.status(), e))) + }; for r_entry in remote_entries.iter() { match &r_entry.r#type { Some(r#type) => match r#type.as_str() { @@ -525,9 +339,9 @@ impl MemFS { let mut inode_map = self.f_ino_map.lock().await; let mut full_name = self.full_path(parent).await.unwrap(); full_name.push(PathBuf::from(f_name)); - self.make_node(parent, OsStr::new(f_name.as_str()), |entry| INode { + let _x = self.make_node(parent, OsStr::new(f_name.as_str()), |entry| INode { attr: { - info!("Adding file {:?}", full_name); + debug!("fetch_remote: Adding file {:?}", full_name); inode_map.push(FileInodeMap { parent, ino: entry.ino(), @@ -550,9 +364,9 @@ impl MemFS { } "directory" => { let f_name = r_entry.name.as_ref().unwrap(); - self.make_node(parent, OsStr::new(f_name.as_str()), |entry| INode { + let _x = self.make_node(parent, OsStr::new(f_name.as_str()), |entry| INode { attr: { - info!("Adding directory {:?} - {:?}", f_name, parent); + debug!("fetch_remote: Adding directory {:?} - {:?}", f_name, parent); let mut attr = FileAttr::default(); attr.set_ino(entry.ino()); attr.set_mtime(r_entry.parse_rfc2822()); @@ -611,18 +425,14 @@ impl MemFS { } None => Some((uri, parent_ino)), }, - INodeKind::RegularFile(_) => { - warn!("inode_mutex {:?}", inode_mutex); - Some((uri, parent_ino)) - } - INodeKind::Symlink(_) => Some((uri, parent_ino)), + _ => Some((uri, parent_ino)), }; ret } //noinspection RsUnresolvedReference async fn do_opendir(&self, op: &op::Opendir<'_>) -> io::Result { - error!("do_opendir: {:?}", op); + debug!("do_opendir: {:?}", op); let mut dirs = self.dir_handles.lock().await; let inodes = self.inodes.lock().await; @@ -647,7 +457,7 @@ impl MemFS { } async fn do_readdir(&self, op: &op::Readdir<'_>) -> io::Result { - // warn!("do_readdir: op: {:?}", op); + debug!("do_readdir: op: {:?}", op); let dirs = self.dir_handles.lock().await; let dir = dirs @@ -681,194 +491,6 @@ impl MemFS { Ok(()) } - async fn do_mknod(&self, op: &op::Mknod<'_>) -> io::Result { - warn!("do_mknod: op: {:?}", op); - match op.mode() & libc::S_IFMT { - libc::S_IFREG => (), - _ => return Err(io::Error::from_raw_os_error(libc::ENOTSUP)), - } - - self.make_node(op.parent(), op.name(), |entry| INode { - attr: { - let mut attr = FileAttr::default(); - attr.set_ino(entry.ino()); - attr.set_nlink(1); - attr.set_mode(op.mode()); - attr - }, - xattrs: HashMap::new(), - refcount: 1, - links: 1, - kind: INodeKind::RegularFile(vec![]), - }) - .await - } - - async fn do_mkdir(&self, op: &op::Mkdir<'_>) -> io::Result { - // warn!("do_mkdir: op: {:?}", op); - self.make_node(op.parent(), op.name(), |entry| INode { - attr: { - let mut attr = FileAttr::default(); - attr.set_ino(entry.ino()); - attr.set_nlink(2); - attr.set_mode(op.mode() | libc::S_IFDIR); - attr - }, - xattrs: HashMap::new(), - refcount: 1, - links: 1, - kind: INodeKind::Directory(Directory { - children: HashMap::new(), - parent: Some(op.parent()), - }), - }) - .await - } - - async fn do_symlink(&self, op: &op::Symlink<'_>) -> io::Result { - self.make_node(op.parent(), op.name(), |entry| INode { - attr: { - let mut attr = FileAttr::default(); - attr.set_ino(entry.ino()); - attr.set_nlink(1); - attr.set_mode(libc::S_IFLNK | 0o777); - attr - }, - xattrs: HashMap::new(), - refcount: 1, - links: 1, - kind: INodeKind::Symlink(Arc::new(op.link().into())), - }) - .await - } - - async fn do_link(&self, op: &op::Link<'_>) -> io::Result { - self.link_node(op.ino(), op.newparent(), op.newname()).await - } - - async fn do_unlink(&self, op: &op::Unlink<'_>) -> io::Result<()> { - self.unlink_node(op.parent(), op.name()).await - } - - async fn do_rmdir(&self, op: &op::Rmdir<'_>) -> io::Result<()> { - self.unlink_node(op.parent(), op.name()).await - } - - async fn do_rename(&self, op: &op::Rename<'_>) -> io::Result<()> { - if op.flags() != 0 { - // TODO: handle RENAME_NOREPLACE and RENAME_EXCHANGE. - return Err(io::Error::from_raw_os_error(libc::EINVAL)); - } - - match (op.parent(), op.newparent()) { - (parent, newparent) if parent == newparent => { - self.rename_node(parent, op.name(), op.newname()).await - } - (parent, newparent) => { - self.graft_node(parent, op.name(), newparent, op.newname()) - .await - } - } - } - - async fn do_getxattr(&self, op: &op::Getxattr<'_>) -> io::Result { - // warn!("do_getxattr: op: {:?}", op); - - let inodes = self.inodes.lock().await; - let inode = inodes.get(op.ino()).ok_or_else(no_entry)?; - let inode = inode.lock().await; - - let value = inode - .xattrs - .get(op.name()) - .ok_or_else(|| io::Error::from_raw_os_error(libc::ENODATA))?; - - match op.size() { - 0 => Ok(Either::Left(ReplyXattr::new(value.len() as u32))), - size => { - if value.len() as u32 > size { - return Err(io::Error::from_raw_os_error(libc::ERANGE)); - } - Ok(Either::Right(value.clone())) - } - } - } - - async fn do_setxattr(&self, op: &op::Setxattr<'_>) -> io::Result<()> { - // warn!("do_setxattr: op: {:?}", op); - - let create = op.flags() as i32 & libc::XATTR_CREATE != 0; - let replace = op.flags() as i32 & libc::XATTR_REPLACE != 0; - if create && replace { - return Err(io::Error::from_raw_os_error(libc::EINVAL)); - } - - let inodes = self.inodes.lock().await; - let inode = inodes.get(op.ino()).ok_or_else(no_entry)?; - let mut inode = inode.lock().await; - - match inode.xattrs.entry(op.name().into()) { - Entry::Occupied(..) if create => Err(io::Error::from_raw_os_error(libc::EEXIST)), - Entry::Occupied(entry) => { - let value = Arc::make_mut(entry.into_mut()); - *value = op.value().into(); - Ok(()) - } - Entry::Vacant(..) if replace => Err(io::Error::from_raw_os_error(libc::ENODATA)), - Entry::Vacant(entry) => { - if create { - entry.insert(Arc::default()); - } else { - entry.insert(Arc::new(op.value().into())); - } - Ok(()) - } - } - } - - async fn do_listxattr(&self, op: &op::Listxattr<'_>) -> io::Result { - // warn!("do_listxattr: op: {:?}", op); - let inodes = self.inodes.lock().await; - let inode = inodes.get(op.ino()).ok_or_else(no_entry)?; - let inode = inode.lock().await; - - match op.size() { - 0 => { - let total_len = inode.xattrs.keys().map(|name| name.len() as u32 + 1).sum(); - Ok(Either::Left(ReplyXattr::new(total_len))) - } - size => { - let mut total_len = 0; - let names = inode.xattrs.keys().fold(OsString::new(), |mut acc, name| { - acc.push(name); - acc.push("\0"); - total_len += name.len() as u32 + 1; - acc - }); - - if total_len > size { - return Err(io::Error::from_raw_os_error(libc::ERANGE)); - } - - Ok(Either::Right(names)) - } - } - } - - async fn do_removexattr(&self, op: &op::Removexattr<'_>) -> io::Result<()> { - let inodes = self.inodes.lock().await; - let inode = inodes.get(op.ino()).ok_or_else(no_entry)?; - let mut inode = inode.lock().await; - - match inode.xattrs.entry(op.name().into()) { - Entry::Occupied(entry) => { - entry.remove(); - Ok(()) - } - Entry::Vacant(..) => Err(io::Error::from_raw_os_error(libc::ENODATA)), - } - } - async fn do_read(&self, op: &op::Read<'_>) -> io::Result { let full_path_mutex = self.f_ino_map.lock().await; let mut counter = 0; @@ -882,60 +504,18 @@ impl MemFS { } counter += 1; }; - // let inodes = self.inodes.lock().await; - // - // let inode = inodes.get(op.ino()).ok_or_else(no_entry)?; - // let inode = inode.lock().await; - // - // - // let content = match inode.kind { - // INodeKind::RegularFile(ref content) => content, - // _ => return Err(io::Error::from_raw_os_error(libc::EINVAL)), - // }; - // let offset = op.offset() as usize; let size = op.size() as usize; drop(full_path_mutex); - let chunk = self.http.read(full_path, size, offset).await.unwrap(); - - //let content = content.get(offset..).unwrap_or(&[]); - //let content = &content[..std::cmp::min(content.len(), size)]; - - Ok(chunk.to_vec()) - } - - async fn do_write( - &self, - op: &op::Write<'_>, - reader: &mut R, - ) -> io::Result - where - R: Reader + Unpin, - { - let inodes = self.inodes.lock().await; - - let inode = inodes.get(op.ino()).ok_or_else(no_entry)?; - let mut inode = inode.lock().await; - let inode = &mut *inode; - - let content = match inode.kind { - INodeKind::RegularFile(ref mut content) => content, - _ => return Err(io::Error::from_raw_os_error(libc::EINVAL)), + let chunk = match self.http.read(full_path, size, offset).await { + Ok(data) => data, + Err (e) => { + let msg = format!("HTTP {:?}: {}", e.status(), e); + error!("Read error. {:?}", msg); + return Err(Error::new(ErrorKind::Other, msg)) + } }; - - let offset = op.offset() as usize; - let size = op.size() as usize; - - content.resize(offset + size, 0); - - use futures::io::AsyncReadExt; - reader - .read_exact(&mut content[offset..offset + size]) - .await?; - - inode.attr.set_size(content.len() as u64); - - Ok(ReplyWrite::new(op.size())) + Ok(chunk.to_vec()) } } @@ -971,40 +551,11 @@ impl Filesystem for MemFS { match op { Operation::Lookup(op) => try_reply!(self.do_lookup(&op)), - Operation::Forget(forgets) => { - self.do_forget(forgets.as_ref()).await; - Ok(()) - } Operation::Getattr(op) => try_reply!(self.do_getattr(&op)), - Operation::Setattr(op) => try_reply!(self.do_setattr(&op)), - Operation::Readlink(op) => try_reply!(self.do_readlink(&op)), - Operation::Opendir(op) => try_reply!(self.do_opendir(&op)), Operation::Readdir(op) => try_reply!(self.do_readdir(&op)), Operation::Releasedir(op) => try_reply!(self.do_releasedir(&op)), - - Operation::Mknod(op) => try_reply!(self.do_mknod(&op)), - Operation::Mkdir(op) => try_reply!(self.do_mkdir(&op)), - Operation::Symlink(op) => try_reply!(self.do_symlink(&op)), - Operation::Unlink(op) => try_reply!(self.do_unlink(&op)), - Operation::Rmdir(op) => try_reply!(self.do_rmdir(&op)), - Operation::Link(op) => try_reply!(self.do_link(&op)), - Operation::Rename(op) => try_reply!(self.do_rename(&op)), - - Operation::Getxattr(op) => try_reply!(self.do_getxattr(&op)), - Operation::Setxattr(op) => try_reply!(self.do_setxattr(&op)), - Operation::Listxattr(op) => try_reply!(self.do_listxattr(&op)), - Operation::Removexattr(op) => try_reply!(self.do_removexattr(&op)), - Operation::Read(op) => try_reply!(self.do_read(&op)), - Operation::Write(op) => { - let res = self - .do_write(&op, &mut cx.reader()) - .instrument(span.clone()) - .await; - try_reply!(async { res }) - } - _ => { span.in_scope(|| tracing::debug!("NOSYS")); Ok(()) @@ -1019,28 +570,4 @@ fn no_entry() -> io::Error { fn unknown_error() -> io::Error { io::Error::from_raw_os_error(libc::EIO) -} - -// FIXME: use either crate. -#[derive(Debug)] -enum Either { - Left(L), - Right(R), -} - -impl Reply for Either -where - L: Reply, - R: Reply, -{ - #[inline] - fn collect_bytes<'a, C: ?Sized>(&'a self, collector: &mut C) - where - C: Collector<'a>, - { - match self { - Either::Left(l) => l.collect_bytes(collector), - Either::Right(r) => r.collect_bytes(collector), - } - } -} +} \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 2459f1f..221e0c1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,21 +3,16 @@ use std::path::PathBuf; extern crate log; use env_logger::Env; use std::process; -use std::ffi::OsStr; mod config; mod filesystem; -mod http; +mod client; use itertools::Itertools; #[tokio::main] async fn main() -> Result<(), std::io::Error> { env_logger::from_env(Env::default().default_filter_or("info")).init(); let cfg = config::read(); - //let http::list_directory(&cfg.server, &cfg.username, &cfg.password, "/").await; - warn!("{:?}", cfg); - - //let mut args = pico_args::Arguments::from_env(); let mountpoint: PathBuf = PathBuf::from(&cfg.mountpoint); if !mountpoint.is_dir() { @@ -27,13 +22,19 @@ async fn main() -> Result<(), std::io::Error> { let options = [ "ro", "fsname=furumi-http", - // "sync_read", "auto_unmount", "allow_other", ].iter().join(","); let memfs = filesystem::MemFS::new(&cfg); - memfs.fetch_remote(PathBuf::from("/"), 1).await; + match memfs.fetch_remote(PathBuf::from("/"), 1).await { + Err(e) => { + error!("Connection failed. Check server address and credentials {}", e); + process::exit(0x0005); + } + _ => {} + } + polyfuse_tokio::mount(memfs, mountpoint, &[ "-o".as_ref(), options.as_ref(),