use core::{ffi::CStr, mem::offset_of};
extern crate alloc;
use alloc::string::{String, ToString};
use crate::{ErrorKind, OrtResult, ort_error, syscall};
pub struct DirFiles {
fd: i32,
buf: [u8; 4096],
pos: usize,
len: usize,
}
impl DirFiles {
pub fn new(p: &CStr) -> OrtResult<Self> {
let fd = syscall::open(p.as_ptr(), syscall::O_RDONLY | syscall::O_DIRECTORY, 0)
.map_err(|_| ort_error(ErrorKind::DirOpenFailed, "open returned error"))?;
Ok(DirFiles {
fd,
buf: [0; 4096],
pos: 0,
len: 0,
})
}
}
impl Iterator for DirFiles {
type Item = String;
fn next(&mut self) -> Option<Self::Item> {
loop {
if self.pos == self.len {
let bytes_read =
syscall::getdents64(self.fd, self.buf.as_mut_ptr().cast(), self.buf.len());
if bytes_read <= 0 {
return None;
}
self.pos = 0;
self.len = bytes_read as usize;
}
let entry_ptr = unsafe { self.buf.as_ptr().add(self.pos) };
let entry = unsafe { &*(entry_ptr as *const syscall::linux_dirent64) };
let reclen = entry.d_reclen as usize;
if reclen == 0 || self.pos + reclen > self.len {
return None;
}
self.pos += reclen;
if entry.d_type != syscall::DT_REG {
continue;
}
let name_ptr = unsafe {
entry_ptr
.add(offset_of!(syscall::linux_dirent64, d_name))
.cast()
};
let s = unsafe { CStr::from_ptr(name_ptr) }
.to_string_lossy()
.to_string();
return Some(s);
}
}
}
impl Drop for DirFiles {
fn drop(&mut self) {
let _ = syscall::close(self.fd);
}
}