* Copyright (c), Huawei Technologies Co., Ltd. 2025-2025. All rights reserved.
*/
#![feature(io_error_more)]
use std::{fs, fs::Metadata, io::ErrorKind};
#[cfg(windows)]
use windows::{
Win32::{
Foundation::{CloseHandle, HANDLE, HLOCAL, LocalFree},
},
};
use self::FileErrorKind::*;
pub enum FileErrorKind<'a> {
ErrorNone,
InvalidFileName(&'a str),
NoSuchFile(&'a str),
DirNotSupported(&'a str),
UnknownError(String, &'a str),
UnsupportedFIleType(&'a str),
BadPermission(&'a str),
InconsistentOwner(&'a str),
BadFile(&'a str),
}
pub struct FileExt;
impl FileExt {
pub fn validate(path: &str) -> FileErrorKind {
let mut metadata = fs::metadata(path);
match metadata {
Ok(ref mut meta) => {
if meta.is_dir() {
return DirNotSupported(path);
}
if meta.is_symlink() {
let path = fs::read_link(path).unwrap();
*meta = fs::metadata(path).unwrap();
}
#[cfg(unix)]
{
use std::os::unix::fs::MetadataExt;
let mode = meta.mode();
if mode & 0o400 == 0 || mode & 0o022 != 0 {
return BadPermission(path);
}
}
#[cfg(unix)]
if !check_owner(meta) {
return InconsistentOwner(path);
}
}
Err(e) =>
return match e.kind() {
ErrorKind::InvalidFilename => InvalidFileName(path),
ErrorKind::NotFound => NoSuchFile(path),
_ => UnknownError(e.to_string(), path),
},
}
ErrorNone
}
}
#[cfg(unix)]
fn check_owner(meta: &Metadata) -> bool {
use std::os::unix::fs::MetadataExt;
let uid = meta.uid();
let euid = unsafe { libc::geteuid() };
uid == euid
}
#[cfg(windows)]
fn local_free_rs<T>(ptr: *mut T) {
if !ptr.is_null() {
unsafe {
LocalFree(Some(HLOCAL(ptr.cast())));
}
}
}
#[cfg(windows)]
fn close_handle_rs(handle: HANDLE) {
unsafe {
if CloseHandle(handle).is_err() {
unimplemented!()
}
}
}