openat: don’t close (-1)
[gnulib.git] / lib / dirent.in.h
bloba0ac39b4968fe211709d43b961b48af17043978a
1 /* A GNU-like <dirent.h>.
2 Copyright (C) 2006-2024 Free Software Foundation, Inc.
4 This file is free software: you can redistribute it and/or modify
5 it under the terms of the GNU Lesser General Public License as
6 published by the Free Software Foundation; either version 2.1 of the
7 License, or (at your option) any later version.
9 This file is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU Lesser General Public License for more details.
14 You should have received a copy of the GNU Lesser General Public License
15 along with this program. If not, see <https://www.gnu.org/licenses/>. */
17 #ifndef _@GUARD_PREFIX@_DIRENT_H
19 #if __GNUC__ >= 3
20 @PRAGMA_SYSTEM_HEADER@
21 #endif
22 @PRAGMA_COLUMNS@
24 /* The include_next requires a split double-inclusion guard. */
25 #if @HAVE_DIRENT_H@
26 # @INCLUDE_NEXT@ @NEXT_DIRENT_H@
27 #endif
29 #ifndef _@GUARD_PREFIX@_DIRENT_H
30 #define _@GUARD_PREFIX@_DIRENT_H
32 /* This file uses _GL_ATTRIBUTE_DEALLOC, _GL_ATTRIBUTE_MALLOC,
33 _GL_ATTRIBUTE_PURE, GNULIB_POSIXCHECK, HAVE_RAW_DECL_*. */
34 #if !_GL_CONFIG_H_INCLUDED
35 #error "Please include config.h first."
36 #endif
38 /* Get ino_t. Needed on some systems, including glibc 2.8. */
39 #include <sys/types.h>
41 #if !@HAVE_DIRENT_H@
42 /* Define types DIR and 'struct dirent'. */
43 # if !GNULIB_defined_struct_dirent
44 struct dirent
46 char d_type;
47 char d_name[1];
49 # define GNULIB_defined_struct_dirent 1
50 # endif
51 #endif
53 /* 'd_type' macros specified in GNU, i.e., POSIX.1-2024 plus DT_WHT,
54 but not (yet) DT_MQ, DT_SEM, DT_SHM, DT_TMO.
55 These macros can be useful even on platforms that do not support
56 d_type or the corresponding file types.
57 The values of these macros are all in the 'unsigned char' range.
58 Default to the Linux values which are also popular elsewhere,
59 and check that all macros have distinct values. */
60 #ifndef DT_UNKNOWN
61 # define DT_UNKNOWN 0
62 #endif
63 #ifndef DT_FIFO
64 # define DT_FIFO 1 /* FIFO */
65 #endif
66 #ifndef DT_CHR
67 # define DT_CHR 2 /* character device */
68 #endif
69 #ifndef DT_DIR
70 # define DT_DIR 4 /* directory */
71 #endif
72 #ifndef DT_BLK
73 # define DT_BLK 6 /* block device */
74 #endif
75 #ifndef DT_REG
76 # define DT_REG 8 /* regular file */
77 #endif
78 #ifndef DT_LNK
79 # define DT_LNK 10 /* symbolic link */
80 #endif
81 #ifndef DT_SOCK
82 # define DT_SOCK 12 /* socket */
83 #endif
84 #ifndef DT_WHT
85 # define DT_WHT 14 /* whiteout */
86 #endif
87 static_assert (DT_UNKNOWN != DT_FIFO && DT_UNKNOWN != DT_CHR
88 && DT_UNKNOWN != DT_BLK && DT_UNKNOWN != DT_REG
89 && DT_UNKNOWN != DT_LNK && DT_UNKNOWN != DT_SOCK
90 && DT_UNKNOWN != DT_WHT
91 && DT_FIFO != DT_CHR && DT_FIFO != DT_BLK && DT_FIFO != DT_REG
92 && DT_FIFO != DT_LNK && DT_FIFO != DT_SOCK && DT_FIFO != DT_WHT
93 && DT_CHR != DT_BLK && DT_CHR != DT_REG && DT_CHR != DT_LNK
94 && DT_CHR != DT_SOCK && DT_CHR != DT_WHT
95 && DT_BLK != DT_REG && DT_BLK != DT_LNK && DT_BLK != DT_SOCK
96 && DT_BLK != DT_WHT
97 && DT_REG != DT_LNK && DT_REG != DT_SOCK && DT_REG != DT_WHT
98 && DT_LNK != DT_SOCK && DT_LNK != DT_WHT
99 && DT_SOCK != DT_WHT);
101 /* Other optional information about a directory entry. */
102 #define _GL_DT_NOTDIR 0x100 /* Not a directory */
104 /* Conversion between S_IF* and DT_* file types. */
105 #if ! (defined IFTODT && defined DTTOIF)
106 # include <sys/stat.h>
107 # ifdef S_ISWHT
108 # define _GL_DIRENT_S_ISWHT(mode) S_ISWHT(mode)
109 # else
110 # define _GL_DIRENT_S_ISWHT(mode) 0
111 # endif
112 # ifdef S_IFWHT
113 # define _GL_DIRENT_S_IFWHT S_IFWHT
114 # else
115 # define _GL_DIRENT_S_IFWHT (DT_WHT << 12) /* just a guess */
116 # endif
117 #endif
118 /* Conversion from a 'stat' mode to a DT_* value. */
119 #ifndef IFTODT
120 # define IFTODT(mode) \
121 (S_ISREG (mode) ? DT_REG : S_ISDIR (mode) ? DT_DIR \
122 : S_ISLNK (mode) ? DT_LNK : S_ISBLK (mode) ? DT_BLK \
123 : S_ISCHR (mode) ? DT_CHR : S_ISFIFO (mode) ? DT_FIFO \
124 : S_ISSOCK (mode) ? DT_SOCK \
125 : _GL_DIRENT_S_ISWHT (mode) ? DT_WHT : DT_UNKNOWN)
126 #endif
127 /* Conversion from a DT_* value to a 'stat' mode. */
128 #ifndef DTTOIF
129 # define DTTOIF(dirtype) \
130 ((dirtype) == DT_REG ? S_IFREG : (dirtype) == DT_DIR ? S_IFDIR \
131 : (dirtype) == DT_LNK ? S_IFLNK : (dirtype) == DT_BLK ? S_IFBLK \
132 : (dirtype) == DT_CHR ? S_IFCHR : dirtype == DT_FIFO ? S_IFIFO \
133 : (dirtype) == DT_SOCK ? S_IFSOCK \
134 : (dirtype) == DT_WHT ? _GL_DIRENT_S_IFWHT \
135 : (dirtype) << 12 /* just a guess */)
136 #endif
138 #if !@DIR_HAS_FD_MEMBER@
139 # if !GNULIB_defined_DIR
140 /* struct gl_directory is a type with a field 'int fd_to_close'.
141 It is needed for implementing fdopendir(). */
142 struct gl_directory;
143 # if @HAVE_DIRENT_H@
144 # define DIR struct gl_directory
145 # else
146 typedef struct gl_directory DIR;
147 # endif
148 # define GNULIB_defined_DIR 1
149 # endif
150 #endif
152 /* _GL_ATTRIBUTE_DEALLOC (F, I) declares that the function returns pointers
153 that can be freed by passing them as the Ith argument to the
154 function F. */
155 #ifndef _GL_ATTRIBUTE_DEALLOC
156 # if __GNUC__ >= 11 && !defined __clang__
157 # define _GL_ATTRIBUTE_DEALLOC(f, i) __attribute__ ((__malloc__ (f, i)))
158 # else
159 # define _GL_ATTRIBUTE_DEALLOC(f, i)
160 # endif
161 #endif
163 /* _GL_ATTRIBUTE_MALLOC declares that the function returns a pointer to freshly
164 allocated memory. */
165 /* Applies to: functions. */
166 #ifndef _GL_ATTRIBUTE_MALLOC
167 # if __GNUC__ >= 3 || defined __clang__
168 # define _GL_ATTRIBUTE_MALLOC __attribute__ ((__malloc__))
169 # else
170 # define _GL_ATTRIBUTE_MALLOC
171 # endif
172 #endif
174 /* The __attribute__ feature is available in gcc versions 2.5 and later.
175 The attribute __pure__ was added in gcc 2.96. */
176 #ifndef _GL_ATTRIBUTE_PURE
177 # if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96) || defined __clang__
178 # define _GL_ATTRIBUTE_PURE __attribute__ ((__pure__))
179 # else
180 # define _GL_ATTRIBUTE_PURE /* empty */
181 # endif
182 #endif
184 /* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */
186 /* The definition of _GL_ARG_NONNULL is copied here. */
188 /* The definition of _GL_WARN_ON_USE is copied here. */
191 /* Declare overridden functions. */
193 #if @GNULIB_CLOSEDIR@
194 # if @REPLACE_CLOSEDIR@
195 # if !(defined __cplusplus && defined GNULIB_NAMESPACE)
196 # undef closedir
197 # define closedir rpl_closedir
198 # define GNULIB_defined_closedir 1
199 # endif
200 _GL_FUNCDECL_RPL (closedir, int, (DIR *dirp), _GL_ARG_NONNULL ((1)));
201 _GL_CXXALIAS_RPL (closedir, int, (DIR *dirp));
202 # else
203 # if !@HAVE_CLOSEDIR@
204 _GL_FUNCDECL_SYS (closedir, int, (DIR *dirp), _GL_ARG_NONNULL ((1)));
205 # endif
206 _GL_CXXALIAS_SYS (closedir, int, (DIR *dirp));
207 # endif
208 _GL_CXXALIASWARN (closedir);
209 #elif defined GNULIB_POSIXCHECK
210 # undef closedir
211 # if HAVE_RAW_DECL_CLOSEDIR
212 _GL_WARN_ON_USE (closedir, "closedir is not portable - "
213 "use gnulib module closedir for portability");
214 # endif
215 #endif
217 #if @GNULIB_OPENDIR@
218 # if @REPLACE_OPENDIR@
219 # if !(defined __cplusplus && defined GNULIB_NAMESPACE)
220 # undef opendir
221 # define opendir rpl_opendir
222 # define GNULIB_defined_opendir 1
223 # endif
224 _GL_FUNCDECL_RPL (opendir, DIR *,
225 (const char *dir_name),
226 _GL_ARG_NONNULL ((1))
227 _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC (closedir, 1));
228 _GL_CXXALIAS_RPL (opendir, DIR *, (const char *dir_name));
229 # else
230 # if !@HAVE_OPENDIR@ || (__GNUC__ >= 11 && !defined __clang__)
231 _GL_FUNCDECL_SYS (opendir, DIR *,
232 (const char *dir_name),
233 _GL_ARG_NONNULL ((1))
234 _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC (closedir, 1));
235 # endif
236 _GL_CXXALIAS_SYS (opendir, DIR *, (const char *dir_name));
237 # endif
238 _GL_CXXALIASWARN (opendir);
239 #else
240 # if @GNULIB_CLOSEDIR@ && !GNULIB_defined_DIR \
241 && (__GNUC__ >= 11 && !defined __clang__) && !defined opendir
242 /* For -Wmismatched-dealloc: Associate opendir with closedir or
243 rpl_closedir. */
244 _GL_FUNCDECL_SYS (opendir, DIR *,
245 (const char *dir_name),
246 _GL_ARG_NONNULL ((1))
247 _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC (closedir, 1));
248 # endif
249 # if defined GNULIB_POSIXCHECK
250 # undef opendir
251 # if HAVE_RAW_DECL_OPENDIR
252 _GL_WARN_ON_USE (opendir, "opendir is not portable - "
253 "use gnulib module opendir for portability");
254 # endif
255 # endif
256 #endif
258 #if @GNULIB_READDIR@
259 # if @REPLACE_READDIR@
260 # if !(defined __cplusplus && defined GNULIB_NAMESPACE)
261 # undef readdir
262 # define readdir rpl_readdir
263 # endif
264 _GL_FUNCDECL_RPL (readdir, struct dirent *, (DIR *dirp), _GL_ARG_NONNULL ((1)));
265 _GL_CXXALIAS_RPL (readdir, struct dirent *, (DIR *dirp));
266 # else
267 # if !@HAVE_READDIR@
268 _GL_FUNCDECL_SYS (readdir, struct dirent *, (DIR *dirp), _GL_ARG_NONNULL ((1)));
269 # endif
270 _GL_CXXALIAS_SYS (readdir, struct dirent *, (DIR *dirp));
271 # endif
272 _GL_CXXALIASWARN (readdir);
273 #elif defined GNULIB_POSIXCHECK
274 # undef readdir
275 # if HAVE_RAW_DECL_READDIR
276 _GL_WARN_ON_USE (readdir, "readdir is not portable - "
277 "use gnulib module readdir for portability");
278 # endif
279 #endif
281 #if @GNULIB_REWINDDIR@
282 # if @REPLACE_REWINDDIR@
283 # if !(defined __cplusplus && defined GNULIB_NAMESPACE)
284 # undef rewinddir
285 # define rewinddir rpl_rewinddir
286 # endif
287 _GL_FUNCDECL_RPL (rewinddir, void, (DIR *dirp), _GL_ARG_NONNULL ((1)));
288 _GL_CXXALIAS_RPL (rewinddir, void, (DIR *dirp));
289 # else
290 # if !@HAVE_REWINDDIR@
291 _GL_FUNCDECL_SYS (rewinddir, void, (DIR *dirp), _GL_ARG_NONNULL ((1)));
292 # endif
293 _GL_CXXALIAS_SYS (rewinddir, void, (DIR *dirp));
294 # endif
295 _GL_CXXALIASWARN (rewinddir);
296 #elif defined GNULIB_POSIXCHECK
297 # undef rewinddir
298 # if HAVE_RAW_DECL_REWINDDIR
299 _GL_WARN_ON_USE (rewinddir, "rewinddir is not portable - "
300 "use gnulib module rewinddir for portability");
301 # endif
302 #endif
304 #if @GNULIB_DIRFD@
305 /* Return the file descriptor associated with the given directory stream,
306 or -1 if none exists. */
307 # if @REPLACE_DIRFD@
308 /* On kLIBC, dirfd() is a macro that does not work. Undefine it. */
309 # if !(defined __cplusplus && defined GNULIB_NAMESPACE) || defined dirfd
310 # undef dirfd
311 # define dirfd rpl_dirfd
312 # endif
313 _GL_FUNCDECL_RPL (dirfd, int, (DIR *), _GL_ARG_NONNULL ((1)));
314 _GL_CXXALIAS_RPL (dirfd, int, (DIR *));
316 # else
317 # if defined __cplusplus && defined GNULIB_NAMESPACE && defined dirfd
318 /* dirfd is defined as a macro and not as a function.
319 Turn it into a function and get rid of the macro. */
320 static inline int (dirfd) (DIR *dp) { return dirfd (dp); }
321 # undef dirfd
322 # endif
323 # if !(@HAVE_DECL_DIRFD@ || defined dirfd)
324 _GL_FUNCDECL_SYS (dirfd, int, (DIR *), _GL_ARG_NONNULL ((1)));
325 # endif
326 _GL_CXXALIAS_SYS (dirfd, int, (DIR *));
327 # endif
328 _GL_CXXALIASWARN (dirfd);
329 #elif defined GNULIB_POSIXCHECK
330 # undef dirfd
331 # if HAVE_RAW_DECL_DIRFD
332 _GL_WARN_ON_USE (dirfd, "dirfd is unportable - "
333 "use gnulib module dirfd for portability");
334 # endif
335 #endif
337 #if @GNULIB_FDOPENDIR@
338 /* Open a directory stream visiting the given directory file
339 descriptor. Return NULL and set errno if fd is not visiting a
340 directory. On success, this function consumes fd (it will be
341 implicitly closed either by this function or by a subsequent
342 closedir). */
343 # if @REPLACE_FDOPENDIR@
344 # if !(defined __cplusplus && defined GNULIB_NAMESPACE)
345 # undef fdopendir
346 # define fdopendir rpl_fdopendir
347 # endif
348 _GL_FUNCDECL_RPL (fdopendir, DIR *,
349 (int fd),
350 _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC (closedir, 1));
351 _GL_CXXALIAS_RPL (fdopendir, DIR *, (int fd));
352 # else
353 # if !@HAVE_FDOPENDIR@ || !@HAVE_DECL_FDOPENDIR@ \
354 || (__GNUC__ >= 11 && !defined __clang__)
355 _GL_FUNCDECL_SYS (fdopendir, DIR *,
356 (int fd),
357 _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC (closedir, 1));
358 # endif
359 _GL_CXXALIAS_SYS (fdopendir, DIR *, (int fd));
360 # endif
361 _GL_CXXALIASWARN (fdopendir);
362 #else
363 # if @GNULIB_CLOSEDIR@ \
364 && (__GNUC__ >= 11 && !defined __clang__) && !defined fdopendir
365 /* For -Wmismatched-dealloc: Associate fdopendir with closedir or
366 rpl_closedir. */
367 _GL_FUNCDECL_SYS (fdopendir, DIR *,
368 (int fd),
369 _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC (closedir, 1));
370 # endif
371 # if defined GNULIB_POSIXCHECK
372 # undef fdopendir
373 # if HAVE_RAW_DECL_FDOPENDIR
374 _GL_WARN_ON_USE (fdopendir, "fdopendir is unportable - "
375 "use gnulib module fdopendir for portability");
376 # endif
377 # endif
378 #endif
380 #if @GNULIB_SCANDIR@
381 /* Scan the directory DIR, calling FILTER on each directory entry.
382 Entries for which FILTER returns nonzero are individually malloc'd,
383 sorted using qsort with CMP, and collected in a malloc'd array in
384 *NAMELIST. Returns the number of entries selected, or -1 on error. */
385 # if !@HAVE_SCANDIR@
386 _GL_FUNCDECL_SYS (scandir, int,
387 (const char *dir, struct dirent ***namelist,
388 int (*filter) (const struct dirent *),
389 int (*cmp) (const struct dirent **, const struct dirent **)),
390 _GL_ARG_NONNULL ((1, 2, 4)));
391 # endif
392 /* Need to cast, because on glibc systems, the fourth parameter is
393 int (*cmp) (const void *, const void *). */
394 _GL_CXXALIAS_SYS_CAST (scandir, int,
395 (const char *dir, struct dirent ***namelist,
396 int (*filter) (const struct dirent *),
397 int (*cmp) (const struct dirent **, const struct dirent **)));
398 _GL_CXXALIASWARN (scandir);
399 #elif defined GNULIB_POSIXCHECK
400 # undef scandir
401 # if HAVE_RAW_DECL_SCANDIR
402 _GL_WARN_ON_USE (scandir, "scandir is unportable - "
403 "use gnulib module scandir for portability");
404 # endif
405 #endif
407 #if @GNULIB_ALPHASORT@
408 /* Compare two 'struct dirent' entries alphabetically. */
409 # if !@HAVE_ALPHASORT@
410 _GL_FUNCDECL_SYS (alphasort, int,
411 (const struct dirent **, const struct dirent **),
412 _GL_ATTRIBUTE_PURE
413 _GL_ARG_NONNULL ((1, 2)));
414 # endif
415 /* Need to cast, because on glibc systems, the parameters are
416 (const void *, const void *). */
417 _GL_CXXALIAS_SYS_CAST (alphasort, int,
418 (const struct dirent **, const struct dirent **));
419 _GL_CXXALIASWARN (alphasort);
420 #elif defined GNULIB_POSIXCHECK
421 # undef alphasort
422 # if HAVE_RAW_DECL_ALPHASORT
423 _GL_WARN_ON_USE (alphasort, "alphasort is unportable - "
424 "use gnulib module alphasort for portability");
425 # endif
426 #endif
429 #endif /* _@GUARD_PREFIX@_DIRENT_H */
430 #endif /* _@GUARD_PREFIX@_DIRENT_H */