1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
|
// Copyright © Tavian Barnes <tavianator@tavianator.com>
// SPDX-License-Identifier: 0BSD
/**
* Directories and their contents.
*/
#ifndef BFS_DIR_H
#define BFS_DIR_H
#include <sys/types.h>
/**
* Whether the implementation uses the getdents() syscall directly, rather than
* libc's readdir().
*/
#if !defined(BFS_USE_GETDENTS) && (__linux__ || __FreeBSD__)
# define BFS_USE_GETDENTS (BFS_HAS_GETDENTS || BFS_HAS_GETDENTS64 | BFS_HAS_GETDENTS64_SYSCALL)
#endif
/**
* A directory.
*/
struct bfs_dir;
/**
* File types.
*/
enum bfs_type {
/** An error occurred for this file. */
BFS_ERROR = -1,
/** Unknown type. */
BFS_UNKNOWN,
/** Block device. */
BFS_BLK,
/** Character device. */
BFS_CHR,
/** Directory. */
BFS_DIR,
/** Solaris door. */
BFS_DOOR,
/** Pipe. */
BFS_FIFO,
/** Symbolic link. */
BFS_LNK,
/** Solaris event port. */
BFS_PORT,
/** Regular file. */
BFS_REG,
/** Socket. */
BFS_SOCK,
/** BSD whiteout. */
BFS_WHT,
};
/**
* Convert a bfs_stat() mode to a bfs_type.
*/
enum bfs_type bfs_mode_to_type(mode_t mode);
/**
* A directory entry.
*/
struct bfs_dirent {
/** The type of this file (possibly unknown). */
enum bfs_type type;
/** The name of this file. */
const char *name;
};
/**
* Allocate space for a directory.
*
* @return
* An allocated, unopen directory, or NULL on failure.
*/
struct bfs_dir *bfs_allocdir(void);
struct arena;
/**
* Initialize an arena for directories.
*
* @param arena
* The arena to initialize.
*/
void bfs_dir_arena(struct arena *arena);
/**
* bfs_opendir() flags.
*/
enum bfs_dir_flags {
/** Include whiteouts in the results. */
BFS_DIR_WHITEOUTS = 1 << 0,
/** @internal Start of private flags. */
BFS_DIR_PRIVATE = 1 << 1,
};
/**
* Open a directory.
*
* @param dir
* The allocated directory.
* @param at_fd
* The base directory for path resolution.
* @param at_path
* The path of the directory to open, relative to at_fd. Pass NULL to
* open at_fd itself.
* @param flags
* Flags that control which directory entries are listed.
* @return
* 0 on success, or -1 on failure.
*/
int bfs_opendir(struct bfs_dir *dir, int at_fd, const char *at_path, enum bfs_dir_flags flags);
/**
* Get the file descriptor for a directory.
*/
int bfs_dirfd(const struct bfs_dir *dir);
/**
* Performs any I/O necessary for the next bfs_readdir() call.
*
* @param dir
* The directory to poll.
* @return
* 1 on success, 0 on EOF, or -1 on failure.
*/
int bfs_polldir(struct bfs_dir *dir);
/**
* Read a directory entry.
*
* @param dir
* The directory to read.
* @param[out] dirent
* The directory entry to populate.
* @return
* 1 on success, 0 on EOF, or -1 on failure.
*/
int bfs_readdir(struct bfs_dir *dir, struct bfs_dirent *de);
/**
* Close a directory.
*
* @return
* 0 on success, -1 on failure.
*/
int bfs_closedir(struct bfs_dir *dir);
/**
* Whether the bfs_unwrapdir() function is supported.
*/
#ifndef BFS_USE_UNWRAPDIR
# define BFS_USE_UNWRAPDIR (BFS_USE_GETDENTS || __FreeBSD__)
#endif
#if BFS_USE_UNWRAPDIR
/**
* Detach the file descriptor from an open directory.
*
* @param dir
* The directory to detach.
* @return
* The file descriptor of the directory.
*/
int bfs_unwrapdir(struct bfs_dir *dir);
#endif
#endif // BFS_DIR_H
|