1/**
2 * D header file for POSIX.
3 *
4 * Copyright: Copyright Sean Kelly 2005 - 2009.
5 * License:   $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
6 * Authors:   Sean Kelly,
7              Alex R��nne Petersn
8 * Standards: The Open Group Base Specifications Issue 6, IEEE Std 1003.1, 2004 Edition
9 */
10
11/*          Copyright Sean Kelly 2005 - 2009.
12 * Distributed under the Boost Software License, Version 1.0.
13 *    (See accompanying file LICENSE or copy at
14 *          http://www.boost.org/LICENSE_1_0.txt)
15 */
16module core.sys.posix.dirent;
17
18import core.sys.posix.config;
19public import core.sys.posix.sys.types; // for ino_t
20
21version (OSX)
22    version = Darwin;
23else version (iOS)
24    version = Darwin;
25else version (TVOS)
26    version = Darwin;
27else version (WatchOS)
28    version = Darwin;
29
30version (Posix):
31extern (C):
32nothrow:
33@nogc:
34@system:
35
36//
37// Required
38//
39/*
40struct dirent
41{
42    char[] d_name;
43}
44*/
45
46version (linux)
47{
48    struct dirent
49    {
50        ino_t       d_ino;
51        off_t       d_off;
52        ushort      d_reclen;
53        ubyte       d_type;
54        char[256]   d_name = 0;
55    }
56}
57else version (Darwin)
58{
59    // _DARWIN_FEATURE_64_BIT_INODE dirent is default for Mac OSX >10.5 and is
60    // only meaningful type for other OS X/Darwin variants (e.g. iOS).
61    // man dir(5) has some info, man stat(2) gives details.
62    struct dirent
63    {
64        ino_t       d_ino;
65        alias       d_fileno = d_ino;
66        ulong       d_seekoff;
67        ushort      d_reclen;
68        ushort      d_namlen;
69        ubyte       d_type;
70        char[1024]  d_name = 0;
71    }
72}
73else version (FreeBSD)
74{
75    import core.sys.freebsd.config;
76
77    static if (__FreeBSD_version >= 1200000)
78    {
79        struct dirent
80        {
81            ino_t     d_fileno;
82            off_t     d_off;
83            ushort    d_reclen;
84            ubyte     d_type;
85            ubyte     d_pad0;
86            ushort    d_namlen;
87            ushort    d_pad1;
88            char[256] d_name = 0;
89        }
90    }
91    else
92    {
93        align(4)
94        struct dirent
95        {
96            uint      d_fileno;
97            ushort    d_reclen;
98            ubyte     d_type;
99            ubyte     d_namlen;
100            char[256] d_name = 0;
101        }
102    }
103}
104else version (NetBSD)
105{
106    struct dirent
107    {
108        ulong      d_fileno;
109        ushort    d_reclen;
110        ushort    d_namlen;
111        ubyte     d_type;
112        char[512] d_name = 0;
113    }
114}
115else version (OpenBSD)
116{
117    align(4)
118    struct dirent
119    {
120        ino_t     d_fileno;
121        off_t     d_off;
122        ushort    d_reclen;
123        ubyte     d_type;
124        ubyte     d_namlen;
125        ubyte[4]  __d_padding;
126        char[256] d_name = 0;
127    }
128}
129else version (DragonFlyBSD)
130{
131    struct dirent
132    {
133        ino_t     d_fileno;       /* file number of entry */
134        ushort    d_reclen;       /* strlen(d_name) */
135        ubyte     d_type;         /* file type, see blow */
136        ubyte     d_unused1;      /* padding, reserved */
137        uint      d_unused2;      /* reserved */
138        char[256] d_name = 0;     /* name, NUL-terminated */
139    }
140}
141else version (Solaris)
142{
143    struct dirent
144    {
145        ino_t d_ino;
146        off_t d_off;
147        ushort d_reclen;
148        char[1] d_name = 0;
149    }
150}
151else
152{
153    static assert(false, "Unsupported platform");
154}
155
156/*
157DIR
158
159int     closedir(DIR*);
160DIR*    opendir(const scope char*);
161dirent* readdir(DIR*);
162void    rewinddir(DIR*);
163*/
164
165version (CRuntime_Glibc)
166{
167    // NOTE: The following constants are non-standard Linux definitions
168    //       for dirent.d_type.
169    enum
170    {
171        DT_UNKNOWN  = 0,
172        DT_FIFO     = 1,
173        DT_CHR      = 2,
174        DT_DIR      = 4,
175        DT_BLK      = 6,
176        DT_REG      = 8,
177        DT_LNK      = 10,
178        DT_SOCK     = 12,
179        DT_WHT      = 14
180    }
181
182    struct DIR
183    {
184        // Managed by OS
185    }
186
187    static if ( __USE_FILE_OFFSET64 )
188    {
189        dirent* readdir64(DIR*);
190        alias   readdir64 readdir;
191    }
192    else
193    {
194        dirent* readdir(DIR*);
195    }
196}
197else version (Darwin)
198{
199    enum
200    {
201        DT_UNKNOWN  = 0,
202        DT_FIFO     = 1,
203        DT_CHR      = 2,
204        DT_DIR      = 4,
205        DT_BLK      = 6,
206        DT_REG      = 8,
207        DT_LNK      = 10,
208        DT_SOCK     = 12,
209        DT_WHT      = 14
210    }
211
212    struct DIR
213    {
214        // Managed by OS
215    }
216
217    // OS X maintains backwards compatibility with older binaries using 32-bit
218    // inode functions by appending $INODE64 to newer 64-bit inode functions.
219    // Other Darwin variants (iOS, TVOS, WatchOS) only support 64-bit inodes,
220    // no suffix needed
221    version (OSX)
222    {
223        version (AArch64)
224            dirent* readdir(DIR*);
225        else
226            pragma(mangle, "readdir$INODE64") dirent* readdir(DIR*);
227    }
228    else
229        dirent* readdir(DIR*);
230}
231else version (FreeBSD)
232{
233    import core.sys.freebsd.config;
234
235    // https://github.com/freebsd/freebsd/blob/master/sys/sys/dirent.h
236    enum
237    {
238        DT_UNKNOWN  = 0,
239        DT_FIFO     = 1,
240        DT_CHR      = 2,
241        DT_DIR      = 4,
242        DT_BLK      = 6,
243        DT_REG      = 8,
244        DT_LNK      = 10,
245        DT_SOCK     = 12,
246        DT_WHT      = 14
247    }
248
249    alias void* DIR;
250
251    version (GNU)
252    {
253        dirent* readdir(DIR*);
254    }
255    else
256    {
257        static if (__FreeBSD_version >= 1200000)
258            pragma(mangle, "readdir@FBSD_1.5") dirent* readdir(DIR*);
259        else
260            pragma(mangle, "readdir@FBSD_1.0") dirent* readdir(DIR*);
261    }
262}
263else version (NetBSD)
264{
265    enum
266    {
267        DT_UNKNOWN  = 0,
268        DT_FIFO     = 1,
269        DT_CHR      = 2,
270        DT_DIR      = 4,
271        DT_BLK      = 6,
272        DT_REG      = 8,
273        DT_LNK      = 10,
274        DT_SOCK     = 12,
275        DT_WHT      = 14
276    }
277
278    alias void* DIR;
279
280    dirent* __readdir30(DIR*);
281    alias __readdir30 readdir;
282}
283else version (OpenBSD)
284{
285    enum
286    {
287        DT_UNKNOWN  = 0,
288        DT_FIFO     = 1,
289        DT_CHR      = 2,
290        DT_DIR      = 4,
291        DT_BLK      = 6,
292        DT_REG      = 8,
293        DT_LNK      = 10,
294        DT_SOCK     = 12,
295    }
296
297    alias void* DIR;
298
299    dirent* readdir(DIR*);
300}
301else version (DragonFlyBSD)
302{
303    enum
304    {
305        DT_UNKNOWN  = 0,
306        DT_FIFO     = 1,
307        DT_CHR      = 2,
308        DT_DIR      = 4,
309        DT_BLK      = 6,
310        DT_REG      = 8,
311        DT_LNK      = 10,
312        DT_SOCK     = 12,
313        DT_WHT      = 14,
314        DT_DBF      = 15,         /* database record file */
315    }
316
317    alias void* DIR;
318
319    dirent* readdir(DIR*);
320}
321else version (Solaris)
322{
323    struct DIR
324    {
325        int dd_fd;
326        int dd_loc;
327        int dd_size;
328        char* dd_buf;
329    }
330
331    version (D_LP64)
332    {
333        dirent* readdir(DIR*);
334        alias readdir64 = readdir;
335    }
336    else
337    {
338        static if (__USE_LARGEFILE64)
339        {
340            dirent* readdir64(DIR*);
341            alias readdir64 readdir;
342        }
343        else
344        {
345            dirent* readdir(DIR*);
346        }
347    }
348}
349else version (CRuntime_Bionic)
350{
351    enum
352    {
353        DT_UNKNOWN  = 0,
354        DT_FIFO     = 1,
355        DT_CHR      = 2,
356        DT_DIR      = 4,
357        DT_BLK      = 6,
358        DT_REG      = 8,
359        DT_LNK      = 10,
360        DT_SOCK     = 12,
361        DT_WHT      = 14
362    }
363
364    struct DIR
365    {
366    }
367
368    dirent* readdir(DIR*);
369}
370else version (CRuntime_Musl)
371{
372    enum
373    {
374        DT_UNKNOWN  = 0,
375        DT_FIFO     = 1,
376        DT_CHR      = 2,
377        DT_DIR      = 4,
378        DT_BLK      = 6,
379        DT_REG      = 8,
380        DT_LNK      = 10,
381        DT_SOCK     = 12,
382        DT_WHT      = 14
383    }
384
385    struct DIR
386    {
387    }
388
389    static if ( __USE_FILE_OFFSET64 )
390    {
391        dirent* readdir64(DIR*);
392        alias   readdir64 readdir;
393    }
394    else
395    {
396        dirent* readdir(DIR*);
397    }
398}
399else version (CRuntime_UClibc)
400{
401    // NOTE: The following constants are non-standard Linux definitions
402    //       for dirent.d_type.
403    enum
404    {
405        DT_UNKNOWN  = 0,
406        DT_FIFO     = 1,
407        DT_CHR      = 2,
408        DT_DIR      = 4,
409        DT_BLK      = 6,
410        DT_REG      = 8,
411        DT_LNK      = 10,
412        DT_SOCK     = 12,
413        DT_WHT      = 14
414    }
415
416    struct DIR
417    {
418        // Managed by OS
419    }
420
421    static if ( __USE_FILE_OFFSET64 )
422    {
423        dirent* readdir64(DIR*);
424        alias   readdir64 readdir;
425    }
426    else
427    {
428        dirent* readdir(DIR*);
429    }
430}
431else
432{
433    static assert(false, "Unsupported platform");
434}
435
436// Only OS X out of the Darwin family needs special treatment.  Other Darwins
437// (iOS, TVOS, WatchOS) are fine with normal symbol names for these functions
438// in else below.
439version (OSX)
440{
441    version (AArch64)
442    {
443        int     closedir(DIR*);
444        DIR*    opendir(const scope char*);
445        void    rewinddir(DIR*);
446    }
447    else version (D_LP64)
448    {
449        int closedir(DIR*);
450        pragma(mangle, "opendir$INODE64")   DIR* opendir(const scope char*);
451        pragma(mangle, "rewinddir$INODE64") void rewinddir(DIR*);
452    }
453    else
454    {
455        // 32-bit mangles __DARWIN_UNIX03 specific functions with $UNIX2003 to
456        // maintain backward compatibility with binaries build pre 10.5
457        pragma(mangle, "closedir$UNIX2003")          int closedir(DIR*);
458        pragma(mangle, "opendir$INODE64$UNIX2003")   DIR* opendir(const scope char*);
459        pragma(mangle, "rewinddir$INODE64$UNIX2003") void rewinddir(DIR*);
460    }
461}
462else version (NetBSD)
463{
464    int     closedir(DIR*);
465    DIR*    __opendir30(const scope char*);
466    alias __opendir30 opendir;
467    void    rewinddir(DIR*);
468}
469else
470{
471    int     closedir(DIR*);
472    DIR*    opendir(const scope char*);
473    //dirent* readdir(DIR*);
474    void    rewinddir(DIR*);
475}
476
477//
478// Thread-Safe Functions (TSF)
479//
480/*
481int readdir_r(DIR*, dirent*, dirent**);
482*/
483
484version (CRuntime_Glibc)
485{
486  static if ( __USE_LARGEFILE64 )
487  {
488    int   readdir64_r(DIR*, dirent*, dirent**);
489    alias readdir64_r readdir_r;
490  }
491  else
492  {
493    int readdir_r(DIR*, dirent*, dirent**);
494  }
495}
496else version (Darwin)
497{
498    version (OSX)
499        pragma(mangle, "readdir_r$INODE64") int readdir_r(DIR*, dirent*, dirent**);
500    else
501        int readdir_r(DIR*, dirent*, dirent**);
502}
503else version (FreeBSD)
504{
505    version (GNU)
506    {
507        int readdir_r(DIR*, dirent*, dirent**);
508    }
509    else
510    {
511        static if (__FreeBSD_version >= 1200000)
512            pragma(mangle, "readdir_r@FBSD_1.5") int readdir_r(DIR*, dirent*, dirent**);
513        else
514            pragma(mangle, "readdir_r@FBSD_1.0") int readdir_r(DIR*, dirent*, dirent**);
515    }
516}
517else version (DragonFlyBSD)
518{
519    int readdir_r(DIR*, dirent*, dirent**);
520}
521else version (NetBSD)
522{
523    int __readdir_r30(DIR*, dirent*, dirent**);
524    alias __readdir_r30 readdir_r;
525}
526else version (OpenBSD)
527{
528    int readdir_r(DIR*, dirent*, dirent**);
529}
530else version (Solaris)
531{
532    static if (__USE_LARGEFILE64)
533    {
534        int readdir64_r(DIR*, dirent*, dirent**);
535        alias readdir64_r readdir_r;
536    }
537    else
538    {
539        int readdir_r(DIR*, dirent*, dirent**);
540    }
541}
542else version (CRuntime_Bionic)
543{
544    int readdir_r(DIR*, dirent*, dirent**);
545}
546else version (CRuntime_Musl)
547{
548    int readdir_r(DIR*, dirent*, dirent**);
549}
550else version (CRuntime_UClibc)
551{
552  static if ( __USE_LARGEFILE64 )
553  {
554    int   readdir64_r(DIR*, dirent*, dirent**);
555    alias readdir64_r readdir_r;
556  }
557  else
558  {
559    int readdir_r(DIR*, dirent*, dirent**);
560  }
561}
562else
563{
564    static assert(false, "Unsupported platform");
565}
566
567//
568// XOpen (XSI)
569//
570/*
571void   seekdir(DIR*, c_long);
572c_long telldir(DIR*);
573*/
574
575version (CRuntime_Glibc)
576{
577    void   seekdir(DIR*, c_long);
578    c_long telldir(DIR*);
579}
580else version (FreeBSD)
581{
582    version (GNU)
583    {
584        void seekdir(DIR*, c_long);
585        c_long telldir(DIR*);
586    }
587    else
588    {
589        pragma(mangle, "seekdir@@FBSD_1.0") void seekdir(DIR*, c_long);
590        pragma(mangle, "telldir@@FBSD_1.0") c_long telldir(DIR*);
591    }
592}
593else version (NetBSD)
594{
595    void   seekdir(DIR*, c_long);
596    c_long telldir(DIR*);
597}
598else version (OpenBSD)
599{
600    void   seekdir(DIR*, c_long);
601    c_long telldir(DIR*);
602}
603else version (DragonFlyBSD)
604{
605    void   seekdir(DIR*, c_long);
606    c_long telldir(DIR*);
607}
608else version (Darwin)
609{
610    version (OSX)
611    {
612        version (D_LP64)
613        {
614            pragma(mangle, "seekdir$INODE64") void seekdir(DIR*, c_long);
615            pragma(mangle, "telldir$INODE64") c_long telldir(DIR*);
616        }
617        else
618        {
619            // 32-bit mangles __DARWIN_UNIX03 specific functions with $UNIX2003 to
620            // maintain backward compatibility with binaries build pre 10.5
621            pragma(mangle, "seekdir$INODE64$UNIX2003") void seekdir(DIR*, c_long);
622            pragma(mangle, "telldir$INODE64$UNIX2003") c_long telldir(DIR*);
623        }
624    }
625    else // other Darwins (e.g. iOS, TVOS, WatchOS)
626    {
627        void seekdir(DIR*, c_long);
628        c_long telldir(DIR*);
629    }
630}
631else version (Solaris)
632{
633    c_long telldir(DIR*);
634    void seekdir(DIR*, c_long);
635}
636else version (CRuntime_Bionic)
637{
638}
639else version (CRuntime_Musl)
640{
641    void   seekdir(DIR*, c_long);
642    c_long telldir(DIR*);
643}
644else version (CRuntime_UClibc)
645{
646    void   seekdir(DIR*, c_long);
647    c_long telldir(DIR*);
648}
649else
650{
651    static assert(false, "Unsupported platform");
652}
653