`readdir(self)`, where `None` means the end of the directory.
(&mut self)
| 126 | |
| 127 | /// `readdir(self)`, where `None` means the end of the directory. |
| 128 | pub fn read(&mut self) -> Option<io::Result<DirEntry>> { |
| 129 | // If we've seen errors, don't continue to try to read anything |
| 130 | // further. |
| 131 | if self.any_errors { |
| 132 | return None; |
| 133 | } |
| 134 | |
| 135 | // If a rewind was requested, seek to the beginning. |
| 136 | if self.rewind { |
| 137 | self.rewind = false; |
| 138 | match io::retry_on_intr(|| { |
| 139 | crate::backend::fs::syscalls::_seek(self.fd.as_fd(), 0, SEEK_SET) |
| 140 | }) { |
| 141 | Ok(_) => (), |
| 142 | Err(err) => { |
| 143 | self.any_errors = true; |
| 144 | return Some(Err(err)); |
| 145 | } |
| 146 | } |
| 147 | } |
| 148 | |
| 149 | // Compute linux_dirent64 field offsets. |
| 150 | let z = linux_dirent64 { |
| 151 | d_ino: 0_u64, |
| 152 | d_off: 0_i64, |
| 153 | d_type: 0_u8, |
| 154 | d_reclen: 0_u16, |
| 155 | d_name: Default::default(), |
| 156 | }; |
| 157 | let base = as_ptr(&z) as usize; |
| 158 | let offsetof_d_reclen = (as_ptr(&z.d_reclen) as usize) - base; |
| 159 | let offsetof_d_name = (as_ptr(&z.d_name) as usize) - base; |
| 160 | let offsetof_d_ino = (as_ptr(&z.d_ino) as usize) - base; |
| 161 | let offsetof_d_off = (as_ptr(&z.d_off) as usize) - base; |
| 162 | let offsetof_d_type = (as_ptr(&z.d_type) as usize) - base; |
| 163 | |
| 164 | // Test if we need more entries, and if so, read more. |
| 165 | if self.buf.len() - self.pos < size_of::<linux_dirent64>() { |
| 166 | match self.read_more()? { |
| 167 | Ok(()) => (), |
| 168 | Err(err) => return Some(Err(err)), |
| 169 | } |
| 170 | } |
| 171 | |
| 172 | // We successfully read an entry. Extract the fields. |
| 173 | let pos = self.pos; |
| 174 | |
| 175 | // Do an unaligned u16 load. |
| 176 | let d_reclen = u16::from_ne_bytes([ |
| 177 | self.buf[pos + offsetof_d_reclen], |
| 178 | self.buf[pos + offsetof_d_reclen + 1], |
| 179 | ]); |
| 180 | assert!(self.buf.len() - pos >= d_reclen as usize); |
| 181 | self.pos += d_reclen as usize; |
| 182 | |
| 183 | // Read the NUL-terminated name from the `d_name` field. Without |
| 184 | // `unsafe`, we need to scan for the NUL twice: once to obtain a size |
| 185 | // for the slice, and then once within `CStr::from_bytes_with_nul`. |
no test coverage detected