summaryrefslogtreecommitdiffstats
path: root/man/man2/getdents.2
diff options
context:
space:
mode:
Diffstat (limited to 'man/man2/getdents.2')
-rw-r--r--man/man2/getdents.2323
1 files changed, 323 insertions, 0 deletions
diff --git a/man/man2/getdents.2 b/man/man2/getdents.2
new file mode 100644
index 000000000..1e630f9e2
--- /dev/null
+++ b/man/man2/getdents.2
@@ -0,0 +1,323 @@
+.\" 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 (date) "Linux man-pages (unreleased)"
+.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>
+.P
+.BI "long syscall(SYS_getdents, unsigned int " fd \
+", struct linux_dirent *" dirp ,
+.BI " unsigned int " count );
+.P
+.BR "#define _GNU_SOURCE" " /* See feature_test_macros(7) */"
+.B #include <dirent.h>
+.P
+.BI "ssize_t getdents64(int " fd ", void " dirp [. count "], size_t " count );
+.fi
+.P
+.IR Note :
+glibc provides no wrapper for
+.BR getdents (),
+necessitating the use of
+.BR syscall (2).
+.P
+.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.
+.P
+The
+.I linux_dirent
+structure is declared as follows:
+.P
+.in +4n
+.EX
+struct linux_dirent {
+ unsigned long d_ino; /* Inode number */
+ unsigned long d_off; /* Not an offset; see below */
+ 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
+.P
+.I d_ino
+is an inode number.
+.I d_off
+is a filesystem-specific value with no specific meaning to user space,
+though on older filesystems it used to be
+the distance from the start of the directory to the start of the next
+.IR linux_dirent ;
+see
+.BR readdir (3) .
+.I d_reclen
+is the size of this entire
+.IR linux_dirent .
+.I d_name
+is a null-terminated filename.
+.P
+.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.
+.P
+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 ).
+.P
+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.
+.P
+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:
+.P
+.in +4n
+.EX
+struct linux_dirent64 {
+ ino64_t d_ino; /* 64\-bit inode number */
+ off64_t d_off; /* Not an offset; see getdents() */
+ 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.
+.P
+Probably, you want to use
+.BR readdir (3)
+instead of these system calls.
+.P
+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:
+.P
+.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)