use core::ffi::CStr;
use super::{OpenMode, sys_flen, sys_open, sys_seek};
pub(crate) use super::{sys_remove as unlink, sys_rename as rename};
use crate::{
fd::{BorrowedFd, OwnedFd},
fs, io,
};
pub(crate) struct Metadata {
size: u64,
}
impl Metadata {
#[inline]
pub(crate) fn size(&self) -> u64 {
self.size
}
}
pub(crate) fn metadata(fd: BorrowedFd<'_>) -> io::Result<Metadata> {
Ok(Metadata { size: sys_flen(fd)? as u64 })
}
pub(crate) fn open(path: &CStr, options: &fs::OpenOptions) -> io::Result<OwnedFd> {
match (options.write, options.append) {
(true, false) => {}
(false, false) => {
if options.truncate || options.create {
return Err(io::Error::EINVAL);
}
}
(_, true) => {
if options.truncate {
return Err(io::Error::EINVAL);
}
}
}
let mode = match (options.read, options.write, options.append, options.create, options.truncate)
{
(true, false, false, false, false) => OpenMode::RDONLY_BINARY,
(true, true, false, false, false) => OpenMode::RDWR_BINARY,
(false, true, false, true, true) => OpenMode::WRONLY_TRUNC_BINARY,
(true, true, false, true, true) => OpenMode::RDWR_TRUNC_BINARY,
(false, true, true, true, false) => OpenMode::WRONLY_APPEND_BINARY,
(true, true, true, true, false) => OpenMode::RDWR_APPEND_BINARY,
_ => return Err(io::Error::UNSUPPORTED_PLATFORM),
};
sys_open(path, mode)
}
#[allow(clippy::cast_possible_wrap, clippy::cast_sign_loss)]
pub(crate) fn seek(fd: BorrowedFd<'_>, pos: io::SeekFrom) -> io::Result<u64> {
let abs_pos = match pos {
io::SeekFrom::Start(pos) => pos,
io::SeekFrom::End(offset) => {
let len = sys_flen(fd)? as u64;
let pos = (len as i64).saturating_add(offset);
if pos.is_negative() {
return Err(io::Error::EINVAL);
}
pos as u64
} };
let abs_pos = isize::try_from(abs_pos).map_err(|_| io::Error::EINVAL)?;
unsafe { sys_seek(fd, abs_pos as usize)? }
Ok(abs_pos as u64)
}