mirror of
https://github.com/OMGeeky/gdriver2.git
synced 2026-02-15 22:14:31 +01:00
Improve implementation & actually mount it for testing
This commit is contained in:
2
Cargo.lock
generated
2
Cargo.lock
generated
@@ -432,11 +432,13 @@ dependencies = [
|
||||
"directories",
|
||||
"futures",
|
||||
"lazy_static",
|
||||
"libc",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tarpc",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
||||
@@ -14,6 +14,7 @@ tarpc = { version = "0.34", features = ["full"] }
|
||||
futures="0.3"
|
||||
lazy_static="1.4"
|
||||
chrono="0.4"
|
||||
libc = "0.2"
|
||||
|
||||
[patch.crates-io]
|
||||
#tarpc = {path = "../../Documents/git/OMGeeky/tarpc/tarpc/"}
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
use chrono::Duration;
|
||||
use gdriver_common::ipc::gdriver_service::errors::*;
|
||||
use gdriver_common::{
|
||||
drive_structure::drive_id::{DriveId, ROOT_ID},
|
||||
ipc::gdriver_service::*,
|
||||
};
|
||||
use std::ffi::OsString;
|
||||
use std::{path::PathBuf, sync::Arc, thread};
|
||||
use tarpc::context::Context;
|
||||
use tokio::sync::Mutex;
|
||||
|
||||
use crate::drive::Drive;
|
||||
@@ -15,6 +18,20 @@ struct GdriverServer {
|
||||
drive: Arc<Mutex<Drive>>,
|
||||
}
|
||||
impl GDriverService for GdriverServer {
|
||||
async fn get_settings(self, _: Context) -> StdResult<GDriverSettings, GetSettingsError> {
|
||||
Ok(GDriverSettings::default()) //todo actually implement this
|
||||
}
|
||||
|
||||
async fn get_file_by_name(
|
||||
self,
|
||||
context: Context,
|
||||
name: OsString,
|
||||
parent: DriveId,
|
||||
) -> StdResult<DriveId, GetFileByPathError> {
|
||||
dbg!(context, name, parent);
|
||||
Err(GetFileByPathError::Other)
|
||||
}
|
||||
|
||||
async fn get_file_by_path(
|
||||
self,
|
||||
context: ::tarpc::context::Context,
|
||||
|
||||
@@ -10,11 +10,11 @@ tarpc.workspace = true
|
||||
tokio.workspace = true
|
||||
tracing.workspace = true
|
||||
serde.workspace = true
|
||||
libc.workspace = true
|
||||
anyhow = "1.0"
|
||||
futures-sink = "0.3.30"
|
||||
fuser = "0.14.0"
|
||||
bimap = "0.6"
|
||||
libc = "0.2.152"
|
||||
futures = "0.3"
|
||||
thiserror = "1.0.56"
|
||||
|
||||
|
||||
@@ -5,11 +5,13 @@ use std::time::Duration;
|
||||
|
||||
use anyhow::anyhow;
|
||||
use bimap::BiMap;
|
||||
use fuser::{KernelConfig, ReplyEntry, Request};
|
||||
use fuser::{KernelConfig, ReplyEntry, ReplyOpen, Request};
|
||||
use tarpc::context::current as current_context;
|
||||
use tracing::*;
|
||||
|
||||
use gdriver_common::drive_structure::drive_id::{DriveId, ROOT_ID};
|
||||
use gdriver_common::drive_structure::meta::read_metadata_file;
|
||||
use gdriver_common::drive_structure::file_handle_flags::HandleFlags;
|
||||
|
||||
use gdriver_common::ipc::gdriver_service::{
|
||||
errors::GDriverServiceError, GDriverServiceClient, GDriverSettings,
|
||||
};
|
||||
@@ -18,7 +20,6 @@ use crate::filesystem::attributes::read_inode_attributes_from_meta_file;
|
||||
use crate::filesystem::errors::FilesystemError;
|
||||
use crate::prelude::macros::*;
|
||||
use crate::prelude::*;
|
||||
use tarpc::context::current as current_context;
|
||||
|
||||
mod macros;
|
||||
|
||||
@@ -26,24 +27,25 @@ mod macros;
|
||||
const TTL: Duration = Duration::from_secs(2);
|
||||
|
||||
type Inode = u64;
|
||||
type FileHandle = u64;
|
||||
|
||||
#[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
|
||||
struct FileIdentifier {
|
||||
parent: Inode,
|
||||
name: OsString,
|
||||
}
|
||||
|
||||
pub struct Filesystem {
|
||||
#[derive(Debug)]
|
||||
pub struct DriveFilesystem {
|
||||
gdriver_client: GDriverServiceClient,
|
||||
|
||||
entry_ids: BiMap<Inode, DriveId>,
|
||||
ino_to_file_handles: HashMap<Inode, Vec<u64>>,
|
||||
ino_to_file_handles: HashMap<Inode, Vec<FileHandle>>,
|
||||
next_ino: u64,
|
||||
gdriver_settings: GDriverSettings,
|
||||
entry_name_parent_to_ino: BiMap<FileIdentifier, Inode>,
|
||||
}
|
||||
|
||||
impl Filesystem {
|
||||
impl DriveFilesystem {
|
||||
pub fn new(gdriver_client: GDriverServiceClient) -> Self {
|
||||
Self {
|
||||
gdriver_client,
|
||||
@@ -62,7 +64,7 @@ impl Filesystem {
|
||||
}
|
||||
|
||||
//region DriveFilesystem ino_to_id
|
||||
impl Filesystem {
|
||||
impl DriveFilesystem {
|
||||
fn get_id_from_ino(&self, ino: Inode) -> Option<&DriveId> {
|
||||
self.entry_ids.get_by_left(&ino)
|
||||
}
|
||||
@@ -91,7 +93,7 @@ impl Filesystem {
|
||||
//endregion
|
||||
mod attributes;
|
||||
|
||||
impl fuser::Filesystem for Filesystem {
|
||||
impl fuser::Filesystem for DriveFilesystem {
|
||||
//region init
|
||||
fn init(&mut self, _req: &Request<'_>, _config: &mut KernelConfig) -> StdResult<(), c_int> {
|
||||
self.entry_ids.insert(1, ROOT_ID.clone());
|
||||
@@ -111,6 +113,9 @@ impl fuser::Filesystem for Filesystem {
|
||||
//endregion
|
||||
//region lookup
|
||||
fn lookup(&mut self, _req: &Request<'_>, parent: u64, name: &OsStr, reply: ReplyEntry) {
|
||||
if name.to_str().unwrap().contains('/') {
|
||||
todo!("The name in lookup can contain multiple path segments, not just a single name, directly under the parent")
|
||||
}
|
||||
let metadata = utils::lookup::lookup(self, parent, name.to_os_string());
|
||||
match metadata {
|
||||
Ok(metadata) => {
|
||||
@@ -133,12 +138,37 @@ impl fuser::Filesystem for Filesystem {
|
||||
}
|
||||
}
|
||||
//endregion
|
||||
//region open
|
||||
fn open(&mut self, _req: &Request<'_>, ino: u64, flags: i32, reply: ReplyOpen) {
|
||||
let data = utils::lookup::open(self, ino, HandleFlags::from(flags));
|
||||
match data {
|
||||
Ok((file_header, flags)) => {
|
||||
reply.opened(file_header, flags.into());
|
||||
}
|
||||
Err(e) => {
|
||||
error!("Got an error during open: {e:?}");
|
||||
match e {
|
||||
FilesystemError::Rpc(_) => reply.error(libc::EREMOTEIO),
|
||||
FilesystemError::NotFound => reply.error(libc::ENOENT),
|
||||
FilesystemError::IO(_) => reply.error(libc::EIO),
|
||||
e => {
|
||||
dbg!(e);
|
||||
todo!("Handle other errors and decide what error code should be used here")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//endregion
|
||||
}
|
||||
|
||||
mod errors {
|
||||
use gdriver_common::ipc::gdriver_service::errors::GDriverServiceError;
|
||||
use std::error::Error;
|
||||
|
||||
use tarpc::client::RpcError;
|
||||
|
||||
use gdriver_common::ipc::gdriver_service::errors::GDriverServiceError;
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum FilesystemError {
|
||||
#[error("Error while executing RPC: {0}")]
|
||||
@@ -153,17 +183,22 @@ mod errors {
|
||||
Other(#[source] Box<dyn Error>),
|
||||
}
|
||||
}
|
||||
|
||||
mod utils {
|
||||
use super::*;
|
||||
|
||||
pub mod lookup {
|
||||
use super::*;
|
||||
use crate::filesystem::attributes::InodeAttributes;
|
||||
use crate::filesystem::errors::FilesystemError;
|
||||
use futures::TryFutureExt;
|
||||
|
||||
use gdriver_common::ipc::gdriver_service::errors::GetFileByPathError;
|
||||
|
||||
use crate::filesystem::attributes::InodeAttributes;
|
||||
use crate::filesystem::errors::FilesystemError;
|
||||
|
||||
use super::*;
|
||||
|
||||
pub fn lookup(
|
||||
fs: &mut Filesystem,
|
||||
fs: &mut DriveFilesystem,
|
||||
parent: Inode,
|
||||
name: OsString,
|
||||
) -> StdResult<InodeAttributes, FilesystemError> {
|
||||
@@ -216,5 +251,14 @@ mod utils {
|
||||
.map_err(FilesystemError::IO)?;
|
||||
Ok(metadata)
|
||||
}
|
||||
|
||||
pub(crate) fn open(
|
||||
fs: &mut DriveFilesystem,
|
||||
inode: Inode,
|
||||
flags: HandleFlags,
|
||||
) -> StdResult<(FileHandle, HandleFlags), FilesystemError> {
|
||||
dbg!(&fs, inode, flags);
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
use fuser::{mount2, MountOption};
|
||||
use std::path::Path;
|
||||
use std::{error::Error, net::IpAddr, result::Result as StdResult};
|
||||
|
||||
use crate::filesystem::DriveFilesystem;
|
||||
use crate::service::create_client;
|
||||
use gdriver_common::ipc::gdriver_service::GDriverServiceClient;
|
||||
use gdriver_common::{ipc::sample::*, prelude::*};
|
||||
use tarpc::{client, tokio_serde::formats::Json};
|
||||
|
||||
@@ -7,7 +12,14 @@ type Result<T> = StdResult<T, Box<dyn Error>>;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<()> {
|
||||
service::start().await?;
|
||||
println!("Hello, world!");
|
||||
let config = &CONFIGURATION;
|
||||
println!("Config: {:?}", **config);
|
||||
let client: GDriverServiceClient = create_client(config.ip, config.port).await?;
|
||||
let fs = DriveFilesystem::new(client);
|
||||
mount2(fs, Path::new("/tmp/gdriver"), &[MountOption::RW])?;
|
||||
|
||||
// service::start().await?;
|
||||
Ok(())
|
||||
}
|
||||
pub mod prelude;
|
||||
|
||||
@@ -8,6 +8,8 @@ edition = "2021"
|
||||
[dependencies]
|
||||
serde.workspace = true
|
||||
tarpc.workspace = true
|
||||
tracing.workspace = true
|
||||
libc.workspace = true
|
||||
tokio.workspace = true
|
||||
futures.workspace = true
|
||||
lazy_static.workspace = true
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
pub mod drive_id;
|
||||
pub mod file_handle_flags;
|
||||
pub mod meta;
|
||||
|
||||
149
gdriver-common/src/drive_structure/file_handle_flags.rs
Normal file
149
gdriver-common/src/drive_structure/file_handle_flags.rs
Normal file
@@ -0,0 +1,149 @@
|
||||
use crate::prelude::*;
|
||||
#[derive(Debug, Copy, Clone, Default)]
|
||||
pub struct HandleFlags {
|
||||
// File status flags used for open() and fcntl() are as follows:
|
||||
/// append mode.
|
||||
o_append: bool,
|
||||
/// [SIO](https://pubs.opengroup.org/onlinepubs/009695399/help/codes.html#SIO) Write according to synchronized I/O data integrity completion.
|
||||
o_dsync: bool,
|
||||
/// Non-blocking mode.
|
||||
o_nonblock: bool,
|
||||
/// [SIO](https://pubs.opengroup.org/onlinepubs/009695399/help/codes.html#SIO) Synchronized read I/O operations.
|
||||
o_rsync: bool,
|
||||
/// Write according to synchronized I/O file integrity completion.
|
||||
o_sync: bool,
|
||||
|
||||
// Mask for use with file access modes is as follows:
|
||||
/// Mask for file access modes.
|
||||
// O_ACCMODE
|
||||
|
||||
// File access modes used for open() and fcntl() are as follows:
|
||||
|
||||
/// Open for reading only.
|
||||
o_rdonly: bool,
|
||||
/// Open for reading and writing.
|
||||
o_rdwr: bool,
|
||||
/// Open for writing only.
|
||||
o_wronly: bool,
|
||||
}
|
||||
|
||||
impl HandleFlags {
|
||||
pub(crate) fn can_write(&self) -> bool {
|
||||
self.o_wronly || self.o_rdwr
|
||||
}
|
||||
|
||||
pub(crate) fn can_read(&self) -> bool {
|
||||
self.o_rdonly || self.o_rdwr
|
||||
}
|
||||
}
|
||||
|
||||
impl From<i32> for HandleFlags {
|
||||
fn from(value: i32) -> Self {
|
||||
debug!("Creating HandleFlags from an i32: {:x}", value);
|
||||
let s = Self {
|
||||
o_append: value & libc::O_APPEND != 0,
|
||||
o_dsync: value & libc::O_DSYNC != 0,
|
||||
o_nonblock: value & libc::O_NONBLOCK != 0,
|
||||
o_rsync: value & libc::O_RSYNC != 0,
|
||||
o_sync: value & libc::O_SYNC != 0,
|
||||
o_rdonly: value & libc::O_ACCMODE == libc::O_RDONLY,
|
||||
o_rdwr: value & libc::O_ACCMODE == libc::O_RDWR,
|
||||
o_wronly: value & libc::O_ACCMODE == libc::O_WRONLY,
|
||||
};
|
||||
#[cfg(test)]
|
||||
{
|
||||
let o_accmode = value & libc::O_ACCMODE;
|
||||
let o_rdonly = o_accmode == libc::O_RDONLY;
|
||||
let o_rdwr = o_accmode == libc::O_RDWR;
|
||||
let o_wronly = o_accmode == libc::O_WRONLY;
|
||||
debug!(
|
||||
"accmode {:x} rdonly {} rdwr {} wronly {}",
|
||||
o_accmode, o_rdonly, o_rdwr, o_wronly
|
||||
);
|
||||
}
|
||||
debug!("created HandleFlags: {:?}", s);
|
||||
s
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<i32> for HandleFlags {
|
||||
fn into(self) -> i32 {
|
||||
let mut flags = 0;
|
||||
if self.o_append {
|
||||
flags |= libc::O_APPEND;
|
||||
}
|
||||
if self.o_dsync {
|
||||
flags |= libc::O_DSYNC;
|
||||
}
|
||||
if self.o_nonblock {
|
||||
flags |= libc::O_NONBLOCK;
|
||||
}
|
||||
if self.o_rsync {
|
||||
flags |= libc::O_RSYNC;
|
||||
}
|
||||
if self.o_sync {
|
||||
flags |= libc::O_SYNC;
|
||||
}
|
||||
if self.o_rdonly {
|
||||
flags |= libc::O_RDONLY;
|
||||
}
|
||||
if self.o_rdwr {
|
||||
flags |= libc::O_RDWR;
|
||||
}
|
||||
if self.o_wronly {
|
||||
flags |= libc::O_WRONLY;
|
||||
}
|
||||
flags
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<u32> for HandleFlags {
|
||||
fn into(self) -> u32 {
|
||||
let i_num: i32 = self.into();
|
||||
i_num as u32
|
||||
}
|
||||
}
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
#[test]
|
||||
fn handle_flags_ro() {
|
||||
let flags = 0;
|
||||
let handle_flags = HandleFlags::from(flags);
|
||||
debug!("flags: {:x} => {:?}", flags, handle_flags);
|
||||
assert!(handle_flags.can_read());
|
||||
assert!(!handle_flags.can_write());
|
||||
let flags = 32768;
|
||||
let handle_flags = HandleFlags::from(flags);
|
||||
debug!("flags: {:x} => {:?}", flags, handle_flags);
|
||||
assert!(handle_flags.can_read());
|
||||
assert!(!handle_flags.can_write());
|
||||
}
|
||||
#[test]
|
||||
fn handle_flags_wo() {
|
||||
let flags = 1;
|
||||
let handle_flags = HandleFlags::from(flags);
|
||||
debug!("flags: {:x} => {:?}", flags, handle_flags);
|
||||
assert!(handle_flags.can_write());
|
||||
assert!(!handle_flags.can_read());
|
||||
}
|
||||
#[test]
|
||||
fn handle_flags_rw() {
|
||||
let flags = 2;
|
||||
let handle_flags = HandleFlags::from(flags);
|
||||
debug!("flags: {:x} => {:?}", flags, handle_flags);
|
||||
debug!("test432");
|
||||
assert!(handle_flags.can_write());
|
||||
assert!(handle_flags.can_read());
|
||||
}
|
||||
#[test]
|
||||
fn handle_flags_into_rw() {
|
||||
debug!("test123");
|
||||
let mut x = HandleFlags::default();
|
||||
x.o_rdwr = true;
|
||||
assert!(x.can_write());
|
||||
assert!(x.can_read());
|
||||
let flags: i32 = x.into();
|
||||
assert_eq!(2, flags);
|
||||
}
|
||||
}
|
||||
@@ -125,7 +125,10 @@ pub mod errors {
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, thiserror::Error)]
|
||||
pub enum GetFileByPathError {}
|
||||
pub enum GetFileByPathError {
|
||||
#[error("Other")]
|
||||
Other,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, thiserror::Error)]
|
||||
pub enum UpdateChangesError {}
|
||||
|
||||
@@ -8,3 +8,4 @@ pub mod result {
|
||||
pub use std::result::Result as StdResult;
|
||||
}
|
||||
pub(crate) use result::*;
|
||||
pub(crate) use tracing::*;
|
||||
|
||||
Reference in New Issue
Block a user