Next: Simple Directory Lister, Previous: Opening a Directory, Up: Accessing Directories

#### 14.2.3 Reading and Closing a Directory Stream

This section describes how to read directory entries from a directory stream, and how to close the stream when you are done with it. All the symbols are declared in the header file `dirent.h`.

— Function: struct dirent * readdir (DIR *dirstream)

> This function reads the next entry from the directory. It normally returns a pointer to a structure containing information about the file. This structure is statically allocated and can be rewritten by a subsequent call.

> Portability Note: On some systems `readdir` may not return entries for `.` and `..`, even though these are always valid file names in any directory. See File Name Resolution.

> If there are no more entries in the directory or an error is detected, `readdir` returns a null pointer. The following `errno` error conditions are defined for this function:

> `EBADF`
>   The dirstream argument is not valid.

> `readdir` is not thread safe. Multiple threads using `readdir` on the same dirstream may overwrite the return value. Use `readdir_r` when this is critical.

— Function: int readdir_r (DIR *dirstream, struct dirent *entry, struct dirent **result)

> This function is the reentrant version of `readdir`. Like `readdir` it returns the next entry from the directory. But to prevent conflicts between simultaneously running threads the result is not stored in statically allocated memory. Instead the argument entry points to a place to store the result.

> Normally `readdir_r` returns zero and sets `*`result to entry. If there are no more entries in the directory or an error is detected, `readdir_r` sets `*`result to a null pointer and returns a nonzero error code, also stored in `errno`, as described for `readdir`.

> Portability Note: On some systems `readdir_r` may not return a NUL terminated string for the file name, even when there is no `d_reclen` field in `struct dirent` and the file name is the maximum allowed size. Modern systems all have the `d_reclen` field, and on old systems multi-threading is not critical. In any case there is no such problem with the `readdir` function, so that even on systems without the `d_reclen` member one could use multiple threads by using external locking.

> It is also important to look at the definition of the `struct dirent` type. Simply passing a pointer to an object of this type for the second parameter of `readdir_r` might not be enough. Some systems don't define the `d_name` element sufficiently long. In this case the user has to provide additional space. There must be room for at least `NAME_MAX + 1` characters in the `d_name` array. Code to call `readdir_r` could look like this:

>                 union
>                 {
>                   struct dirent d;
>                   char b[offsetof (struct dirent, d_name) + NAME_MAX + 1];
>                 } u;

>                 if (readdir_r (dir, &u.d, &res) == 0)
>                   ...

To support large filesystems on 32-bit machines there are LFS variants of the last two functions.

— Function: struct dirent64 * readdir64 (DIR *dirstream)

> The `readdir64` function is just like the `readdir` function except that it returns a pointer to a record of type `struct dirent64`. Some of the members of this data type (notably `d_ino`) might have a different size to allow large filesystems.

> In all other aspects this function is equivalent to `readdir`.

— Function: int readdir64_r (DIR *dirstream, struct dirent64 *entry, struct dirent64 **result)

> The `readdir64_r` function is equivalent to the `readdir_r` function except that it takes parameters of base type `struct dirent64` instead of `struct dirent` in the second and third position. The same precautions mentioned in the documentation of `readdir_r` also apply here.

— Function: int closedir (DIR *dirstream)

> This function closes the directory stream dirstream. It returns `0` on success and `-1` on failure.

> The following `errno` error conditions are defined for this function:

> `EBADF`
>   The dirstream argument is not valid.