GETDENTS - Linux手册页
Linux程序员手册 第2部分
更新日期: 2020-06-09
名称
getdents,getdents64-获取目录条目
语法
int getdents(unsigned int fd, struct linux_dirent *dirp, unsigned int count); int getdents64(unsigned int fd, struct linux_dirent64 *dirp, unsigned int count);
注意:getdents()没有glibc包装器;请参阅注释。
说明
这些不是您感兴趣的接口。请查看readdir(3)以了解符合POSIX的C库接口。本页记录了裸内核系统调用接口。
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是一个索引节点号。 d_off是从目录开始到下一个linux_dirent的距离。 d_reclen是整个linux_dirent的大小。 d_name是一个以空值结尾的文件名。
d_type是结构末尾的字节,指示文件类型。它包含以下值之一(在中定义):
- DT_BLK
- 这是一个块设备。
- DT_CHR
- 这是字符设备。
- DT_DIR
- 这是一个目录。
- DT_FIFO
- 这是一个命名管道(FIFO)。
- DT_LNK
- 这是一个符号链接。
- DT_REG
- 这是一个常规文件。
- DT_SOCK
- 这是UNIX域套接字。
- DT_UNKNOWN
- 文件类型未知。
从Linux 2.6.4开始实现d_type字段。它占用的空间以前是linux_dirent结构中的零填充填充字节。因此,在2.6.3及以下版本的内核上,尝试访问此字段始终提供值0(DT_UNKNOWN)。
当前,只有某些文件系统(其中包括Btrfs,ext2,ext3和ext4)完全支持返回d_type中的文件类型。所有应用程序都必须正确处理DT_UNKNOWN的返回。
getdents64()
原始的Linux getdents()系统调用无法处理大型文件系统和大型文件偏移量。因此,Linux 2.4添加了getdents64(),其中d_ino和d_off字段的类型更大。另外,getdents64()支持显式的d_type字段。
getdents64()系统调用类似于getdents(),不同之处在于它的第二个参数是指向包含以下类型结构的缓冲区的指针:
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。
备注
在glibc 2.30中添加了对getdents64()的库支持。没有用于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
Program source
#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 { 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, 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); }
出版信息
这个页面是Linux手册页项目5.08版的一部分。有关项目的说明、有关报告错误的信息以及此页面的最新版本,请访问https://www.kernel.org/doc/man-pages/。