pub struct RawDir<'buf, Fd: AsFd> { /* private fields */ }
Expand description
A directory iterator implemented with getdents.
Note: This implementation does not handle growing the buffer. If this
functionality is necessary, you’ll need to drop the current iterator,
resize the buffer, and then re-create the iterator. The iterator is
guaranteed to continue where it left off provided the file descriptor isn’t
changed. See the example in RawDir::new
.
Implementations§
source§impl<'buf, Fd: AsFd> RawDir<'buf, Fd>
impl<'buf, Fd: AsFd> RawDir<'buf, Fd>
sourcepub fn new(fd: Fd, buf: &'buf mut [MaybeUninit<u8>]) -> Self
pub fn new(fd: Fd, buf: &'buf mut [MaybeUninit<u8>]) -> Self
Create a new iterator from the given file descriptor and buffer.
Note: the buffer size may be trimmed to accommodate alignment requirements.
Examples
Simple but non-portable
These examples are non-portable, because file systems may not have a maximum file name length. If you can make assumptions that bound this length, then these examples may suffice.
Using the heap:
let fd = openat(
CWD,
cstr!("."),
OFlags::RDONLY | OFlags::DIRECTORY | OFlags::CLOEXEC,
Mode::empty(),
)
.unwrap();
let mut buf = Vec::with_capacity(8192);
let mut iter = RawDir::new(fd, buf.spare_capacity_mut());
while let Some(entry) = iter.next() {
let entry = entry.unwrap();
dbg!(&entry);
}
Using the stack:
let fd = openat(
CWD,
cstr!("."),
OFlags::RDONLY | OFlags::DIRECTORY | OFlags::CLOEXEC,
Mode::empty(),
)
.unwrap();
let mut buf = [MaybeUninit::uninit(); 2048];
let mut iter = RawDir::new(fd, &mut buf);
while let Some(entry) = iter.next() {
let entry = entry.unwrap();
dbg!(&entry);
}
Portable
Heap allocated growing buffer for supporting directory entries with arbitrarily large file names:
# // The `notrust` above can be removed when we can depend on Rust 1.65.
# use std::mem::MaybeUninit;
# use rustix::fs::{CWD, Mode, OFlags, openat, RawDir};
# use rustix::io::Errno;
# use rustix::cstr;
let fd = openat(
CWD,
cstr!("."),
OFlags::RDONLY | OFlags::DIRECTORY | OFlags::CLOEXEC,
Mode::empty(),
)
.unwrap();
let mut buf = Vec::with_capacity(8192);
'read: loop {
'resize: {
let mut iter = RawDir::new(&fd, buf.spare_capacity_mut());
while let Some(entry) = iter.next() {
let entry = match entry {
Err(Errno::INVAL) => break 'resize,
r => r.unwrap(),
};
dbg!(&entry);
}
break 'read;
}
let new_capacity = buf.capacity() * 2;
buf.reserve(new_capacity);
}
source§impl<'buf, Fd: AsFd> RawDir<'buf, Fd>
impl<'buf, Fd: AsFd> RawDir<'buf, Fd>
sourcepub fn next(&mut self) -> Option<Result<RawDirEntry<'_>>>
pub fn next(&mut self) -> Option<Result<RawDirEntry<'_>>>
Identical to Iterator::next
except that Iterator::Item
borrows
from self.
Note: this interface will be broken to implement a stdlib iterator API with GAT support once one becomes available.
sourcepub fn is_buffer_empty(&self) -> bool
pub fn is_buffer_empty(&self) -> bool
Returns true if the internal buffer is empty and will be refilled when
calling next
.