readdir_r(3) ディレクトリを読み込む

Other Alias

readdir

書式

#include <dirent.h>


struct dirent *readdir(DIR *dirp);

int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result);

glibc 向けの機能検査マクロの要件 (feature_test_macros(7) 参照):

readdir_r():

_POSIX_C_SOURCE >= 1 || _XOPEN_SOURCE || _BSD_SOURCE || _SVID_SOURCE || _POSIX_SOURCE

説明

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

Linux では 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[] と (XSI 拡張での) d_ino だけである。 d_name[] はその大きさも規定されておらず、 このフィールドには最大で NAME_MAX 個の文字と、それに続く終端の ヌルバイト ('\0')が格納される。 他のフィールドは非標準であり、全てのシステムに存在するわけではない。 詳細については、下記の「注意」を参照のこと。

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

readdir_r() 関数は readdir() のリエントラント版である。 この関数はディレクトリストリーム dirp から次のディレクトリエントリを読み込み、 entry が指す呼び出し元が割り当てたバッファにそのエントリを格納して返す (このバッファの割り当てについては「注意」の節を参照のこと)。 返されるエントリへのポインタが *result に格納される。ディレクトリストリームの末尾に達した場合は、 NULL が *result に格納される。

返り値

成功すると、 readdir() は dirent 構造体へのポインタを返す。 (この構造体は静的に割り当てられているかもしれない。 このポインタを free(3) しようとしないこと。) ディレクトリストリームの末尾に達した場合には、NULL が返され、 errno は変化しない。 エラーが発生した場合、NULL が返され、 errno が適切に設定される。

成功すると、 readdir_r() 関数は 0 を返す。 エラーの場合、(「エラー」の節のリストに載っている) 正のエラー番号を返す。 ディレクトリストリームの末尾に達した場合、 readdir_r() は返り値として 0 を返し、 *result に NULL を格納する。

エラー

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

属性

マルチスレッディング (pthreads(7) 参照)

readdir() 関数はスレッドセーフではない。

readdir_r() 関数はスレッドセーフである。

準拠

SVr4, 4.3BSD, POSIX.1-2001.

注意

フィールド d_named_ino だけが POSIX.1-2001 で規定されている。 残りのフィールドは多くのシステムに存在するが、全てのシステムに 存在するわけではない。 glibc では、プログラムが POSIX.1 で定義されていないフィールドが 利用できるかをチェックすることができる。 チェックするには、マクロ _DIRENT_HAVE_D_NAMLEN, _DIRENT_HAVE_D_RECLEN, _DIRENT_HAVE_D_OFF, _DIRENT_HAVE_D_TYPE が定義されているかをテストすればよい。

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

d_type フィールドは、Linux 以外では、 主に BSD 系のシステムにだけ存在する。 このフィールドを使うと、 その後の動作がファイルの種別により決まる場合に、 lstat(2) を呼び出すコストを避けることができる。 機能検査マクロ _BSD_SOURCE が定義された場合、glibc は d_type で返される値として以下のマクロ定数を定義する。

DT_BLK
ブロックデバイスである。
DT_CHR
キャラクタデバイスである。
DT_DIR
ディレクトリである。
DT_FIFO
名前付きパイプ (FIFO) である。
DT_LNK
シンボリックリンクである。
DT_REG
通常のファイルである。
DT_SOCK
UNIX ドメインソケットである。
DT_UNKNOWN
ファイルタイプが不明である。

ファイル種別を決定できなかった場合には、 d_typeDT_UNKNOWN が入る。

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

POSIX.1 では d_name フィールドのサイズは規定されておらず、 dirent 構造体の d_name の後ろに他の非標準のフィールドがあるかもしれないので、 移植性が必要なアプリケーションで readdir_r() を使う場合は entry に渡すバッファを次のようにして割り当てるべきである。

name_max = pathconf(dirpath, _PC_NAME_MAX);
if (name_max == -1)         /* 上限が定義されていない、またはエラー */
    name_max = 255;         /* 適当な値を入れる */
len = offsetof(struct dirent, d_name) + name_max + 1;
entryp = malloc(len);
(POSIX.1 では struct dirent の最後のフィールドが d_name であることを要求している。)

この文書について

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