alnyan/yggdrasil: implement most of directory/fileattr

This commit is contained in:
2023-07-22 16:21:07 +03:00
parent f3735a19c6
commit 19819a25a2
3 changed files with 114 additions and 59 deletions
+52 -21
View File
@@ -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) })
})
}
+51 -38
View File
@@ -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> {
+11
View File
@@ -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),