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(Solaris)183 else version (Solaris)
184 {
185     static if (__USE_FILE_OFFSET64 && __WORDSIZE != 64)
186     {
187         int   fgetpos64(FILE*, fpos_t *);
188         alias fgetpos = fgetpos64;
189 
190         FILE* fopen64(in char*, in char*);
191         alias fopen = fopen64;
192 
193         FILE* freopen64(in char*, in char*, FILE*);
194         alias freopen = freopen64;
195 
196         int   fseek(FILE*, c_long, int);
197 
198         int   fsetpos64(FILE*, in fpos_t*);
199         alias fsetpos = fsetpos64;
200 
201         FILE* tmpfile64();
202         alias tmpfile = tmpfile64;
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 }
214 
215 //
216 // C Extension (CX)
217 //
218 /*
219 L_ctermid
220 
221 char*  ctermid(char*);
222 FILE*  fdopen(int, in char*);
223 int    fileno(FILE*);
224 int    fseeko(FILE*, off_t, int);
225 off_t  ftello(FILE*);
226 char*  gets(char*);
227 int    pclose(FILE*);
228 FILE*  popen(in char*, in char*);
229 */
230 
version(CRuntime_Glibc)231 version (CRuntime_Glibc)
232 {
233     enum L_ctermid = 9;
234 
235   static if ( __USE_FILE_OFFSET64 )
236   {
237     int   fseeko64(FILE*, off_t, int);
238     alias fseeko64 fseeko;
239   }
240   else
241   {
242     int   fseeko(FILE*, off_t, int);
243   }
244 
245   static if ( __USE_FILE_OFFSET64 )
246   {
247     off_t ftello64(FILE*);
248     alias ftello64 ftello;
249   }
250   else
251   {
252     off_t ftello(FILE*);
253   }
254 }
version(CRuntime_UClibc)255 else version (CRuntime_UClibc)
256 {
257     enum L_ctermid = 9;
258     enum L_cuserid = 9;
259 
260   static if ( __USE_FILE_OFFSET64 )
261   {
262     int   fseeko64(FILE*, off_t, int);
263     alias fseeko64 fseeko;
264   }
265   else
266   {
267     int   fseeko(FILE*, off_t, int);
268   }
269 
270   static if ( __USE_FILE_OFFSET64 )
271   {
272     off_t ftello64(FILE*);
273     alias ftello64 ftello;
274   }
275   else
276   {
277     off_t ftello(FILE*);
278   }
279 }
version(Solaris)280 else version (Solaris)
281 {
282     enum L_ctermid = 9;
283     enum L_cuserid = 9;
284 
285     static if (__USE_FILE_OFFSET64 && __WORDSIZE != 64)
286     {
287         int   fseeko64(FILE*, off_t, int);
288         alias fseeko = fseeko64;
289     }
290     else
291     {
292         int   fseeko(FILE*, off_t, int);
293     }
294 
295     static if (__USE_FILE_OFFSET64 && __WORDSIZE != 64)
296     {
297         off_t ftello64(FILE*);
298         alias ftello = ftello64;
299     }
300     else
301     {
302         off_t ftello(FILE*);
303     }
304 }
version(Posix)305 else version (Posix)
306 {
307     int   fseeko(FILE*, off_t, int);
308     off_t ftello(FILE*);
309 }
310 
311 char*  ctermid(char*);
312 FILE*  fdopen(int, in char*);
313 int    fileno(FILE*);
314 //int    fseeko(FILE*, off_t, int);
315 //off_t  ftello(FILE*);
316 char*  gets(char*);
317 int    pclose(FILE*);
318 FILE*  popen(in char*, in char*);
319 
320 
321 // memstream functions are conforming to POSIX.1-2008.  These functions are
322 // not specified in POSIX.1-2001 and are not widely available on other
323 // systems.
324 version (CRuntime_Glibc)                     // as of glibc 1.0x
325     version = HaveMemstream;
326 else version (FreeBSD)                      // as of FreeBSD 9.2
327     version = HaveMemstream;
328 else version (DragonFlyBSD)                 // for DragonFlyBSD
329     version = HaveMemstream;
330 else version (OpenBSD)                      // as of OpenBSD 5.4
331     version = HaveMemstream;
332 else version (CRuntime_UClibc)
333     version = HaveMemstream;
334 
version(HaveMemstream)335 version (HaveMemstream)
336 {
337     FILE*  fmemopen(in void* buf, in size_t size, in char* mode);
338     FILE*  open_memstream(char** ptr, size_t* sizeloc);
339     version (CRuntime_UClibc) {} else
340     FILE*  open_wmemstream(wchar_t** ptr, size_t* sizeloc);
341 }
342 
343 //
344 // Thread-Safe Functions (TSF)
345 //
346 /*
347 void   flockfile(FILE*);
348 int    ftrylockfile(FILE*);
349 void   funlockfile(FILE*);
350 int    getc_unlocked(FILE*);
351 int    getchar_unlocked();
352 int    putc_unlocked(int, FILE*);
353 int    putchar_unlocked(int);
354 */
355 
version(CRuntime_Glibc)356 version (CRuntime_Glibc)
357 {
358     void   flockfile(FILE*);
359     int    ftrylockfile(FILE*);
360     void   funlockfile(FILE*);
361     int    getc_unlocked(FILE*);
362     int    getchar_unlocked();
363     int    putc_unlocked(int, FILE*);
364     int    putchar_unlocked(int);
365 }
version(OpenBSD)366 else version (OpenBSD)
367 {
368     void   flockfile(FILE*);
369     int    ftrylockfile(FILE*);
370     void   funlockfile(FILE*);
371     int    getc_unlocked(FILE*);
372     int    getchar_unlocked();
373     int    putc_unlocked(int, FILE*);
374     int    putchar_unlocked(int);
375 }
version(Solaris)376 else version (Solaris)
377 {
378     void   flockfile(FILE*);
379     int    ftrylockfile(FILE*);
380     void   funlockfile(FILE*);
381     int    getc_unlocked(FILE*);
382     int    getchar_unlocked();
383     int    putc_unlocked(int, FILE*);
384     int    putchar_unlocked(int);
385 }
version(CRuntime_UClibc)386 else version (CRuntime_UClibc)
387 {
388     void   flockfile(FILE*);
389     int    ftrylockfile(FILE*);
390     void   funlockfile(FILE*);
391     int    getc_unlocked(FILE*);
392     int    getchar_unlocked();
393     int    putc_unlocked(int, FILE*);
394     int    putchar_unlocked(int);
395 }
396 
397 //
398 // XOpen (XSI)
399 //
400 /*
401 P_tmpdir
402 va_list (defined in core.stdc.stdarg)
403 
404 char*  tempnam(in char*, in char*);
405 */
406 
407 char*  tempnam(in char*, in char*);
408 
version(CRuntime_Glibc)409 version (CRuntime_Glibc)
410 {
411     enum P_tmpdir  = "/tmp";
412 }
version(CRuntime_Musl)413 version (CRuntime_Musl)
414 {
415     enum P_tmpdir  = "/tmp";
416 }
version(Darwin)417 version (Darwin)
418 {
419     enum P_tmpdir  = "/var/tmp";
420 }
version(FreeBSD)421 version (FreeBSD)
422 {
423     enum P_tmpdir  = "/var/tmp/";
424 }
version(NetBSD)425 version (NetBSD)
426 {
427     enum P_tmpdir  = "/var/tmp/";
428 }
version(OpenBSD)429 version (OpenBSD)
430 {
431     enum P_tmpdir  = "/tmp/";
432 }
version(DragonFlyBSD)433 version (DragonFlyBSD)
434 {
435     enum P_tmpdir  = "/var/tmp/";
436 }
version(Solaris)437 version (Solaris)
438 {
439     enum P_tmpdir  = "/var/tmp/";
440 }
version(CRuntime_UClibc)441 version (CRuntime_UClibc)
442 {
443     enum P_tmpdir  = "/tmp";
444 }
445 
version(HaveMemstream)446 version (HaveMemstream)
447 unittest
448 { /* fmemopen */
449     import core.stdc.string : memcmp;
450     byte[10] buf;
451     auto f = fmemopen(buf.ptr, 10, "w");
452     assert(f !is null);
453     assert(fprintf(f, "hello") == "hello".length);
454     assert(fflush(f) == 0);
455     assert(memcmp(buf.ptr, "hello".ptr, "hello".length) == 0);
456     //assert(buf
457     assert(fclose(f) == 0);
458 }
459 
version(HaveMemstream)460 version (HaveMemstream)
461 unittest
462 { /* Note: open_memstream is only useful for writing */
463     import core.stdc.string : memcmp;
464     char* ptr = null;
465     char[6] testdata = ['h', 'e', 'l', 'l', 'o', 0];
466     size_t sz = 0;
467     auto f = open_memstream(&ptr, &sz);
468     assert(f !is null);
469     assert(fprintf(f, "%s", testdata.ptr) == 5);
470     assert(fflush(f) == 0);
471     assert(memcmp(ptr, testdata.ptr, testdata.length) == 0);
472     assert(fclose(f) == 0);
473 }
474 
version(CRuntime_UClibc)475 version (CRuntime_UClibc) {} else
version(HaveMemstream)476 version (HaveMemstream)
477 unittest
478 { /* Note: open_wmemstream is only useful for writing */
479     import core.stdc.string : memcmp;
480     import core.stdc.wchar_ : fwprintf;
481     wchar_t* ptr = null;
482     wchar_t[6] testdata = ['h', 'e', 'l', 'l', 'o', 0];
483     size_t sz = 0;
484     auto f = open_wmemstream(&ptr, &sz);
485     assert(f !is null);
486     assert(fwprintf(f, testdata.ptr) == 5);
487     assert(fflush(f) == 0);
488     assert(memcmp(ptr, testdata.ptr, testdata.length*wchar_t.sizeof) == 0);
489     assert(fclose(f) == 0);
490 }
491 
492 
493 ssize_t getdelim (char** lineptr, size_t* n, int delimiter, FILE* stream);
494 ssize_t getline (char** lineptr, size_t* n, FILE* stream);
495