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

Linux                                              2020-11-01                                        GETDENTS(2)