READDIR(3)

名前
readdir - ディレクトリを読み込む

書式
#include <dirent.h>

struct dirent *readdir(DIR *dirp);

説明
readdir() 関数は、dirp が指すディレクトリストリームの中で、 次のディレクトリエントリーを表す dirent 構造体へのポインターを返す。 ディレクトリストリームの末尾に達した場合や、 エラーが発生した場合は、 NULL を返す。

glibc の実装では dirent 構造体は以下のように定義されている。

    struct dirent {
        ino_t          d_ino;       /* inode 番号 */
        off_t          d_off;       /* オフセットではない; 下記を参照 */
        unsigned short d_reclen;    /* このレコードの長さ */
        unsigned char  d_type;      /* ファイル種別。全ファイルシステム */
                                       でサポートされているわけではない */
        char           d_name[256]; /* ヌル終端されたファイル名 */
    };

dirent 構造体のフィールドのうち POSIX.1 で要求されているのは、 d_name と d_ino だけである。他のフィールドは非標準であり、すべてのシステムで存在するわけではない。 詳細については、下記の「注意」を参照のこと。

dirent 構造体のフィールドは以下の通りである:

d_ino
    ファイルの inode 番号である。

d_off
    d_off で返される値は、ディレクトリストリームの現在の位置で telldir(3) を呼び出した場合の返り値と同じである。フィールドの型や名前はこうなっているが、最近のファイルシステムでは d_off フィールドが何らかのディレクトリオフセットであることはめったにない。アプリケーションプログラムでは、必ずこの値を内容を意識せず単なる値として扱うべきであり、その内容について前提を持つべきではない。 telldir(3) も参照。

d_reclen
    返されたレコードの (バイト単位の) サイズである。この値は上記の構造体の定義のサイズとは一致しないかもしれない。「注意」を参照。

d_type
    ファイル種別を示す値が格納される。これにより、これ以降の処理がファイル種別に依存している場合に lstat(2) を呼び出すコストを避けることができる。

    適切な機能検査マクロ (glibc 2.19 以降では _DEFAULT_SOURCE、 glibc 2.19 以前では _BSD_SOURCE) が定義されている場合、 glibc は d_type の値に対応する以下のマクロ定数を定義する。

    DT_BLK
        ブロックデバイスである。

    DT_CHR
        キャラクターデバイスである。

    DT_DIR
        ディレクトリである。

    DT_FIFO
        名前付きパイプ (FIFO) である。

    DT_LNK
        シンボリックリンクである。

    DT_REG
        通常のファイルである。

    DT_SOCK
        UNIX ドメインソケットである。

    DT_UNKNOWN
        ファイル種別が判別できなかった。

    現在のところ、 d_type でファイルタイプを返す機能が完全にサポートされているのは、 いくつかのファイルシステムにおいてのみである (Btrfs, ext2, ext3, ext4 はサポートしている)。 どのアプリケーションも DT_UNKNOWN が返された際に適切に処理できなければならない。

d_name
    このフィールドはヌル終端されたファイル名である。「注意」を参照。

readdir() によって返されるデータは、それ以降の同じストリームに対する readdir() の呼び出しによって上書きされる可能性がある。

返り値
成功すると、 readdir() は dirent 構造体へのポインターを返す。 (この構造体は静的に割り当てられているかもしれない。 このポインターを free(3) しようとしないこと。)

ディレクトリストリームの末尾に達した場合には、NULL が返され、 errno は変化しない。 エラーが発生した場合、NULL が返され、 errno が適切に設定される。エラーからストリームの末尾を区別するには、 readdir() を呼び出す前に errno を 0 に設定しておき、 NULL が返された場合に errno の値を確認すればよい。

エラー

EBADF
    ディレクトリストリームディスクリプター dirp が無効である。

属性
この節で使用されている用語の説明については、 attributes(7) を参照。
インターフェース | 属性 | 値
readdir() | Thread safety | MT-Unsafe race:dirstream

現在の POSIX.1 標準 (POSIX.1-2008) では、 readdir() がスレッドセーフであることは求められていない。しかしながら、最近の実装 (glibc による実装も含む) では、異なるディレクトリストリームに対する readdir() の同時並行の呼び出しはスレッドセーフである。複数のスレッドが同じディレクトリストリームから読み込みを行う必要がある場合も、非推奨の readdir_r(3) 関数を使用するよりも、外部同期を用いた readdir() を使う方が推奨される。 POSIX.1 の将来のバージョンでは、 readdir() は異なるディレクトリストリームに対して同時に使用された際にスレッドセーフであることが必須となる予定である。

準拠
POSIX.1-2001, POSIX.1-2008, SVr4, 4.3BSD.

注意
ディレクトリストリームは opendir(3) を使ってオープンする。

連続する readdir() の呼び出しで読み込まれるファイル名の順序は、ファイルシステムの実装に依存する。名前が何らかの方法でソートされていることはありえない。

フィールド d_name と (XSI 拡張の) d_ino だけが POSIX.1 で規定されている。 d_type フィールドは、 Linux 以外では、おもに BSD 系のシステムでのみ利用可能である。残りのフィールドは多くのシステムに存在するが、全てのシステムに存在するわけではない。 glibc では、プログラムが POSIX.1 で定義されていないフィールドが 利用できるかをチェックすることができる。 チェックするには、マクロ _DIRENT_HAVE_D_NAMLEN, _DIRENT_HAVE_D_RECLEN, _DIRENT_HAVE_D_OFF, _DIRENT_HAVE_D_TYPE が定義されているかをテストすればよい。

  d_name フィールド
上記の dirent 構造体の定義は glibc のヘッダーからの引用であり、 d_name フィールドは固定サイズとなっている。

警告: アプリケーションは、 d_name フィールドのサイズに依存すべきではない。 POSIX ではこのフィールドは char d_name[] (サイズ不定の文字配列) として規定しており、最大で終端のヌルバイト ('\0') の前に NAME_MAX 文字が入る。

POSIX.1 は、このフィールドを左辺値として使用すべきではないと明記している。また、 POSIX.1 では、 sizeof(d_name) の使用は間違いであり、代わりに strlen(d_name) を使用するように、との注記もある (いくつかのシステムでは、このフィールドは char d_name[1]! として定義されている)。このことは、 d_name を含むレコードのサイズを取得するために sizeof(struct dirent) を使用することも間違いであることを暗に示している。

多くのファイルシステムでは、

    fpathconf(fd, _PC_NAME_MAX)

の呼び出しは値 255 を返すが、いくつかのファイルシステム (例えば CIFS や Windows SMB サーバーなど) では、(正しい動作なのだが) d_name で返されるヌル終端されたファイル名は実際にはこのサイズを超える場合がある点に注意すること。このような場合、 d_reclen フィールドは、上記の glibc dirent 構造体のサイズよりも大きな値となる。

関連項目
getdents(2), read(2), closedir(3), dirfd(3), ftw(3), offsetof(3), opendir(3), readdir_r(3), rewinddir(3), scandir(3), seekdir(3), telldir(3)

この文書について
この man ページは Linux man-pages プロジェクトのリリース 5.10 の一部である。プロジェクトの説明とバグ報告に関する情報は https://www.kernel.org/doc/man-pages/ に書かれている。