mirror of
https://github.com/uutils/procps.git
synced 2026-06-10 16:14:00 -07:00
free: add Windows support
Values are virtual the same as resmon. Unfortunately, it is slightly hacky to get the page "Swap" file sizes.
This commit is contained in:
Generated
+69
-4
@@ -877,7 +877,7 @@ dependencies = [
|
||||
"memchr",
|
||||
"ntapi",
|
||||
"rayon",
|
||||
"windows",
|
||||
"windows 0.57.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1021,6 +1021,7 @@ dependencies = [
|
||||
"clap",
|
||||
"sysinfo",
|
||||
"uucore",
|
||||
"windows 0.58.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1292,6 +1293,16 @@ dependencies = [
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows"
|
||||
version = "0.58.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dd04d41d93c4992d421894c18c8b43496aa748dd4c081bac0dc93eb0489272b6"
|
||||
dependencies = [
|
||||
"windows-core 0.58.0",
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-core"
|
||||
version = "0.52.0"
|
||||
@@ -1307,9 +1318,22 @@ version = "0.57.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d2ed2439a290666cd67ecce2b0ffaad89c2a56b976b736e6ece670297897832d"
|
||||
dependencies = [
|
||||
"windows-implement",
|
||||
"windows-interface",
|
||||
"windows-result",
|
||||
"windows-implement 0.57.0",
|
||||
"windows-interface 0.57.0",
|
||||
"windows-result 0.1.2",
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-core"
|
||||
version = "0.58.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6ba6d44ec8c2591c134257ce647b7ea6b20335bf6379a27dac5f1641fcf59f99"
|
||||
dependencies = [
|
||||
"windows-implement 0.58.0",
|
||||
"windows-interface 0.58.0",
|
||||
"windows-result 0.2.0",
|
||||
"windows-strings",
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
@@ -1324,6 +1348,17 @@ dependencies = [
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-implement"
|
||||
version = "0.58.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-interface"
|
||||
version = "0.57.0"
|
||||
@@ -1335,6 +1370,17 @@ dependencies = [
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-interface"
|
||||
version = "0.58.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-result"
|
||||
version = "0.1.2"
|
||||
@@ -1344,6 +1390,25 @@ dependencies = [
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-result"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e"
|
||||
dependencies = [
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-strings"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10"
|
||||
dependencies = [
|
||||
"windows-result 0.2.0",
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.48.0"
|
||||
|
||||
@@ -60,6 +60,7 @@ chrono = { version = "0.4.38", default-features = false, features = ["clock"] }
|
||||
walkdir = "2.5.0"
|
||||
prettytable-rs = "0.10.0"
|
||||
nix = { version = "0.29", default-features = false, features = ["process"] }
|
||||
windows = { version = "0.58.0" }
|
||||
|
||||
[dependencies]
|
||||
clap = { workspace = true }
|
||||
|
||||
@@ -18,6 +18,7 @@ clap = { workspace = true }
|
||||
bytesize = { workspace = true }
|
||||
|
||||
sysinfo = { workspace = true }
|
||||
windows = { workspace = true, features = ["Wdk_System_SystemInformation", "Win32_System_ProcessStatus", "Win32_System_SystemInformation"] }
|
||||
|
||||
[lib]
|
||||
path = "src/free.rs"
|
||||
|
||||
+37
-2
@@ -3,6 +3,9 @@
|
||||
// For the full copyright and license information, please view the LICENSE
|
||||
// file that was distributed with this source code.
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
mod windows_util;
|
||||
|
||||
use bytesize::{ByteSize, GB, GIB, KB, KIB, MB, MIB, PB, PIB, TB, TIB};
|
||||
use clap::{arg, crate_version, ArgAction, ArgGroup, ArgMatches, Command};
|
||||
use std::env;
|
||||
@@ -118,10 +121,42 @@ fn parse_meminfo() -> Result<MemInfo, Box<dyn std::error::Error>> {
|
||||
Ok(mem_info)
|
||||
}
|
||||
|
||||
// TODO: implement function
|
||||
#[cfg(target_os = "windows")]
|
||||
fn parse_meminfo() -> Result<MemInfo, Box<dyn std::error::Error>> {
|
||||
Ok(MemInfo::default())
|
||||
use std::mem::size_of;
|
||||
use windows::Win32::System::{
|
||||
ProcessStatus::{GetPerformanceInfo, PERFORMANCE_INFORMATION},
|
||||
SystemInformation::{GlobalMemoryStatusEx, MEMORYSTATUSEX},
|
||||
};
|
||||
|
||||
let (pagefile_used, pagefile_total) = windows_util::get_pagefile_usage()?;
|
||||
|
||||
let mut status = MEMORYSTATUSEX {
|
||||
dwLength: size_of::<MEMORYSTATUSEX>() as u32,
|
||||
..Default::default()
|
||||
};
|
||||
unsafe { GlobalMemoryStatusEx(&mut status)? }
|
||||
|
||||
let mut perf_info = PERFORMANCE_INFORMATION {
|
||||
cb: size_of::<PERFORMANCE_INFORMATION>() as u32,
|
||||
..Default::default()
|
||||
};
|
||||
unsafe { GetPerformanceInfo(&mut perf_info, perf_info.cb)? }
|
||||
|
||||
let mem_info = MemInfo {
|
||||
total: status.ullTotalPhys / 1024,
|
||||
free: (status.ullAvailPhys - (perf_info.SystemCache * perf_info.PageSize) as u64) / 1024,
|
||||
available: status.ullAvailPhys / 1024,
|
||||
cached: (perf_info.SystemCache * perf_info.PageSize) as u64 / 1024,
|
||||
swap_total: (pagefile_total as u64 * perf_info.PageSize as u64) / 1024,
|
||||
swap_free: ((pagefile_total - pagefile_used) as u64 * perf_info.PageSize as u64) / 1024,
|
||||
swap_used: (pagefile_used as u64 * perf_info.PageSize as u64) / 1024,
|
||||
commit_limit: (perf_info.CommitLimit * perf_info.PageSize) as u64 / 1024,
|
||||
committed: (perf_info.CommitTotal * perf_info.PageSize) as u64 / 1024,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
Ok(mem_info)
|
||||
}
|
||||
|
||||
// print total - used - free combo that is used for everything except memory for now
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
use std::ffi::c_void;
|
||||
|
||||
use windows::{
|
||||
core::Result,
|
||||
Wdk::System::SystemInformation::{NtQuerySystemInformation, SYSTEM_INFORMATION_CLASS},
|
||||
Win32::Foundation::{STATUS_INFO_LENGTH_MISMATCH, STATUS_SUCCESS, UNICODE_STRING},
|
||||
};
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Default, Debug)]
|
||||
#[allow(non_snake_case)]
|
||||
struct SYSTEM_PAGEFILE_INFORMATION {
|
||||
NextEntryOffset: u32,
|
||||
TotalSize: u32,
|
||||
TotalInUse: u32,
|
||||
PeakUsage: u32,
|
||||
PageFileName: UNICODE_STRING,
|
||||
}
|
||||
|
||||
/// Get the usage and total size of all page files.
|
||||
pub(crate) fn get_pagefile_usage() -> Result<(u32, u32)> {
|
||||
let mut buf: Vec<u8> = Vec::new();
|
||||
|
||||
let mut return_len: u32 = 0;
|
||||
|
||||
loop {
|
||||
let status = unsafe {
|
||||
NtQuerySystemInformation(
|
||||
// SystemPageFileInformation
|
||||
SYSTEM_INFORMATION_CLASS(0x12),
|
||||
buf.as_mut_ptr() as *mut c_void,
|
||||
buf.len() as u32,
|
||||
&mut return_len,
|
||||
)
|
||||
};
|
||||
|
||||
debug_assert!(buf.len() <= return_len as usize);
|
||||
|
||||
if status == STATUS_INFO_LENGTH_MISMATCH {
|
||||
debug_assert!(return_len > buf.len() as u32);
|
||||
buf.resize(return_len as usize, 0);
|
||||
continue;
|
||||
} else if status == STATUS_SUCCESS {
|
||||
debug_assert!(return_len == buf.len() as u32);
|
||||
break;
|
||||
} else {
|
||||
return Err(status.into());
|
||||
}
|
||||
}
|
||||
|
||||
let mut usage = 0;
|
||||
let mut total = 0;
|
||||
|
||||
if return_len > 0 {
|
||||
let ptr = buf.as_ptr();
|
||||
let mut offset = 0;
|
||||
loop {
|
||||
let ptr_offset =
|
||||
unsafe { ptr.byte_offset(offset) } as *const SYSTEM_PAGEFILE_INFORMATION;
|
||||
let record = unsafe { std::ptr::read(ptr_offset) };
|
||||
|
||||
usage += record.TotalInUse;
|
||||
total += record.TotalSize;
|
||||
|
||||
offset = record.NextEntryOffset as isize;
|
||||
|
||||
if offset == 0 {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok((usage, total))
|
||||
}
|
||||
Reference in New Issue
Block a user