The facilities described in this section let you read the contents of a directory file. This is useful if you want your program to list all the files in a directory, perhaps as part of a menu.
The opendir function opens a directory stream whose elements are directory entries. You use the readdir function on the directory stream to retrieve these entries, represented as struct dirent objects. The name of the file for each entry is stored in the d_name member of this structure. There are obvious parallels here to the stream facilities for ordinary files, described in Chapter 13.
This section describes what you find in a single directory entry, as you might obtain it from a directory stream. All the symbols are declared in the header file dirent.h.
function>struct dirent/function> This is a structure type used to return information about directory entries. It contains the following fields:
This is the null-terminated file name component. This is the only field you can count on in all POSIX systems.
This is the file serial number. For BSD compatibility, you can also refer to this member as d_ino. In the GNU system and most POSIX systems, for most files this the same as the st_ino member that stat will return for the file. the section called “File Attributes”.
This is the length of the file name, not including the terminating null character. Its type is unsigned char because that is the integer type of the appropriate size
This is the type of the file, possibly unknown. The following constants are defined for its value:
The type is unknown. On some systems this is the only value returned.
A regular file.
A directory.
A named pipe, or FIFO. the section called “FIFO Special Files”.
A local-domain socket.
A character device.
A block device.
This member is a BSD extension. The symbol _DIRENT_HAVE_D_TYPE is defined if this member is available. On systems where it is used, it corresponds to the file type bits in the st_mode member of struct statbuf. If the value cannot be determine the member value is DT_UNKNOWN. These two macros convert between d_type values and st_mode values:
int function>IFTODT/function> (mode_t mode) This returns the d_type value corresponding to mode.
mode_t function>DTTOIF/function> (int dtype) This returns the st_mode value corresponding to dtype.
This structure may contain additional members in the future. Their availability is always announced in the compilation environment by a macro names _DIRENT_HAVE_D_xxx where xxx is replaced by the name of the new member. For instance, the member d_reclen available on some systems is announced through the macro _DIRENT_HAVE_D_RECLEN.
When a file has multiple names, each name has its own directory entry. The only way you can tell that the directory entries belong to a single file is that they have the same value for the d_fileno field.
File attributes such as size, modification times etc., are part of the file itself, not of any particular directory entry. the section called “File Attributes”.
This section describes how to open a directory stream. All the symbols are declared in the header file dirent.h.
function>DIR/function> The DIR data type represents a directory stream.
You shouldn't ever allocate objects of the struct dirent or DIR data types, since the directory access functions do that for you. Instead, you refer to these objects using the pointers returned by the following functions.
DIR * function>opendir/function> (const char *dirname) The opendir function opens and returns a directory stream for reading the directory whose file name is dirname. The stream has type DIR *.
If unsuccessful, opendir returns a null pointer. In addition to the usual file name errors (the section called “File Name Errors”), the following errno error conditions are defined for this function:
Read permission is denied for the directory named by dirname.
The process has too many files open.
The entire system, or perhaps the file system which contains the directory, cannot support any additional open files at the moment. (This problem cannot happen on the GNU system.)
The DIR type is typically implemented using a file descriptor, and the opendir function in terms of the open function. Chapter 14. Directory streams and the underlying file descriptors are closed on exec (the section called “Executing a File”).
In some situations it can be desirable to get hold of the file descriptor which is created by the opendir call. For instance, to switch the current working directory to the directory just read the fchdir function could be used. Historically the DIR type was exposed and programs could access the fields. This does not happen in the GNU C library. Instead a separate function is provided to allow access.
int function>dirfd/function> (DIR *dirstream) The function dirfd returns the file descriptor associated with the directory stream dirstream. This descriptor can be used until the directory is closed with closedir. If the directory stream implementation is not using file descriptors the return value is -1.
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.
struct dirent * function>readdir/function> (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. the section called “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:
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.
int function>readdir_r/function> (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.
struct dirent64 * function>readdir64/function> (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.
int function>readdir64_r/function> (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.
int function>closedir/function> (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:
The dirstream argument is not valid.
Here's a simple program that prints the names of the files in the current working directory:
#include stddef.h #include stdio.h #include sys/types.h #include dirent.h int main (void) { DIR *dp; struct dirent *ep; dp = opendir ("./"); if (dp != NULL) { while (ep = readdir (dp)) puts (ep-d_name); (void) closedir (dp); } else perror ("Couldn't open the directory"); return 0; }
The order in which files appear in a directory tends to be fairly random. A more useful program would sort the entries (perhaps by alphabetizing them) before printing them; see the section called “Scanning the Content of a Directory”, and the section called “Array Sort Function”.
This section describes how to reread parts of a directory that you have already read from an open directory stream. All the symbols are declared in the header file dirent.h.
void function>rewinddir/function> (DIR *dirstream) The rewinddir function is used to reinitialize the directory stream dirstream, so that if you call readdir it returns information about the first entry in the directory again. This function also notices if files have been added or removed to the directory since it was opened with opendir. (Entries for these files might or might not be returned by readdir if they were added or removed since you last called opendir or rewinddir.)
off_t function>telldir/function> (DIR *dirstream) The telldir function returns the file position of the directory stream dirstream. You can use this value with seekdir to restore the directory stream to that position.
void function>seekdir/function> (DIR *dirstream, off_t pos) The seekdir function sets the file position of the directory stream dirstream to pos. The value pos must be the result of a previous call to telldir on this particular stream; closing and reopening the directory can invalidate values returned by telldir.
A higher-level interface to the directory handling functions is the scandir function. With its help one can select a subset of the entries in a directory, possibly sort them and get a list of names as the result.
int function>scandir/function> (const char *dir, struct dirent ***namelist, int (*selector) (const struct dirent *), int (*cmp) (const void *, const void *)) The scandir function scans the contents of the directory selected by dir. The result in *namelist is an array of pointers to structure of type struct dirent which describe all selected directory entries and which is allocated using malloc. Instead of always getting all directory entries returned, the user supplied function selector can be used to decide which entries are in the result. Only the entries for which selector returns a non-zero value are selected.
Finally the entries in *namelist are sorted using the user-supplied function cmp. The arguments passed to the cmp function are of type struct dirent **, therefore one cannot directly use the strcmp or strcoll functions; instead see the functions alphasort and versionsort below.
The return value of the function is the number of entries placed in *namelist. If it is -1 an error occurred (either the directory could not be opened for reading or the malloc call failed) and the global variable errno contains more information on the error.
As described above the fourth argument to the scandir function must be a pointer to a sorting function. For the convenience of the programmer the GNU C library contains implementations of functions which are very helpful for this purpose.
int function>alphasort/function> (const void *a, const void *b) The alphasort function behaves like the strcoll function (the section called “String/Array Comparison”). The difference is that the arguments are not string pointers but instead they are of type struct dirent **.
The return value of alphasort is less than, equal to, or greater than zero depending on the order of the two entries a and b.
int function>versionsort/function> (const void *a, const void *b) The versionsort function is like alphasort except that it uses the strverscmp function internally.
If the filesystem supports large files we cannot use the scandir anymore since the dirent structure might not able to contain all the information. The LFS provides the new type struct dirent64. To use this we need a new function.
int function>scandir64/function> (const char *dir, struct dirent64 ***namelist, int (*selector) (const struct dirent64 *), int (*cmp) (const void *, const void *)) The scandir64 function works like the scandir function except that the directory entries it returns are described by elements of type struct dirent64. The function pointed to by selector is again used to select the desired entries, except that selector now must point to a function which takes a struct dirent64 * parameter.
Similarly the cmp function should expect its two arguments to be of type struct dirent64 **.
As cmp is now a function of a different type, the functions alphasort and versionsort cannot be supplied for that argument. Instead we provide the two replacement functions below.
int function>alphasort64/function> (const void *a, const void *b) The alphasort64 function behaves like the strcoll function (the section called “String/Array Comparison”). The difference is that the arguments are not string pointers but instead they are of type struct dirent64 **.
Return value of alphasort64 is less than, equal to, or greater than zero depending on the order of the two entries a and b.
int function>versionsort64/function> (const void *a, const void *b) The versionsort64 function is like alphasort64, excepted that it uses the strverscmp function internally.
It is important not to mix the use of scandir and the 64-bit comparison functions or vice versa. There are systems on which this works but on others it will fail miserably.
Here is a revised version of the directory lister found above (the section called “Simple Program to List a Directory”). Using the scandir function we can avoid the functions which work directly with the directory contents. After the call the returned entries are available for direct use.
#include stdio.h #include dirent.h static int one (struct dirent *unused) { return 1; } int main (void) { struct dirent **eps; int n; n = scandir ("./", eps, one, alphasort); if (n = 0) { int cnt; for (cnt = 0; cnt n; ++cnt) puts (eps[cnt]-d_name); } else perror ("Couldn't open the directory"); return 0; }
Note the simple selector function in this example. Since we want to see all directory entries we always return 1.