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