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