Provided by: manpages-ja-dev_0.5.0.0.20221215+dfsg-1_all
名前
getdents, getdents64 - ディレクトリエントリーを取得する
書式
long getdents(unsigned int fd, struct linux_dirent *dirp, unsigned int count); #define _GNU_SOURCE /* feature_test_macros(7) 参照 */ #include <dirent.h> ssize_t getdents64(int fd, void *dirp, size_t count); 注: getdents() の glibc のラッパー関数は存在しない。「注意」の節を参照。
説明
これらはあなたの関心を引くようなインターフェースではないだろう。 POSIX 準拠の C ライブラリ インターフェースについては readdir(3) を参照のこと。このページは、カーネルシステムコールの 生のインターフェースについて記載したものである。 getdents() getdents() システムコールは、オープン済みのファイルディスクリプター fd で参照されるディレ クトリから linux_dirent 構造体をいくつか読み出し、 dirp が指しているバッファーに格納する。 count 引数はそのバッファーのサイズを示す。 linux_dirent 構造体は以下のように宣言されている。 struct linux_dirent { unsigned long d_ino; /* inode 番号 */ unsigned long d_off; /* 次の linux_dirent へのオフセット */ unsigned short d_reclen; /* この linux_dirent の長さ */ char d_name[]; /* (ヌル終端された) ファイル名 */ /* 実際の長さは (d_reclen - 2 - offsetof(struct linux_dirent, d_name)) */ /* char pad; // 値 0 のパディングバイト char d_type; // ファイル種別 (Linux 2.6.4 以降のみ); // オフセットは (d_reclen - 1) */ } d_ino は inode 番号である。 d_off はディレクトリの先頭から次の linux_dirent の先頭までの距 離である。 d_reclen はこの linux_dirent 全体のサイズである。 d_name はヌル文字で終わるファ イル名である。 d_type は、構造体の最後のバイトであり、ファイルタイプを示す。 d_type は以下の値のいずれか 一つを取る (<dirent.h> で定義されている)。 DT_BLK ブロックデバイスである。 DT_CHR キャラクターデバイスである。 DT_DIR ディレクトリである。 DT_FIFO 名前付きパイプ (FIFO) である。 DT_LNK シンボリックリンクである。 DT_REG 通常のファイルである。 DT_SOCK UNIX ドメインソケットである。 DT_UNKNOWN ファイルタイプが不明。 d_type フィールドは Linux 2.6.4 以降で実装されている。 このフィールドは、 linux_dirent 構 造体の中で以前はゼロで埋められていた空間に配置されている。 したがって、2.6.3 以前のカーネ ルでは、このフィールドにアクセスしようとすると 常に値 0 (DT_UNKNOWN) が返される。 現在のところ、 d_type でファイルタイプを返す機能が完全にサポートされているのは、 いくつか のファイルシステムにおいてのみである (Btrfs, ext2, ext3, ext4 はサポートしている)。 どのア プリケーションも DT_UNKNOWN が返された際に適切に処理できなければならない。 getdents64() 元々の Linux の getdents() システムコールは、大きなファイルシステムと大きなファイルオフ セットを扱うことができなかった。そのため、Linux 2.4 で getdents64() が追加された。 getdents64() では、 d_ino と d_off でビット幅の大きなデータ型が使われている。また、 getdents64() では d_type フィールドが明示的にサポートされている。 getdents64() システムコールは getdents() と似ているが、 2 番目の引数が以下の構造体が入った バッファへのポインターである点が異なる。 struct linux_dirent64 { ino64_t d_ino; /* 64 ビットの inode 番号 */ off64_t d_off; /* 次の構造体への 64 ビットのオフセット */ unsigned short d_reclen; /* この dirent の大きさ */ unsigned char d_type; /* ファイル種別 */ char d_name[]; /* (ヌル終端された) ファイル名 */ };
返り値
成功した場合は、読み込んだバイト数が返される。 ディレクトリの終わりならば 0 が返される。 エラーの場合は -1 が返され、 errno に適切な値が設定される。
エラー
EBADF ファイルディスクリプター fd が不正である。 EFAULT 引数が呼び出し元プロセスのアドレス空間外を指している。 EINVAL 結果用のバッファーが小さすぎる。 ENOENT そのようなディレクトリは存在しない。 ENOTDIR ファイルディスクリプターがディレクトリを参照していない。
準拠
SVr4.
注意
getdents64() に対応するライブラリのサポートは glibc 2.30 で追加された。 getdents() に対す る glibc ラッパー関数は存在しない。 getdents() (もしくは glibc の古いバージョンでの getdents64()) を呼び出すには、 syscall(2) を使う必要がある。その場合、構造体 linux_dirent や linux_dirent64 を自分で定義する必要があるだろう。 おそらく、あなたが使いたいのは、これらのシステムコールではなく readdir(3) の方であろう。 これらのシステムコールは readdir(2) を置き換えるものである。
例
下記のプログラムは getdents() の使用例を示したものである。 以下は、このプログラムを ext2 ディレクトリで実行した際に得られる 出力の例である。 $ ./a.out /testfs/ --------------- nread=120 --------------- inode# file type d_reclen d_off d_name 2 directory 16 12 . 2 directory 16 24 .. 11 directory 24 44 lost+found 12 regular 16 56 a 228929 directory 16 68 sub 16353 directory 16 80 sub2 130817 directory 16 4096 sub3 プログラムのソース #define _GNU_SOURCE #include <dirent.h> /* DT_* 定数の定義 */ #include <fcntl.h> #include <stdint.h> #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <sys/stat.h> #include <sys/syscall.h> #define handle_error(msg) \ do { perror(msg); exit(EXIT_FAILURE); } while (0) struct linux_dirent { unsigned long d_ino; off_t d_off; unsigned short d_reclen; char d_name[]; }; #define BUF_SIZE 1024 int main(int argc, char *argv[]) { int fd; long nread; char buf[BUF_SIZE]; struct linux_dirent *d; char d_type; fd = open(argc > 1 ? argv[1] : ".", O_RDONLY | O_DIRECTORY); if (fd == -1) handle_error("open"); for (;;) { nread = syscall(SYS_getdents, fd, buf, BUF_SIZE); if (nread == -1) handle_error("getdents"); if (nread == 0) break; printf("--------------- nread=%d ---------------\n", nread); printf("inode# file type d_reclen d_off d_name\n"); for (long bpos = 0; bpos < nread;) { d = (struct linux_dirent *) (buf + bpos); printf("%8ld ", d->d_ino); d_type = *(buf + bpos + d->d_reclen - 1); printf("%-10s ", (d_type == DT_REG) ? "regular" : (d_type == DT_DIR) ? "directory" : (d_type == DT_FIFO) ? "FIFO" : (d_type == DT_SOCK) ? "socket" : (d_type == DT_LNK) ? "symlink" : (d_type == DT_BLK) ? "block dev" : (d_type == DT_CHR) ? "char dev" : "???"); printf("%4d %10jd %s\n", d->d_reclen, (intmax_t) d->d_off, d->d_name); bpos += d->d_reclen; } } exit(EXIT_SUCCESS); }
関連項目
readdir(2), readdir(3), inode(7)
この文書について
この man ページは Linux man-pages プロジェクトのリリース 5.10 の一部である。プロジェクトの 説明とバグ報告に関する情報は https://www.kernel.org/doc/man-pages/ に書かれている。