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 */ 15module core.sys.posix.stdio; 16 17import core.sys.posix.config; 18public import core.stdc.stdio; 19public import core.sys.posix.sys.types; // for off_t 20 21version (OSX) 22 version = Darwin; 23else version (iOS) 24 version = Darwin; 25else version (TVOS) 26 version = Darwin; 27else version (WatchOS) 28 version = Darwin; 29 30version (Posix): 31extern (C): 32 33nothrow: 34@nogc: 35@system: 36 37// 38// Required (defined in core.stdc.stdio) 39// 40/* 41BUFSIZ 42_IOFBF 43_IOLBF 44_IONBF 45L_tmpnam 46SEEK_CUR 47SEEK_END 48SEEK_SET 49FILENAME_MAX 50FOPEN_MAX 51TMP_MAX 52EOF 53NULL 54stderr 55stdin 56stdout 57FILE 58fpos_t 59size_t 60 61void clearerr(FILE*); 62int fclose(FILE*); 63int feof(FILE*); 64int ferror(FILE*); 65int fflush(FILE*); 66int fgetc(FILE*); 67int fgetpos(FILE*, fpos_t *); 68char* fgets(char*, int, FILE*); 69FILE* fopen(const scope char*, const scope char*); 70int fprintf(FILE*, const scope char*, ...); 71int fputc(int, FILE*); 72int fputs(const scope char*, FILE*); 73size_t fread(void *, size_t, size_t, FILE*); 74FILE* freopen(const scope char*, const scope char*, FILE*); 75int fscanf(FILE*, const scope char*, ...); 76int fseek(FILE*, c_long, int); 77int fsetpos(FILE*, const scope fpos_t*); 78c_long ftell(FILE*); 79size_t fwrite(in void *, size_t, size_t, FILE*); 80int getc(FILE*); 81int getchar(); 82char* gets(char*); 83void perror(const scope char*); 84int printf(const scope char*, ...); 85int putc(int, FILE*); 86int putchar(int); 87int puts(const scope char*); 88int remove(const scope char*); 89int rename(const scope char*, const scope char*); 90void rewind(FILE*); 91int scanf(const scope char*, ...); 92void setbuf(FILE*, char*); 93int setvbuf(FILE*, char*, int, size_t); 94int snprintf(char*, size_t, const scope char*, ...); 95int sprintf(char*, const scope char*, ...); 96int sscanf(const scope char*, const scope char*, int ...); 97FILE* tmpfile(); 98char* tmpnam(char*); 99int ungetc(int, FILE*); 100int vfprintf(FILE*, const scope char*, va_list); 101int vfscanf(FILE*, const scope char*, va_list); 102int vprintf(const scope char*, va_list); 103int vscanf(const scope char*, va_list); 104int vsnprintf(char*, size_t, const scope char*, va_list); 105int vsprintf(char*, const scope char*, va_list); 106int vsscanf(const scope char*, const scope char*, va_list arg); 107*/ 108 109version (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} 145else 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} 153else 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} 184else 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} 215else 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/* 251L_ctermid 252 253char* ctermid(char*); 254FILE* fdopen(int, const scope char*); 255int fileno(FILE*); 256int fseeko(FILE*, off_t, int); 257off_t ftello(FILE*); 258ssize_t getdelim(char**, size_t*, int, FILE*); 259ssize_t getline(char**, size_t*, FILE*); 260char* gets(char*); 261int pclose(FILE*); 262FILE* popen(const scope char*, const scope char*); 263*/ 264 265version (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} 292else 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} 320else 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} 347else 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} 374else 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} 384else 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} 399else 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} 409else 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} 419else 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} 429else 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} 457else version (Posix) 458{ 459 int fseeko(FILE*, off_t, int); 460 off_t ftello(FILE*); 461} 462 463char* ctermid(char*); 464FILE* fdopen(int, const scope char*); 465int fileno(FILE*); 466char* gets(char*); 467int pclose(FILE*); 468FILE* 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. 474version (CRuntime_Glibc) // as of glibc 1.0x 475 version = HaveMemstream; 476else version (FreeBSD) // as of FreeBSD 9.2 477 version = HaveMemstream; 478else version (DragonFlyBSD) // for DragonFlyBSD 479 version = HaveMemstream; 480else version (OpenBSD) // as of OpenBSD 5.4 481 version = HaveMemstream; 482else version (CRuntime_UClibc) 483 version = HaveMemstream; 484// http://git.musl-libc.org/cgit/musl/commit/src/stdio/open_memstream.c?id=b158b32a44d56ef20407d4285b58180447ffff1f 485else version (CRuntime_Musl) 486 version = HaveMemstream; 487 488version (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/* 500void flockfile(FILE*); 501int ftrylockfile(FILE*); 502void funlockfile(FILE*); 503int getc_unlocked(FILE*); 504int getchar_unlocked(); 505int putc_unlocked(int, FILE*); 506int putchar_unlocked(int); 507*/ 508 509version (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} 519else 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} 529else 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} 539else 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} 549else 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} 559else 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} 569else 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} 579else 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} 589else 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} 599else 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/* 614P_tmpdir 615va_list (defined in core.stdc.stdarg) 616 617char* tempnam(const scope char*, const scope char*); 618*/ 619 620char* tempnam(const scope char*, const scope char*); 621 622version (CRuntime_Glibc) 623{ 624 enum P_tmpdir = "/tmp"; 625} 626else version (CRuntime_Musl) 627{ 628 enum P_tmpdir = "/tmp"; 629} 630else version (Darwin) 631{ 632 enum P_tmpdir = "/var/tmp"; 633} 634else version (FreeBSD) 635{ 636 enum P_tmpdir = "/var/tmp/"; 637} 638else version (NetBSD) 639{ 640 enum P_tmpdir = "/var/tmp/"; 641} 642else version (OpenBSD) 643{ 644 enum P_tmpdir = "/tmp/"; 645} 646else version (DragonFlyBSD) 647{ 648 enum P_tmpdir = "/var/tmp/"; 649} 650else version (Solaris) 651{ 652 enum P_tmpdir = "/var/tmp/"; 653} 654else version (CRuntime_UClibc) 655{ 656 enum P_tmpdir = "/tmp"; 657} 658 659version (HaveMemstream) 660unittest 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 673version (HaveMemstream) 674unittest 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 688version (CRuntime_UClibc) {} else 689version (HaveMemstream) 690unittest 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