diff --git a/Cargo.toml b/Cargo.toml index bbda702..66f67d2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,6 +21,7 @@ winapi = { version = "0.3", features = [ "winnt", ] } windows = "0.28" +encoding_rs = "0.8" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" libc = "0.2" diff --git a/src/disk/mod.rs b/src/disk/mod.rs new file mode 100755 index 0000000..a24ecac --- /dev/null +++ b/src/disk/mod.rs @@ -0,0 +1,56 @@ +extern crate winapi; + +use std::ffi::CString; +use winapi::um::fileapi::GetVolumeInformationA; +use encoding_rs::GBK; + +extern crate log; + +pub fn get_disk_info(drive: &str) -> Option<(String, String, u32)> { + let mut volume_name: [i8; 100] = [0; 100]; + let mut file_system_name: [i8; 100] = [0; 100]; + let mut volume_serial_number: u32 = 0; + let mut max_component_length: u32 = 0; + let mut file_system_flags: u32 = 0; + let tstr = CString::new(drive).unwrap(); + let success = unsafe { + GetVolumeInformationA( + tstr.as_ptr(), + volume_name.as_mut_ptr(), + volume_name.len() as u32, + &mut volume_serial_number, + &mut max_component_length, + &mut file_system_flags, + file_system_name.as_mut_ptr(), + file_system_name.len() as u32, + ) + }; + fn gbk2uft8(gbk: &[i8]) -> String { + let unsigned_slice = gbk.iter().map(|&x| x as u8).collect::>(); + let (utf8, _, _) = GBK.decode(&unsigned_slice); + utf8.replace("\0", "").to_string() + } + + if success != 0 { + let volume_label = gbk2uft8(&volume_name); + let file_system_name = gbk2uft8(&file_system_name); + log::info!("Volume Label: {}, file_system: {}, serial_number:{}\n", volume_label, file_system_name, volume_serial_number); + return Some((volume_label, file_system_name, volume_serial_number)); + } else { + log::debug!("volume {} Failed to get volume information.\n", drive); + return None; + } +} +#[test] +fn test_get_disk_info() { + env_logger::init(); + let (label, file_system, serial_number) = get_disk_info("C:\\").unwrap(); + assert_eq!(label, "系统"); + assert_eq!(file_system, "NTFS"); + assert_ne!(serial_number, 0); + + let (label, file_system, serial_number) = get_disk_info("V:\\").unwrap(); + assert_eq!(label, "homes"); + assert_eq!(file_system, "NTFS"); + assert_ne!(serial_number, 0); +} diff --git a/src/lib.rs b/src/lib.rs index b27edbf..042d5a8 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,6 +4,7 @@ use lws_vfs::{ Access, Chown, FileInfo, Flush, Fstat, Getattr, Getxattr, HelloReply, HelloRequest, Mkdir, Open, Read, Readdir, Release, Rmdir, Setxattr, Truncate, Utimens, Write, Create, Unlink, Opendir, Releasedir, Rename, GetConfig, }; + use self::fs_impl::FSImpl; use serde_json::{self, Value}; use serde::Serialize; @@ -15,6 +16,7 @@ use std::collections::HashMap; extern crate log; mod fs_impl; +mod disk; pub mod lws_vfs { tonic::include_proto!("lws_vfs"); } @@ -54,15 +56,44 @@ impl Config { ))) } }; - let mount_map = mounts - .iter() - .map(|(key, value)| { - ( - key.as_str().to_string(), - value.as_str().unwrap().to_string(), - ) - }) - .collect(); + let mut mount_map: HashMap = mounts.iter().filter(|(key, _)| { + match disk::get_disk_info(&key) { + None => false, + Some(_) => true, + } + }).map(|(key, value)| (key.to_string(), value.to_string())).collect(); + + let mut volume_names = HashMap::new(); + + // 获取所有的盘符对应的卷标便于后续进行比对 + for drive in 'C'..='Z' { + let drive = format!("{}:\\", drive); + if let Some((volume, _, _)) = disk::get_disk_info(&drive) { + //TODO: 这里如果存在同名的卷标会出现问题 + volume_names.insert(volume, drive); + } + } + log::info!("local disk: {:?}", volume_names); + + // 遍历配置的盘符和卷标,将配置的盘符和卷标映射到实际盘符上 + for (key, value) in mounts.iter() { + // 直接看下是不是盘符 + if let Some((drive, _, _)) = disk::get_disk_info(&key) { + mount_map.insert(drive.to_string(), value.to_string()); + } else { + // 看下是不是卷标 + if let Some(drive) = volume_names.get(key.as_str()) { + mount_map.insert(drive.to_string(), value.to_string()); + } else { + log::error!("mount volume name [{}] not found in disk list", key); + return Err(Box::new(std::io::Error::new( + std::io::ErrorKind::Other, + "mount map unavailable", + ))) + } + + } + } Ok(Config { port, mount_map }) } @@ -564,3 +595,10 @@ impl LwsVfs for LwsVfsIns { Ok(Response::new(reply)) } } + +# [test] +fn test_config_new() { + env_logger::init(); + let _config = Config::new("config.json").unwrap(); + println!("Config: {:#?}", _config); +} \ No newline at end of file diff --git a/src/server.rs b/src/server.rs index 54b8019..1e5cb2a 100644 --- a/src/server.rs +++ b/src/server.rs @@ -3,16 +3,6 @@ use tonic::transport; use lws_vfs::LwsVfsIns; use lws_vfs::lws_vfs::lws_vfs_server::LwsVfsServer; extern crate log; -// fn main() { -// println!("Hello, world!"); -// let file = "test.txt"; -// let mut sta = Stat { -// st_size: 0, -// st_mode: 0, -// }; -// let mut fi = FuseFileInfo {}; -// getattr(file, &mut sta, &mut fi); -// } #[tokio::main] async fn main() -> Result<(), Box> {