wip: complete get owner function and change some interface sign

This commit is contained in:
DaLaw2 2025-03-04 01:19:55 +08:00
parent c50cf6ba05
commit 938d49fa2a
10 changed files with 234 additions and 87 deletions

View File

@ -27,8 +27,6 @@ sha2 = "0.10.8"
blake2 = "0.10.6"
digest = "0.10.7"
md-5 = "0.10.6"
windows-acl = "0.3.0"
windows = { version = "0.60.0", features = ["Win32", "Win32_Security", "Win32_Storage", "Win32_System", "Win32_Storage_FileSystem", "Win32_System_Memory", "Win32_Security_Authorization"] }
[dependencies.blake3]
version = "1.6.1"
@ -38,6 +36,13 @@ features = ["traits-preview"]
version = "1.13.1"
features = ["v4", "fast-rng", "serde"]
[target.'cfg(windows)'.dependencies.windows-acl]
version = "0.3.0"
[target.'cfg(windows)'.dependencies.windows]
version = "0.60.0"
features = ["Win32", "Win32_Security", "Win32_Storage", "Win32_System", "Win32_Storage_FileSystem", "Win32_System_Memory", "Win32_Security_Authorization"]
[target.'cfg(windows)'.dependencies.windows-sys]
version = "0.59.0"
features = ["Win32_UI_Shell", "Win32_Foundation", "Win32_Security", "Win32_System_Threading", "Win32_System_Registry", "Win32_System_Com", "Win32_UI_WindowsAndMessaging"]

View File

