Skip to content

Commit dad2fa1

Browse files
committed
Allow io::block::File to take Windows volume/drives
1 parent dad8f07 commit dad2fa1

File tree

3 files changed

+53
-4
lines changed

3 files changed

+53
-4
lines changed

Cargo.lock

Lines changed: 10 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/io/Cargo.toml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ usernet = { path = "../usernet", optional = true }
2121
p9 = { path = "../p9", optional = true }
2222
fdt = { path = "../fdt", optional = true }
2323

24+
[target.'cfg(windows)'.dependencies]
25+
windows = { version = "0.48", optional = true, features = ["Win32_System_Ioctl", "Win32_System_IO", "Win32_Foundation"] }
26+
2427
[features]
2528
default = [
2629
"block-file",
@@ -40,7 +43,7 @@ default = [
4043
"virtio-console",
4144
"system",
4245
]
43-
block-file = []
46+
block-file = ["windows"]
4447
block-shadow = ["fnv"]
4548
network-logger = ["byteorder"]
4649
network-usernet = ["usernet"]

lib/io/src/block/file.rs

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,19 +13,55 @@ pub struct File {
1313
len: u64,
1414
}
1515

16+
#[cfg(windows)]
17+
fn get_disk_len(f: &mut std::fs::File) -> Result<u64> {
18+
use std::os::windows::io::AsRawHandle;
19+
use windows::Win32::Foundation::HANDLE;
20+
use windows::Win32::System::Ioctl::{GET_LENGTH_INFORMATION, IOCTL_DISK_GET_LENGTH_INFO};
21+
22+
let handle = HANDLE(f.as_raw_handle() as _);
23+
let mut out_buffer: GET_LENGTH_INFORMATION = Default::default();
24+
let mut bytes_returned = 0;
25+
26+
let ret = unsafe {
27+
windows::Win32::System::IO::DeviceIoControl(
28+
handle,
29+
IOCTL_DISK_GET_LENGTH_INFO,
30+
None,
31+
0,
32+
Some(&mut out_buffer as *mut GET_LENGTH_INFORMATION as _),
33+
std::mem::size_of::<GET_LENGTH_INFORMATION>() as _,
34+
Some(&mut bytes_returned),
35+
None,
36+
)
37+
.as_bool()
38+
};
39+
40+
if !ret {
41+
return Err(std::io::Error::last_os_error());
42+
}
43+
44+
Ok(out_buffer.Length as _)
45+
}
46+
1647
fn query_len(f: &mut std::fs::File) -> Result<u64> {
1748
if let Ok(metadata) = f.metadata() {
1849
if metadata.is_file() {
1950
return Ok(metadata.len());
2051
}
2152
}
2253

23-
if let Ok(x) = f.seek(SeekFrom::End(0)) {
24-
if x != 0 {
25-
return Ok(x);
54+
if let Ok(len) = f.seek(SeekFrom::End(0)) {
55+
if len != 0 {
56+
return Ok(len);
2657
}
2758
}
2859

60+
#[cfg(windows)]
61+
if let Ok(len) = get_disk_len(f) {
62+
return Ok(len);
63+
}
64+
2965
Err(Error::new(ErrorKind::Other, "cannot get file size"))
3066
}
3167

0 commit comments

Comments
 (0)