Skip to content

Commit

Permalink
Fixes raw_open and microtime on windows (obhq#772)
Browse files Browse the repository at this point in the history
  • Loading branch information
SuchAFuriousDeath committed Mar 27, 2024
1 parent dcbf2ac commit 2ca7ebe
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 47 deletions.
57 changes: 39 additions & 18 deletions src/kernel/src/fs/host/file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -197,27 +197,27 @@ impl HostFile {
Err(Error::last_os_error())
} else {
// TODO: Store mode somewhere that work on any FS. We should not use mode on the host
// for this because it can be lose when the user restore their files from the backup.
// for this because it can be lost when the user restores their files from the backup.
Self::raw_open(parent, name)
}
}

#[cfg(windows)]
fn raw_mkdir(parent: RawFile, name: &str, mode: u32) -> Result<RawFile, Error> {
fn raw_mkdir(parent: RawFile, name: &str, _mode: u32) -> Result<RawFile, Error> {
use std::mem::size_of;
use std::ptr::null_mut;
use windows_sys::Wdk::Foundation::OBJECT_ATTRIBUTES;
use windows_sys::Wdk::Storage::FileSystem::{
NtCreateFile, FILE_CREATE, FILE_DIRECTORY_FILE,
use windows_sys::Wdk::{
Foundation::OBJECT_ATTRIBUTES,
Storage::FileSystem::{NtCreateFile, FILE_DIRECTORY_FILE, FILE_OPEN},
};
use windows_sys::Win32::Foundation::{
RtlNtStatusToDosError, STATUS_SUCCESS, UNICODE_STRING,
};
use windows_sys::Win32::Storage::FileSystem::{
FILE_ATTRIBUTE_DIRECTORY, FILE_LIST_DIRECTORY, FILE_READ_ATTRIBUTES, FILE_READ_EA,
FILE_SHARE_READ, FILE_SHARE_WRITE, FILE_TRAVERSE, FILE_WRITE_ATTRIBUTES, FILE_WRITE_EA,
use windows_sys::Win32::{
Foundation::{RtlNtStatusToDosError, STATUS_SUCCESS, UNICODE_STRING},
Storage::FileSystem::{
FILE_ATTRIBUTE_DIRECTORY, FILE_LIST_DIRECTORY, FILE_READ_ATTRIBUTES, FILE_READ_EA,
FILE_SHARE_READ, FILE_SHARE_WRITE, FILE_TRAVERSE, FILE_WRITE_ATTRIBUTES,
FILE_WRITE_EA,
},
};
use windows_sys::Win32::System::WindowsProgramming::FILE_EXISTS;

// Encode name.
let mut name: Vec<u16> = name.encode_utf16().collect();
Expand Down Expand Up @@ -255,7 +255,7 @@ impl HostFile {
null_mut(),
FILE_ATTRIBUTE_DIRECTORY,
FILE_SHARE_READ | FILE_SHARE_WRITE,
FILE_CREATE,
FILE_OPEN,
FILE_DIRECTORY_FILE,
null_mut(),
0,
Expand Down Expand Up @@ -344,7 +344,8 @@ impl HostFile {
use std::ptr::null_mut;
use windows_sys::Wdk::Foundation::OBJECT_ATTRIBUTES;
use windows_sys::Wdk::Storage::FileSystem::{
NtCreateFile, FILE_NON_DIRECTORY_FILE, FILE_OPEN, FILE_RANDOM_ACCESS,
NtCreateFile, FILE_DIRECTORY_FILE, FILE_NON_DIRECTORY_FILE, FILE_OPEN,
FILE_RANDOM_ACCESS,
};
use windows_sys::Win32::Foundation::{
RtlNtStatusToDosError, STATUS_SUCCESS, UNICODE_STRING,
Expand Down Expand Up @@ -394,10 +395,30 @@ impl HostFile {
if err == STATUS_SUCCESS {
Ok(handle)
} else {
// TODO: Check if file is a directory.
Err(Error::from_raw_os_error(unsafe {
RtlNtStatusToDosError(err).try_into().unwrap()
}))
// Try open as a directory.
let err = unsafe {
NtCreateFile(
&mut handle,
DELETE | FILE_GENERIC_READ | FILE_GENERIC_WRITE,
&mut attr,
&mut status,
null_mut(),
0,
0,
FILE_OPEN,
FILE_DIRECTORY_FILE,
null_mut(),
0,
)
};

if err == STATUS_SUCCESS {
Ok(handle)
} else {
Err(Error::from_raw_os_error(unsafe {
RtlNtStatusToDosError(err).try_into().unwrap()
}))
}
}
}
}
Expand Down
4 changes: 3 additions & 1 deletion src/kernel/src/fs/host/vnode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,10 @@ impl crate::fs::VnodeBackend for VnodeBackend {
return Err(Box::new(LookupError::InvalidName));
}

let host_file = self.file.open(name).map_err(LookupError::OpenFailed)?;

// Lookup the file.
Cow::Owned(self.file.open(name).map_err(LookupError::OpenFailed)?)
Cow::Owned(host_file)
}
};

Expand Down
2 changes: 1 addition & 1 deletion src/kernel/src/fs/null/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use super::{
Filesystem, Fs, FsConfig, LookupError, Mount, MountFlags, MountOpts, MountSource, VPathBuf,
Vnode,
};
use crate::errno::{Errno, EDEADLK, EOPNOTSUPP};
use crate::errno::{Errno, EOPNOTSUPP};
use crate::ucred::Ucred;
use macros::Errno;
use std::sync::Arc;
Expand Down
41 changes: 14 additions & 27 deletions src/kernel/src/time/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,8 @@ impl From<TimeVal> for TimeSpec {

#[repr(C)]
struct TimeVal {
sec: i64, // tv_sec
usec: i64, // tv_usec
sec: i64, // tv_sec (seconds)
usec: i64, // tv_usec (microseconds)
}

impl TimeVal {
Expand All @@ -88,37 +88,24 @@ impl TimeVal {
#[cfg(windows)]
fn microtime() -> Result<Self, MicroTimeError> {
use std::mem::MaybeUninit;
use windows_sys::Win32::System::{
SystemInformation::GetSystemTime, Time::SystemTimeToFileTime,
};
use windows_sys::Win32::System::SystemInformation::GetSystemTimePreciseAsFileTime;

// The number of hundreds of nanoseconds between the Windows epoch (1601-01-01T00:00:00Z)
// and the Unix epoch (1970-01-01T00:00:00Z)
const EPOCH: u64 = 116444736000000000;
let mut file_time = MaybeUninit::uninit();

let mut system_time = MaybeUninit::uninit();
let mut filetime = MaybeUninit::uninit();

let (system_time, filetime) = unsafe {
GetSystemTime(system_time.as_mut_ptr());
let res = SystemTimeToFileTime(system_time.as_ptr(), filetime.as_mut_ptr());

if res == 0 {
Err(std::io::Error::last_os_error())?
}
unsafe {
GetSystemTimePreciseAsFileTime(file_time.as_mut_ptr());
}

(system_time.assume_init(), filetime.assume_init())
};
let file_time = unsafe { file_time.assume_init() };

let mut time = 0;
let intervals = (file_time.dwHighDateTime as u64) << 32 | file_time.dwLowDateTime as u64;

time += filetime.dwLowDateTime as u64;
time += (filetime.dwHighDateTime as u64) << 32;
let sec = (intervals / 10_000_000 - 11_644_473_600)
.try_into()
.unwrap();
let usec = (intervals % 10_000_000).try_into().unwrap();

Ok(Self {
sec: ((time - EPOCH) / 10_000_000) as i64,
usec: (system_time.wMilliseconds * 1000) as i64,
})
Ok(Self { sec, usec })
}
}

Expand Down

0 comments on commit 2ca7ebe

Please sign in to comment.