180 lines
5.5 KiB
C
180 lines
5.5 KiB
C
#ifndef VLIBC_DIRENT_H
|
|
#define VLIBC_DIRENT_H
|
|
|
|
/*
|
|
* vlibc — <dirent.h>.
|
|
*
|
|
* Directory streams: opendir/fdopendir/readdir/rewinddir/closedir,
|
|
* seekdir/telldir/dirfd (POSIX.1-2008 base) iterate a directory via the
|
|
* SYS_getdents64 kernel ABI, exposing one entry at a time.
|
|
*
|
|
* Level 1 (onlyposix): the base family above.
|
|
* Level 2 (muslmimic): scandir, alphasort (XSI) and readdir_r
|
|
* (obsolescent). versionsort is GNU and is not
|
|
* provided.
|
|
*
|
|
* struct dirent mirrors the x86_64 getdents64 record layout (verified by
|
|
* the static assertions below): d_ino/d_off are 64-bit, d_reclen is the
|
|
* kernel record length, d_type carries the DT_* file type, and d_name is a
|
|
* 256-byte NUL-terminated name buffer (NAME_MAX 255 + NUL).
|
|
*
|
|
* DIR is an opaque handle whose layout lives in the internal header
|
|
* src/dirent/dirent_impl.h. None of these declarations carries an intent
|
|
* attribute: every function performs I/O with side effects and reports
|
|
* failures through errno, so const/pure would be unsound (the same
|
|
* rationale sys/stat.h documents for its I/O family).
|
|
*/
|
|
|
|
#include <vlibc/features.h>
|
|
|
|
#include <stddef.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
/* File type values for the d_type member of struct dirent (kernel UAPI). */
|
|
#define DT_UNKNOWN 0
|
|
#define DT_FIFO 1
|
|
#define DT_CHR 2
|
|
#define DT_DIR 4
|
|
#define DT_BLK 6
|
|
#define DT_REG 8
|
|
#define DT_LNK 10
|
|
#define DT_SOCK 12
|
|
#define DT_WHT 14
|
|
|
|
/*
|
|
* One directory entry. Layout equals the x86_64 struct linux_dirent64
|
|
* fields 0..18 verbatim; the name then follows at offset 19, stored in the
|
|
* conventional 256-byte buffer.
|
|
*/
|
|
struct dirent
|
|
{
|
|
ino_t d_ino; /* 0: inode number */
|
|
off_t d_off; /* 8: offset of the next entry (seek cookie) */
|
|
unsigned short d_reclen; /* 16: length of the kernel record */
|
|
unsigned char d_type; /* 18: DT_* file type */
|
|
char d_name[256]; /* 19: NUL-terminated file name */
|
|
};
|
|
|
|
/* Pin the layout to the x86_64 kernel ABI. */
|
|
_Static_assert(sizeof(struct dirent) == 280, "struct dirent must match the x86_64 getdents64 layout");
|
|
_Static_assert(offsetof(struct dirent, d_off) == 8, "d_off must sit at offset 8");
|
|
_Static_assert(offsetof(struct dirent, d_type) == 18, "d_type must sit at offset 18");
|
|
_Static_assert(offsetof(struct dirent, d_name) == 19, "d_name must sit at offset 19");
|
|
|
|
/*
|
|
* Opaque directory stream handle. The struct tag stays usable from the
|
|
* internal layout header, which defines struct vlibc_DIR (see
|
|
* src/dirent/dirent_impl.h).
|
|
*/
|
|
typedef struct vlibc_DIR DIR;
|
|
|
|
/*
|
|
* Open the directory named by path for reading and return a directory
|
|
* stream positioned at its first entry, or NULL with errno set (a
|
|
* non-directory path fails with ENOTDIR). The stream owns a descriptor
|
|
* that closedir() releases.
|
|
*/
|
|
DIR *
|
|
opendir(const char *path);
|
|
|
|
/*
|
|
* Like opendir(), but over the already-open descriptor fd, which must
|
|
* refer to a directory (validated with fstat). On failure NULL is returned
|
|
* with errno set and fd is left open and owned by the caller.
|
|
*/
|
|
DIR *
|
|
fdopendir(int fd);
|
|
|
|
/*
|
|
* Return the next directory entry of dir, or NULL at the end of the
|
|
* directory (errno untouched) or on error (errno set). The result points
|
|
* at storage owned by dir and is valid until the next call to readdir,
|
|
* rewinddir, seekdir, or closedir on the same stream.
|
|
*/
|
|
struct dirent *
|
|
readdir(DIR *dir);
|
|
|
|
/*
|
|
* Reset dir to the beginning of the directory: the next readdir returns
|
|
* the first entry again. Never fails.
|
|
*/
|
|
void
|
|
rewinddir(DIR *dir);
|
|
|
|
/*
|
|
* Close dir, releasing its descriptor and storage. Return 0, or -1 with
|
|
* errno set if the underlying close fails.
|
|
*/
|
|
int
|
|
closedir(DIR *dir);
|
|
|
|
/*
|
|
* Reposition dir so the next readdir resumes at the location loc, which
|
|
* must be a value previously returned by telldir (a getdents64 seek
|
|
* cookie). Never fails.
|
|
*/
|
|
void
|
|
seekdir(DIR *dir, long loc);
|
|
|
|
/*
|
|
* Return the current location of dir, for a later seekdir. The location is
|
|
* the point after the entry most recently returned by readdir; it becomes
|
|
* indeterminate after rewinddir or closedir.
|
|
*/
|
|
long
|
|
telldir(DIR *dir);
|
|
|
|
/*
|
|
* Return the descriptor underlying dir. The descriptor stays owned by the
|
|
* stream and remains valid until closedir.
|
|
*/
|
|
int
|
|
dirfd(DIR *dir);
|
|
|
|
#if VLIBC_LEVEL_GE(2)
|
|
|
|
/* Level 2 (muslmimic): XSI and obsolescent. */
|
|
|
|
/*
|
|
* Reentrant readdir: store the next entry in *buf and set *result to buf;
|
|
* at the end of the directory *result is NULL. Returns 0 at end of
|
|
* directory, an error number on failure (errno is not used for the error
|
|
* report), and leaves errno unmodified on success. Obsolescent.
|
|
*/
|
|
int
|
|
readdir_r(DIR *restrict dir, struct dirent *restrict buf,
|
|
struct dirent **restrict result);
|
|
|
|
/*
|
|
* Read the whole directory named by path and store a malloc'd array of
|
|
* malloc'd struct dirent copies in *res (both released with free; the
|
|
* array is NULL-terminated with one extra NULL pointer). Only entries for
|
|
* which sel is NULL or returns nonzero are kept; cmp, when non-NULL, sorts
|
|
* the array (alphasort is the strcmp-on-name comparator). Returns the
|
|
* number of entries, or -1 with errno set. XSI.
|
|
*/
|
|
int
|
|
scandir(const char *path, struct dirent ***res,
|
|
int (*sel)(const struct dirent *),
|
|
int (*cmp)(const struct dirent **, const struct dirent **));
|
|
|
|
/*
|
|
* Lexicographic comparator over the d_name fields of two struct dirent
|
|
* pointers, for use as scandir's cmp argument. XSI.
|
|
*/
|
|
int
|
|
alphasort(const struct dirent **a, const struct dirent **b);
|
|
|
|
#endif /* VLIBC_LEVEL_GE(2) */
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif /* VLIBC_DIRENT_H */
|