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  * Standards: The Open Group Base Specifications Issue 6, IEEE Std 1003.1, 2004 Edition
8  */
9 
10 /*          Copyright Sean Kelly 2005 - 2009.
11  * Distributed under the Boost Software License, Version 1.0.
12  *    (See accompanying file LICENSE or copy at
13  *          http://www.boost.org/LICENSE_1_0.txt)
14  */
15 module core.sys.posix.stdio;
16 
17 private import core.sys.posix.config;
18 public import core.stdc.stdio;
19 public import core.sys.posix.sys.types; // for off_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 
33 nothrow:
34 @nogc:
35 
36 //
37 // Required (defined in core.stdc.stdio)
38 //
39 /*
40 BUFSIZ
41 _IOFBF
42 _IOLBF
43 _IONBF
44 L_tmpnam
45 SEEK_CUR
46 SEEK_END
47 SEEK_SET
48 FILENAME_MAX
49 FOPEN_MAX
50 TMP_MAX
51 EOF
52 NULL
53 stderr
54 stdin
55 stdout
56 FILE
57 fpos_t
58 size_t
59 
60 void   clearerr(FILE*);
61 int    fclose(FILE*);
62 int    feof(FILE*);
63 int    ferror(FILE*);
64 int    fflush(FILE*);
65 int    fgetc(FILE*);
66 int    fgetpos(FILE*, fpos_t *);
67 char*  fgets(char*, int, FILE*);
68 FILE*  fopen(in char*, in char*);
69 int    fprintf(FILE*, in char*, ...);
70 int    fputc(int, FILE*);
71 int    fputs(in char*, FILE*);
72 size_t fread(void *, size_t, size_t, FILE*);
73 FILE*  freopen(in char*, in char*, FILE*);
74 int    fscanf(FILE*, in char*, ...);
75 int    fseek(FILE*, c_long, int);
76 int    fsetpos(FILE*, in fpos_t*);
77 c_long ftell(FILE*);
78 size_t fwrite(in void *, size_t, size_t, FILE*);
79 int    getc(FILE*);
80 int    getchar();
81 char*  gets(char*);
82 void   perror(in char*);
83 int    printf(in char*, ...);
84 int    putc(int, FILE*);
85 int    putchar(int);
86 int    puts(in char*);
87 int    remove(in char*);
88 int    rename(in char*, in char*);
89 void   rewind(FILE*);
90 int    scanf(in char*, ...);
91 void   setbuf(FILE*, char*);
92 int    setvbuf(FILE*, char*, int, size_t);
93 int    snprintf(char*, size_t, in char*, ...);
94 int    sprintf(char*, in char*, ...);
95 int    sscanf(in char*, in char*, int ...);
96 FILE*  tmpfile();
97 char*  tmpnam(char*);
98 int    ungetc(int, FILE*);
99 int    vfprintf(FILE*, in char*, va_list);
100 int    vfscanf(FILE*, in char*, va_list);
101 int    vprintf(in char*, va_list);
102 int    vscanf(in char*, va_list);
103 int    vsnprintf(char*, size_t, in char*, va_list);
104 int    vsprintf(char*, in char*, va_list);
105 int    vsscanf(in char*, in char*, va_list arg);
106 */
107 
108 version (CRuntime_Glibc)
109 {
110     /*
111      * actually, if __USE_FILE_OFFSET64 && !_LARGEFILE64_SOURCE
112      * the *64 functions shouldn't be visible, but the aliases should
113      * still be supported
114      */
115     static if ( __USE_FILE_OFFSET64 )
116     {
117         int   fgetpos64(FILE*, fpos_t *);
118         alias fgetpos64 fgetpos;
119 
120         FILE* fopen64(in char*, in char*);
121         alias fopen64 fopen;
122 
123         FILE* freopen64(in char*, in char*, FILE*);
124         alias freopen64 freopen;
125 
126         int   fseek(FILE*, c_long, int);
127 
128         int   fsetpos64(FILE*, in fpos_t*);
129         alias fsetpos64 fsetpos;
130 
131         FILE* tmpfile64();
132         alias tmpfile64 tmpfile;
133     }
134     else
135     {
136         int   fgetpos(FILE*, fpos_t *);
137         FILE* fopen(in char*, in char*);
138         FILE* freopen(in char*, in char*, FILE*);
139         int   fseek(FILE*, c_long, int);
140         int   fsetpos(FILE*, in fpos_t*);
141         FILE* tmpfile();
142     }
143 }
version(CRuntime_Bionic)144 else version (CRuntime_Bionic)
145 {
146     int   fgetpos(FILE*, fpos_t *);
147     FILE* fopen(in char*, in char*);
148     FILE* freopen(in char*, in char*, FILE*);
149     int   fseek(FILE*, c_long, int);
150     int   fsetpos(FILE*, in fpos_t*);
151 }
version(CRuntime_UClibc)152 else version (CRuntime_UClibc)
153 {
154     static if ( __USE_FILE_OFFSET64 )
155     {
156         int   fgetpos64(FILE*, fpos_t *);
157         alias fgetpos64 fgetpos;
158 
159         FILE* fopen64(in char*, in char*);
160         alias fopen64 fopen;
161 
162         FILE* freopen64(in char*, in char*, FILE*);
163         alias freopen64 freopen;
164 
165         int   fseek(FILE*, c_long, int);
166 
167         int   fsetpos64(FILE*, in fpos_t*);
168         alias fsetpos64 fsetpos;
169 
170         FILE* tmpfile64();
171         alias tmpfile64 tmpfile;
172     }
173     else
174     {
175         int   fgetpos(FILE*, fpos_t *);
176         FILE* fopen(in char*, in char*);
177         FILE* freopen(in char*, in char*, FILE*);
178         int   fseek(FILE*, c_long, int);
179         int   fsetpos(FILE*, in fpos_t*);
180         FILE* tmpfile();
181     }
182 }
version(CRuntime_Musl)183 else version (CRuntime_Musl)
184 {
185     static if ( __USE_FILE_OFFSET64 )
186     {
187         int   fgetpos64(FILE*, fpos_t *);
188         alias fgetpos64 fgetpos;
189 
190         FILE* fopen64(in char*, in char*);
191         alias fopen64 fopen;
192 
193         FILE* freopen64(in char*, in char*, FILE*);
194         alias freopen64 freopen;
195 
196         int   fseek(FILE*, c_long, int);
197 
198         int   fsetpos64(FILE*, in fpos_t*);
199         alias fsetpos64 fsetpos;
200 
201         FILE* tmpfile64();
202         alias tmpfile64 tmpfile;
203     }
204     else
205     {
206         int   fgetpos(FILE*, fpos_t *);
207         FILE* fopen(in char*, in char*);
208         FILE* freopen(in char*, in char*, FILE*);
209         int   fseek(FILE*, c_long, int);
210         int   fsetpos(FILE*, in fpos_t*);
211         FILE* tmpfile();
212     }
213 }
version(Solaris)214 else version (Solaris)
215 {
216     static if (__USE_FILE_OFFSET64 && __WORDSIZE != 64)
217     {
218         int   fgetpos64(FILE*, fpos_t *);
219         alias fgetpos = fgetpos64;
220 
221         FILE* fopen64(in char*, in char*);
222         alias fopen = fopen64;
223 
224         FILE* freopen64(in char*, in char*, FILE*);
225         alias freopen = freopen64;
226 
227         int   fseek(FILE*, c_long, int);
228 
229         int   fsetpos64(FILE*, in fpos_t*);
230         alias fsetpos = fsetpos64;
231 
232         FILE* tmpfile64();
233         alias tmpfile = tmpfile64;
234     }
235     else
236     {
237         int   fgetpos(FILE*, fpos_t *);
238         FILE* fopen(in char*, in char*);
239         FILE* freopen(in char*, in char*, FILE*);
240         int   fseek(FILE*, c_long, int);
241         int   fsetpos(FILE*, in fpos_t*);
242         FILE* tmpfile();
243     }
244 }
245 
246 //
247 // C Extension (CX)
248 //
249 /*
250 L_ctermid
251 
252 char*  ctermid(char*);
253 FILE*  fdopen(int, in char*);
254 int    fileno(FILE*);
255 int    fseeko(FILE*, off_t, int);
256 off_t  ftello(FILE*);
257 char*  gets(char*);
258 int    pclose(FILE*);
259 FILE*  popen(in char*, in char*);
260 */
261 
version(CRuntime_Glibc)262 version (CRuntime_Glibc)
263 {
264     enum L_ctermid = 9;
265 
266   static if ( __USE_FILE_OFFSET64 )
267   {
268     int   fseeko64(FILE*, off_t, int);
269     alias fseeko64 fseeko;
270   }
271   else
272   {
273     int   fseeko(FILE*, off_t, int);
274   }
275 
276   static if ( __USE_FILE_OFFSET64 )
277   {
278     off_t ftello64(FILE*);
279     alias ftello64 ftello;
280   }
281   else
282   {
283     off_t ftello(FILE*);
284   }
285 }
version(CRuntime_UClibc)286 else version (CRuntime_UClibc)
287 {
288     enum L_ctermid = 9;
289     enum L_cuserid = 9;
290 
291   static if ( __USE_FILE_OFFSET64 )
292   {
293     int   fseeko64(FILE*, off_t, int);
294     alias fseeko64 fseeko;
295   }
296   else
297   {
298     int   fseeko(FILE*, off_t, int);
299   }
300 
301   static if ( __USE_FILE_OFFSET64 )
302   {
303     off_t ftello64(FILE*);
304     alias ftello64 ftello;
305   }
306   else
307   {
308     off_t ftello(FILE*);
309   }
310 }
version(CRuntime_Musl)311 else version (CRuntime_Musl)
312 {
313     enum L_ctermid = 20;
314 
315     static if ( __USE_FILE_OFFSET64 )
316     {
317         int   fseeko64(FILE*, off_t, int);
318         alias fseeko64 fseeko;
319     }
320     else
321     {
322         int   fseeko(FILE*, off_t, int);
323     }
324 
325     static if ( __USE_FILE_OFFSET64 )
326     {
327         off_t ftello64(FILE*);
328         alias ftello64 ftello;
329     }
330     else
331     {
332         off_t ftello(FILE*);
333     }
334 }
version(Solaris)335 else version (Solaris)
336 {
337     enum L_ctermid = 9;
338     enum L_cuserid = 9;
339 
340     static if (__USE_FILE_OFFSET64 && __WORDSIZE != 64)
341     {
342         int   fseeko64(FILE*, off_t, int);
343         alias fseeko = fseeko64;
344     }
345     else
346     {
347         int   fseeko(FILE*, off_t, int);
348     }
349 
350     static if (__USE_FILE_OFFSET64 && __WORDSIZE != 64)
351     {
352         off_t ftello64(FILE*);
353         alias ftello = ftello64;
354     }
355     else
356     {
357         off_t ftello(FILE*);
358     }
359 }
version(Posix)360 else version (Posix)
361 {
362     int   fseeko(FILE*, off_t, int);
363     off_t ftello(FILE*);
364 }
365 
366 char*  ctermid(char*);
367 FILE*  fdopen(int, in char*);
368 int    fileno(FILE*);
369 //int    fseeko(FILE*, off_t, int);
370 //off_t  ftello(FILE*);
371 char*  gets(char*);
372 int    pclose(FILE*);
373 FILE*  popen(in char*, in char*);
374 
375 
376 // memstream functions are conforming to POSIX.1-2008.  These functions are
377 // not specified in POSIX.1-2001 and are not widely available on other
378 // systems.
379 version (CRuntime_Glibc)                     // as of glibc 1.0x
380     version = HaveMemstream;
381 else version (FreeBSD)                      // as of FreeBSD 9.2
382     version = HaveMemstream;
383 else version (DragonFlyBSD)                 // for DragonFlyBSD
384     version = HaveMemstream;
385 else version (OpenBSD)                      // as of OpenBSD 5.4
386     version = HaveMemstream;
387 else version (CRuntime_UClibc)
388     version = HaveMemstream;
389 // http://git.musl-libc.org/cgit/musl/commit/src/stdio/open_memstream.c?id=b158b32a44d56ef20407d4285b58180447ffff1f
390 else version (CRuntime_Musl)
391     version = HaveMemstream;
392 
version(HaveMemstream)393 version (HaveMemstream)
394 {
395     FILE*  fmemopen(in void* buf, in size_t size, in char* mode);
396     FILE*  open_memstream(char** ptr, size_t* sizeloc);
397     version (CRuntime_UClibc) {} else
398     FILE*  open_wmemstream(wchar_t** ptr, size_t* sizeloc);
399 }
400 
401 //
402 // Thread-Safe Functions (TSF)
403 //
404 /*
405 void   flockfile(FILE*);
406 int    ftrylockfile(FILE*);
407 void   funlockfile(FILE*);
408 int    getc_unlocked(FILE*);
409 int    getchar_unlocked();
410 int    putc_unlocked(int, FILE*);
411 int    putchar_unlocked(int);
412 */
413 
version(CRuntime_Glibc)414 version (CRuntime_Glibc)
415 {
416     void   flockfile(FILE*);
417     int    ftrylockfile(FILE*);
418     void   funlockfile(FILE*);
419     int    getc_unlocked(FILE*);
420     int    getchar_unlocked();
421     int    putc_unlocked(int, FILE*);
422     int    putchar_unlocked(int);
423 }
version(OpenBSD)424 else version (OpenBSD)
425 {
426     void   flockfile(FILE*);
427     int    ftrylockfile(FILE*);
428     void   funlockfile(FILE*);
429     int    getc_unlocked(FILE*);
430     int    getchar_unlocked();
431     int    putc_unlocked(int, FILE*);
432     int    putchar_unlocked(int);
433 }
version(Solaris)434 else version (Solaris)
435 {
436     void   flockfile(FILE*);
437     int    ftrylockfile(FILE*);
438     void   funlockfile(FILE*);
439     int    getc_unlocked(FILE*);
440     int    getchar_unlocked();
441     int    putc_unlocked(int, FILE*);
442     int    putchar_unlocked(int);
443 }
version(CRuntime_UClibc)444 else version (CRuntime_UClibc)
445 {
446     void   flockfile(FILE*);
447     int    ftrylockfile(FILE*);
448     void   funlockfile(FILE*);
449     int    getc_unlocked(FILE*);
450     int    getchar_unlocked();
451     int    putc_unlocked(int, FILE*);
452     int    putchar_unlocked(int);
453 }
454 
455 //
456 // XOpen (XSI)
457 //
458 /*
459 P_tmpdir
460 va_list (defined in core.stdc.stdarg)
461 
462 char*  tempnam(in char*, in char*);
463 */
464 
465 char*  tempnam(in char*, in char*);
466 
version(CRuntime_Glibc)467 version (CRuntime_Glibc)
468 {
469     enum P_tmpdir  = "/tmp";
470 }
version(CRuntime_Musl)471 version (CRuntime_Musl)
472 {
473     enum P_tmpdir  = "/tmp";
474 }
version(Darwin)475 version (Darwin)
476 {
477     enum P_tmpdir  = "/var/tmp";
478 }
version(FreeBSD)479 version (FreeBSD)
480 {
481     enum P_tmpdir  = "/var/tmp/";
482 }
version(NetBSD)483 version (NetBSD)
484 {
485     enum P_tmpdir  = "/var/tmp/";
486 }
version(OpenBSD)487 version (OpenBSD)
488 {
489     enum P_tmpdir  = "/tmp/";
490 }
version(DragonFlyBSD)491 version (DragonFlyBSD)
492 {
493     enum P_tmpdir  = "/var/tmp/";
494 }
version(Solaris)495 version (Solaris)
496 {
497     enum P_tmpdir  = "/var/tmp/";
498 }
version(CRuntime_UClibc)499 version (CRuntime_UClibc)
500 {
501     enum P_tmpdir  = "/tmp";
502 }
503 
version(HaveMemstream)504 version (HaveMemstream)
505 unittest
506 { /* fmemopen */
507     import core.stdc.string : memcmp;
508     byte[10] buf;
509     auto f = fmemopen(buf.ptr, 10, "w");
510     assert(f !is null);
511     assert(fprintf(f, "hello") == "hello".length);
512     assert(fflush(f) == 0);
513     assert(memcmp(buf.ptr, "hello".ptr, "hello".length) == 0);
514     //assert(buf
515     assert(fclose(f) == 0);
516 }
517 
version(HaveMemstream)518 version (HaveMemstream)
519 unittest
520 { /* Note: open_memstream is only useful for writing */
521     import core.stdc.string : memcmp;
522     char* ptr = null;
523     char[6] testdata = ['h', 'e', 'l', 'l', 'o', 0];
524     size_t sz = 0;
525     auto f = open_memstream(&ptr, &sz);
526     assert(f !is null);
527     assert(fprintf(f, "%s", testdata.ptr) == 5);
528     assert(fflush(f) == 0);
529     assert(memcmp(ptr, testdata.ptr, testdata.length) == 0);
530     assert(fclose(f) == 0);
531 }
532 
version(CRuntime_UClibc)533 version (CRuntime_UClibc) {} else
version(HaveMemstream)534 version (HaveMemstream)
535 unittest
536 { /* Note: open_wmemstream is only useful for writing */
537     import core.stdc.string : memcmp;
538     import core.stdc.wchar_ : fwprintf;
539     wchar_t* ptr = null;
540     wchar_t[6] testdata = ['h', 'e', 'l', 'l', 'o', 0];
541     size_t sz = 0;
542     auto f = open_wmemstream(&ptr, &sz);
543     assert(f !is null);
544     assert(fwprintf(f, testdata.ptr) == 5);
545     assert(fflush(f) == 0);
546     assert(memcmp(ptr, testdata.ptr, testdata.length*wchar_t.sizeof) == 0);
547     assert(fclose(f) == 0);
548 }
549 
550 
551 ssize_t getdelim (char** lineptr, size_t* n, int delimiter, FILE* stream);
552 ssize_t getline (char** lineptr, size_t* n, FILE* stream);
553