summaryrefslogtreecommitdiffstats
path: root/src/dir.h
blob: 35a459d759495a2cdad32beeeff1ee695fc02a7e (plain)
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
171
172
173
174
175
176
177
178
// Copyright © Tavian Barnes <tavianator@tavianator.com>
// SPDX-License-Identifier: 0BSD

/**
 * Directories and their contents.
 */

#ifndef BFS_DIR_H
#define BFS_DIR_H

#include "bfs.h"

#include <sys/types.h>

/**
 * Whether the implementation uses the getdents() syscall directly, rather than
 * libc's readdir().
 */
#ifndef BFS_USE_GETDENTS
#  if BFS_HAS_POSIX_GETDENTS
#    define BFS_USE_GETDENTS true
#  elif __linux__ || __FreeBSD__
#    define BFS_USE_GETDENTS (BFS_HAS_GETDENTS || BFS_HAS_GETDENTS64 | BFS_HAS_GETDENTS64_SYSCALL)
#  else
#    define BFS_USE_GETDENTS false
#  endif
#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.
 *
 * @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.
 *
 * @dir
 *         The allocated directory.
 * @at_fd
 *         The base directory for path resolution.
 * @at_path
 *         The path of the directory to open, relative to at_fd.  Pass NULL to
 *         open at_fd itself.
 * @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.
 *
 * @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.
 *
 * @dir
 *         The directory to read.
 * @dirent (out)
 *         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 || BFS_HAS_FDCLOSEDIR)
#endif

#if BFS_USE_UNWRAPDIR
/**
 * Detach the file descriptor from an open directory.
 *
 * @dir
 *         The directory to detach.
 * @return
 *         The file descriptor of the directory.
 */
int bfs_unwrapdir(struct bfs_dir *dir);
#endif

#endif // BFS_DIR_H