Provided by: manpages-ja-dev_0.5.0.0.20221215+dfsg-1_all bug

名前

       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_inod_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_direntlinux_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/ に書かれている。