The OpenD Programming Language

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     dirent* readdir(DIR*);
389     alias readdir64 = readdir;
390 }
391 else version (CRuntime_UClibc)
392 {
393     // NOTE: The following constants are non-standard Linux definitions
394     //       for dirent.d_type.
395     enum
396     {
397         DT_UNKNOWN  = 0,
398         DT_FIFO     = 1,
399         DT_CHR      = 2,
400         DT_DIR      = 4,
401         DT_BLK      = 6,
402         DT_REG      = 8,
403         DT_LNK      = 10,
404         DT_SOCK     = 12,
405         DT_WHT      = 14
406     }
407 
408     struct DIR
409     {
410         // Managed by OS
411     }
412 
413     static if ( __USE_FILE_OFFSET64 )
414     {
415         dirent* readdir64(DIR*);
416         alias   readdir64 readdir;
417     }
418     else
419     {
420         dirent* readdir(DIR*);
421     }
422 }
423 else
424 {
425     static assert(false, "Unsupported platform");
426 }
427 
428 // Only OS X out of the Darwin family needs special treatment.  Other Darwins
429 // (iOS, TVOS, WatchOS) are fine with normal symbol names for these functions
430 // in else below.
431 version (OSX)
432 {
433     version (AArch64)
434     {
435         int     closedir(DIR*);
436         DIR*    opendir(const scope char*);
437         void    rewinddir(DIR*);
438     }
439     else version (D_LP64)
440     {
441         int closedir(DIR*);
442         pragma(mangle, "opendir$INODE64")   DIR* opendir(const scope char*);
443         pragma(mangle, "rewinddir$INODE64") void rewinddir(DIR*);
444     }
445     else
446     {
447         // 32-bit mangles __DARWIN_UNIX03 specific functions with $UNIX2003 to
448         // maintain backward compatibility with binaries build pre 10.5
449         pragma(mangle, "closedir$UNIX2003")          int closedir(DIR*);
450         pragma(mangle, "opendir$INODE64$UNIX2003")   DIR* opendir(const scope char*);
451         pragma(mangle, "rewinddir$INODE64$UNIX2003") void rewinddir(DIR*);
452     }
453 }
454 else version (NetBSD)
455 {
456     int     closedir(DIR*);
457     DIR*    __opendir30(const scope char*);
458     alias __opendir30 opendir;
459     void    rewinddir(DIR*);
460 }
461 else
462 {
463     int     closedir(DIR*);
464     DIR*    opendir(const scope char*);
465     //dirent* readdir(DIR*);
466     void    rewinddir(DIR*);
467 }
468 
469 //
470 // Thread-Safe Functions (TSF)
471 //
472 /*
473 int readdir_r(DIR*, dirent*, dirent**);
474 */
475 
476 version (CRuntime_Glibc)
477 {
478   static if ( __USE_LARGEFILE64 )
479   {
480     int   readdir64_r(DIR*, dirent*, dirent**);
481     alias readdir64_r readdir_r;
482   }
483   else
484   {
485     int readdir_r(DIR*, dirent*, dirent**);
486   }
487 }
488 else version (Darwin)
489 {
490     version (OSX)
491         pragma(mangle, "readdir_r$INODE64") int readdir_r(DIR*, dirent*, dirent**);
492     else
493         int readdir_r(DIR*, dirent*, dirent**);
494 }
495 else version (FreeBSD)
496 {
497     version (GNU)
498     {
499         int readdir_r(DIR*, dirent*, dirent**);
500     }
501     else
502     {
503         static if (__FreeBSD_version >= 1200000)
504             pragma(mangle, "readdir_r@FBSD_1.5") int readdir_r(DIR*, dirent*, dirent**);
505         else
506             pragma(mangle, "readdir_r@FBSD_1.0") int readdir_r(DIR*, dirent*, dirent**);
507     }
508 }
509 else version (DragonFlyBSD)
510 {
511     int readdir_r(DIR*, dirent*, dirent**);
512 }
513 else version (NetBSD)
514 {
515     int __readdir_r30(DIR*, dirent*, dirent**);
516     alias __readdir_r30 readdir_r;
517 }
518 else version (OpenBSD)
519 {
520     int readdir_r(DIR*, dirent*, dirent**);
521 }
522 else version (Solaris)
523 {
524     static if (__USE_LARGEFILE64)
525     {
526         int readdir64_r(DIR*, dirent*, dirent**);
527         alias readdir64_r readdir_r;
528     }
529     else
530     {
531         int readdir_r(DIR*, dirent*, dirent**);
532     }
533 }
534 else version (CRuntime_Bionic)
535 {
536     int readdir_r(DIR*, dirent*, dirent**);
537 }
538 else version (CRuntime_Musl)
539 {
540     int readdir_r(DIR*, dirent*, dirent**);
541 }
542 else version (CRuntime_UClibc)
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
555 {
556     static assert(false, "Unsupported platform");
557 }
558 
559 //
560 // XOpen (XSI)
561 //
562 /*
563 void   seekdir(DIR*, c_long);
564 c_long telldir(DIR*);
565 */
566 
567 version (CRuntime_Glibc)
568 {
569     void   seekdir(DIR*, c_long);
570     c_long telldir(DIR*);
571 }
572 else version (FreeBSD)
573 {
574     version (GNU)
575     {
576         void seekdir(DIR*, c_long);
577         c_long telldir(DIR*);
578     }
579     else
580     {
581         pragma(mangle, "seekdir@@FBSD_1.0") void seekdir(DIR*, c_long);
582         pragma(mangle, "telldir@@FBSD_1.0") c_long telldir(DIR*);
583     }
584 }
585 else version (NetBSD)
586 {
587     void   seekdir(DIR*, c_long);
588     c_long telldir(DIR*);
589 }
590 else version (OpenBSD)
591 {
592     void   seekdir(DIR*, c_long);
593     c_long telldir(DIR*);
594 }
595 else version (DragonFlyBSD)
596 {
597     void   seekdir(DIR*, c_long);
598     c_long telldir(DIR*);
599 }
600 else version (Darwin)
601 {
602     version (OSX)
603     {
604         version (D_LP64)
605         {
606             pragma(mangle, "seekdir$INODE64") void seekdir(DIR*, c_long);
607             pragma(mangle, "telldir$INODE64") c_long telldir(DIR*);
608         }
609         else
610         {
611             // 32-bit mangles __DARWIN_UNIX03 specific functions with $UNIX2003 to
612             // maintain backward compatibility with binaries build pre 10.5
613             pragma(mangle, "seekdir$INODE64$UNIX2003") void seekdir(DIR*, c_long);
614             pragma(mangle, "telldir$INODE64$UNIX2003") c_long telldir(DIR*);
615         }
616     }
617     else // other Darwins (e.g. iOS, TVOS, WatchOS)
618     {
619         void seekdir(DIR*, c_long);
620         c_long telldir(DIR*);
621     }
622 }
623 else version (Solaris)
624 {
625     c_long telldir(DIR*);
626     void seekdir(DIR*, c_long);
627 }
628 else version (CRuntime_Bionic)
629 {
630 }
631 else version (CRuntime_Musl)
632 {
633     void   seekdir(DIR*, c_long);
634     c_long telldir(DIR*);
635 }
636 else version (CRuntime_UClibc)
637 {
638     void   seekdir(DIR*, c_long);
639     c_long telldir(DIR*);
640 }
641 else
642 {
643     static assert(false, "Unsupported platform");
644 }