use crate::DirEntryError;
///Generic result type for directory entry operations
pub type Result<T> = core::result::Result<T, DirEntryError>;
/// A buffer used to hold the bytes sent from the OS for `getdents`/`getdirentries` calls
#[cfg(any(
target_os = "linux",
target_os = "android",
target_os = "macos",
target_os = "freebsd",
target_os = "openbsd",
target_os = "netbsd",
target_os = "solaris",
target_os = "illumos"
))]
pub type SyscallBuffer = crate::fs::AlignedBuffer<u8, BUFFER_SIZE>;
/// A safe abstraction around file descriptors for internal IO
#[derive(Debug)]
#[repr(transparent)]
pub struct FileDes(pub(crate) i32);
impl FileDes {
/// Returns a borrowed reference to the underlying file descriptor.
#[must_use]
#[inline]
pub const fn as_borrowed_fd(&self) -> &i32 {
&self.0
}
/// Checks if the file descriptor is currently open
/// Returns `true` if the file descriptor is open, `false` otherwise
#[must_use]
#[inline]
pub fn is_open(&self) -> bool {
// Use fcntl with F_GETFD to check if the file descriptor is valid
// If it returns -1 with errno EBADF, the fd is closed
//SAFETY: Always safe
unsafe { libc::fcntl(self.0, libc::F_GETFD) != -1 }
}
/**
Checks if the file descriptor is closed or invalid.
This is the inverse of [`is_open()`](Self::is_open) and provides
a more readable alternative for checking closed status.
*/
#[must_use]
#[inline]
pub fn is_closed(&self) -> bool {
!self.is_open()
}
}
#[cfg(all(target_os = "android", not(debug_assertions)))]
pub const BUFFER_SIZE: usize = 4200;
/*
// straced on android
strace -f ls -R ~ 2>&1 | grep getdents | head
getdents64(3, 0xb400007d5b602840 /* 25 entries /, 4200) = 808 getdents64(3, 0xb400007d5b602840 / 0 entries /, 4200) = 0 getdents64(3, 0xb400007d5b602840 / 27 entries /, 4200) = 880 getdents64(3, 0xb400007d5b602840 / 0 entries /, 4200) = 0 getdents64(3, 0xb400007d5b602840 / 15 entries /, 4200) = 616 getdents64(3, 0xb400007d5b602840 / 0 entries /, 4200) = 0 getdents64(3, 0xb400007d5b602840 / 4 entries */, 4200) = 128
*/
#[cfg(all(target_os = "linux", not(debug_assertions)))]
pub const BUFFER_SIZE: usize = 8 * 4096;
/*
//straced on linux
λ sudo strace -f fd NOMATCHLOL / -HI 2>&1 | grep getdents | head
[pid 18321] getdents64(3, 0x7ff8e4000cb0 /* 21 entries */, 32768) = 520
[pid 18321] getdents64(3, 0x7ff8e4000cb0 /* 0 entries */, 32768) = 0
[pid 18321] getdents64(3, 0x7ff8e4000cb0 /* 7 entries */, 32768) = 224
[pid 18321] getdents64(3, 0x7ff8e4000cb0 /* 0 entries */, 32768) = 0
[pid 18321] getdents64(3 <unfinished ...>
[pid 18327] getdents64(4 <unfinished ...>
λ sudo strace -f ls / 2>&1 | grep getdents | head
getdents64(3, 0x557e625c37a0 /* 21 entries */, 32768) = 520
getdents64(3, 0x557e625c37a0 /* 0 entries */, 32768) = 0
*/
#[cfg(all(
any(target_os = "illumos", target_os = "solaris"),
not(debug_assertions)
))]
pub const BUFFER_SIZE: usize = 8192;
#[cfg(all(any(target_os = "illumos", target_os = "solaris"), debug_assertions))]
pub const BUFFER_SIZE: usize = 4096;
// Same buffer sizes for illumos/solaris(essentially identical)
/*
alexc@omnios:~% sudo truss -f ls . 2>&1 | grep -Eiv '^/' | grep getdents
6890: getdents64(3, 0xFEC64000, 8192) = 616
6890: getdents64(3, 0xFEC64000, 8192) = 0
alexc@omnios:~%
*/
#[cfg(target_os = "netbsd")]
pub const BUFFER_SIZE: usize = 0x1000;
/*
# kdump | grep getdents | head
27582 16284 fdfind CALL __getdents30(3,0x71a95f64c000,0x1000)
27582 16284 fdfind RET __getdents30 608/0x260
27582 16284 fdfind CALL __getdents30(3,0x71a95f64c000,0x1000)
27582 16284 fdfind RET __getdents30 0
27582 16284 fdfind CALL __getdents30(3,0x71a95f64c000,0x1000)
27582 16284 fdfind RET __getdents30 56/0x38
*/
#[cfg(all(any(target_os = "linux", target_os = "android"), debug_assertions))]
pub const BUFFER_SIZE: usize = 4096; // Crashes during testing due to parallel processes taking up too much stack
#[cfg(target_os = "freebsd")]
pub const BUFFER_SIZE: usize = 4096; // freebsd's buffer size (verified)
#[cfg(all(target_os = "openbsd", not(debug_assertions)))]
pub const BUFFER_SIZE: usize = 0x10000;
#[cfg(all(target_os = "openbsd", debug_assertions))]
pub const BUFFER_SIZE: usize = 4096; //avoid stack overflow during parallelised tests
/*.
foo# ktrace fd -H . / > /dev/null 2>&1; kdump | grep getdents | head
57610 fd CALL getdents(3,0xad7363e0000,0x10000)
57610 fd RET getdents 688/0x2b0
57610 fd CALL getdents(3,0xad7363e0000,0x10000)
57610 fd RET getdents 0
57610 fd CALL getdents(3,0xad7363e0000,0x10000)
57610 fd RET getdents 2680/0xa78
57610 fd CALL getdents(3,0xad7363e0000,0x10000)
57610 fd RET getdents 0
57610 fd CALL getdents(3,0xad7363e0000,0x10000)
57610 fd RET getdents 856/0x358
*/
#[cfg(all(target_os = "macos", not(debug_assertions)))]
pub const BUFFER_SIZE: usize = 0x2000; //readdir calls this value for buffer size, look at syscall tracing below (8192)
#[cfg(all(target_os = "macos", debug_assertions))]
pub const BUFFER_SIZE: usize = 0x1000; // Give a smaller size to avoid stack overflow when going on tests
/*
/tmp/fdf_test getdirentries ❯ sudo dtruss fd -HI . 2>&1 | grep getdirentries | head ✘ INT alexc@alexcs-iMac 00:52:24
getdirentries64(0x3, 0x7FD166808A00, 0x2000) = 896 0
getdirentries64(0x3, 0x7FD166808A00, 0x2000) = 408 0
getdirentries64(0x3, 0x7FD166808A00, 0x2000) = 288 0
/tmp/fdf_test getdirentries ❯ sudo dtruss ls . -R 2>&1 | grep getdirentries | head alexc@alexcs-iMac 00:58:19
getdirentries64(0x3, 0x7FEE86013C00, 0x2000) = 896 0
getdirentries64(0x3, 0x7FEE86013C00, 0x2000) = 104 0
getdirentries64(0x3, 0x7FEE86013C00, 0x2000) = 1520 0
getdirentries64(0x3, 0x7FEE86013C00, 0x2000) = 112 0
getdirentries64(0x3, 0x7FEE86013C00, 0x2000) = 344 0
*/
//TODO, use this info for dragonflybsd when I add support
/*
root@:~ # kdump | grep getdirentries | head
1036:4 fd CALL getdirentries(0x5,0x8015b8000,0x4000,0x7fdfe0402178)
1036:4 fd RET getdirentries 496/0x1f0
1036:4 fd CALL getdirentries(0x5,0x8015b8000,0x4000,0x7fdfe0402178)
1036:4 fd RET getdirentries 0
1036:4 fd CALL getdirentries(0x5,0x8015b8000,0x4000,0x7fdfe0402178)
1036:4 fd RET getdirentries 2776/0xad8
1036:6 fd CALL getdirentries(0x8,0x802910000,0x4000,0x7fdfe0804178)
1036:4 fd CALL getdirentries(0x5,0x8015b8000,0x4000,0x7fdfe0402178)
1036:6 fd RET getdirentries 216/0xd8
1036:6 fd CALL getdirentries(0x8,0x802910000,0x4000,0x7fdfe0804178)
root@:~ # uname -a
DragonFly 6.4-RELEASE DragonFly v6.4.2-RELEASE #11: Fri May 9 14:08:53 EDT 2025 root@www.shiningsilence.com:/usr/obj/home/justin/release/6_4/sys/X86_64_GENERIC x86_64
*/