(
path: OptionalArg<Option<OsPathOrFd<'_>>>,
vm: &VirtualMachine,
)
| 406 | |
| 407 | #[pyfunction] |
| 408 | fn listdir( |
| 409 | path: OptionalArg<Option<OsPathOrFd<'_>>>, |
| 410 | vm: &VirtualMachine, |
| 411 | ) -> PyResult<Vec<PyObjectRef>> { |
| 412 | let path = path |
| 413 | .flatten() |
| 414 | .unwrap_or_else(|| OsPathOrFd::Path(OsPath::new_str("."))); |
| 415 | let list = match path { |
| 416 | OsPathOrFd::Path(path) => { |
| 417 | let dir_iter = match fs::read_dir(&path) { |
| 418 | Ok(iter) => iter, |
| 419 | Err(err) => { |
| 420 | return Err(OSErrorBuilder::with_filename(&err, path, vm)); |
| 421 | } |
| 422 | }; |
| 423 | let mode = path.mode(); |
| 424 | dir_iter |
| 425 | .map(|entry| match entry { |
| 426 | Ok(entry_path) => Ok(mode.process_path(entry_path.file_name(), vm)), |
| 427 | Err(err) => Err(OSErrorBuilder::with_filename(&err, path.clone(), vm)), |
| 428 | }) |
| 429 | .collect::<PyResult<_>>()? |
| 430 | } |
| 431 | OsPathOrFd::Fd(fno) => { |
| 432 | #[cfg(not(all(unix, not(target_os = "redox"))))] |
| 433 | { |
| 434 | let _ = fno; |
| 435 | return Err( |
| 436 | vm.new_not_implemented_error("can't pass fd to listdir on this platform") |
| 437 | ); |
| 438 | } |
| 439 | #[cfg(all(unix, not(target_os = "redox")))] |
| 440 | { |
| 441 | use rustpython_common::os::ffi::OsStrExt; |
| 442 | use std::os::unix::io::IntoRawFd; |
| 443 | let new_fd = nix::unistd::dup(fno).map_err(|e| e.into_pyexception(vm))?; |
| 444 | let raw_fd = new_fd.into_raw_fd(); |
| 445 | let dir = OwnedDir::from_fd(raw_fd).map_err(|e| { |
| 446 | unsafe { libc::close(raw_fd) }; |
| 447 | e.into_pyexception(vm) |
| 448 | })?; |
| 449 | // OwnedDir::drop calls rewinddir (reset to start) then closedir. |
| 450 | let mut list = Vec::new(); |
| 451 | loop { |
| 452 | nix::errno::Errno::clear(); |
| 453 | let entry = unsafe { libc::readdir(dir.as_ptr()) }; |
| 454 | if entry.is_null() { |
| 455 | let err = nix::errno::Errno::last(); |
| 456 | if err != nix::errno::Errno::UnknownErrno { |
| 457 | return Err(io::Error::from(err).into_pyexception(vm)); |
| 458 | } |
| 459 | break; |
| 460 | } |
| 461 | let fname = unsafe { core::ffi::CStr::from_ptr((*entry).d_name.as_ptr()) } |
| 462 | .to_bytes(); |
| 463 | match fname { |
| 464 | b"." | b".." => continue, |
| 465 | _ => list.push( |
nothing calls this directly
no test coverage detected