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
20 @PRAGMA_SYSTEM_HEADER@
24 /* The include_next requires a split double-inclusion guard. */
26 # @INCLUDE_NEXT@ @NEXT_DIRENT_H@
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."
38 /* Get ino_t. Needed on some systems, including glibc 2.8. */
39 #include <sys/types.h>
42 /* Define types DIR and 'struct dirent'. */
43 # if !GNULIB_defined_struct_dirent
49 # define GNULIB_defined_struct_dirent 1
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. */
64 # define DT_FIFO 1 /* FIFO */
67 # define DT_CHR 2 /* character device */
70 # define DT_DIR 4 /* directory */
73 # define DT_BLK 6 /* block device */
76 # define DT_REG 8 /* regular file */
79 # define DT_LNK 10 /* symbolic link */
82 # define DT_SOCK 12 /* socket */
85 # define DT_WHT 14 /* whiteout */
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
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>
108 # define _GL_DIRENT_S_ISWHT(mode) S_ISWHT(mode)
110 # define _GL_DIRENT_S_ISWHT(mode) 0
113 # define _GL_DIRENT_S_IFWHT S_IFWHT
115 # define _GL_DIRENT_S_IFWHT (DT_WHT << 12) /* just a guess */
118 /* Conversion from a 'stat' mode to a DT_* value. */
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)
127 /* Conversion from a DT_* value to a 'stat' mode. */
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 */)
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(). */
144 # define DIR struct gl_directory
146 typedef struct gl_directory
DIR;
148 # define GNULIB_defined_DIR 1
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
155 #ifndef _GL_ATTRIBUTE_DEALLOC
156 # if __GNUC__ >= 11 && !defined __clang__
157 # define _GL_ATTRIBUTE_DEALLOC(f, i) __attribute__ ((__malloc__ (f, i)))
159 # define _GL_ATTRIBUTE_DEALLOC(f, i)
163 /* _GL_ATTRIBUTE_MALLOC declares that the function returns a pointer to freshly
165 /* Applies to: functions. */
166 #ifndef _GL_ATTRIBUTE_MALLOC
167 # if __GNUC__ >= 3 || defined __clang__
168 # define _GL_ATTRIBUTE_MALLOC __attribute__ ((__malloc__))
170 # define _GL_ATTRIBUTE_MALLOC
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__))
180 # define _GL_ATTRIBUTE_PURE /* empty */
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)
197 # define closedir rpl_closedir
198 # define GNULIB_defined_closedir 1
200 _GL_FUNCDECL_RPL (closedir
, int, (DIR *dirp
), _GL_ARG_NONNULL ((1)));
201 _GL_CXXALIAS_RPL (closedir
, int, (DIR *dirp
));
203 # if !@HAVE_CLOSEDIR@
204 _GL_FUNCDECL_SYS (closedir
, int, (DIR *dirp
), _GL_ARG_NONNULL ((1)));
206 _GL_CXXALIAS_SYS (closedir
, int, (DIR *dirp
));
208 _GL_CXXALIASWARN (closedir
);
209 #elif defined GNULIB_POSIXCHECK
211 # if HAVE_RAW_DECL_CLOSEDIR
212 _GL_WARN_ON_USE (closedir
, "closedir is not portable - "
213 "use gnulib module closedir for portability");
218 # if @REPLACE_OPENDIR@
219 # if !(defined __cplusplus && defined GNULIB_NAMESPACE)
221 # define opendir rpl_opendir
222 # define GNULIB_defined_opendir 1
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
));
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));
236 _GL_CXXALIAS_SYS (opendir
, DIR *, (const char *dir_name
));
238 _GL_CXXALIASWARN (opendir
);
240 # if @GNULIB_CLOSEDIR@ && !GNULIB_defined_DIR \
241 && (__GNUC__ >= 11 && !defined __clang__) && !defined opendir
242 /* For -Wmismatched-dealloc: Associate opendir with closedir or
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));
249 # if defined GNULIB_POSIXCHECK
251 # if HAVE_RAW_DECL_OPENDIR
252 _GL_WARN_ON_USE (opendir
, "opendir is not portable - "
253 "use gnulib module opendir for portability");
259 # if @REPLACE_READDIR@
260 # if !(defined __cplusplus && defined GNULIB_NAMESPACE)
262 # define readdir rpl_readdir
264 _GL_FUNCDECL_RPL (readdir
, struct dirent
*, (DIR *dirp
), _GL_ARG_NONNULL ((1)));
265 _GL_CXXALIAS_RPL (readdir
, struct dirent
*, (DIR *dirp
));
268 _GL_FUNCDECL_SYS (readdir
, struct dirent
*, (DIR *dirp
), _GL_ARG_NONNULL ((1)));
270 _GL_CXXALIAS_SYS (readdir
, struct dirent
*, (DIR *dirp
));
272 _GL_CXXALIASWARN (readdir
);
273 #elif defined GNULIB_POSIXCHECK
275 # if HAVE_RAW_DECL_READDIR
276 _GL_WARN_ON_USE (readdir
, "readdir is not portable - "
277 "use gnulib module readdir for portability");
281 #if @GNULIB_REWINDDIR@
282 # if @REPLACE_REWINDDIR@
283 # if !(defined __cplusplus && defined GNULIB_NAMESPACE)
285 # define rewinddir rpl_rewinddir
287 _GL_FUNCDECL_RPL (rewinddir
, void, (DIR *dirp
), _GL_ARG_NONNULL ((1)));
288 _GL_CXXALIAS_RPL (rewinddir
, void, (DIR *dirp
));
290 # if !@HAVE_REWINDDIR@
291 _GL_FUNCDECL_SYS (rewinddir
, void, (DIR *dirp
), _GL_ARG_NONNULL ((1)));
293 _GL_CXXALIAS_SYS (rewinddir
, void, (DIR *dirp
));
295 _GL_CXXALIASWARN (rewinddir
);
296 #elif defined GNULIB_POSIXCHECK
298 # if HAVE_RAW_DECL_REWINDDIR
299 _GL_WARN_ON_USE (rewinddir
, "rewinddir is not portable - "
300 "use gnulib module rewinddir for portability");
305 /* Return the file descriptor associated with the given directory stream,
306 or -1 if none exists. */
308 /* On kLIBC, dirfd() is a macro that does not work. Undefine it. */
309 # if !(defined __cplusplus && defined GNULIB_NAMESPACE) || defined dirfd
311 # define dirfd rpl_dirfd
313 _GL_FUNCDECL_RPL (dirfd
, int, (DIR *), _GL_ARG_NONNULL ((1)));
314 _GL_CXXALIAS_RPL (dirfd
, int, (DIR *));
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
); }
323 # if !(@HAVE_DECL_DIRFD@ || defined dirfd)
324 _GL_FUNCDECL_SYS (dirfd
, int, (DIR *), _GL_ARG_NONNULL ((1)));
326 _GL_CXXALIAS_SYS (dirfd
, int, (DIR *));
328 _GL_CXXALIASWARN (dirfd
);
329 #elif defined GNULIB_POSIXCHECK
331 # if HAVE_RAW_DECL_DIRFD
332 _GL_WARN_ON_USE (dirfd
, "dirfd is unportable - "
333 "use gnulib module dirfd for portability");
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
343 # if @REPLACE_FDOPENDIR@
344 # if !(defined __cplusplus && defined GNULIB_NAMESPACE)
346 # define fdopendir rpl_fdopendir
348 _GL_FUNCDECL_RPL (fdopendir
, DIR *,
350 _GL_ATTRIBUTE_MALLOC
_GL_ATTRIBUTE_DEALLOC (closedir
, 1));
351 _GL_CXXALIAS_RPL (fdopendir
, DIR *, (int fd
));
353 # if !@HAVE_FDOPENDIR@ || !@HAVE_DECL_FDOPENDIR@ \
354 || (__GNUC__ >= 11 && !defined __clang__)
355 _GL_FUNCDECL_SYS (fdopendir
, DIR *,
357 _GL_ATTRIBUTE_MALLOC
_GL_ATTRIBUTE_DEALLOC (closedir
, 1));
359 _GL_CXXALIAS_SYS (fdopendir
, DIR *, (int fd
));
361 _GL_CXXALIASWARN (fdopendir
);
363 # if @GNULIB_CLOSEDIR@ \
364 && (__GNUC__ >= 11 && !defined __clang__) && !defined fdopendir
365 /* For -Wmismatched-dealloc: Associate fdopendir with closedir or
367 _GL_FUNCDECL_SYS (fdopendir
, DIR *,
369 _GL_ATTRIBUTE_MALLOC
_GL_ATTRIBUTE_DEALLOC (closedir
, 1));
371 # if defined GNULIB_POSIXCHECK
373 # if HAVE_RAW_DECL_FDOPENDIR
374 _GL_WARN_ON_USE (fdopendir
, "fdopendir is unportable - "
375 "use gnulib module fdopendir for portability");
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. */
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)));
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
401 # if HAVE_RAW_DECL_SCANDIR
402 _GL_WARN_ON_USE (scandir
, "scandir is unportable - "
403 "use gnulib module scandir for portability");
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
**),
413 _GL_ARG_NONNULL ((1, 2)));
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
422 # if HAVE_RAW_DECL_ALPHASORT
423 _GL_WARN_ON_USE (alphasort
, "alphasort is unportable - "
424 "use gnulib module alphasort for portability");
429 #endif /* _@GUARD_PREFIX@_DIRENT_H */
430 #endif /* _@GUARD_PREFIX@_DIRENT_H */