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 int fgetpos(FILE*, fpos_t *); 186 FILE* fopen(const scope char*, const scope char*); 187 FILE* freopen(const scope char*, const scope char*, FILE*); 188 int fseek(FILE*, c_long, int); 189 int fsetpos(FILE*, const scope fpos_t*); 190 FILE* tmpfile(); 191 192 alias fgetpos64 = fgetpos; 193 alias fopen64 = fopen; 194 alias freopen64 = freopen; 195 alias fsetpos64 = fsetpos; 196 alias tmpfile64 = tmpfile; 197 } 198 else version (Solaris) 199 { 200 static if (__USE_FILE_OFFSET64 && __WORDSIZE != 64) 201 { 202 int fgetpos64(FILE*, fpos_t *); 203 alias fgetpos = fgetpos64; 204 205 FILE* fopen64(const scope char*, const scope char*); 206 alias fopen = fopen64; 207 208 FILE* freopen64(const scope char*, const scope char*, FILE*); 209 alias freopen = freopen64; 210 211 int fseek(FILE*, c_long, int); 212 213 int fsetpos64(FILE*, const scope fpos_t*); 214 alias fsetpos = fsetpos64; 215 216 FILE* tmpfile64(); 217 alias tmpfile = tmpfile64; 218 } 219 else 220 { 221 int fgetpos(FILE*, fpos_t *); 222 FILE* fopen(const scope char*, const scope char*); 223 FILE* freopen(const scope char*, const scope char*, FILE*); 224 int fseek(FILE*, c_long, int); 225 int fsetpos(FILE*, const scope fpos_t*); 226 FILE* tmpfile(); 227 } 228 } 229 230 // 231 // C Extension (CX) 232 // 233 /* 234 L_ctermid 235 236 char* ctermid(char*); 237 FILE* fdopen(int, const scope char*); 238 int fileno(FILE*); 239 int fseeko(FILE*, off_t, int); 240 off_t ftello(FILE*); 241 ssize_t getdelim(char**, size_t*, int, FILE*); 242 ssize_t getline(char**, size_t*, FILE*); 243 char* gets(char*); 244 int pclose(FILE*); 245 FILE* popen(const scope char*, const scope char*); 246 */ 247 248 version (CRuntime_Glibc) 249 { 250 enum L_ctermid = 9; 251 252 static if ( __USE_FILE_OFFSET64 ) 253 { 254 int fseeko64(FILE*, off_t, int); 255 alias fseeko64 fseeko; 256 } 257 else 258 { 259 int fseeko(FILE*, off_t, int); 260 } 261 262 static if ( __USE_FILE_OFFSET64 ) 263 { 264 off_t ftello64(FILE*); 265 alias ftello64 ftello; 266 } 267 else 268 { 269 off_t ftello(FILE*); 270 } 271 272 ssize_t getdelim(char**, size_t*, int, FILE*); 273 ssize_t getline(char**, size_t*, FILE*); 274 } 275 else version (CRuntime_UClibc) 276 { 277 enum L_ctermid = 9; 278 enum L_cuserid = 9; 279 280 static if ( __USE_FILE_OFFSET64 ) 281 { 282 int fseeko64(FILE*, off_t, int); 283 alias fseeko64 fseeko; 284 } 285 else 286 { 287 int fseeko(FILE*, off_t, int); 288 } 289 290 static if ( __USE_FILE_OFFSET64 ) 291 { 292 off_t ftello64(FILE*); 293 alias ftello64 ftello; 294 } 295 else 296 { 297 off_t ftello(FILE*); 298 } 299 300 ssize_t getdelim(char**, size_t*, int, FILE*); 301 ssize_t getline(char**, size_t*, FILE*); 302 } 303 else version (CRuntime_Musl) 304 { 305 enum L_ctermid = 20; 306 307 int fseeko(FILE*, off_t, int); 308 alias fseeko64 = fseeko; 309 310 off_t ftello(FILE*); 311 alias ftello64 = ftello; 312 313 ssize_t getdelim(char**, size_t*, int, FILE*); 314 ssize_t getline(char**, size_t*, FILE*); 315 } 316 else version (CRuntime_Bionic) 317 { 318 enum L_ctermid = 1024; 319 320 static if ( __USE_FILE_OFFSET64 ) 321 { 322 int fseeko64(FILE*, off_t, int); 323 alias fseeko64 fseeko; 324 } 325 else 326 { 327 int fseeko(FILE*, off_t, int); 328 } 329 330 static if ( __USE_FILE_OFFSET64 ) 331 { 332 off_t ftello64(FILE*); 333 alias ftello64 ftello; 334 } 335 else 336 { 337 off_t ftello(FILE*); 338 } 339 340 ssize_t getdelim(char**, size_t*, int, FILE*); 341 ssize_t getline(char**, size_t*, FILE*); 342 } 343 else version (Darwin) 344 { 345 enum L_ctermid = 1024; 346 347 int fseeko(FILE*, off_t, int); 348 off_t ftello(FILE*); 349 350 ssize_t getdelim(char**, size_t*, int, FILE*); 351 ssize_t getline(char**, size_t*, FILE*); 352 } 353 else version (FreeBSD) 354 { 355 import core.sys.freebsd.config; 356 357 enum L_ctermid = 1024; 358 359 int fseeko(FILE*, off_t, int); 360 off_t ftello(FILE*); 361 362 static if (__FreeBSD_version >= 800000) 363 { 364 ssize_t getdelim(char**, size_t*, int, FILE*); 365 ssize_t getline(char**, size_t*, FILE*); 366 } 367 } 368 else version (NetBSD) 369 { 370 enum L_ctermid = 1024; 371 372 int fseeko(FILE*, off_t, int); 373 off_t ftello(FILE*); 374 375 ssize_t getdelim(char**, size_t*, int, FILE*); 376 ssize_t getline(char**, size_t*, FILE*); 377 } 378 else version (OpenBSD) 379 { 380 enum L_ctermid = 1024; 381 382 int fseeko(FILE*, off_t, int); 383 off_t ftello(FILE*); 384 385 ssize_t getdelim(char**, size_t*, int, FILE*); 386 ssize_t getline(char**, size_t*, FILE*); 387 } 388 else version (DragonFlyBSD) 389 { 390 enum L_ctermid = 1024; 391 392 int fseeko(FILE*, off_t, int); 393 off_t ftello(FILE*); 394 395 ssize_t getdelim(char**, size_t*, int, FILE*); 396 ssize_t getline(char**, size_t*, FILE*); 397 } 398 else version (Solaris) 399 { 400 enum L_ctermid = 9; 401 enum L_cuserid = 9; 402 403 static if (__USE_FILE_OFFSET64 && __WORDSIZE != 64) 404 { 405 int fseeko64(FILE*, off_t, int); 406 alias fseeko = fseeko64; 407 } 408 else 409 { 410 int fseeko(FILE*, off_t, int); 411 } 412 413 static if (__USE_FILE_OFFSET64 && __WORDSIZE != 64) 414 { 415 off_t ftello64(FILE*); 416 alias ftello = ftello64; 417 } 418 else 419 { 420 off_t ftello(FILE*); 421 } 422 423 ssize_t getdelim(char**, size_t*, int, FILE*); 424 ssize_t getline(char**, size_t*, FILE*); 425 } 426 else version (Posix) 427 { 428 int fseeko(FILE*, off_t, int); 429 off_t ftello(FILE*); 430 } 431 432 char* ctermid(char*); 433 FILE* fdopen(int, const scope char*); 434 int fileno(FILE*); 435 char* gets(char*); 436 int pclose(FILE*); 437 FILE* popen(const scope char*, const scope char*); 438 439 440 // memstream functions are conforming to POSIX.1-2008. These functions are 441 // not specified in POSIX.1-2001 and are not widely available on other 442 // systems. 443 version (CRuntime_Glibc) // as of glibc 1.0x 444 version = HaveMemstream; 445 else version (FreeBSD) // as of FreeBSD 9.2 446 version = HaveMemstream; 447 else version (DragonFlyBSD) // for DragonFlyBSD 448 version = HaveMemstream; 449 else version (OpenBSD) // as of OpenBSD 5.4 450 version = HaveMemstream; 451 else version (CRuntime_UClibc) 452 version = HaveMemstream; 453 // http://git.musl-libc.org/cgit/musl/commit/src/stdio/open_memstream.c?id=b158b32a44d56ef20407d4285b58180447ffff1f 454 else version (CRuntime_Musl) 455 version = HaveMemstream; 456 457 version (HaveMemstream) 458 { 459 FILE* fmemopen(const scope void* buf, size_t size, const scope char* mode); 460 FILE* open_memstream(char** ptr, size_t* sizeloc); 461 version (CRuntime_UClibc) {} else 462 FILE* open_wmemstream(wchar_t** ptr, size_t* sizeloc); 463 } 464 465 // 466 // Thread-Safe Functions (TSF) 467 // 468 /* 469 void flockfile(FILE*); 470 int ftrylockfile(FILE*); 471 void funlockfile(FILE*); 472 int getc_unlocked(FILE*); 473 int getchar_unlocked(); 474 int putc_unlocked(int, FILE*); 475 int putchar_unlocked(int); 476 */ 477 478 version (CRuntime_Glibc) 479 { 480 void flockfile(FILE*); 481 int ftrylockfile(FILE*); 482 void funlockfile(FILE*); 483 int getc_unlocked(FILE*); 484 int getchar_unlocked(); 485 int putc_unlocked(int, FILE*); 486 int putchar_unlocked(int); 487 } 488 else version (CRuntime_Musl) 489 { 490 void flockfile(FILE*); 491 int ftrylockfile(FILE*); 492 void funlockfile(FILE*); 493 int getc_unlocked(FILE*); 494 int getchar_unlocked(); 495 int putc_unlocked(int, FILE*); 496 int putchar_unlocked(int); 497 } 498 else version (CRuntime_Bionic) 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 else version (Darwin) 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 (FreeBSD) 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 (NetBSD) 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 (OpenBSD) 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 (DragonFlyBSD) 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 (Solaris) 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 (CRuntime_UClibc) 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 579 // 580 // XOpen (XSI) 581 // 582 /* 583 P_tmpdir 584 va_list (defined in core.stdc.stdarg) 585 586 char* tempnam(const scope char*, const scope char*); 587 */ 588 589 char* tempnam(const scope char*, const scope char*); 590 591 version (CRuntime_Glibc) 592 { 593 enum P_tmpdir = "/tmp"; 594 } 595 else version (CRuntime_Musl) 596 { 597 enum P_tmpdir = "/tmp"; 598 } 599 else version (Darwin) 600 { 601 enum P_tmpdir = "/var/tmp"; 602 } 603 else version (FreeBSD) 604 { 605 enum P_tmpdir = "/var/tmp/"; 606 } 607 else version (NetBSD) 608 { 609 enum P_tmpdir = "/var/tmp/"; 610 } 611 else version (OpenBSD) 612 { 613 enum P_tmpdir = "/tmp/"; 614 } 615 else version (DragonFlyBSD) 616 { 617 enum P_tmpdir = "/var/tmp/"; 618 } 619 else version (Solaris) 620 { 621 enum P_tmpdir = "/var/tmp/"; 622 } 623 else version (CRuntime_UClibc) 624 { 625 enum P_tmpdir = "/tmp"; 626 } 627 628 version (HaveMemstream) 629 unittest 630 { /* fmemopen */ 631 import core.stdc.string : memcmp; 632 byte[10] buf; 633 auto f = fmemopen(buf.ptr, 10, "w"); 634 assert(f !is null); 635 assert(fprintf(f, "hello") == "hello".length); 636 assert(fflush(f) == 0); 637 assert(memcmp(buf.ptr, "hello".ptr, "hello".length) == 0); 638 //assert(buf 639 assert(fclose(f) == 0); 640 } 641 642 version (HaveMemstream) 643 unittest 644 { /* Note: open_memstream is only useful for writing */ 645 import core.stdc.string : memcmp; 646 char* ptr = null; 647 char[6] testdata = ['h', 'e', 'l', 'l', 'o', 0]; 648 size_t sz = 0; 649 auto f = open_memstream(&ptr, &sz); 650 assert(f !is null); 651 assert(fprintf(f, "%s", testdata.ptr) == 5); 652 assert(fflush(f) == 0); 653 assert(memcmp(ptr, testdata.ptr, testdata.length) == 0); 654 assert(fclose(f) == 0); 655 } 656 657 version (CRuntime_UClibc) {} else 658 version (HaveMemstream) 659 unittest 660 { /* Note: open_wmemstream is only useful for writing */ 661 import core.stdc.string : memcmp; 662 import core.stdc.wchar_ : fwprintf; 663 wchar_t* ptr = null; 664 wchar_t[6] testdata = ['h', 'e', 'l', 'l', 'o', 0]; 665 size_t sz = 0; 666 auto f = open_wmemstream(&ptr, &sz); 667 assert(f !is null); 668 assert(fwprintf(f, testdata.ptr) == 5); 669 assert(fflush(f) == 0); 670 assert(memcmp(ptr, testdata.ptr, testdata.length*wchar_t.sizeof) == 0); 671 assert(fclose(f) == 0); 672 }