Skip to content

Commit 7f32ba1

Browse files
Gavin-Niedermanmax-niederman
authored andcommitted
feat: almost working directory reading
1 parent c0cc793 commit 7f32ba1

File tree

1 file changed

+80
-24
lines changed
  • library/std/src/sys/pal/vexos

1 file changed

+80
-24
lines changed

library/std/src/sys/pal/vexos/fs.rs

Lines changed: 80 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,18 @@ pub struct File {
1717
#[derive(Clone)]
1818
pub struct FileAttr {
1919
size: u64,
20+
is_dir: bool,
2021
}
2122

22-
pub struct ReadDir(!);
23+
#[derive(Debug)]
24+
pub struct ReadDir {
25+
entries: Vec<DirEntry>,
26+
}
2327

24-
pub struct DirEntry(!);
28+
#[derive(Debug)]
29+
pub struct DirEntry {
30+
path: PathBuf,
31+
}
2532

2633
#[derive(Clone, Debug)]
2734
pub struct OpenOptions {
@@ -52,9 +59,31 @@ impl FileAttr {
5259
let size = unsafe { vex_sdk::vexFileSize(fd) };
5360

5461
if size >= 0 {
55-
Ok(Self { size: size as u64 })
62+
Ok(Self { size: size as u64, is_dir: false })
63+
} else {
64+
Err(io::Error::new(io::ErrorKind::InvalidData, "Failed to get file size"))
65+
}
66+
}
67+
68+
fn from_path(path: &Path) -> io::Result<Self> {
69+
let c_path = CString::new(path.as_os_str().as_encoded_bytes()).map_err(|_| {
70+
io::Error::new(io::ErrorKind::InvalidData, "Path contained a null byte")
71+
})?;
72+
73+
let file_type = unsafe { vex_sdk::vexFileStatus(c_path.as_ptr()) };
74+
let is_dir = file_type == 3;
75+
println!("{is_dir}");
76+
77+
// We can't get the size if its a directory because we cant open it as a file
78+
if is_dir {
79+
Ok(Self { size: 0, is_dir: true })
5680
} else {
57-
Err(io::Error::new(io::ErrorKind::NotSeekable, "Failed to seek file"))
81+
let mut opts = OpenOptions::new();
82+
opts.read(true);
83+
let file = File::open(path, &opts)?;
84+
let fd = file.fd.0;
85+
86+
Self::from_fd(fd)
5887
}
5988
}
6089

@@ -67,7 +96,7 @@ impl FileAttr {
6796
}
6897

6998
pub fn file_type(&self) -> FileType {
70-
FileType { is_dir: false }
99+
FileType { is_dir: self.is_dir }
71100
}
72101

73102
pub fn modified(&self) -> io::Result<SystemTime> {
@@ -112,35 +141,32 @@ impl FileType {
112141
}
113142
}
114143

115-
impl fmt::Debug for ReadDir {
116-
fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
117-
self.0
118-
}
119-
}
120-
121144
impl Iterator for ReadDir {
122145
type Item = io::Result<DirEntry>;
123146

124147
fn next(&mut self) -> Option<io::Result<DirEntry>> {
125-
self.0
148+
self.entries.pop().map(Ok)
126149
}
127150
}
128151

129152
impl DirEntry {
130153
pub fn path(&self) -> PathBuf {
131-
self.0
154+
self.path.clone()
132155
}
133156

134157
pub fn file_name(&self) -> OsString {
135-
self.0
158+
self.path
159+
.file_name()
160+
.unwrap_or(crate::ffi::OsStr::new(""))
161+
.to_os_string()
136162
}
137163

138164
pub fn metadata(&self) -> io::Result<FileAttr> {
139-
self.0
165+
stat(&self.path)
140166
}
141167

142168
pub fn file_type(&self) -> io::Result<FileType> {
143-
self.0
169+
Ok(self.metadata()?.file_type())
144170
}
145171
}
146172

@@ -406,8 +432,43 @@ impl Drop for File {
406432
}
407433
}
408434

409-
pub fn readdir(_p: &Path) -> io::Result<ReadDir> {
410-
todo!()
435+
pub fn readdir(p: &Path) -> io::Result<ReadDir> {
436+
if !stat(p)?.file_type().is_dir() {
437+
return Err(io::Error::new(io::ErrorKind::InvalidInput, "Given directory was not a path"));
438+
}
439+
440+
// getting directory entries does not work with trailing slashes
441+
let path = p
442+
.to_str()
443+
.ok_or(io::Error::new(io::ErrorKind::InvalidInput, "Path contained invalid characters"))?
444+
.trim_end_matches("/");
445+
let path = CString::new(path.as_bytes())
446+
.map_err(|_| io::Error::new(io::ErrorKind::InvalidInput, "Path contained a null byte"))?;
447+
448+
//TODO: Figure out if there is any way to check the number of entries in a directory/the needed length
449+
let mut filenames_buffer = [0u8; 1000];
450+
unsafe {
451+
vex_sdk::vexFileDirectoryGet(
452+
path.as_ptr(),
453+
filenames_buffer.as_mut_ptr().cast(),
454+
filenames_buffer.len() as _,
455+
);
456+
}
457+
let filenames_buffer = filenames_buffer.to_vec();
458+
// stop at null-terminator
459+
let filenames = match filenames_buffer.split(|&e| e == 0).next() {
460+
Some(filenames) => filenames,
461+
None => &filenames_buffer
462+
};
463+
let filenames = String::from_utf8(filenames.to_vec()).map_err(|_| io::Error::new(io::ErrorKind::InvalidData, "Path contained a null byte"))?;
464+
let paths = filenames.split('\n').map(|filename| {
465+
let mut path = PathBuf::new();
466+
path.push(p);
467+
path.push(filename);
468+
DirEntry { path }
469+
}).collect::<Vec<_>>();
470+
471+
Ok(ReadDir { entries: paths })
411472
}
412473

413474
pub fn unlink(_p: &Path) -> io::Result<()> {
@@ -451,12 +512,7 @@ pub fn link(_src: &Path, _dst: &Path) -> io::Result<()> {
451512
}
452513

453514
pub fn stat(p: &Path) -> io::Result<FileAttr> {
454-
let mut opts = OpenOptions::new();
455-
opts.read(true);
456-
let file = File::open(p, &opts)?;
457-
let fd = file.fd.0;
458-
459-
FileAttr::from_fd(fd)
515+
FileAttr::from_path(p)
460516
}
461517

462518
pub fn lstat(p: &Path) -> io::Result<FileAttr> {

0 commit comments

Comments
 (0)