GETDENTS

Section: Linux Programmer's Manual (2)
Updated: 2020-11-01
Index JM Home Page roff page
 

名前

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 number */
    unsigned long  d_off;     /* Offset to next linux_dirent */
    unsigned short d_reclen;  /* Length of this linux_dirent */
    char           d_name[];  /* Filename (null-terminated) */
                      /* length is actually (d_reclen - 2 -
                         offsetof(struct linux_dirent, d_name)) */
    /*
    char           pad;       // Zero padding byte
    char           d_type;    // File type (only since Linux
                              // 2.6.4); offset is (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()

The original Linux getdents() system call did not handle large filesystems and large file offsets. Consequently, Linux 2.4 added getdents64(), with wider types for the d_ino and d_off fields. In addition, getdents64() supports an explicit d_type field.

The getdents64() system call is like getdents(), except that its second argument is a pointer to a buffer containing structures of the following type:

struct linux_dirent64 {
    ino64_t        d_ino;    /* 64-bit inode number */
    off64_t        d_off;    /* 64-bit offset to next structure */
    unsigned short d_reclen; /* Size of this dirent */
    unsigned char  d_type;   /* File type */
    char           d_name[]; /* Filename (null-terminated) */ };  

返り値

成功した場合は、読み込んだバイト数が返される。 ディレクトリの終わりならば 0 が返される。 エラーの場合は -1 を返され、 errno に適切な値が設定される。  

エラー

EBADF
ファイルディスクリプター fd が不正である。
EFAULT
引き数が呼び出したプロセスのアドレス空間外を指している。
EINVAL
結果用のバッファーが小さすぎる。
ENOENT
そのようなディレクトリは存在しない。
ENOTDIR
ファイルディスクリプターがディレクトリを参照していない。
 

準拠

SVr4.  

注意

Library support for getdents64() was added in glibc 2.30; there is no glibc wrapper for getdents(). Calling getdents() (or getdents64() on earlier glibc versions) requires the use of syscall(2). In that case you will need to define the linux_dirent or linux_dirent64 structure yourself.

Probably, you want to use readdir(3) instead of these system calls.

これらのシステムコールは 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> /* Defines DT_* constants */ #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/ に書かれている。


 

Index

名前
書式
説明
getdents()
getdents64()
返り値
エラー
準拠
注意
プログラムのソース
関連項目
この文書について

This document was created by man2html, using the manual pages.
Time: 11:55:21 GMT, May 01, 2021