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 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 @system:
36
37 //
38 // Required (defined in core.stdc.stdio)
39 //
40 /*
41 BUFSIZ
42 _IOFBF
43 _IOLBF
44 _IONBF
45 L_tmpnam
46 SEEK_CUR
47 SEEK_END
48 SEEK_SET
49 FILENAME_MAX
50 FOPEN_MAX
51 TMP_MAX
52 EOF
53 NULL
54 stderr
55 stdin
56 stdout
57 FILE
58 fpos_t
59 size_t
60
61 void clearerr(FILE*);
62 int fclose(FILE*);
63 int feof(FILE*);
64 int ferror(FILE*);
65 int fflush(FILE*);
66 int fgetc(FILE*);
67 int fgetpos(FILE*, fpos_t *);
68 char* fgets(char*, int, FILE*);
69 FILE* fopen(const scope char*, const scope char*);
70 int fprintf(FILE*, const scope char*, ...);
71 int fputc(int, FILE*);
72 int fputs(const scope char*, FILE*);
73 size_t fread(void *, size_t, size_t, FILE*);
74 FILE* freopen(const scope char*, const scope char*, FILE*);
75 int fscanf(FILE*, const scope char*, ...);
76 int fseek(FILE*, c_long, int);
77 int fsetpos(FILE*, const scope fpos_t*);
78 c_long ftell(FILE*);
79 size_t fwrite(in void *, size_t, size_t, FILE*);
80 int getc(FILE*);
81 int getchar();
82 char* gets(char*);
83 void perror(const scope char*);
84 int printf(const scope char*, ...);
85 int putc(int, FILE*);
86 int putchar(int);
87 int puts(const scope char*);
88 int remove(const scope char*);
89 int rename(const scope char*, const scope char*);
90 void rewind(FILE*);
91 int scanf(const scope char*, ...);
92 void setbuf(FILE*, char*);
93 int setvbuf(FILE*, char*, int, size_t);
94 int snprintf(char*, size_t, const scope char*, ...);
95 int sprintf(char*, const scope char*, ...);
96 int sscanf(const scope char*, const scope char*, int ...);
97 FILE* tmpfile();
98 char* tmpnam(char*);
99 int ungetc(int, FILE*);
100 int vfprintf(FILE*, const scope char*, va_list);
101 int vfscanf(FILE*, const scope char*, va_list);
102 int vprintf(const scope char*, va_list);
103 int vscanf(const scope char*, va_list);
104 int vsnprintf(char*, size_t, const scope char*, va_list);
105 int vsprintf(char*, const scope char*, va_list);
106 int vsscanf(const scope char*, const scope char*, va_list arg);
107 */
108
109 version (CRuntime_Glibc)
110 {
111 /*
112 * actually, if __USE_FILE_OFFSET64 && !_LARGEFILE64_SOURCE
113 * the *64 functions shouldn't be visible, but the aliases should
114 * still be supported
115 */
116 static if ( __USE_FILE_OFFSET64 )
117 {
118 int fgetpos64(FILE*, fpos_t *);
119 alias fgetpos64 fgetpos;
120
121 FILE* fopen64(const scope char*, const scope char*);
122 alias fopen64 fopen;
123
124 FILE* freopen64(const scope char*, const scope char*, FILE*);
125 alias freopen64 freopen;
126
127 int fseek(FILE*, c_long, int);
128
129 int fsetpos64(FILE*, const scope fpos_t*);
130 alias fsetpos64 fsetpos;
131
132 FILE* tmpfile64();
133 alias tmpfile64 tmpfile;
134 }
135 else
136 {
137 int fgetpos(FILE*, fpos_t *);
138 FILE* fopen(const scope char*, const scope char*);
139 FILE* freopen(const scope char*, const scope char*, FILE*);
140 int fseek(FILE*, c_long, int);
141 int fsetpos(FILE*, const scope fpos_t*);
142 FILE* tmpfile();
143 }
144 }
version(CRuntime_Bionic)145 else version (CRuntime_Bionic)
146 {
147 int fgetpos(FILE*, fpos_t *);
148 FILE* fopen(const scope char*, const scope char*);
149 FILE* freopen(const scope char*, const scope char*, FILE*);
150 int fseek(FILE*, c_long, int);
151 int fsetpos(FILE*, const scope fpos_t*);
152 }
version(CRuntime_UClibc)153 else version (CRuntime_UClibc)
154 {
155 static if ( __USE_FILE_OFFSET64 )
156 {
157 int fgetpos64(FILE*, fpos_t *);
158 alias fgetpos64 fgetpos;
159
160 FILE* fopen64(const scope char*, const scope char*);
161 alias fopen64 fopen;
162
163 FILE* freopen64(const scope char*, const scope char*, FILE*);
164 alias freopen64 freopen;
165
166 int fseek(FILE*, c_long, int);
167
168 int fsetpos64(FILE*, const scope fpos_t*);
169 alias fsetpos64 fsetpos;
170
171 FILE* tmpfile64();
172 alias tmpfile64 tmpfile;
173 }
174 else
175 {
176 int fgetpos(FILE*, fpos_t *);
177 FILE* fopen(const scope char*, const scope char*);
178 FILE* freopen(const scope char*, const scope char*, FILE*);
179 int fseek(FILE*, c_long, int);
180 int fsetpos(FILE*, const scope fpos_t*);
181 FILE* tmpfile();
182 }
183 }
version(CRuntime_Musl)184 else version (CRuntime_Musl)
185 {
186 static if ( __USE_FILE_OFFSET64 )
187 {
188 int fgetpos64(FILE*, fpos_t *);
189 alias fgetpos64 fgetpos;
190
191 FILE* fopen64(const scope char*, const scope char*);
192 alias fopen64 fopen;
193
194 FILE* freopen64(const scope char*, const scope char*, FILE*);
195 alias freopen64 freopen;
196
197 int fseek(FILE*, c_long, int);
198
199 int fsetpos64(FILE*, const scope fpos_t*);
200 alias fsetpos64 fsetpos;
201
202 FILE* tmpfile64();
203 alias tmpfile64 tmpfile;
204 }
205 else
206 {
207 int fgetpos(FILE*, fpos_t *);
208 FILE* fopen(const scope char*, const scope char*);
209 FILE* freopen(const scope char*, const scope char*, FILE*);
210 int fseek(FILE*, c_long, int);
211 int fsetpos(FILE*, const scope fpos_t*);
212 FILE* tmpfile();
213 }
214 }
version(Solaris)215 else version (Solaris)
216 {
217 static if (__USE_FILE_OFFSET64 && __WORDSIZE != 64)
218 {
219 int fgetpos64(FILE*, fpos_t *);
220 alias fgetpos = fgetpos64;
221
222 FILE* fopen64(const scope char*, const scope char*);
223 alias fopen = fopen64;
224
225 FILE* freopen64(const scope char*, const scope char*, FILE*);
226 alias freopen = freopen64;
227
228 int fseek(FILE*, c_long, int);
229
230 int fsetpos64(FILE*, const scope fpos_t*);
231 alias fsetpos = fsetpos64;
232
233 FILE* tmpfile64();
234 alias tmpfile = tmpfile64;
235 }
236 else
237 {
238 int fgetpos(FILE*, fpos_t *);
239 FILE* fopen(const scope char*, const scope char*);
240 FILE* freopen(const scope char*, const scope char*, FILE*);
241 int fseek(FILE*, c_long, int);
242 int fsetpos(FILE*, const scope fpos_t*);
243 FILE* tmpfile();
244 }
245 }
246
247 //
248 // C Extension (CX)
249 //
250 /*
251 L_ctermid
252
253 char* ctermid(char*);
254 FILE* fdopen(int, const scope char*);
255 int fileno(FILE*);
256 int fseeko(FILE*, off_t, int);
257 off_t ftello(FILE*);
258 ssize_t getdelim(char**, size_t*, int, FILE*);
259 ssize_t getline(char**, size_t*, FILE*);
260 char* gets(char*);
261 int pclose(FILE*);
262 FILE* popen(const scope char*, const scope char*);
263 */
264
version(CRuntime_Glibc)265 version (CRuntime_Glibc)
266 {
267 enum L_ctermid = 9;
268
269 static if ( __USE_FILE_OFFSET64 )
270 {
271 int fseeko64(FILE*, off_t, int);
272 alias fseeko64 fseeko;
273 }
274 else
275 {
276 int fseeko(FILE*, off_t, int);
277 }
278
279 static if ( __USE_FILE_OFFSET64 )
280 {
281 off_t ftello64(FILE*);
282 alias ftello64 ftello;
283 }
284 else
285 {
286 off_t ftello(FILE*);
287 }
288
289 ssize_t getdelim(char**, size_t*, int, FILE*);
290 ssize_t getline(char**, size_t*, FILE*);
291 }
version(CRuntime_UClibc)292 else version (CRuntime_UClibc)
293 {
294 enum L_ctermid = 9;
295 enum L_cuserid = 9;
296
297 static if ( __USE_FILE_OFFSET64 )
298 {
299 int fseeko64(FILE*, off_t, int);
300 alias fseeko64 fseeko;
301 }
302 else
303 {
304 int fseeko(FILE*, off_t, int);
305 }
306
307 static if ( __USE_FILE_OFFSET64 )
308 {
309 off_t ftello64(FILE*);
310 alias ftello64 ftello;
311 }
312 else
313 {
314 off_t ftello(FILE*);
315 }
316
317 ssize_t getdelim(char**, size_t*, int, FILE*);
318 ssize_t getline(char**, size_t*, FILE*);
319 }
version(CRuntime_Musl)320 else version (CRuntime_Musl)
321 {
322 enum L_ctermid = 20;
323
324 static if ( __USE_FILE_OFFSET64 )
325 {
326 int fseeko64(FILE*, off_t, int);
327 alias fseeko64 fseeko;
328 }
329 else
330 {
331 int fseeko(FILE*, off_t, int);
332 }
333
334 static if ( __USE_FILE_OFFSET64 )
335 {
336 off_t ftello64(FILE*);
337 alias ftello64 ftello;
338 }
339 else
340 {
341 off_t ftello(FILE*);
342 }
343
344 ssize_t getdelim(char**, size_t*, int, FILE*);
345 ssize_t getline(char**, size_t*, FILE*);
346 }
version(CRuntime_Bionic)347 else version (CRuntime_Bionic)
348 {
349 enum L_ctermid = 1024;
350
351 static if ( __USE_FILE_OFFSET64 )
352 {
353 int fseeko64(FILE*, off_t, int);
354 alias fseeko64 fseeko;
355 }
356 else
357 {
358 int fseeko(FILE*, off_t, int);
359 }
360
361 static if ( __USE_FILE_OFFSET64 )
362 {
363 off_t ftello64(FILE*);
364 alias ftello64 ftello;
365 }
366 else
367 {
368 off_t ftello(FILE*);
369 }
370
371 ssize_t getdelim(char**, size_t*, int, FILE*);
372 ssize_t getline(char**, size_t*, FILE*);
373 }
version(Darwin)374 else version (Darwin)
375 {
376 enum L_ctermid = 1024;
377
378 int fseeko(FILE*, off_t, int);
379 off_t ftello(FILE*);
380
381 ssize_t getdelim(char**, size_t*, int, FILE*);
382 ssize_t getline(char**, size_t*, FILE*);
383 }
version(FreeBSD)384 else version (FreeBSD)
385 {
386 import core.sys.freebsd.config;
387
388 enum L_ctermid = 1024;
389
390 int fseeko(FILE*, off_t, int);
391 off_t ftello(FILE*);
392
393 static if (__FreeBSD_version >= 800000)
394 {
395 ssize_t getdelim(char**, size_t*, int, FILE*);
396 ssize_t getline(char**, size_t*, FILE*);
397 }
398 }
version(NetBSD)399 else version (NetBSD)
400 {
401 enum L_ctermid = 1024;
402
403 int fseeko(FILE*, off_t, int);
404 off_t ftello(FILE*);
405
406 ssize_t getdelim(char**, size_t*, int, FILE*);
407 ssize_t getline(char**, size_t*, FILE*);
408 }
version(OpenBSD)409 else version (OpenBSD)
410 {
411 enum L_ctermid = 1024;
412
413 int fseeko(FILE*, off_t, int);
414 off_t ftello(FILE*);
415
416 ssize_t getdelim(char**, size_t*, int, FILE*);
417 ssize_t getline(char**, size_t*, FILE*);
418 }
version(DragonFlyBSD)419 else version (DragonFlyBSD)
420 {
421 enum L_ctermid = 1024;
422
423 int fseeko(FILE*, off_t, int);
424 off_t ftello(FILE*);
425
426 ssize_t getdelim(char**, size_t*, int, FILE*);
427 ssize_t getline(char**, size_t*, FILE*);
428 }
version(Solaris)429 else version (Solaris)
430 {
431 enum L_ctermid = 9;
432 enum L_cuserid = 9;
433
434 static if (__USE_FILE_OFFSET64 && __WORDSIZE != 64)
435 {
436 int fseeko64(FILE*, off_t, int);
437 alias fseeko = fseeko64;
438 }
439 else
440 {
441 int fseeko(FILE*, off_t, int);
442 }
443
444 static if (__USE_FILE_OFFSET64 && __WORDSIZE != 64)
445 {
446 off_t ftello64(FILE*);
447 alias ftello = ftello64;
448 }
449 else
450 {
451 off_t ftello(FILE*);
452 }
453
454 ssize_t getdelim(char**, size_t*, int, FILE*);
455 ssize_t getline(char**, size_t*, FILE*);
456 }
version(Posix)457 else version (Posix)
458 {
459 int fseeko(FILE*, off_t, int);
460 off_t ftello(FILE*);
461 }
462
463 char* ctermid(char*);
464 FILE* fdopen(int, const scope char*);
465 int fileno(FILE*);
466 char* gets(char*);
467 int pclose(FILE*);
468 FILE* popen(const scope char*, const scope char*);
469
470
471 // memstream functions are conforming to POSIX.1-2008. These functions are
472 // not specified in POSIX.1-2001 and are not widely available on other
473 // systems.
474 version (CRuntime_Glibc) // as of glibc 1.0x
475 version = HaveMemstream;
476 else version (FreeBSD) // as of FreeBSD 9.2
477 version = HaveMemstream;
478 else version (DragonFlyBSD) // for DragonFlyBSD
479 version = HaveMemstream;
480 else version (OpenBSD) // as of OpenBSD 5.4
481 version = HaveMemstream;
482 else version (CRuntime_UClibc)
483 version = HaveMemstream;
484 // http://git.musl-libc.org/cgit/musl/commit/src/stdio/open_memstream.c?id=b158b32a44d56ef20407d4285b58180447ffff1f
485 else version (CRuntime_Musl)
486 version = HaveMemstream;
487
version(HaveMemstream)488 version (HaveMemstream)
489 {
490 FILE* fmemopen(const scope void* buf, in size_t size, const scope char* mode);
491 FILE* open_memstream(char** ptr, size_t* sizeloc);
492 version (CRuntime_UClibc) {} else
493 FILE* open_wmemstream(wchar_t** ptr, size_t* sizeloc);
494 }
495
496 //
497 // Thread-Safe Functions (TSF)
498 //
499 /*
500 void flockfile(FILE*);
501 int ftrylockfile(FILE*);
502 void funlockfile(FILE*);
503 int getc_unlocked(FILE*);
504 int getchar_unlocked();
505 int putc_unlocked(int, FILE*);
506 int putchar_unlocked(int);
507 */
508
version(CRuntime_Glibc)509 version (CRuntime_Glibc)
510 {
511 void flockfile(FILE*);
512 int ftrylockfile(FILE*);
513 void funlockfile(FILE*);
514 int getc_unlocked(FILE*);
515 int getchar_unlocked();
516 int putc_unlocked(int, FILE*);
517 int putchar_unlocked(int);
518 }
version(CRuntime_Musl)519 else version (CRuntime_Musl)
520 {
521 void flockfile(FILE*);
522 int ftrylockfile(FILE*);
523 void funlockfile(FILE*);
524 int getc_unlocked(FILE*);
525 int getchar_unlocked();
526 int putc_unlocked(int, FILE*);
527 int putchar_unlocked(int);
528 }
version(CRuntime_Bionic)529 else version (CRuntime_Bionic)
530 {
531 void flockfile(FILE*);
532 int ftrylockfile(FILE*);
533 void funlockfile(FILE*);
534 int getc_unlocked(FILE*);
535 int getchar_unlocked();
536 int putc_unlocked(int, FILE*);
537 int putchar_unlocked(int);
538 }
version(Darwin)539 else version (Darwin)
540 {
541 void flockfile(FILE*);
542 int ftrylockfile(FILE*);
543 void funlockfile(FILE*);
544 int getc_unlocked(FILE*);
545 int getchar_unlocked();
546 int putc_unlocked(int, FILE*);
547 int putchar_unlocked(int);
548 }
version(FreeBSD)549 else version (FreeBSD)
550 {
551 void flockfile(FILE*);
552 int ftrylockfile(FILE*);
553 void funlockfile(FILE*);
554 int getc_unlocked(FILE*);
555 int getchar_unlocked();
556 int putc_unlocked(int, FILE*);
557 int putchar_unlocked(int);
558 }
version(NetBSD)559 else version (NetBSD)
560 {
561 void flockfile(FILE*);
562 int ftrylockfile(FILE*);
563 void funlockfile(FILE*);
564 int getc_unlocked(FILE*);
565 int getchar_unlocked();
566 int putc_unlocked(int, FILE*);
567 int putchar_unlocked(int);
568 }
version(OpenBSD)569 else version (OpenBSD)
570 {
571 void flockfile(FILE*);
572 int ftrylockfile(FILE*);
573 void funlockfile(FILE*);
574 int getc_unlocked(FILE*);
575 int getchar_unlocked();
576 int putc_unlocked(int, FILE*);
577 int putchar_unlocked(int);
578 }
version(DragonFlyBSD)579 else version (DragonFlyBSD)
580 {
581 void flockfile(FILE*);
582 int ftrylockfile(FILE*);
583 void funlockfile(FILE*);
584 int getc_unlocked(FILE*);
585 int getchar_unlocked();
586 int putc_unlocked(int, FILE*);
587 int putchar_unlocked(int);
588 }
version(Solaris)589 else version (Solaris)
590 {
591 void flockfile(FILE*);
592 int ftrylockfile(FILE*);
593 void funlockfile(FILE*);
594 int getc_unlocked(FILE*);
595 int getchar_unlocked();
596 int putc_unlocked(int, FILE*);
597 int putchar_unlocked(int);
598 }
version(CRuntime_UClibc)599 else version (CRuntime_UClibc)
600 {
601 void flockfile(FILE*);
602 int ftrylockfile(FILE*);
603 void funlockfile(FILE*);
604 int getc_unlocked(FILE*);
605 int getchar_unlocked();
606 int putc_unlocked(int, FILE*);
607 int putchar_unlocked(int);
608 }
609
610 //
611 // XOpen (XSI)
612 //
613 /*
614 P_tmpdir
615 va_list (defined in core.stdc.stdarg)
616
617 char* tempnam(const scope char*, const scope char*);
618 */
619
620 char* tempnam(const scope char*, const scope char*);
621
version(CRuntime_Glibc)622 version (CRuntime_Glibc)
623 {
624 enum P_tmpdir = "/tmp";
625 }
version(CRuntime_Musl)626 version (CRuntime_Musl)
627 {
628 enum P_tmpdir = "/tmp";
629 }
version(Darwin)630 version (Darwin)
631 {
632 enum P_tmpdir = "/var/tmp";
633 }
version(FreeBSD)634 version (FreeBSD)
635 {
636 enum P_tmpdir = "/var/tmp/";
637 }
version(NetBSD)638 version (NetBSD)
639 {
640 enum P_tmpdir = "/var/tmp/";
641 }
version(OpenBSD)642 version (OpenBSD)
643 {
644 enum P_tmpdir = "/tmp/";
645 }
version(DragonFlyBSD)646 version (DragonFlyBSD)
647 {
648 enum P_tmpdir = "/var/tmp/";
649 }
version(Solaris)650 version (Solaris)
651 {
652 enum P_tmpdir = "/var/tmp/";
653 }
version(CRuntime_UClibc)654 version (CRuntime_UClibc)
655 {
656 enum P_tmpdir = "/tmp";
657 }
658
version(HaveMemstream)659 version (HaveMemstream)
660 unittest
661 { /* fmemopen */
662 import core.stdc.string : memcmp;
663 byte[10] buf;
664 auto f = fmemopen(buf.ptr, 10, "w");
665 assert(f !is null);
666 assert(fprintf(f, "hello") == "hello".length);
667 assert(fflush(f) == 0);
668 assert(memcmp(buf.ptr, "hello".ptr, "hello".length) == 0);
669 //assert(buf
670 assert(fclose(f) == 0);
671 }
672
version(HaveMemstream)673 version (HaveMemstream)
674 unittest
675 { /* Note: open_memstream is only useful for writing */
676 import core.stdc.string : memcmp;
677 char* ptr = null;
678 char[6] testdata = ['h', 'e', 'l', 'l', 'o', 0];
679 size_t sz = 0;
680 auto f = open_memstream(&ptr, &sz);
681 assert(f !is null);
682 assert(fprintf(f, "%s", testdata.ptr) == 5);
683 assert(fflush(f) == 0);
684 assert(memcmp(ptr, testdata.ptr, testdata.length) == 0);
685 assert(fclose(f) == 0);
686 }
687
version(CRuntime_UClibc)688 version (CRuntime_UClibc) {} else
version(HaveMemstream)689 version (HaveMemstream)
690 unittest
691 { /* Note: open_wmemstream is only useful for writing */
692 import core.stdc.string : memcmp;
693 import core.stdc.wchar_ : fwprintf;
694 wchar_t* ptr = null;
695 wchar_t[6] testdata = ['h', 'e', 'l', 'l', 'o', 0];
696 size_t sz = 0;
697 auto f = open_wmemstream(&ptr, &sz);
698 assert(f !is null);
699 assert(fwprintf(f, testdata.ptr) == 5);
700 assert(fflush(f) == 0);
701 assert(memcmp(ptr, testdata.ptr, testdata.length*wchar_t.sizeof) == 0);
702 assert(fclose(f) == 0);
703 }
704