RawDir is a low-level directory iterator implemented using the getdents system call. It allows you to iterate over directory entries (including . and ..) using a provided buffer.
Important Constraints
- Fixed Buffer Size: This implementation does not automatically grow the buffer. If the buffer is too small to hold the next entry (e.g., due to a very long filename),
next() may return an error (specifically Errno::INVAL). - Resizing Strategy: To handle arbitrarily large filenames, you must catch the error, drop the current iterator, resize your buffer, and create a new
RawDir iterator. The iterator is guaranteed to continue where it left off if the file descriptor remains the same.
Usage Patterns
Using a Heap-allocated Buffer (Simple)
This approach is suitable if you can assume a maximum filename length.
use std::mem::MaybeUninit;
use rustix::fs::{CWD, Mode, OFlags, openat, RawDir};
use rustix::cstr;
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 a Portable Growing Buffer
This pattern handles entries with arbitrarily large filenames by catching Errno::INVAL and resizing the buffer.
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);
}