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