Next: , 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.

The return value is 0 in case the next entry was read successfully. In this case a pointer to the result is returned in *result. It is not required that *result is the same as entry. If something goes wrong while executing readdir_r the function returns a value indicating the error (as described for readdir).

If there are no more directory entries, readdir_r's return value is 0, and *result is set to NULL.

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.