diff options
Diffstat (limited to '')
-rw-r--r-- | man2/getdents.2 | 319 |
1 files changed, 319 insertions, 0 deletions
diff --git a/man2/getdents.2 b/man2/getdents.2 new file mode 100644 index 0000000..604a6ef --- /dev/null +++ b/man2/getdents.2 @@ -0,0 +1,319 @@ +.\" Copyright (C) 1995 Andries Brouwer (aeb@cwi.nl) +.\" and Copyright 2008, 2015 Michael Kerrisk <mtk.manpages@gmail.com> +.\" +.\" SPDX-License-Identifier: Linux-man-pages-copyleft +.\" +.\" Written 11 June 1995 by Andries Brouwer <aeb@cwi.nl> +.\" Modified 22 July 1995 by Michael Chastain <mec@duracef.shout.net>: +.\" Derived from 'readdir.2'. +.\" Modified Tue Oct 22 08:11:14 EDT 1996 by Eric S. Raymond <esr@thyrsus.com> +.\" +.TH getdents 2 2023-05-03 "Linux man-pages 6.05.01" +.SH NAME +getdents, getdents64 \- get directory entries +.SH LIBRARY +Standard C library +.RI ( libc ", " \-lc ) +.SH SYNOPSIS +.nf +.BR "#include <sys/syscall.h>" " /* Definition of " SYS_* " constants */" +.B #include <unistd.h> +.PP +.BI "long syscall(SYS_getdents, unsigned int " fd \ +", struct linux_dirent *" dirp , +.BI " unsigned int " count ); +.PP +.BR "#define _GNU_SOURCE" " /* See feature_test_macros(7) */" +.B #include <dirent.h> +.PP +.BI "ssize_t getdents64(int " fd ", void " dirp [. count "], size_t " count ); +.fi +.PP +.IR Note : +glibc provides no wrapper for +.BR getdents (), +necessitating the use of +.BR syscall (2). +.PP +.IR Note : +There is no definition of +.I struct linux_dirent +in glibc; see NOTES. +.SH DESCRIPTION +These are not the interfaces you are interested in. +Look at +.BR readdir (3) +for the POSIX-conforming C library interface. +This page documents the bare kernel system call interfaces. +.SS getdents() +The system call +.BR getdents () +reads several +.I linux_dirent +structures from the directory +referred to by the open file descriptor +.I fd +into the buffer pointed to by +.IR dirp . +The argument +.I count +specifies the size of that buffer. +.PP +The +.I linux_dirent +structure is declared as follows: +.PP +.in +4n +.EX +struct linux_dirent { + unsigned long d_ino; /* Inode number */ + unsigned long d_off; /* Offset to next \fIlinux_dirent\fP */ + unsigned short d_reclen; /* Length of this \fIlinux_dirent\fP */ + 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) + */ +} +.EE +.in +.PP +.I d_ino +is an inode number. +.I d_off +is the distance from the start of the directory to the start of the next +.IR linux_dirent . +.I d_reclen +is the size of this entire +.IR linux_dirent . +.I d_name +is a null-terminated filename. +.PP +.I d_type +is a byte at the end of the structure that indicates the file type. +It contains one of the following values (defined in +.IR <dirent.h> ): +.TP 12 +.B DT_BLK +This is a block device. +.TP +.B DT_CHR +This is a character device. +.TP +.B DT_DIR +This is a directory. +.TP +.B DT_FIFO +This is a named pipe (FIFO). +.TP +.B DT_LNK +This is a symbolic link. +.TP +.B DT_REG +This is a regular file. +.TP +.B DT_SOCK +This is a UNIX domain socket. +.TP +.B DT_UNKNOWN +The file type is unknown. +.PP +The +.I d_type +field is implemented since Linux 2.6.4. +It occupies a space that was previously a zero-filled padding byte in the +.I linux_dirent +structure. +Thus, on kernels up to and including Linux 2.6.3, +attempting to access this field always provides the value 0 +.RB ( DT_UNKNOWN ). +.PP +Currently, +.\" kernel 2.6.27 +.\" The same sentence is in readdir.2 +only some filesystems (among them: Btrfs, ext2, ext3, and ext4) +have full support for returning the file type in +.IR d_type . +All applications must properly handle a return of +.BR DT_UNKNOWN . +.SS getdents64() +The original Linux +.BR getdents () +system call did not handle large filesystems and large file offsets. +Consequently, Linux 2.4 added +.BR getdents64 (), +with wider types for the +.I d_ino +and +.I d_off +fields. +In addition, +.BR getdents64 () +supports an explicit +.I d_type +field. +.PP +The +.BR getdents64 () +system call is like +.BR getdents (), +except that its second argument is a pointer to a buffer containing +structures of the following type: +.PP +.in +4n +.EX +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) */ +}; +.EE +.in +.SH RETURN VALUE +On success, the number of bytes read is returned. +On end of directory, 0 is returned. +On error, \-1 is returned, and +.I errno +is set to indicate the error. +.SH ERRORS +.TP +.B EBADF +Invalid file descriptor +.IR fd . +.TP +.B EFAULT +Argument points outside the calling process's address space. +.TP +.B EINVAL +Result buffer is too small. +.TP +.B ENOENT +No such directory. +.TP +.B ENOTDIR +File descriptor does not refer to a directory. +.SH STANDARDS +None. +.SH HISTORY +SVr4. +.\" SVr4 documents additional ENOLINK, EIO error conditions. +.TP +.BR getdents64 () +glibc 2.30. +.SH NOTES +glibc does not provide a wrapper for +.BR getdents (); +call +.BR getdents () +using +.BR syscall (2). +In that case you will need to define the +.I linux_dirent +or +.I linux_dirent64 +structure yourself. +.PP +Probably, you want to use +.BR readdir (3) +instead of these system calls. +.PP +These calls supersede +.BR readdir (2). +.SH EXAMPLES +.\" FIXME The example program needs to be revised, since it uses the older +.\" getdents() system call and the structure with smaller field widths. +The program below demonstrates the use of +.BR getdents (). +The following output shows an example of what we see when running this +program on an ext2 directory: +.PP +.in +4n +.EX +.RB "$" " ./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 +.EE +.in +.SS Program source +\& +.\" SRC BEGIN (getdents.c) +.EX +#define _GNU_SOURCE +#include <dirent.h> /* Defines DT_* constants */ +#include <err.h> +#include <fcntl.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <sys/syscall.h> +#include <unistd.h> +\& +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 \-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\en", nread); + printf("inode# file type d_reclen d_off d_name\en"); + 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\en", d\->d_reclen, + (intmax_t) d\->d_off, d\->d_name); + bpos += d\->d_reclen; + } + } +\& + exit(EXIT_SUCCESS); +} +.EE +.\" SRC END +.SH SEE ALSO +.BR readdir (2), +.BR readdir (3), +.BR inode (7) |