mirror of
https://github.com/rustfs/rustfs.git
synced 2026-08-13 16:46:55 +00:00
refactor(utils/os): Optimize Windows OS utilities and add safety comments (#1671)
Co-authored-by: weisd <weishidavip@163.com>
This commit is contained in:
@@ -12,7 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use super::{DiskInfo, IOStats};
|
||||
use crate::os::{DiskInfo, IOStats};
|
||||
use rustix::fs::statfs;
|
||||
use std::fs::File;
|
||||
use std::io::{self, BufRead, Error, ErrorKind};
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use super::{DiskInfo, IOStats};
|
||||
use crate::os::{DiskInfo, IOStats};
|
||||
use rustix::fs::{StatVfs, statvfs};
|
||||
use std::io::Error;
|
||||
use std::path::Path;
|
||||
|
||||
@@ -12,7 +12,9 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use super::{DiskInfo, IOStats};
|
||||
#![allow(unsafe_code)] // TODO: audit unsafe code
|
||||
|
||||
use crate::os::{DiskInfo, IOStats};
|
||||
use std::io::Error;
|
||||
use std::path::Path;
|
||||
use windows::Win32::Foundation::MAX_PATH;
|
||||
@@ -20,17 +22,15 @@ use windows::Win32::Storage::FileSystem::{GetDiskFreeSpaceExW, GetDiskFreeSpaceW
|
||||
|
||||
/// Returns total and free bytes available in a directory, e.g. `C:\`.
|
||||
pub fn get_info(p: impl AsRef<Path>) -> std::io::Result<DiskInfo> {
|
||||
let path_wide = p
|
||||
.as_ref()
|
||||
.to_string_lossy()
|
||||
.encode_utf16()
|
||||
.chain(std::iter::once(0))
|
||||
.collect::<Vec<u16>>();
|
||||
let path_wide = to_wide_path(p.as_ref());
|
||||
|
||||
let mut free_bytes_available = 0u64;
|
||||
let mut total_number_of_bytes = 0u64;
|
||||
let mut total_number_of_free_bytes = 0u64;
|
||||
|
||||
// SAFETY:
|
||||
// 1. `path_wide` is a valid null-terminated UTF-16 string.
|
||||
// 2. Pointers to `u64` variables are valid and point to initialized stack memory.
|
||||
unsafe {
|
||||
GetDiskFreeSpaceExW(
|
||||
windows::core::PCWSTR::from_raw(path_wide.as_ptr()),
|
||||
@@ -56,6 +56,9 @@ pub fn get_info(p: impl AsRef<Path>) -> std::io::Result<DiskInfo> {
|
||||
let mut number_of_free_clusters = 0u32;
|
||||
let mut total_number_of_clusters = 0u32;
|
||||
|
||||
// SAFETY:
|
||||
// 1. `path_wide` is a valid null-terminated UTF-16 string.
|
||||
// 2. Pointers to `u32` variables are valid and point to initialized stack memory.
|
||||
unsafe {
|
||||
GetDiskFreeSpaceW(
|
||||
windows::core::PCWSTR::from_raw(path_wide.as_ptr()),
|
||||
@@ -87,6 +90,10 @@ fn get_windows_fs_type(p: &[u16]) -> std::io::Result<String> {
|
||||
let mut volume_name_buffer = [0u16; MAX_PATH as usize];
|
||||
let mut file_system_name_buffer = [0u16; MAX_PATH as usize];
|
||||
|
||||
// SAFETY:
|
||||
// 1. `path` is a valid null-terminated UTF-16 string (volume root path).
|
||||
// 2. Buffers are allocated with `MAX_PATH` size, which is sufficient for standard Windows paths.
|
||||
// 3. Pointers to output variables are valid.
|
||||
unsafe {
|
||||
GetVolumeInformationW(
|
||||
windows::core::PCWSTR::from_raw(path.as_ptr()),
|
||||
@@ -105,6 +112,11 @@ fn get_windows_fs_type(p: &[u16]) -> std::io::Result<String> {
|
||||
fn get_volume_name(v: &[u16]) -> std::io::Result<Vec<u16>> {
|
||||
let mut volume_name_buffer = [0u16; MAX_PATH as usize];
|
||||
|
||||
// SAFETY:
|
||||
// 1. `v` is a valid null-terminated UTF-16 string.
|
||||
// 2. `volume_name_buffer` is allocated with `MAX_PATH` size.
|
||||
// 3. `GetVolumePathNameW` writes to the buffer and respects the buffer size (implicitly MAX_PATH for this API context usually, though explicit length param isn't present, it expects a buffer large enough).
|
||||
// Note: GetVolumePathNameW documentation says "The buffer should be large enough to hold the path". MAX_PATH is generally safe for volume roots.
|
||||
unsafe {
|
||||
GetVolumePathNameW(windows::core::PCWSTR::from_raw(v.as_ptr()), &mut volume_name_buffer)
|
||||
.map_err(|e| Error::from_raw_os_error(e.code().0 as i32))?;
|
||||
@@ -122,9 +134,16 @@ fn utf16_to_string(v: &[u16]) -> String {
|
||||
String::from_utf16_lossy(&v[..len])
|
||||
}
|
||||
|
||||
fn to_wide_path(path: &Path) -> Vec<u16> {
|
||||
path.as_os_str().encode_wide().chain(std::iter::once(0)).collect()
|
||||
}
|
||||
|
||||
// Helper trait to access encode_wide which is only available on Windows
|
||||
use std::os::windows::ffi::OsStrExt;
|
||||
|
||||
pub fn same_disk(disk1: &str, disk2: &str) -> std::io::Result<bool> {
|
||||
let path1_wide: Vec<u16> = disk1.encode_utf16().chain(std::iter::once(0)).collect();
|
||||
let path2_wide: Vec<u16> = disk2.encode_utf16().chain(std::iter::once(0)).collect();
|
||||
let path1_wide = to_wide_path(Path::new(disk1));
|
||||
let path2_wide = to_wide_path(Path::new(disk2));
|
||||
|
||||
let volume1 = get_volume_name(&path1_wide)?;
|
||||
let volume2 = get_volume_name(&path2_wide)?;
|
||||
|
||||
Reference in New Issue
Block a user