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/ に書かれている。 Linux 2020-11-01 GETDENTS(2)