alnyan/yggdrasil: implement most of directory/fileattr
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
use yggdrasil_rt::io::DirectoryEntry as OsDirectoryEntry;
|
||||
use yggdrasil_rt::io::{DirectoryEntry as OsDirectoryEntry, FileMode as OsFileMode};
|
||||
|
||||
use crate::ffi::OsString;
|
||||
use crate::fmt;
|
||||
@@ -8,8 +8,8 @@ use crate::os::yggdrasil::io::{AsRawFd, FromRawFd};
|
||||
use crate::path::{Path, PathBuf};
|
||||
use crate::str::FromStr;
|
||||
use crate::sys::fd::FileDesc;
|
||||
use crate::sys::yggdrasil::cvt_io;
|
||||
use crate::sys::yggdrasil::fs::{FileAttr, FileType};
|
||||
use crate::sys::yggdrasil::fs::{get_metadata_inner, FileAttr, FileType};
|
||||
use crate::sys::yggdrasil::{cvt_io, run_with_path_str};
|
||||
|
||||
pub struct DirEntry {
|
||||
filename: OsString,
|
||||
@@ -20,18 +20,27 @@ pub struct DirEntry {
|
||||
pub struct ReadDir {
|
||||
fd: FileDesc,
|
||||
path: PathBuf,
|
||||
// TODO fetch more entries at a time
|
||||
buffer: Option<OsDirectoryEntry>,
|
||||
eof: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct DirBuilder {}
|
||||
pub struct DirBuilder {
|
||||
mode: OsFileMode,
|
||||
}
|
||||
|
||||
impl ReadDir {
|
||||
fn open(path: &Path) -> io::Result<Self> {
|
||||
let path_buf = PathBuf::from(path);
|
||||
let path_str = path.to_str().unwrap();
|
||||
let fd = cvt_io(unsafe { yggdrasil_rt::sys::open_directory(None, path_str) })?;
|
||||
Ok(ReadDir { fd: unsafe { FileDesc::from_raw_fd(fd) }, buffer: None, path: path_buf })
|
||||
Ok(ReadDir {
|
||||
fd: unsafe { FileDesc::from_raw_fd(fd) },
|
||||
buffer: None,
|
||||
path: path_buf,
|
||||
eof: false,
|
||||
})
|
||||
}
|
||||
|
||||
fn fill_buffer(&mut self) -> io::Result<()> {
|
||||
@@ -47,6 +56,8 @@ impl ReadDir {
|
||||
assert!(count <= 1);
|
||||
if count == 1 {
|
||||
self.buffer.replace(unsafe { readbuf[0].assume_init() });
|
||||
} else {
|
||||
self.eof = true;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@@ -57,20 +68,34 @@ impl Iterator for ReadDir {
|
||||
type Item = io::Result<DirEntry>;
|
||||
|
||||
fn next(&mut self) -> Option<io::Result<DirEntry>> {
|
||||
if let Err(e) = self.fill_buffer() {
|
||||
return Some(Err(e));
|
||||
if self.eof {
|
||||
return None;
|
||||
}
|
||||
|
||||
// buffer should have an entry by now
|
||||
let entry = self.buffer.take();
|
||||
loop {
|
||||
if let Err(e) = self.fill_buffer() {
|
||||
break Some(Err(e));
|
||||
}
|
||||
|
||||
entry.map(|e| Ok(DirEntry::from_raw(self.path.clone(), &e)))
|
||||
// buffer should have an entry by now
|
||||
let entry = self.buffer.take();
|
||||
|
||||
break if let Some(entry) = entry {
|
||||
if &entry.name[..2] == b".\0" || &entry.name[..3] == b"..\0" {
|
||||
continue;
|
||||
}
|
||||
|
||||
Some(Ok(DirEntry::from_raw(self.path.clone(), &entry)))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for ReadDir {
|
||||
fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
todo!()
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt::Debug::fmt(&*self.path, f)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,7 +118,7 @@ impl DirEntry {
|
||||
}
|
||||
|
||||
pub fn metadata(&self) -> io::Result<FileAttr> {
|
||||
todo!()
|
||||
run_with_path_str(self.path.as_ref(), |path_str| get_metadata_inner(None, path_str, false))
|
||||
}
|
||||
|
||||
pub fn file_type(&self) -> io::Result<FileType> {
|
||||
@@ -102,12 +127,14 @@ impl DirEntry {
|
||||
}
|
||||
|
||||
impl DirBuilder {
|
||||
pub fn new() -> DirBuilder {
|
||||
todo!()
|
||||
pub fn new() -> Self {
|
||||
Self { mode: OsFileMode::default_dir() }
|
||||
}
|
||||
|
||||
pub fn mkdir(&self, _p: &Path) -> io::Result<()> {
|
||||
todo!()
|
||||
pub fn mkdir(&self, path: &Path) -> io::Result<()> {
|
||||
run_with_path_str(path, |path_str| {
|
||||
cvt_io(unsafe { yggdrasil_rt::sys::create_directory(None, path_str, self.mode) })
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -115,10 +142,14 @@ pub fn readdir(path: &Path) -> io::Result<ReadDir> {
|
||||
ReadDir::open(path)
|
||||
}
|
||||
|
||||
pub fn rmdir(_p: &Path) -> io::Result<()> {
|
||||
todo!()
|
||||
pub fn rmdir(path: &Path) -> io::Result<()> {
|
||||
run_with_path_str(path, |path_str| {
|
||||
cvt_io(unsafe { yggdrasil_rt::sys::remove(None, path_str, false) })
|
||||
})
|
||||
}
|
||||
|
||||
pub fn remove_dir_all(_p: &Path) -> io::Result<()> {
|
||||
todo!()
|
||||
pub fn remove_dir_all(path: &Path) -> io::Result<()> {
|
||||
run_with_path_str(path, |path_str| {
|
||||
cvt_io(unsafe { yggdrasil_rt::sys::remove(None, path_str, true) })
|
||||
})
|
||||
}
|
||||
|
||||
@@ -3,8 +3,11 @@ use crate::hash::Hash;
|
||||
use crate::io;
|
||||
use crate::path::{Path, PathBuf};
|
||||
use crate::sys::time::SystemTime;
|
||||
use crate::sys::{cvt_io, run_with_path_str};
|
||||
|
||||
use yggdrasil_rt::io::FileType as OsFileType;
|
||||
use yggdrasil_rt::io::{
|
||||
FileAttr as OsFileAttr, FileMode as OsFileMode, FileType as OsFileType, RawFd as OsRawFd,
|
||||
};
|
||||
|
||||
mod dir;
|
||||
mod file;
|
||||
@@ -12,10 +15,13 @@ mod file;
|
||||
pub use dir::{readdir, remove_dir_all, rmdir, DirBuilder, DirEntry, ReadDir};
|
||||
pub use file::{File, OpenOptions};
|
||||
|
||||
pub struct FileAttr(!);
|
||||
pub struct FilePermissions(!);
|
||||
#[derive(Clone, Copy, PartialEq, Debug)]
|
||||
pub struct FileAttr(OsFileAttr);
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
|
||||
#[derive(Clone, Copy, PartialEq, Eq)]
|
||||
pub struct FilePermissions(OsFileMode);
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub struct FileType(OsFileType);
|
||||
|
||||
#[derive(Copy, Clone, Debug, Default)]
|
||||
@@ -23,33 +29,36 @@ pub struct FileTimes {}
|
||||
|
||||
impl FileAttr {
|
||||
pub fn size(&self) -> u64 {
|
||||
todo!()
|
||||
self.0.size
|
||||
}
|
||||
|
||||
pub fn perm(&self) -> FilePermissions {
|
||||
todo!()
|
||||
FilePermissions(self.0.mode)
|
||||
}
|
||||
|
||||
pub fn file_type(&self) -> FileType {
|
||||
todo!()
|
||||
FileType(self.0.ty)
|
||||
}
|
||||
|
||||
pub fn modified(&self) -> io::Result<SystemTime> {
|
||||
todo!()
|
||||
Err(crate::io::const_io_error!(
|
||||
crate::io::ErrorKind::Unsupported,
|
||||
"feature not implemented"
|
||||
))
|
||||
}
|
||||
|
||||
pub fn accessed(&self) -> io::Result<SystemTime> {
|
||||
todo!()
|
||||
Err(crate::io::const_io_error!(
|
||||
crate::io::ErrorKind::Unsupported,
|
||||
"feature not implemented"
|
||||
))
|
||||
}
|
||||
|
||||
pub fn created(&self) -> io::Result<SystemTime> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for FileAttr {
|
||||
fn clone(&self) -> Self {
|
||||
todo!()
|
||||
Err(crate::io::const_io_error!(
|
||||
crate::io::ErrorKind::Unsupported,
|
||||
"feature not implemented"
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,23 +72,9 @@ impl FilePermissions {
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for FilePermissions {
|
||||
fn clone(&self) -> Self {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for FilePermissions {
|
||||
fn eq(&self, _other: &Self) -> bool {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for FilePermissions {}
|
||||
|
||||
impl fmt::Debug for FilePermissions {
|
||||
fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
todo!()
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt::Debug::fmt(&self.0.bits(), f)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,6 +92,12 @@ impl FileType {
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for FileType {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt::Debug::fmt(&self.0, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl FileTimes {
|
||||
pub fn set_accessed(&mut self, _t: SystemTime) {
|
||||
todo!()
|
||||
@@ -107,8 +108,20 @@ impl FileTimes {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn unlink(_p: &Path) -> io::Result<()> {
|
||||
todo!()
|
||||
pub(self) fn get_metadata_inner(
|
||||
at: Option<OsRawFd>,
|
||||
path: &str,
|
||||
follow: bool,
|
||||
) -> io::Result<FileAttr> {
|
||||
let mut metadata = crate::mem::MaybeUninit::uninit();
|
||||
cvt_io(unsafe { yggdrasil_rt::sys::get_metadata(at, path, &mut metadata, follow) })?;
|
||||
Ok(unsafe { FileAttr(metadata.assume_init()) })
|
||||
}
|
||||
|
||||
pub fn unlink(path: &Path) -> io::Result<()> {
|
||||
run_with_path_str(path, |path_str| {
|
||||
cvt_io(unsafe { yggdrasil_rt::sys::remove(None, path_str, false) })
|
||||
})
|
||||
}
|
||||
|
||||
pub fn rename(_old: &Path, _new: &Path) -> io::Result<()> {
|
||||
@@ -131,12 +144,12 @@ pub fn link(_original: &Path, _link: &Path) -> io::Result<()> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
pub fn stat(_p: &Path) -> io::Result<FileAttr> {
|
||||
todo!()
|
||||
pub fn stat(path: &Path) -> io::Result<FileAttr> {
|
||||
run_with_path_str(path, |path_str| get_metadata_inner(None, path_str, true))
|
||||
}
|
||||
|
||||
pub fn lstat(_p: &Path) -> io::Result<FileAttr> {
|
||||
todo!()
|
||||
pub fn lstat(path: &Path) -> io::Result<FileAttr> {
|
||||
run_with_path_str(path, |path_str| get_metadata_inner(None, path_str, false))
|
||||
}
|
||||
|
||||
pub fn canonicalize(_p: &Path) -> io::Result<PathBuf> {
|
||||
|
||||
@@ -32,6 +32,8 @@ pub(self) use yggdrasil_rt;
|
||||
|
||||
use yggdrasil_rt::Error as OsError;
|
||||
|
||||
use crate::path::Path;
|
||||
|
||||
#[doc(hidden)]
|
||||
pub trait IsNegative {
|
||||
fn is_negative(&self) -> bool;
|
||||
@@ -94,9 +96,18 @@ fn cvt_io_err(e: OsError) -> crate::io::Error {
|
||||
OsError::NotADirectory => {
|
||||
crate::io::const_io_error!(ErrorKind::NotADirectory, "not a directory")
|
||||
}
|
||||
OsError::DirectoryNotEmpty => {
|
||||
crate::io::const_io_error!(ErrorKind::DirectoryNotEmpty, "directory is not empty")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn run_with_path_str<T, F: FnOnce(&str) -> T>(path: &Path, f: F) -> T {
|
||||
let path_str = path.to_str().unwrap();
|
||||
f(path_str)
|
||||
}
|
||||
|
||||
pub fn cvt_io<T>(t: Result<T, OsError>) -> crate::io::Result<T> {
|
||||
match t {
|
||||
Ok(t) => Ok(t),
|
||||
|
||||
Reference in New Issue
Block a user