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