Skip to content

Commit 163c207

Browse files
committed
Auto merge of #94750 - cuviper:dirent64_min, r=joshtriplett
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.
2 parents 803a759 + e8b9ba8 commit 163c207

File tree

1 file changed

+47
-10
lines changed
  • library/std/src/sys/unix

1 file changed

+47
-10
lines changed

library/std/src/sys/unix/fs.rs

+47-10
Original file line numberDiff line numberDiff line change
@@ -228,23 +228,54 @@ struct Dir(*mut libc::DIR);
228228
unsafe impl Send for Dir {}
229229
unsafe impl Sync for Dir {}
230230

231+
#[cfg(any(
232+
target_os = "android",
233+
target_os = "linux",
234+
target_os = "solaris",
235+
target_os = "illumos",
236+
target_os = "fuchsia",
237+
target_os = "redox"
238+
))]
231239
pub struct DirEntry {
232-
entry: dirent64,
233240
dir: Arc<InnerReadDir>,
241+
entry: dirent64_min,
234242
// We need to store an owned copy of the entry name on platforms that use
235243
// readdir() (not readdir_r()), because a) struct dirent may use a flexible
236244
// array to store the name, b) it lives only until the next readdir() call.
237-
#[cfg(any(
238-
target_os = "android",
239-
target_os = "linux",
240-
target_os = "solaris",
241-
target_os = "illumos",
242-
target_os = "fuchsia",
243-
target_os = "redox"
244-
))]
245245
name: CString,
246246
}
247247

248+
// Define a minimal subset of fields we need from `dirent64`, especially since
249+
// we're not using the immediate `d_name` on these targets. Keeping this as an
250+
// `entry` field in `DirEntry` helps reduce the `cfg` boilerplate elsewhere.
251+
#[cfg(any(
252+
target_os = "android",
253+
target_os = "linux",
254+
target_os = "solaris",
255+
target_os = "illumos",
256+
target_os = "fuchsia",
257+
target_os = "redox"
258+
))]
259+
struct dirent64_min {
260+
d_ino: u64,
261+
#[cfg(not(any(target_os = "solaris", target_os = "illumos")))]
262+
d_type: u8,
263+
}
264+
265+
#[cfg(not(any(
266+
target_os = "android",
267+
target_os = "linux",
268+
target_os = "solaris",
269+
target_os = "illumos",
270+
target_os = "fuchsia",
271+
target_os = "redox"
272+
)))]
273+
pub struct DirEntry {
274+
dir: Arc<InnerReadDir>,
275+
// The full entry includes a fixed-length `d_name`.
276+
entry: dirent64,
277+
}
278+
248279
#[derive(Clone, Debug)]
249280
pub struct OpenOptions {
250281
// generic
@@ -501,8 +532,14 @@ impl Iterator for ReadDir {
501532
let entry_name = entry_bytes.add(name_offset);
502533
ptr::copy_nonoverlapping(entry_bytes, copy_bytes, name_offset);
503534

535+
let entry = dirent64_min {
536+
d_ino: copy.d_ino as u64,
537+
#[cfg(not(any(target_os = "solaris", target_os = "illumos")))]
538+
d_type: copy.d_type as u8,
539+
};
540+
504541
let ret = DirEntry {
505-
entry: copy,
542+
entry,
506543
// d_name is guaranteed to be null-terminated.
507544
name: CStr::from_ptr(entry_name as *const _).to_owned(),
508545
dir: Arc::clone(&self.inner),

0 commit comments

Comments
 (0)