mirror of
https://github.com/house-of-vanity/furumi.git
synced 2025-07-06 21:24:08 +00:00
Linting.
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@ -1 +1,2 @@
|
|||||||
/target
|
/target
|
||||||
|
/mus-fuse.yml
|
||||||
|
106
Cargo.lock
generated
106
Cargo.lock
generated
@ -168,16 +168,6 @@ version = "0.7.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b3a71ab494c0b5b860bdc8407ae08978052417070c2ced38573a9157ad75b8ac"
|
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]]
|
[[package]]
|
||||||
name = "dtoa"
|
name = "dtoa"
|
||||||
version = "0.4.5"
|
version = "0.4.5"
|
||||||
@ -251,29 +241,26 @@ checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "furumi"
|
name = "furumi"
|
||||||
version = "0.1.0"
|
version = "1.0.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"base64",
|
"base64",
|
||||||
"chrono",
|
"chrono",
|
||||||
"clap",
|
"clap",
|
||||||
"config",
|
"config",
|
||||||
"ctrlc",
|
|
||||||
"env_logger",
|
"env_logger",
|
||||||
"futures",
|
"futures",
|
||||||
"futures-intrusive",
|
"futures-intrusive",
|
||||||
|
"http",
|
||||||
"itertools",
|
"itertools",
|
||||||
"libc",
|
"libc",
|
||||||
"log",
|
"log",
|
||||||
"percent-encoding",
|
|
||||||
"polyfuse",
|
"polyfuse",
|
||||||
"polyfuse-tokio",
|
"polyfuse-tokio",
|
||||||
"reqwest",
|
"reqwest",
|
||||||
"serde 1.0.106",
|
"serde 1.0.106",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"size_format",
|
|
||||||
"slab",
|
"slab",
|
||||||
"time",
|
|
||||||
"tokio",
|
"tokio",
|
||||||
"tracing",
|
"tracing",
|
||||||
"tracing-futures",
|
"tracing-futures",
|
||||||
@ -382,15 +369,6 @@ dependencies = [
|
|||||||
"slab",
|
"slab",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "generic-array"
|
|
||||||
version = "0.12.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec"
|
|
||||||
dependencies = [
|
|
||||||
"typenum",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "getrandom"
|
name = "getrandom"
|
||||||
version = "0.1.14"
|
version = "0.1.14"
|
||||||
@ -763,19 +741,6 @@ dependencies = [
|
|||||||
"winapi 0.3.8",
|
"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]]
|
[[package]]
|
||||||
name = "nom"
|
name = "nom"
|
||||||
version = "4.2.3"
|
version = "4.2.3"
|
||||||
@ -786,29 +751,6 @@ dependencies = [
|
|||||||
"version_check 0.1.5",
|
"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]]
|
[[package]]
|
||||||
name = "num-integer"
|
name = "num-integer"
|
||||||
version = "0.1.42"
|
version = "0.1.42"
|
||||||
@ -819,28 +761,6 @@ dependencies = [
|
|||||||
"num-traits 0.2.11",
|
"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]]
|
[[package]]
|
||||||
name = "num-traits"
|
name = "num-traits"
|
||||||
version = "0.1.43"
|
version = "0.1.43"
|
||||||
@ -1331,16 +1251,6 @@ dependencies = [
|
|||||||
"libc",
|
"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]]
|
[[package]]
|
||||||
name = "slab"
|
name = "slab"
|
||||||
version = "0.4.2"
|
version = "0.4.2"
|
||||||
@ -1603,12 +1513,6 @@ version = "0.2.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e604eb7b43c06650e854be16a2a03155743d3752dd1c943f6829e26b7a36e382"
|
checksum = "e604eb7b43c06650e854be16a2a03155743d3752dd1c943f6829e26b7a36e382"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "typenum"
|
|
||||||
version = "1.12.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicase"
|
name = "unicase"
|
||||||
version = "2.6.0"
|
version = "2.6.0"
|
||||||
@ -1683,12 +1587,6 @@ version = "0.9.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed"
|
checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "void"
|
|
||||||
version = "1.0.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "want"
|
name = "want"
|
||||||
version = "0.3.0"
|
version = "0.3.0"
|
||||||
|
18
Cargo.toml
18
Cargo.toml
@ -1,8 +1,13 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "furumi"
|
name = "furumi"
|
||||||
version = "0.1.0"
|
version = "1.0.0"
|
||||||
authors = ["AB <ultradesu@hexor.ru>"]
|
authors = ["AB <ultradesu@hexor.ru>"]
|
||||||
edition = "2018"
|
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
|
# 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"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
clap = {version = "2.33", features = ["yaml"]}
|
clap = {version = "2.33", features = ["yaml"]}
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
percent-encoding = "2.1"
|
#percent-encoding = "2.1"
|
||||||
time = "0.1"
|
#time = "0.1"
|
||||||
chrono = "0.4"
|
chrono = "0.4"
|
||||||
env_logger = "0.7"
|
env_logger = "0.7"
|
||||||
log = { version = "^0.4.5", features = ["std"] }
|
log = { version = "^0.4.5", features = ["std"] }
|
||||||
size_format = "1.0"
|
#size_format = "1.0"
|
||||||
base64 = "0.12"
|
base64 = "0.12"
|
||||||
ctrlc = "3.1"
|
#ctrlc = "3.1"
|
||||||
config = "0.9"
|
config = "0.9"
|
||||||
itertools = "*"
|
itertools = "0.9"
|
||||||
|
http = "0.2"
|
||||||
|
|
||||||
[dev-dependencies.tokio]
|
[dev-dependencies.tokio]
|
||||||
version = "0.2"
|
version = "0.2"
|
||||||
|
@ -5,9 +5,7 @@ use reqwest::{header, Client, Error};
|
|||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use std::{
|
use std::{
|
||||||
path::PathBuf,
|
path::PathBuf,
|
||||||
process,
|
time::SystemTime,
|
||||||
thread::sleep,
|
|
||||||
time::{Duration, SystemTime},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static APP_USER_AGENT: &str = concat!(env!("CARGO_PKG_NAME"), "/", env!("CARGO_PKG_VERSION"),);
|
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<Vec<RemoteEntry>, Error> {
|
pub async fn list(&self, path: PathBuf) -> Result<Vec<RemoteEntry>, Error> {
|
||||||
debug!("Fetching path '{}/{}'", self.server, path.display());
|
debug!("Fetching path '{}/{}'", self.server, path.display());
|
||||||
let mut client = &self.client;
|
let client = &self.client;
|
||||||
let resp = client
|
let resp = client
|
||||||
.get(format!("{}/{}", self.server, path.display()).as_str())
|
.get(format!("{}/{}", self.server, path.display()).as_str())
|
||||||
.send()
|
.send()
|
||||||
@ -71,16 +69,14 @@ impl HTTP {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn read(&self, path: PathBuf, size: usize, offset: usize) -> Result<Vec<u8>, Error> {
|
pub async fn read(&self, path: PathBuf, size: usize, offset: usize) -> Result<Vec<u8>, Error> {
|
||||||
debug!("Reading path '{}/{}'", self.server, path.display());
|
|
||||||
let mut headers = header::HeaderMap::new();
|
let mut headers = header::HeaderMap::new();
|
||||||
let range = format!("bytes={}-{}", offset, { offset + size - 1 });
|
let range = format!("bytes={}-{}", offset, {offset + size - 1});
|
||||||
info!("range = {:?}", range);
|
debug!("Reading path '{}' range {} ({} bytes)", path.display(), range, size);
|
||||||
headers.insert(
|
headers.insert(
|
||||||
header::RANGE,
|
header::RANGE,
|
||||||
header::HeaderValue::from_str(range.as_str()).unwrap(),
|
header::HeaderValue::from_str(range.as_str()).unwrap(),
|
||||||
);
|
);
|
||||||
|
let client = &self.client;
|
||||||
let mut client = &self.client;
|
|
||||||
let resp = client
|
let resp = client
|
||||||
.get(format!("{}/{}", self.server, path.display()).as_str())
|
.get(format!("{}/{}", self.server, path.display()).as_str())
|
||||||
.headers(headers)
|
.headers(headers)
|
||||||
@ -88,7 +84,7 @@ impl HTTP {
|
|||||||
.await?
|
.await?
|
||||||
.bytes()
|
.bytes()
|
||||||
.await?;
|
.await?;
|
||||||
info!("Found {} entries into '{}'", resp.len(), path.display());
|
debug!("Received {} bytes of '{}'", resp.len(), path.display());
|
||||||
Ok(resp.to_vec())
|
Ok(resp.to_vec())
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -2,18 +2,18 @@
|
|||||||
#![deny(clippy::unimplemented)]
|
#![deny(clippy::unimplemented)]
|
||||||
|
|
||||||
use crate::config;
|
use crate::config;
|
||||||
use crate::http;
|
use crate::client;
|
||||||
|
|
||||||
use polyfuse::{
|
use polyfuse::{
|
||||||
io::{Reader, Writer},
|
io::{Reader, Writer},
|
||||||
op,
|
op,
|
||||||
reply::{Collector, Reply, ReplyAttr, ReplyEntry, ReplyOpen, ReplyWrite, ReplyXattr},
|
reply::{Reply, ReplyAttr, ReplyEntry, ReplyOpen},
|
||||||
Context, DirEntry, FileAttr, Filesystem, Forget, Operation,
|
Context, DirEntry, FileAttr, Filesystem, Operation,
|
||||||
};
|
};
|
||||||
use slab::Slab;
|
use slab::Slab;
|
||||||
|
|
||||||
use crate::http::HTTP;
|
use crate::client::HTTP;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::PathBuf;
|
||||||
use std::{
|
use std::{
|
||||||
collections::hash_map::{Entry, HashMap},
|
collections::hash_map::{Entry, HashMap},
|
||||||
ffi::{OsStr, OsString},
|
ffi::{OsStr, OsString},
|
||||||
@ -24,7 +24,7 @@ use std::{
|
|||||||
};
|
};
|
||||||
use tokio::sync::Mutex;
|
use tokio::sync::Mutex;
|
||||||
use tracing_futures::Instrument;
|
use tracing_futures::Instrument;
|
||||||
|
use std::io::{Error, ErrorKind};
|
||||||
type Ino = u64;
|
type Ino = u64;
|
||||||
|
|
||||||
//noinspection RsUnresolvedReference
|
//noinspection RsUnresolvedReference
|
||||||
@ -51,11 +51,6 @@ impl INodeTable {
|
|||||||
fn get(&self, ino: Ino) -> Option<Arc<Mutex<INode>>> {
|
fn get(&self, ino: Ino) -> Option<Arc<Mutex<INode>>> {
|
||||||
self.map.get(&ino).cloned()
|
self.map.get(&ino).cloned()
|
||||||
}
|
}
|
||||||
|
|
||||||
//noinspection RsUnresolvedReference
|
|
||||||
fn remove(&mut self, ino: Ino) -> Option<Arc<Mutex<INode>>> {
|
|
||||||
self.map.remove(&ino)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@ -90,7 +85,6 @@ struct INode {
|
|||||||
enum INodeKind {
|
enum INodeKind {
|
||||||
RegularFile(Vec<u8>),
|
RegularFile(Vec<u8>),
|
||||||
Directory(Directory),
|
Directory(Directory),
|
||||||
Symlink(Arc<OsString>),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
@ -140,7 +134,7 @@ struct FileInodeMap {
|
|||||||
//noinspection RsUnresolvedReference
|
//noinspection RsUnresolvedReference
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct MemFS {
|
pub struct MemFS {
|
||||||
http: http::HTTP,
|
http: client::HTTP,
|
||||||
inodes: Mutex<INodeTable>,
|
inodes: Mutex<INodeTable>,
|
||||||
f_ino_map: Mutex<Vec<FileInodeMap>>,
|
f_ino_map: Mutex<Vec<FileInodeMap>>,
|
||||||
ttl: Duration,
|
ttl: Duration,
|
||||||
@ -243,128 +237,6 @@ impl MemFS {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn link_node(&self, ino: u64, newparent: Ino, newname: &OsStr) -> io::Result<ReplyEntry> {
|
|
||||||
{
|
|
||||||
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<PathBuf> {
|
async fn full_path(&self, parent_ino: u64) -> io::Result<PathBuf> {
|
||||||
let mut full_uri: PathBuf = PathBuf::new();
|
let mut full_uri: PathBuf = PathBuf::new();
|
||||||
if parent_ino == 1 {
|
if parent_ino == 1 {
|
||||||
@ -396,7 +268,7 @@ impl MemFS {
|
|||||||
match inodes.get(p_inode).ok_or_else(no_entry) {
|
match inodes.get(p_inode).ok_or_else(no_entry) {
|
||||||
Ok(inode) => {
|
Ok(inode) => {
|
||||||
let inode = inode.lock().await;
|
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 {
|
match &inode.kind {
|
||||||
INodeKind::Directory(ref dir) => match dir.children.get(name) {
|
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<ReplyEntry> {
|
async fn do_lookup(&self, op: &op::Lookup<'_>) -> io::Result<ReplyEntry> {
|
||||||
warn!("do_lookup {:?}", op);
|
debug!("do_lookup: {:?}", op);
|
||||||
|
|
||||||
//warn!("do_lookup f_inode {:?}", f_inode);
|
|
||||||
|
|
||||||
match self.name_to_inode(op.parent(), op.name()).await {
|
match self.name_to_inode(op.parent(), op.name()).await {
|
||||||
Some(f_inode) => {
|
Some(f_inode) => {
|
||||||
warn!("do_lookup f_inode {:?}", f_inode);
|
|
||||||
let inodes = self.inodes.lock().await;
|
let inodes = self.inodes.lock().await;
|
||||||
let inode = inodes.get(f_inode).ok_or_else(no_entry)?;
|
let inode = inodes.get(f_inode).ok_or_else(no_entry)?;
|
||||||
let inode = inode.lock().await;
|
let inode = inode.lock().await;
|
||||||
warn!("do_lookup inode {:?}", inode);
|
|
||||||
match &inode.kind {
|
match &inode.kind {
|
||||||
INodeKind::Directory(_) => {
|
INodeKind::Directory(_) => {
|
||||||
drop(inode);
|
drop(inode);
|
||||||
drop(inodes);
|
drop(inodes);
|
||||||
let mut file_path = self.full_path(op.parent()).await.unwrap();
|
let mut file_path = self.full_path(op.parent()).await.unwrap();
|
||||||
file_path.push(op.name());
|
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);
|
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
|
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<ReplyAttr> {
|
async fn do_getattr(&self, op: &op::Getattr<'_>) -> io::Result<ReplyAttr> {
|
||||||
// warn!("do_getattr: op: {:?}", op);
|
// debug!("do_getattr: op: {:?}", op);
|
||||||
let inodes = self.inodes.lock().await;
|
let inodes = self.inodes.lock().await;
|
||||||
|
|
||||||
let inode = inodes.get(op.ino()).ok_or_else(no_entry)?;
|
let inode = inodes.get(op.ino()).ok_or_else(no_entry)?;
|
||||||
@ -469,54 +326,11 @@ impl MemFS {
|
|||||||
Ok(reply)
|
Ok(reply)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn do_setattr(&self, op: &op::Setattr<'_>) -> io::Result<ReplyAttr> {
|
|
||||||
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<Arc<OsString>> {
|
|
||||||
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<()> {
|
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() {
|
for r_entry in remote_entries.iter() {
|
||||||
match &r_entry.r#type {
|
match &r_entry.r#type {
|
||||||
Some(r#type) => match r#type.as_str() {
|
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 inode_map = self.f_ino_map.lock().await;
|
||||||
let mut full_name = self.full_path(parent).await.unwrap();
|
let mut full_name = self.full_path(parent).await.unwrap();
|
||||||
full_name.push(PathBuf::from(f_name));
|
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: {
|
attr: {
|
||||||
info!("Adding file {:?}", full_name);
|
debug!("fetch_remote: Adding file {:?}", full_name);
|
||||||
inode_map.push(FileInodeMap {
|
inode_map.push(FileInodeMap {
|
||||||
parent,
|
parent,
|
||||||
ino: entry.ino(),
|
ino: entry.ino(),
|
||||||
@ -550,9 +364,9 @@ impl MemFS {
|
|||||||
}
|
}
|
||||||
"directory" => {
|
"directory" => {
|
||||||
let f_name = r_entry.name.as_ref().unwrap();
|
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: {
|
attr: {
|
||||||
info!("Adding directory {:?} - {:?}", f_name, parent);
|
debug!("fetch_remote: Adding directory {:?} - {:?}", f_name, parent);
|
||||||
let mut attr = FileAttr::default();
|
let mut attr = FileAttr::default();
|
||||||
attr.set_ino(entry.ino());
|
attr.set_ino(entry.ino());
|
||||||
attr.set_mtime(r_entry.parse_rfc2822());
|
attr.set_mtime(r_entry.parse_rfc2822());
|
||||||
@ -611,18 +425,14 @@ impl MemFS {
|
|||||||
}
|
}
|
||||||
None => Some((uri, parent_ino)),
|
None => Some((uri, parent_ino)),
|
||||||
},
|
},
|
||||||
INodeKind::RegularFile(_) => {
|
_ => Some((uri, parent_ino)),
|
||||||
warn!("inode_mutex {:?}", inode_mutex);
|
|
||||||
Some((uri, parent_ino))
|
|
||||||
}
|
|
||||||
INodeKind::Symlink(_) => Some((uri, parent_ino)),
|
|
||||||
};
|
};
|
||||||
ret
|
ret
|
||||||
}
|
}
|
||||||
|
|
||||||
//noinspection RsUnresolvedReference
|
//noinspection RsUnresolvedReference
|
||||||
async fn do_opendir(&self, op: &op::Opendir<'_>) -> io::Result<ReplyOpen> {
|
async fn do_opendir(&self, op: &op::Opendir<'_>) -> io::Result<ReplyOpen> {
|
||||||
error!("do_opendir: {:?}", op);
|
debug!("do_opendir: {:?}", op);
|
||||||
|
|
||||||
let mut dirs = self.dir_handles.lock().await;
|
let mut dirs = self.dir_handles.lock().await;
|
||||||
let inodes = self.inodes.lock().await;
|
let inodes = self.inodes.lock().await;
|
||||||
@ -647,7 +457,7 @@ impl MemFS {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn do_readdir(&self, op: &op::Readdir<'_>) -> io::Result<impl Reply + Debug> {
|
async fn do_readdir(&self, op: &op::Readdir<'_>) -> io::Result<impl Reply + Debug> {
|
||||||
// warn!("do_readdir: op: {:?}", op);
|
debug!("do_readdir: op: {:?}", op);
|
||||||
let dirs = self.dir_handles.lock().await;
|
let dirs = self.dir_handles.lock().await;
|
||||||
|
|
||||||
let dir = dirs
|
let dir = dirs
|
||||||
@ -681,194 +491,6 @@ impl MemFS {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn do_mknod(&self, op: &op::Mknod<'_>) -> io::Result<ReplyEntry> {
|
|
||||||
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<ReplyEntry> {
|
|
||||||
// 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<ReplyEntry> {
|
|
||||||
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<ReplyEntry> {
|
|
||||||
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<impl Reply + Debug> {
|
|
||||||
// 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<impl Reply + Debug> {
|
|
||||||
// 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<impl Reply + Debug> {
|
async fn do_read(&self, op: &op::Read<'_>) -> io::Result<impl Reply + Debug> {
|
||||||
let full_path_mutex = self.f_ino_map.lock().await;
|
let full_path_mutex = self.f_ino_map.lock().await;
|
||||||
let mut counter = 0;
|
let mut counter = 0;
|
||||||
@ -882,60 +504,18 @@ impl MemFS {
|
|||||||
}
|
}
|
||||||
counter += 1;
|
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 offset = op.offset() as usize;
|
||||||
let size = op.size() as usize;
|
let size = op.size() as usize;
|
||||||
drop(full_path_mutex);
|
drop(full_path_mutex);
|
||||||
let chunk = self.http.read(full_path, size, offset).await.unwrap();
|
let chunk = match self.http.read(full_path, size, offset).await {
|
||||||
|
Ok(data) => data,
|
||||||
//let content = content.get(offset..).unwrap_or(&[]);
|
Err (e) => {
|
||||||
//let content = &content[..std::cmp::min(content.len(), size)];
|
let msg = format!("HTTP {:?}: {}", e.status(), e);
|
||||||
|
error!("Read error. {:?}", msg);
|
||||||
Ok(chunk.to_vec())
|
return Err(Error::new(ErrorKind::Other, msg))
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn do_write<R: ?Sized>(
|
|
||||||
&self,
|
|
||||||
op: &op::Write<'_>,
|
|
||||||
reader: &mut R,
|
|
||||||
) -> io::Result<ReplyWrite>
|
|
||||||
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)),
|
|
||||||
};
|
};
|
||||||
|
Ok(chunk.to_vec())
|
||||||
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()))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -971,40 +551,11 @@ impl Filesystem for MemFS {
|
|||||||
|
|
||||||
match op {
|
match op {
|
||||||
Operation::Lookup(op) => try_reply!(self.do_lookup(&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::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::Opendir(op) => try_reply!(self.do_opendir(&op)),
|
||||||
Operation::Readdir(op) => try_reply!(self.do_readdir(&op)),
|
Operation::Readdir(op) => try_reply!(self.do_readdir(&op)),
|
||||||
Operation::Releasedir(op) => try_reply!(self.do_releasedir(&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::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"));
|
span.in_scope(|| tracing::debug!("NOSYS"));
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -1019,28 +570,4 @@ fn no_entry() -> io::Error {
|
|||||||
|
|
||||||
fn unknown_error() -> io::Error {
|
fn unknown_error() -> io::Error {
|
||||||
io::Error::from_raw_os_error(libc::EIO)
|
io::Error::from_raw_os_error(libc::EIO)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: use either crate.
|
|
||||||
#[derive(Debug)]
|
|
||||||
enum Either<L, R> {
|
|
||||||
Left(L),
|
|
||||||
Right(R),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<L, R> Reply for Either<L, R>
|
|
||||||
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),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
17
src/main.rs
17
src/main.rs
@ -3,21 +3,16 @@ use std::path::PathBuf;
|
|||||||
extern crate log;
|
extern crate log;
|
||||||
use env_logger::Env;
|
use env_logger::Env;
|
||||||
use std::process;
|
use std::process;
|
||||||
use std::ffi::OsStr;
|
|
||||||
|
|
||||||
mod config;
|
mod config;
|
||||||
mod filesystem;
|
mod filesystem;
|
||||||
mod http;
|
mod client;
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> Result<(), std::io::Error> {
|
async fn main() -> Result<(), std::io::Error> {
|
||||||
env_logger::from_env(Env::default().default_filter_or("info")).init();
|
env_logger::from_env(Env::default().default_filter_or("info")).init();
|
||||||
let cfg = config::read();
|
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);
|
let mountpoint: PathBuf = PathBuf::from(&cfg.mountpoint);
|
||||||
if !mountpoint.is_dir() {
|
if !mountpoint.is_dir() {
|
||||||
@ -27,13 +22,19 @@ async fn main() -> Result<(), std::io::Error> {
|
|||||||
let options = [
|
let options = [
|
||||||
"ro",
|
"ro",
|
||||||
"fsname=furumi-http",
|
"fsname=furumi-http",
|
||||||
// "sync_read",
|
|
||||||
"auto_unmount",
|
"auto_unmount",
|
||||||
"allow_other",
|
"allow_other",
|
||||||
].iter().join(",");
|
].iter().join(",");
|
||||||
|
|
||||||
let memfs = filesystem::MemFS::new(&cfg);
|
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, &[
|
polyfuse_tokio::mount(memfs, mountpoint, &[
|
||||||
"-o".as_ref(),
|
"-o".as_ref(),
|
||||||
options.as_ref(),
|
options.as_ref(),
|
||||||
|
Reference in New Issue
Block a user