diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-06-07 05:48:48 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-06-07 05:48:48 +0000 |
commit | ef24de24a82fe681581cc130f342363c47c0969a (patch) | |
tree | 0d494f7e1a38b95c92426f58fe6eaa877303a86c /vendor/rustix/src/backend/linux_raw/fs | |
parent | Releasing progress-linux version 1.74.1+dfsg1-1~progress7.99u1. (diff) | |
download | rustc-ef24de24a82fe681581cc130f342363c47c0969a.tar.xz rustc-ef24de24a82fe681581cc130f342363c47c0969a.zip |
Merging upstream version 1.75.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/rustix/src/backend/linux_raw/fs')
-rw-r--r-- | vendor/rustix/src/backend/linux_raw/fs/dir.rs | 95 | ||||
-rw-r--r-- | vendor/rustix/src/backend/linux_raw/fs/inotify.rs | 17 | ||||
-rw-r--r-- | vendor/rustix/src/backend/linux_raw/fs/syscalls.rs | 8 | ||||
-rw-r--r-- | vendor/rustix/src/backend/linux_raw/fs/types.rs | 26 |
4 files changed, 110 insertions, 36 deletions
diff --git a/vendor/rustix/src/backend/linux_raw/fs/dir.rs b/vendor/rustix/src/backend/linux_raw/fs/dir.rs index 4df589af5..ea1017957 100644 --- a/vendor/rustix/src/backend/linux_raw/fs/dir.rs +++ b/vendor/rustix/src/backend/linux_raw/fs/dir.rs @@ -18,9 +18,17 @@ pub struct Dir { /// The `OwnedFd` that we read directory entries from. fd: OwnedFd, + /// Have we seen any errors in this iteration? + any_errors: bool, + + /// Should we rewind the stream on the next iteration? + rewind: bool, + + /// The buffer for `linux_dirent64` entries. buf: Vec<u8>, + + /// Where we are in the buffer. pos: usize, - next: Option<u64>, } impl Dir { @@ -38,25 +46,39 @@ impl Dir { Ok(Self { fd: fd_for_dir, + any_errors: false, + rewind: false, buf: Vec::new(), pos: 0, - next: None, }) } /// `rewinddir(self)` #[inline] pub fn rewind(&mut self) { + self.any_errors = false; + self.rewind = true; self.pos = self.buf.len(); - self.next = Some(0); } /// `readdir(self)`, where `None` means the end of the directory. pub fn read(&mut self) -> Option<io::Result<DirEntry>> { - if let Some(next) = self.next.take() { - match crate::backend::fs::syscalls::_seek(self.fd.as_fd(), next as i64, SEEK_SET) { + // If we've seen errors, don't continue to try to read anyting further. + if self.any_errors { + return None; + } + + // If a rewind was requested, seek to the beginning. + if self.rewind { + self.rewind = false; + match io::retry_on_intr(|| { + crate::backend::fs::syscalls::_seek(self.fd.as_fd(), 0, SEEK_SET) + }) { Ok(_) => (), - Err(err) => return Some(Err(err)), + Err(err) => { + self.any_errors = true; + return Some(Err(err)); + } } } @@ -78,7 +100,7 @@ impl Dir { if self.buf.len() - self.pos < size_of::<linux_dirent64>() { match self.read_more()? { Ok(()) => (), - Err(e) => return Some(Err(e)), + Err(err) => return Some(Err(err)), } } @@ -136,14 +158,31 @@ impl Dir { } fn read_more(&mut self) -> Option<io::Result<()>> { - let og_len = self.buf.len(); - // Capacity increment currently chosen by wild guess. - self.buf - .resize(self.buf.capacity() + 32 * size_of::<linux_dirent64>(), 0); - let nread = match crate::backend::fs::syscalls::getdents(self.fd.as_fd(), &mut self.buf) { + // The first few times we're called, we allocate a relatively small + // buffer, because many directories are small. If we're called more, + // use progressively larger allocations, up to a fixed maximum. + // + // The specific sizes and policy here have not been tuned in detail yet + // and may need to be adjusted. In doing so, we should be careful to + // avoid unbounded buffer growth. This buffer only exists to share the + // cost of a `getdents` call over many entries, so if it gets too big, + // cache and heap usage will outweigh the benefit. And ultimately, + // directories can contain more entries than we can allocate contiguous + // memory for, so we'll always need to cap the size at some point. + if self.buf.len() < 1024 * size_of::<linux_dirent64>() { + self.buf.reserve(32 * size_of::<linux_dirent64>()); + } + self.buf.resize(self.buf.capacity(), 0); + let nread = match io::retry_on_intr(|| { + crate::backend::fs::syscalls::getdents(self.fd.as_fd(), &mut self.buf) + }) { Ok(nread) => nread, + Err(io::Errno::NOENT) => { + self.any_errors = true; + return None; + } Err(err) => { - self.buf.resize(og_len, 0); + self.any_errors = true; return Some(Err(err)); } }; @@ -225,3 +264,33 @@ impl DirEntry { self.d_ino } } + +#[test] +fn dir_iterator_handles_io_errors() { + // create a dir, keep the FD, then delete the dir + let tmp = tempfile::tempdir().unwrap(); + let fd = crate::fs::openat( + crate::fs::CWD, + tmp.path(), + crate::fs::OFlags::RDONLY | crate::fs::OFlags::CLOEXEC, + crate::fs::Mode::empty(), + ) + .unwrap(); + + let file_fd = crate::fs::openat( + &fd, + tmp.path().join("test.txt"), + crate::fs::OFlags::WRONLY | crate::fs::OFlags::CREATE, + crate::fs::Mode::RWXU, + ) + .unwrap(); + + let mut dir = Dir::read_from(&fd).unwrap(); + + // Reach inside the `Dir` and replace its directory with a file, which + // will cause the subsequent `getdents64` to fail. + crate::io::dup2(&file_fd, &mut dir.fd).unwrap(); + + assert!(matches!(dir.next(), Some(Err(_)))); + assert!(matches!(dir.next(), None)); +} diff --git a/vendor/rustix/src/backend/linux_raw/fs/inotify.rs b/vendor/rustix/src/backend/linux_raw/fs/inotify.rs index ef205ffdf..aaba71d7c 100644 --- a/vendor/rustix/src/backend/linux_raw/fs/inotify.rs +++ b/vendor/rustix/src/backend/linux_raw/fs/inotify.rs @@ -18,7 +18,7 @@ bitflags! { /// `IN_NONBLOCK` const NONBLOCK = linux_raw_sys::general::IN_NONBLOCK; - /// <https://docs.rs/bitflags/latest/bitflags/#externally-defined-flags> + /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags> const _ = !0; } } @@ -38,7 +38,7 @@ bitflags! { const CLOSE_NOWRITE = linux_raw_sys::general::IN_CLOSE_NOWRITE; /// `IN_CLOSE_WRITE` const CLOSE_WRITE = linux_raw_sys::general::IN_CLOSE_WRITE; - /// `IN_CREATE ` + /// `IN_CREATE` const CREATE = linux_raw_sys::general::IN_CREATE; /// `IN_DELETE` const DELETE = linux_raw_sys::general::IN_DELETE; @@ -75,7 +75,7 @@ bitflags! { /// `IN_ONLYDIR` const ONLYDIR = linux_raw_sys::general::IN_ONLYDIR; - /// <https://docs.rs/bitflags/latest/bitflags/#externally-defined-flags> + /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags> const _ = !0; } } @@ -92,13 +92,12 @@ pub fn inotify_init(flags: CreateFlags) -> io::Result<OwnedFd> { /// `inotify_add_watch(self, path, flags)`—Adds a watch to inotify. /// -/// This registers or updates a watch for the filesystem path `path` -/// and returns a watch descriptor corresponding to this watch. +/// This registers or updates a watch for the filesystem path `path` and +/// returns a watch descriptor corresponding to this watch. /// -/// Note: Due to the existence of hardlinks, providing two -/// different paths to this method may result in it returning -/// the same watch descriptor. An application should keep track of this -/// externally to avoid logic errors. +/// Note: Due to the existence of hardlinks, providing two different paths to +/// this method may result in it returning the same watch descriptor. An +/// application should keep track of this externally to avoid logic errors. #[inline] pub fn inotify_add_watch<P: crate::path::Arg>( inot: BorrowedFd<'_>, diff --git a/vendor/rustix/src/backend/linux_raw/fs/syscalls.rs b/vendor/rustix/src/backend/linux_raw/fs/syscalls.rs index e72afb8ab..f856fa8b0 100644 --- a/vendor/rustix/src/backend/linux_raw/fs/syscalls.rs +++ b/vendor/rustix/src/backend/linux_raw/fs/syscalls.rs @@ -378,6 +378,7 @@ pub(crate) fn fadvise(fd: BorrowedFd<'_>, pos: u64, len: u64, advice: Advice) -> lo(len) )) } + // On mips, the arguments are not reordered, and padding is inserted // instead to ensure alignment. #[cfg(any(target_arch = "mips", target_arch = "mips32r6"))] @@ -393,6 +394,9 @@ pub(crate) fn fadvise(fd: BorrowedFd<'_>, pos: u64, len: u64, advice: Advice) -> advice )) } + + // For all other 32-bit architectures, use `fadvise64_64` so that we get a + // 64-bit length. #[cfg(all( target_pointer_width = "32", not(any( @@ -413,6 +417,8 @@ pub(crate) fn fadvise(fd: BorrowedFd<'_>, pos: u64, len: u64, advice: Advice) -> advice )) } + + // On 64-bit architectures, use `fadvise64` which is sufficient. #[cfg(target_pointer_width = "64")] unsafe { ret(syscall_readonly!( @@ -951,7 +957,7 @@ pub(crate) fn readlink(path: &CStr, buf: &mut [u8]) -> io::Result<usize> { } } -#[cfg(feature = "alloc")] +#[cfg(any(feature = "alloc", all(linux_kernel, feature = "procfs")))] #[inline] pub(crate) fn readlinkat( dirfd: BorrowedFd<'_>, diff --git a/vendor/rustix/src/backend/linux_raw/fs/types.rs b/vendor/rustix/src/backend/linux_raw/fs/types.rs index 6e2e14f1e..85fe018a3 100644 --- a/vendor/rustix/src/backend/linux_raw/fs/types.rs +++ b/vendor/rustix/src/backend/linux_raw/fs/types.rs @@ -20,7 +20,7 @@ bitflags! { /// `F_OK` const EXISTS = linux_raw_sys::general::F_OK; - /// <https://docs.rs/bitflags/latest/bitflags/#externally-defined-flags> + /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags> const _ = !0; } } @@ -61,7 +61,7 @@ bitflags! { /// `AT_STATX_DONT_SYNC` const STATX_DONT_SYNC = linux_raw_sys::general::AT_STATX_DONT_SYNC; - /// <https://docs.rs/bitflags/latest/bitflags/#externally-defined-flags> + /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags> const _ = !0; } } @@ -120,7 +120,7 @@ bitflags! { /// `S_ISVTX` const SVTX = linux_raw_sys::general::S_ISVTX; - /// <https://docs.rs/bitflags/latest/bitflags/#externally-defined-flags> + /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags> const _ = !0; } } @@ -179,9 +179,9 @@ bitflags! { /// Similar to `ACCMODE`, but just includes the read/write flags, and /// no other flags. /// - /// Some implementations include `O_PATH` in `O_ACCMODE`, when + /// On some platforms, `PATH` may be included in `ACCMODE`, when /// sometimes we really just want the read/write bits. Caution is - /// indicated, as the presence of `O_PATH` may mean that the read/write + /// indicated, as the presence of `PATH` may mean that the read/write /// bits don't have their usual meaning. const RWMODE = linux_raw_sys::general::O_RDONLY | linux_raw_sys::general::O_WRONLY | @@ -250,7 +250,7 @@ bitflags! { /// `O_DIRECT` const DIRECT = linux_raw_sys::general::O_DIRECT; - /// <https://docs.rs/bitflags/latest/bitflags/#externally-defined-flags> + /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags> const _ = !0; } } @@ -280,7 +280,7 @@ bitflags! { /// `RESOLVE_CACHED` (since Linux 5.12) const CACHED = linux_raw_sys::general::RESOLVE_CACHED as u64; - /// <https://docs.rs/bitflags/latest/bitflags/#externally-defined-flags> + /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags> const _ = !0; } } @@ -301,7 +301,7 @@ bitflags! { /// `RENAME_WHITEOUT` const WHITEOUT = linux_raw_sys::general::RENAME_WHITEOUT; - /// <https://docs.rs/bitflags/latest/bitflags/#externally-defined-flags> + /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags> const _ = !0; } } @@ -453,7 +453,7 @@ bitflags! { /// `MFD_HUGE_16GB` const HUGE_16GB = linux_raw_sys::general::MFD_HUGE_16GB; - /// <https://docs.rs/bitflags/latest/bitflags/#externally-defined-flags> + /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags> const _ = !0; } } @@ -478,7 +478,7 @@ bitflags! { /// `F_SEAL_FUTURE_WRITE` (since Linux 5.1) const FUTURE_WRITE = linux_raw_sys::general::F_SEAL_FUTURE_WRITE; - /// <https://docs.rs/bitflags/latest/bitflags/#externally-defined-flags> + /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags> const _ = !0; } } @@ -538,7 +538,7 @@ bitflags! { /// `STATX_ALL` const ALL = linux_raw_sys::general::STATX_ALL; - /// <https://docs.rs/bitflags/latest/bitflags/#externally-defined-flags> + /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags> const _ = !0; } } @@ -565,7 +565,7 @@ bitflags! { /// `FALLOC_FL_UNSHARE_RANGE` const UNSHARE_RANGE = linux_raw_sys::general::FALLOC_FL_UNSHARE_RANGE; - /// <https://docs.rs/bitflags/latest/bitflags/#externally-defined-flags> + /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags> const _ = !0; } } @@ -602,7 +602,7 @@ bitflags! { /// `ST_SYNCHRONOUS` const SYNCHRONOUS = linux_raw_sys::general::MS_SYNCHRONOUS as u64; - /// <https://docs.rs/bitflags/latest/bitflags/#externally-defined-flags> + /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags> const _ = !0; } } |