use core::ffi::{CStr, c_char, c_int, c_void};
use core::mem::MaybeUninit;
extern crate alloc;
use crate::common::time;
use crate::{ErrorKind, OrtResult, Read, Write, libc, ort_error};
pub struct File {
fd: c_int,
}
impl File {
pub unsafe fn create(path: &[u8]) -> OrtResult<Self> {
let flags = libc::O_CLOEXEC | libc::O_WRONLY | libc::O_CREAT | libc::O_TRUNC;
let fd = unsafe { libc::open64(path.as_ptr() as *const c_char, flags, 0o660 as c_int) };
if fd == -1 {
return Err(ort_error(ErrorKind::FileCreateFailed, "open64 failed"));
}
Ok(File { fd })
}
}
impl Read for File {
fn read(&mut self, buf: &mut [u8]) -> OrtResult<usize> {
let bytes_read = unsafe { libc::read(self.fd, buf.as_mut_ptr() as *mut c_void, buf.len()) };
if bytes_read < 0 {
Err(ort_error(ErrorKind::FileReadFailed, "syscall read error"))
} else {
Ok(bytes_read as usize)
}
}
}
impl Write for File {
fn write(&mut self, buf: &[u8]) -> OrtResult<usize> {
let bytes_written =
unsafe { libc::write(self.fd, buf.as_ptr() as *const c_void, buf.len()) };
if bytes_written < 0 {
Err(ort_error(ErrorKind::FileWriteFailed, "syscall write error"))
} else {
Ok(bytes_written as usize)
}
}
fn flush(&mut self) -> OrtResult<()> {
Ok(())
}
}
pub fn last_modified(path: &CStr) -> OrtResult<time::Instant> {
let mut st = MaybeUninit::<libc::stat>::uninit();
unsafe {
if libc::stat(path.as_ptr(), st.as_mut_ptr()) != 0 {
#[cfg(debug_assertions)]
libc::write(2, path.as_ptr().cast(), path.count_bytes());
return Err(ort_error(ErrorKind::FileStatFailed, ""));
}
}
let st = unsafe { st.assume_init() };
Ok(time::Instant::new(
st.st_mtime as u64,
st.st_mtime_nsec as u64,
))
}