Skip to content

Commit

Permalink
Make metadata handle store the metadata, instead of just a path. Add …
Browse files Browse the repository at this point in the history
…test for this case.
  • Loading branch information
CraftSpider committed Dec 8, 2024
1 parent 938430f commit 3c2ed8a
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 15 deletions.
12 changes: 7 additions & 5 deletions src/shims/windows/fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use std::io::IsTerminal;
use std::path::PathBuf;
use std::time::SystemTime;

use crate::shims::files::{FileDescription, FileDescriptionRef};
use crate::shims::files::FileDescription;
use crate::shims::time::system_time_to_duration;
use crate::shims::windows::handle::{EvalContextExt as _, Handle};
use crate::*;
Expand Down Expand Up @@ -80,7 +80,7 @@ impl FileDescription for DirHandle {

#[derive(Debug)]
pub struct MetadataHandle {
pub(crate) path: PathBuf,
pub(crate) meta: Metadata,
}

impl FileDescription for MetadataHandle {
Expand All @@ -89,7 +89,7 @@ impl FileDescription for MetadataHandle {
}

fn metadata<'tcx>(&self) -> InterpResult<'tcx, io::Result<Metadata>> {
interp_ok(self.path.metadata())
interp_ok(Ok(self.meta.clone()))
}

fn close<'tcx>(
Expand Down Expand Up @@ -238,8 +238,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// Windows supports handles with no permissions. These allow things such as reading
// metadata, but not file content.
let fh = &mut this.machine.fds;
let fd_num = fh.insert_new(MetadataHandle { path: file_name });
Ok(Handle::File(fd_num))
file_name.metadata().map(|meta| {
let fd_num = fh.insert_new(MetadataHandle { meta });
Handle::File(fd_num)
})
} else {
options.open(file_name).map(|file| {
let fh = &mut this.machine.fds;
Expand Down
41 changes: 31 additions & 10 deletions tests/pass-dep/shims/windows-fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#![allow(nonstandard_style)]

use std::os::windows::ffi::OsStrExt;
use std::path::Path;
use std::ptr;

#[path = "../../utils/mod.rs"]
Expand All @@ -24,10 +25,7 @@ fn main() {

unsafe fn test_create_dir_file() {
let temp = utils::tmp();
let mut raw_path = temp.as_os_str().encode_wide().collect::<Vec<_>>();
// encode_wide doesn't add a null-terminator
raw_path.push(0);
raw_path.push(0);
let raw_path = to_wide_cstr(&temp);
let handle = CreateFileW(
raw_path.as_ptr(),
GENERIC_READ,
Expand All @@ -37,7 +35,7 @@ unsafe fn test_create_dir_file() {
FILE_FLAG_BACKUP_SEMANTICS,
0,
);
assert_ne!(handle, -1, "CreateNewW Failed: {}", GetLastError());
assert_ne!(handle, -1, "CreateFileW Failed: {}", GetLastError());
let mut info = std::mem::zeroed::<BY_HANDLE_FILE_INFORMATION>();
if GetFileInformationByHandle(handle, &mut info) == 0 {
panic!("Failed to get file information")
Expand All @@ -50,10 +48,7 @@ unsafe fn test_create_dir_file() {

unsafe fn test_create_normal_file() {
let temp = utils::tmp().join("test.txt");
let mut raw_path = temp.as_os_str().encode_wide().collect::<Vec<_>>();
// encode_wide doesn't add a null-terminator
raw_path.push(0);
raw_path.push(0);
let raw_path = to_wide_cstr(&temp);
let handle = CreateFileW(
raw_path.as_ptr(),
GENERIC_READ | GENERIC_WRITE,
Expand All @@ -63,7 +58,7 @@ unsafe fn test_create_normal_file() {
0,
0,
);
assert_ne!(handle, -1, "CreateNewW Failed: {}", GetLastError());
assert_ne!(handle, -1, "CreateFileW Failed: {}", GetLastError());
let mut info = std::mem::zeroed::<BY_HANDLE_FILE_INFORMATION>();
if GetFileInformationByHandle(handle, &mut info) == 0 {
panic!("Failed to get file information: {}", GetLastError())
Expand All @@ -72,4 +67,30 @@ unsafe fn test_create_normal_file() {
if CloseHandle(handle) == 0 {
panic!("Failed to close file")
};

// Test metadata-only handle
let handle = CreateFileW(
raw_path.as_ptr(),
0,
FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
ptr::null_mut(),
OPEN_EXISTING,
0,
0,
);
assert_ne!(handle, -1, "CreateFileW Failed: {}", GetLastError());
let mut info = std::mem::zeroed::<BY_HANDLE_FILE_INFORMATION>();
if GetFileInformationByHandle(handle, &mut info) == 0 {
panic!("Failed to get file information: {}", GetLastError())
};
assert!(info.dwFileAttributes & FILE_ATTRIBUTE_NORMAL != 0);
if CloseHandle(handle) == 0 {
panic!("Failed to close file")
};
}

fn to_wide_cstr(path: &Path) -> Vec<u16> {
let mut raw_path = path.as_os_str().encode_wide().collect::<Vec<_>>();
raw_path.extend([0, 0]);
raw_path
}

0 comments on commit 3c2ed8a

Please sign in to comment.