August Feng

Rust ReadDir Iterator

About

The std::fs::read_dir returns a ReadDir struct, which is an Iterator, wrapped in a Result. The Result value resolves to an error in the following conditions:

  • The process doesn't have permission to read the directory.
  • The directory doesn't exist.
  • The path is not a directory.

This is understandable. What's annoying is that each item returned by the iterator is of also Result type.

Consequently, I investigated the Iterator implementation ReadDir to see when would an Err occur.

Learning

Rust

The Iterator implementation of ReadDir eventually invokes a system call: readdir_r.

System call

The readdir_r system call accepts a pointer to a dirent struct and will mutate it. It's return type is int, which communicats a potential error.

When I investigated the potential errors, I understood that it's not a deterministic set. In fact, any error from sys/errno.h may be returned so it's implementation dependant.

Luckily man pages (man 3 readdir_r) hint that the returned value may be any values documented for the getdirentries(2) system call.

ERRORS
     getdirentries() will fail if:

     [EBADF]            fd is not a valid file descriptor open for reading.

     [EFAULT]           Either buf or basep point outside the allocated address space.

     [EIO]              An I/O error occurred while reading from or writing to the file system.

The manual pages from BSD are also friendly and hint that it may return any error that getdents returns:

ERRORS
       The getdirentries() system call will fail if:

       [EBADF]		  The  fd argument is not a valid file descriptor open
			  for reading.

       [EFAULT]		  Either buf or	non-NULL basep point outside the allo-
			  cated	address	space.

       [EINVAL]		  The file referenced by fd is	not  a	directory,  or
			  nbytes  is too small for returning a directory entry
			  or block of entries, or the current position pointer
			  is invalid.

       [EIO]		  An I/O error occurred	while reading from or  writing
			  to the file system.

       [EINTEGRITY]	  Corrupted  data  was detected	while reading from the
			  file system.

       [ENOENT]		  Directory unlinked but still open.

Overall, these errors seem very edge casey. I think I'll just handle the errors with a log and skip for my code.

Iteration state

The Iterator for ReadDir does not use Rust code to keep a state of the iteration. Instead, it uses a directory stream that's incremented by subsequent readdir_r calls.