unix: reduce the size of DirEntry
On platforms where we call `readdir` instead of `readdir_r`, we store the name as an allocated `CString` for variable length. There's no point carrying around a full `dirent64` with its fixed-length `d_name` too.
This commit is contained in:
parent
64187b8374
commit
e8b9ba84be
1 changed files with 47 additions and 10 deletions
|
@ -228,12 +228,6 @@ struct Dir(*mut libc::DIR);
|
|||
unsafe impl Send for Dir {}
|
||||
unsafe impl Sync for Dir {}
|
||||
|
||||
pub struct DirEntry {
|
||||
entry: dirent64,
|
||||
dir: Arc<InnerReadDir>,
|
||||
// We need to store an owned copy of the entry name on platforms that use
|
||||
// readdir() (not readdir_r()), because a) struct dirent may use a flexible
|
||||
// array to store the name, b) it lives only until the next readdir() call.
|
||||
#[cfg(any(
|
||||
target_os = "android",
|
||||
target_os = "linux",
|
||||
|
@ -242,9 +236,46 @@ pub struct DirEntry {
|
|||
target_os = "fuchsia",
|
||||
target_os = "redox"
|
||||
))]
|
||||
pub struct DirEntry {
|
||||
dir: Arc<InnerReadDir>,
|
||||
entry: dirent64_min,
|
||||
// We need to store an owned copy of the entry name on platforms that use
|
||||
// readdir() (not readdir_r()), because a) struct dirent may use a flexible
|
||||
// array to store the name, b) it lives only until the next readdir() call.
|
||||
name: CString,
|
||||
}
|
||||
|
||||
// Define a minimal subset of fields we need from `dirent64`, especially since
|
||||
// we're not using the immediate `d_name` on these targets. Keeping this as an
|
||||
// `entry` field in `DirEntry` helps reduce the `cfg` boilerplate elsewhere.
|
||||
#[cfg(any(
|
||||
target_os = "android",
|
||||
target_os = "linux",
|
||||
target_os = "solaris",
|
||||
target_os = "illumos",
|
||||
target_os = "fuchsia",
|
||||
target_os = "redox"
|
||||
))]
|
||||
struct dirent64_min {
|
||||
d_ino: u64,
|
||||
#[cfg(not(any(target_os = "solaris", target_os = "illumos")))]
|
||||
d_type: u8,
|
||||
}
|
||||
|
||||
#[cfg(not(any(
|
||||
target_os = "android",
|
||||
target_os = "linux",
|
||||
target_os = "solaris",
|
||||
target_os = "illumos",
|
||||
target_os = "fuchsia",
|
||||
target_os = "redox"
|
||||
)))]
|
||||
pub struct DirEntry {
|
||||
dir: Arc<InnerReadDir>,
|
||||
// The full entry includes a fixed-length `d_name`.
|
||||
entry: dirent64,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct OpenOptions {
|
||||
// generic
|
||||
|
@ -501,8 +532,14 @@ impl Iterator for ReadDir {
|
|||
let entry_name = entry_bytes.add(name_offset);
|
||||
ptr::copy_nonoverlapping(entry_bytes, copy_bytes, name_offset);
|
||||
|
||||
let entry = dirent64_min {
|
||||
d_ino: copy.d_ino as u64,
|
||||
#[cfg(not(any(target_os = "solaris", target_os = "illumos")))]
|
||||
d_type: copy.d_type as u8,
|
||||
};
|
||||
|
||||
let ret = DirEntry {
|
||||
entry: copy,
|
||||
entry,
|
||||
// d_name is guaranteed to be null-terminated.
|
||||
name: CStr::from_ptr(entry_name as *const _).to_owned(),
|
||||
dir: Arc::clone(&self.inner),
|
||||
|
|
Loading…
Add table
Reference in a new issue