@ -31,10 +31,13 @@ pub trait FileSystemTrait {
.await
.map_err(|_| IOEntry::SemaphoreClosed)?;
let mut result = Vec::new();
let reader = fs::read_dir(&path).await?;
let reader = fs::read_dir(&path)
.await
.map_err(|_| IOEntry::ReadDirectoryFailed)?;
let mut entries = ReadDirStream::new(reader);
while let Some(entry) = entries.next().await {
result.push(entry?.path());
let path = entry.map_err(|_| IOEntry::ReadFileFailed)?.path();
result.push(path);
}
let event = ListDirectoryEvent { task_id, path };
EventBus::publish(event).await?;
@ -47,7 +50,9 @@ pub trait FileSystemTrait {
.acquire_owned()
.await
.map_err(|_| IOEntry::SemaphoreClosed)?;
fs::create_dir_all(&path).await?;
fs::create_dir_all(&path)
.await
.map_err(|_| IOEntry::CreateDirectoryFailed)?;
let event = CreateDirectoryEvent { task_id, path };
EventBus::publish(event).await?;
Ok(())
@ -59,7 +64,9 @@ pub trait FileSystemTrait {
.acquire_owned()
.await
.map_err(|_| IOEntry::SemaphoreClosed)?;
fs::remove_dir_all(&path).await?;
fs::remove_dir_all(&path)
.await
.map_err(|_| IOEntry::DeleteDirectoryFailed)?;
let event = DeleteDirectoryEvent { task_id, path };
EventBus::publish(event).await?;
Ok(())
@ -76,7 +83,9 @@ pub trait FileSystemTrait {
.acquire_owned()
.await
.map_err(|_| IOEntry::SemaphoreClosed)?;
fs::copy(&source, &destination).await?;
fs::copy(&source, &destination)
.await
.map_err(|_| IOEntry::CopyFileFailed)?;
let event = CopyFileEvent {
task_id,
source,
@ -92,7 +101,9 @@ pub trait FileSystemTrait {
.acquire_owned()
.await
.map_err(|_| IOEntry::SemaphoreClosed)?;
fs::remove_file(&path).await?;
fs::remove_file(&path)
.await
.map_err(|_| IOEntry::DeleteFileFailed)?;
let event = DeleteFileEvent { task_id, path };
EventBus::publish(event).await?;
Ok(())
@ -122,26 +133,41 @@ pub trait FileSystemTrait {
async fn compare_attributes(
&self,
task_id: Uuid,
source: PathBuf,
destination: PathBuf,
) -> anyhow::Result<bool>;
async fn compare_advanced_attributes(
&self,
task_id: Uuid,
source: PathBuf,
destination: PathBuf,
) -> anyhow::Result<bool>;
async fn get_permission(
&self,
task_id: Uuid,
path: PathBuf,
) -> anyhow::Result<PermissionAttributes>;
async fn set_permission(
&self,
task_id: Uuid,
permission: PermissionAttributes,
) -> anyhow::Result<()>;
async fn standard_compare(
&self,
task_id: Uuid,
source: PathBuf,
destination: PathBuf,
advanced_attributes: bool,
) -> anyhow::Result<bool> {
let compare_result = if advanced_attributes {
self.compare_attributes(source, destination).await?
self.compare_attributes(task_id, source, destination).await?
} else {
self.compare_advanced_attributes(source, destination).await?
self.compare_advanced_attributes(task_id, source, destination).await?
};
if !compare_result {
return Ok(false);
@ -178,19 +204,25 @@ pub trait FileSystemTrait {
async fn thorough_compare(
&self,
task_id: Uuid,
source: PathBuf,
destination: PathBuf,
hash_type: HashType,
advanced_attributes: bool,
) -> anyhow::Result<bool> {
if !self
.standard_compare(source.clone(), destination.clone(), advanced_attributes)
.standard_compare(
task_id,
source.clone(),
destination.clone(),
advanced_attributes,
)
.await?
{
return Ok(false);
}
let source_file_hash = self.calculate_hash(source, hash_type).await?;
let destination_file_hash = self.calculate_hash(destination, hash_type).await?;
let source_file_hash = self.calculate_hash(task_id, source, hash_type).await?;
let destination_file_hash = self.calculate_hash(task_id, destination, hash_type).await?;
Ok(source_file_hash == destination_file_hash)
}

View File

@ -1,11 +0,0 @@
use crate::interface::event_system::event::Event;
use std::path::PathBuf;
use uuid::Uuid;
#[derive(Clone)]
pub struct ChangeAccessControlListEvent {
pub task_id: Uuid,
pub path: PathBuf,
}
impl Event for ChangeAccessControlListEvent {}

View File

@ -1,5 +1,5 @@
pub mod acl;
pub mod attributes;
pub mod directory;
pub mod file;
pub mod hash;
pub mod permission;

View File

@ -0,0 +1,19 @@
use crate::interface::event_system::event::Event;
use std::path::PathBuf;
use uuid::Uuid;
#[derive(Clone)]
pub struct GetPermissionEvent {
pub task_id: Uuid,
pub path: PathBuf,
}
impl Event for GetPermissionEvent {}
#[derive(Clone)]
pub struct SetPermissionEvent {
pub task_id: Uuid,
pub path: PathBuf,
}
impl Event for SetPermissionEvent {}

View File

@ -1,5 +1,5 @@
use crate::interface::file_system::FileSystemTrait;
use crate::platform::attributes::{AdvancedAttributes, Attributes};
use crate::platform::attributes::{AdvancedAttributes, Attributes, PermissionAttributes};
use async_trait::async_trait;
use std::path::PathBuf;
use std::sync::Arc;
@ -52,6 +52,7 @@ impl FileSystemTrait for FileSystem {
async fn compare_attributes(
&self,
task_id: Uuid,
source: PathBuf,
destination: PathBuf,
) -> anyhow::Result<bool> {
@ -60,9 +61,26 @@ impl FileSystemTrait for FileSystem {
async fn compare_advanced_attributes(
&self,
task_id: Uuid,
source: PathBuf,
destination: PathBuf,
) -> anyhow::Result<bool> {
todo!()
}
async fn get_permission(
&self,
task_id: Uuid,
path: PathBuf,
) -> anyhow::Result<PermissionAttributes> {
todo!()
}
async fn set_permission(
&self,
task_id: Uuid,
permission: PermissionAttributes,
) -> anyhow::Result<()> {
todo!()
}
}

View File

@ -1,6 +1,7 @@
use std::time::SystemTime;
use windows_acl::acl::ACL;
#[derive(Clone, PartialEq, Eq)]
pub struct Attributes {
pub read_only: bool,
pub hidden: bool,
@ -11,17 +12,21 @@ pub struct Attributes {
pub change_time: SystemTime,
}
#[derive(Clone, PartialEq, Eq)]
pub struct AdvancedAttributes {
pub read_only: bool,
pub hidden: bool,
pub system: bool,
pub archive: bool,
pub compression: bool,
pub encryption: bool,
pub index: bool,
pub encryption: bool,
pub creation_time: SystemTime,
pub last_access_time: SystemTime,
pub change_time: SystemTime,
}
pub struct PermissionAttributes {
pub owner: String,
pub access_control_list: ACL,
}

View File

@ -1,20 +1,21 @@
use std::fs;
use crate::core::event_system::event_bus::EventBus;
use crate::interface::file_system::FileSystemTrait;
use crate::model::event::io::attributes::GetAttributesEvent;
use crate::platform::attributes::{AdvancedAttributes, Attributes};
use crate::model::event::io::attributes::{GetAttributesEvent, SetAttributesEvent};
use crate::model::event::io::permission::GetPermissionEvent;
use crate::platform::attributes::{AdvancedAttributes, Attributes, PermissionAttributes};
use crate::utils::log_entry::io::IOEntry;
use std::os::windows::fs::MetadataExt;
use std::path::PathBuf;
use std::sync::Arc;
use tokio::sync::Semaphore;
use uuid::Uuid;
use windows_acl::acl::ACL;
#[cfg(target_os = "windows")]
pub struct FileSystem {
semaphore: Arc<Semaphore>,
}
#[cfg(target_os = "windows")]
impl FileSystemTrait for FileSystem {
fn new(semaphore: Arc<Semaphore>) -> Self {
FileSystem { semaphore }
@ -24,9 +25,9 @@ impl FileSystemTrait for FileSystem {
self.semaphore.clone()
}
#[cfg(target_os = "windows")]
async fn get_attributes(&self, task_id: Uuid, path: PathBuf) -> anyhow::Result<Attributes> {
let metadata = tokio::fs::metadata(path).await
let metadata = tokio::fs::metadata(path)
.await
.map_err(|_| IOEntry::GetMetadataFailed)?;
let (read_only, hidden, system, archive) = {
@ -35,15 +36,18 @@ impl FileSystemTrait for FileSystem {
(attributes & 0x1) != 0,
(attributes & 0x2) != 0,
(attributes & 0x4) != 0,
(attributes & 0x20) != 0
(attributes & 0x32) != 0,
)
};
let creation_time = metadata.created()
let creation_time = metadata
.created()
.map_err(|_| IOEntry::GetMetadataFailed)?;
let last_access_time = metadata.accessed()
let last_access_time = metadata
.accessed()
.map_err(|_| IOEntry::GetMetadataFailed)?;
let change_time = metadata.modified()
let change_time = metadata
.modified()
.map_err(|_| IOEntry::GetMetadataFailed)?;
let attributes = Attributes {
@ -56,72 +60,58 @@ impl FileSystemTrait for FileSystem {
change_time,
};
let event = GetAttributesEvent {
task_id,
path,
};
let event = GetAttributesEvent { task_id, path };
EventBus::publish(event).await?;
Ok(attributes)
}
#[cfg(target_os = "windows")]
async fn get_advanced_attributes(
&self,
task_id: Uuid,
path: PathBuf,
) -> anyhow::Result<AdvancedAttributes> {
let metadata = tokio::fs::metadata(path).await
let metadata = tokio::fs::metadata(path)
.await
.map_err(|_| IOEntry::GetMetadataFailed)?;
let (read_only, hidden, system, archive, compression, encryption, index) = {
use std::os::windows::fs::MetadataExt;
let (read_only, hidden, system, archive, compression, index, encryption) = {
let attributes = metadata.file_attributes();
(
(attributes & 0x1) != 0,
(attributes & 0x2) != 0,
(attributes & 0x4) != 0,
(attributes & 0x20) != 0,
(attributes & 0x800) != 0,
(attributes & 0x4000) != 0,
(attributes & 0x2000) != 0,
(attributes & 0x32) != 0,
(attributes & 0x2048) != 0,
(attributes & 0x8192) != 0,
(attributes & 0x16384) != 0,
)
};
let creation_time = metadata.created()
let creation_time = metadata
.created()
.map_err(|_| IOEntry::GetMetadataFailed)?;
let last_access_time = metadata.accessed()
let last_access_time = metadata
.accessed()
.map_err(|_| IOEntry::GetMetadataFailed)?;
let change_time = metadata.modified()
let change_time = metadata
.modified()
.map_err(|_| IOEntry::GetMetadataFailed)?;
let (owner, access_control_list) = {
let path_str = path.to_string_lossy().to_string();
let acl = ACL::from_file_path(&path_str, true)
.map_err(|_| IOEntry::GetMetadataFailed)?;
let owner = String::new();
(owner, acl)
};
let attributes = AdvancedAttributes {
read_only,
hidden,
system,
archive,
compression,
encryption,
index,
encryption,
creation_time,
last_access_time,
change_time,
owner,
access_control_list,
};
let event = GetAttributesEvent {
task_id,
path,
};
let event = GetAttributesEvent { task_id, path };
EventBus::publish(event).await?;
Ok(attributes)
@ -133,7 +123,9 @@ impl FileSystemTrait for FileSystem {
path: PathBuf,
attributes: Attributes,
) -> anyhow::Result<()> {
todo!()
let event = SetAttributesEvent { task_id, path };
EventBus::publish(event).await?;
Ok(())
}
async fn set_advanced_attributes(
@ -142,11 +134,14 @@ impl FileSystemTrait for FileSystem {
path: PathBuf,
attributes: AdvancedAttributes,
) -> anyhow::Result<()> {
todo!()
let event = SetAttributesEvent { task_id, path };
EventBus::publish(event).await?;
Ok(())
}
async fn compare_attributes(
&self,
task_id: Uuid,
source: PathBuf,
destination: PathBuf,
) -> anyhow::Result<bool> {
@ -155,9 +150,30 @@ impl FileSystemTrait for FileSystem {
async fn compare_advanced_attributes(
&self,
task_id: Uuid,
source: PathBuf,
destination: PathBuf,
) -> anyhow::Result<bool> {
todo!()
}
async fn get_permission(
&self,
task_id: Uuid,
path: PathBuf,
) -> anyhow::Result<PermissionAttributes> {
let event = GetPermissionEvent { task_id, path };
EventBus::publish(event).await?;
Ok()
}
async fn set_permission(
&self,
task_id: Uuid,
permission: PermissionAttributes,
) -> anyhow::Result<()> {
let event = SetAttributesEvent { task_id, path };
EventBus::publish(event).await?;
Ok(())
}
}

View File

@ -1,22 +1,20 @@
use crate::utils::log_entry::io::IOEntry;
use std::ffi::OsString;
use std::os::windows::prelude::*;
use std::path::{Path, PathBuf};
use std::ptr;
use windows::{
core::*,
Win32::Foundation::*,
Win32::Security::*,
Win32::Security::Authorization,
Win32::Storage::FileSystem::*,
Win32::System::Memory::*,
use std::path::PathBuf;
use windows::core::{PCWSTR, PWSTR};
use windows::Win32::Foundation::{LocalFree, ERROR_SUCCESS, HLOCAL};
use windows::Win32::Security::Authorization::{
GetNamedSecurityInfoW, SE_FILE_OBJECT, SE_OBJECT_TYPE,
};
use windows::Win32::Security::{
LookupAccountSidW, OWNER_SECURITY_INFORMATION, PSECURITY_DESCRIPTOR, PSID, SID_NAME_USE,
};
use windows::Win32::Security::Authorization::{GetNamedSecurityInfoW, SE_FILE_OBJECT, SE_OBJECT_TYPE};
use crate::utils::log_entry::io::IOEntry;
pub fn get_security_descriptor(path: PathBuf) -> anyhow::Result<()> {
pub fn get_owner(path: PathBuf) -> anyhow::Result<String> {
let file_path_wild: Vec<u16> = path.as_os_str().encode_wide().chain(Some(0)).collect();
let p_owner: *mut PSID = ptr::null_mut();
let mut p_sid_owner = PSID::default();
let mut p_security_descriptor: PSECURITY_DESCRIPTOR = PSECURITY_DESCRIPTOR::default();
unsafe {
@ -24,7 +22,7 @@ pub fn get_security_descriptor(path: PathBuf) -> anyhow::Result<()> {
PCWSTR(file_path_wild.as_ptr()),
SE_OBJECT_TYPE(SE_FILE_OBJECT.0),
OWNER_SECURITY_INFORMATION,
Some(p_owner),
Some(&mut p_sid_owner),
None,
None,
None,
@ -35,12 +33,64 @@ pub fn get_security_descriptor(path: PathBuf) -> anyhow::Result<()> {
Err(IOEntry::GetMetadataFailed)?
}
LookupAccountSidW()
let mut name_size: u32 = 0;
let mut domain_size: u32 = 0;
let mut sid_type = SID_NAME_USE::default();
let _ = LookupAccountSidW(
PCWSTR::null(),
p_sid_owner,
None,
&mut name_size,
None,
&mut domain_size,
&mut sid_type,
);
let mut name_buffer = vec![0u16; name_size as usize];
let mut domain_buffer = vec![0u16; domain_size as usize];
let lookup_result = LookupAccountSidW(
PCWSTR::null(),
p_sid_owner,
Some(PWSTR(name_buffer.as_mut_ptr())),
&mut name_size,
Some(PWSTR(domain_buffer.as_mut_ptr())),
&mut domain_size,
&mut sid_type,
);
if lookup_result.is_err() {
let security_descriptor_handle = HLOCAL(p_security_descriptor.0 as *mut _);
LocalFree(Some(security_descriptor_handle));
Err(IOEntry::GetMetadataFailed)?
}
if name_size > 0 {
name_buffer.truncate(name_size as usize - 1);
}
if domain_size > 0 {
domain_buffer.truncate(domain_size as usize - 1);
}
let account_name = OsString::from_wide(&name_buffer)
.to_string_lossy()
.to_string();
let domain_name = OsString::from_wide(&domain_buffer)
.to_string_lossy()
.to_string();
let security_descriptor_handle = HLOCAL(p_security_descriptor.0 as *mut _);
LocalFree(Some(security_descriptor_handle));
if domain_name.is_empty() {
Ok(account_name)
} else {
Ok(format!("{}\\{}", domain_name, account_name))
}
}
Ok(())
}
fn lookup_account_sid(sid: PSID) -> Result<(String, String)> {
pub fn get_owner_sid(path: PathBuf) -> anyhow::Result<String> {
}

View File

@ -4,8 +4,21 @@ use thiserror::Error;
pub enum IOEntry {
#[error("Semaphore has been closed")]
SemaphoreClosed,
#[error("Create directory failed")]
CreateDirectoryFailed,
#[error("Read directory failed")]
ReadDirectoryFailed,
#[error("Read file failed")]
ReadFileFailed,
#[error("Copy file failed")]
CopyFileFailed,
#[error("Delete directory failed")]
DeleteDirectoryFailed,
#[error("Delete file failed")]
DeleteFileFailed,
#[error("Get file metadata failed")]
GetMetadataFailed,
}