getdents(2) System Calls Manual getdents(2) getdents, getdents64 - LIBRARY Standard C library (libc, -lc) #include /* SYS_* */ #include long syscall(SYS_getdents, unsigned int fd, struct linux_dirent *dirp, unsigned int count); #define _GNU_SOURCE /* feature_test_macros(7) */ #include ssize_t getdents64(int fd, void dirp[.count], size_t count); Note: glibc provides no wrapper for getdents(), necessitating the use of syscall(2). Note: There is no definition of struct linux_dirent in glibc; see NOTES. , . readdir(3), C, POSIX. . getdents() getdents() linux_dirent , fd, , dirp. count . linux_dirent : struct linux_dirent { unsigned long d_ino; /* */ unsigned long d_off; /* linux_dirent */ unsigned short d_reclen; /* linux_dirent */ char d_name[]; /* ( null) */ /* (d_reclen - 2 - offsetof(struct linux_dirent, d_name)) */ /* char pad; // char d_type; // ( Linux // 2.6.4); (d_reclen - 1) */ } d_ino inode. d_off linux_dirent. d_reclen linux_dirent . d_name , null. d_type -- , . ( ): DT_BLK DT_CHR DT_DIR DT_FIFO (FIFO) DT_LNK DT_REG DT_SOCK UNIX DT_UNKNOWN . The d_type field is implemented since Linux 2.6.4. It occupies a space that was previously a zero-filled padding byte in the linux_dirent structure. Thus, on kernels up to and including Linux 2.6.3, attempting to access this field always provides the value 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- */ off64_t d_off; /* 64- */ unsigned short d_reclen; /* dirent */ unsigned char d_type; /* */ char d_name[]; /* ( null) */ }; On success, the number of bytes read is returned. On end of directory, 0 is returned. On error, -1 is returned, and errno is set to indicate the error. EBADF fd. EFAULT . EINVAL . ENOENT . ENOTDIR . None. SVr4. getdents64() glibc 2.30. glibc does not provide a wrapper for getdents(); call getdents() using 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 /* Defines DT_* constants */ #include #include #include #include #include #include #include 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; char d_type; char buf[BUF_SIZE]; long nread; struct linux_dirent *d; fd = open(argc > 1 ? argv[1] : ".", O_RDONLY | O_DIRECTORY); if (fd == -1) err(EXIT_FAILURE, "open"); for (;;) { nread = syscall(SYS_getdents, fd, buf, BUF_SIZE); if (nread == -1) err(EXIT_FAILURE, "getdents"); if (nread == 0) break; printf("--------------- nread=%ld ---------------\n", nread); printf("inode# file type d_reclen d_off d_name\n"); for (size_t bpos = 0; bpos < nread;) { d = (struct linux_dirent *) (buf + bpos); printf("%8lu ", 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) Azamat Hackimov , Dmitry Bolkhovskikh , Vladislav , Yuri Kozlov ; GNU 3 , . . , , . Linux man-pages 6.06 31 2023 . getdents(2)