Manpages

名 前

getdents − デ ィ レ ク ト リ エ ン ト リ ー を 取 得 す る

書 式

int getdents(unsigned int fd, struct linux_dirent *dirp,
unsigned int
count); : こ の シ ス テ ム コ ー ル に は glibc の ラ ッ パ ー 関 数 は 存 在 し な い 。 「 注 意 」 の 節 を 参 照 。

説 明

こ れ は あ な た の 関 心 を 引 く よ う な 関 数 で は な い 。 POSIX 準 拠 の C ラ イ ブ ラ リ イ ン タ ー フ ェ ー ス に つ い て は readdir(3) を 見 る こ と 。 こ の ペ ー ジ は 、 カ ー ネ ル シ ス テ ム コ ー ル の 生 の イ ン タ ー フ ェ ー ス に つ い て 記 載 し た も の で あ る 。

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 が 返 さ れ た 際 に 適 切 に 処 理 で き な け れ ば な ら な い 。

返 り 値

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

エ ラ ー

EBADF フ ァ イ ル デ ィ ス ク リ プ タ ー

fd が 不 正 で あ る 。

EFAULT 引 き 数 が 呼 び 出 し た プ ロ セ ス

の ア ド レ ス 空 間 外 を 指 し て い る 。

EINVAL 結 果 用 の バ ッ フ ァ ー が 小 さ す ぎ る 。

ENOENT そ の よ う な デ ィ レ ク ト リ は 存 在 し な い 。

ENOTDIR フ ァ イ ル デ ィ ス ク リ プ タ ー が デ ィ レ ク ト リ を 参 照 し て い な い 。

準 拠

SVr4.

注 意

glibc は こ の シ ス テ ム コ ー ル に 対 す る ラ ッ パ ー 関 数 を 提 供 し て い な い の で 、 syscall(2) を 使 っ て 呼 び 出 す こ と 。 linux_dirent 構 造 体 は 自 分 で 定 義 す る 必 要 が あ る 。 し か し 、 た い て い は こ の シ ス テ ム コ ー ル で は な く readdir(3) を 使 う べ き 場 面 の こ と が 多 い 。 こ の シ ス テ ム コ ー ル は readdir(2) を 置 き 換 え る も の で あ る 。 元 々 の Linux の getdents() シ ス テ ム コ ー ル は 、 大 き な フ ァ イ ル シ ス テ ム と 大 き な フ ァ イ ル オ フ セ ッ ト を 扱 う こ と が で き な か っ た 。 そ の 結 果 、 Linux 2.4 で getdents64() が 追 加 さ れ た 。 getdents64() で は 、 linux_dirent 構 造 体 の フ ィ ー ル ド d_inod_off で ビ ッ ト 幅 の 大 き な デ ー タ 型 が 使 わ れ て い る 。

下 記 の プ ロ グ ラ ム は 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 <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 {
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, nread;
char buf[BUF_SIZE];
struct linux_dirent *d;
int bpos;
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 (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 %10lld %s\n", d−>d_reclen,
(long long) d−>d_off, d−>d_name);
bpos += d−>d_reclen; } }

exit(EXIT_SUCCESS); }

関 連 項 目

readdir(2), readdir(3)

こ の 文 書 に つ い て

こ の man ペ ー ジ は Linux man−pages プ ロ ジ ェ ク ト の リ リ ー ス 3.79 の 一 部 で あ る 。 プ ロ ジ ェ ク ト の 説 明 と バ グ 報 告 に 関 す る 情 報 は http://www.kernel.org/doc/man−pages/ に 書 か れ て い る 。