Changeset 8cd8bf6 in mainline for uspace/lib/posix/stdio.c
- Timestamp:
- 2011-07-08T17:25:53Z (13 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 11809eab
- Parents:
- f5b2522 (diff), ddc63fd (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/posix/stdio.c
rf5b2522 r8cd8bf6 36 36 #define LIBPOSIX_INTERNAL 37 37 38 #include <assert.h> 39 #include <errno.h>38 /* Has to be first. */ 39 #include "stdbool.h" 40 40 41 41 #include "internal/common.h" 42 42 #include "stdio.h" 43 44 #include "assert.h" 45 #include "errno.h" 43 46 #include "string.h" 44 45 /* not the best of solutions, but freopen will eventually 47 #include "sys/types.h" 48 49 #include "libc/io/printf_core.h" 50 #include "libc/str.h" 51 #include "libc/malloc.h" 52 53 54 /* not the best of solutions, but freopen and ungetc will eventually 46 55 * need to be implemented in libc anyway 47 56 */ 48 57 #include "../c/generic/private/stdio.h" 49 58 50 /** 51 * 52 * @param c 53 * @param stream 54 * @return 59 /** Clears the stream's error and end-of-file indicators. 60 * 61 * @param stream Stream whose indicators shall be cleared. 62 */ 63 void posix_clearerr(FILE *stream) 64 { 65 stream->error = 0; 66 stream->eof = 0; 67 } 68 69 /** 70 * Generate a pathname for the controlling terminal. 71 * 72 * @param s Allocated buffer to which the pathname shall be put. 73 * @return Either s or static location filled with the requested pathname. 74 */ 75 char *posix_ctermid(char *s) 76 { 77 /* Currently always returns an error value (empty string). */ 78 // TODO: return a real terminal path 79 80 static char dummy_path[L_ctermid] = {'\0'}; 81 82 if (s == NULL) { 83 return dummy_path; 84 } 85 86 s[0] = '\0'; 87 return s; 88 } 89 90 /** 91 * Push byte back into input stream. 92 * 93 * @param c Byte to be pushed back. 94 * @param stream Stream to where the byte shall be pushed. 95 * @return Provided byte on success or EOF if not possible. 55 96 */ 56 97 int posix_ungetc(int c, FILE *stream) 57 98 { 58 // TODO 59 not_implemented(); 60 } 61 62 /** 63 * 64 * @param filename 65 * @param mode 66 * @param stream 67 * @return 99 uint8_t b = (uint8_t) c; 100 101 bool can_unget = 102 /* Provided character is legal. */ 103 c != EOF && 104 /* Stream is consistent. */ 105 !stream->error && 106 /* Stream is buffered. */ 107 stream->btype != _IONBF && 108 /* Last operation on the stream was a read operation. */ 109 stream->buf_state == _bs_read && 110 /* Stream buffer is already allocated (i.e. there was already carried 111 * out either write or read operation on the stream). This is probably 112 * redundant check but let's be safe. */ 113 stream->buf != NULL && 114 /* There is still space in the stream to retreat. POSIX demands the 115 * possibility to unget at least 1 character. It should be always 116 * possible, assuming the last operation on the stream read at least 1 117 * character, because the buffer is refilled in the lazily manner. */ 118 stream->buf_tail > stream->buf; 119 120 if (can_unget) { 121 --stream->buf_tail; 122 stream->buf_tail[0] = b; 123 stream->eof = false; 124 return (int) b; 125 } else { 126 return EOF; 127 } 128 } 129 130 /** 131 * Read a stream until the delimiter (or EOF) is encountered. 132 * 133 * @param lineptr Pointer to the output buffer in which there will be stored 134 * nul-terminated string together with the delimiter (if encountered). 135 * Will be resized if necessary. 136 * @param n Pointer to the size of the output buffer. Will be increased if 137 * necessary. 138 * @param delimiter Delimiter on which to finish reading the stream. 139 * @param stream Input stream. 140 * @return Number of fetched characters (including delimiter if encountered) 141 * or -1 on error (set in errno). 142 */ 143 ssize_t posix_getdelim(char **restrict lineptr, size_t *restrict n, 144 int delimiter, FILE *restrict stream) 145 { 146 /* Check arguments for sanity. */ 147 if (!lineptr || !n) { 148 errno = EINVAL; 149 return -1; 150 } 151 152 size_t alloc_step = 80; /* Buffer size gain during reallocation. */ 153 char *pos = *lineptr; /* Next free byte of the output buffer. */ 154 size_t cnt = 0; /* Number of fetched characters. */ 155 int c = fgetc(stream); /* Current input character. Might be EOF. */ 156 157 do { 158 /* Mask EOF as NUL to terminate string. */ 159 if (c == EOF) { 160 c = '\0'; 161 } 162 163 /* Ensure there is still space left in the buffer. */ 164 if (pos == *lineptr + *n) { 165 *lineptr = realloc(*lineptr, *n + alloc_step); 166 if (*lineptr) { 167 pos = *lineptr + *n; 168 *n += alloc_step; 169 } else { 170 errno = ENOMEM; 171 return -1; 172 } 173 } 174 175 /* Store the fetched character. */ 176 *pos = c; 177 178 /* Fetch the next character according to the current character. */ 179 if (c != '\0') { 180 ++pos; 181 ++cnt; 182 if (c == delimiter) { 183 /* Delimiter was just stored. Provide EOF as the next 184 * character - it will be masked as NUL and output string 185 * will be properly terminated. */ 186 c = EOF; 187 } else { 188 /* Neither delimiter nor EOF were encountered. Just fetch 189 * the next character from the stream. */ 190 c = fgetc(stream); 191 } 192 } 193 } while (c != '\0'); 194 195 if (errno == EOK && cnt > 0) { 196 return cnt; 197 } else { 198 /* Either some error occured or the stream was already at EOF. */ 199 return -1; 200 } 201 } 202 203 /** 204 * Read a stream until the newline (or EOF) is encountered. 205 * 206 * @param lineptr Pointer to the output buffer in which there will be stored 207 * nul-terminated string together with the delimiter (if encountered). 208 * Will be resized if necessary. 209 * @param n Pointer to the size of the output buffer. Will be increased if 210 * necessary. 211 * @param stream Input stream. 212 * @return Number of fetched characters (including newline if encountered) 213 * or -1 on error (set in errno). 214 */ 215 ssize_t posix_getline(char **restrict lineptr, size_t *restrict n, 216 FILE *restrict stream) 217 { 218 return posix_getdelim(lineptr, n, '\n', stream); 219 } 220 221 /** 222 * Reopen a file stream. 223 * 224 * @param filename Pathname of a file to be reopened or NULL for changing 225 * the mode of the stream. 226 * @param mode Mode to be used for reopening the file or changing current 227 * mode of the stream. 228 * @param stream Current stream associated with the opened file. 229 * @return On success, either a stream of the reopened file or the provided 230 * stream with a changed mode. NULL otherwise. 68 231 */ 69 232 FILE *posix_freopen( … … 115 278 /** 116 279 * 117 * @param s 118 */ 119 void posix_perror(const char *s) 280 * @param buf 281 * @param size 282 * @param mode 283 * @return 284 */ 285 FILE *posix_fmemopen(void *restrict buf, size_t size, 286 const char *restrict mode) 120 287 { 121 288 // TODO … … 124 291 125 292 /** 126 * 127 * @param stream 128 * @param offset 129 * @param whence 293 * 294 * @param bufp 295 * @param sizep 130 296 * @return 131 297 */ 132 int posix_fseeko(FILE *stream, posix_off_t offset, int whence)298 FILE *posix_open_memstream(char **bufp, size_t *sizep) 133 299 { 134 300 // TODO … … 137 303 138 304 /** 139 * 140 * @param stream 305 * Write error messages to standard error. 306 * 307 * @param s Error message. 308 */ 309 void posix_perror(const char *s) 310 { 311 if (s == NULL || s[0] == '\0') { 312 fprintf(stderr, "%s\n", posix_strerror(errno)); 313 } else { 314 fprintf(stderr, "%s: %s\n", s, posix_strerror(errno)); 315 } 316 } 317 318 struct _posix_fpos { 319 off64_t offset; 320 }; 321 322 /** Restores stream a to position previously saved with fgetpos(). 323 * 324 * @param stream Stream to restore 325 * @param pos Position to restore 326 * @return Zero on success, non-zero (with errno set) on failure 327 */ 328 int posix_fsetpos(FILE *stream, const posix_fpos_t *pos) 329 { 330 return fseek(stream, pos->offset, SEEK_SET); 331 } 332 333 /** Saves the stream's position for later use by fsetpos(). 334 * 335 * @param stream Stream to save 336 * @param pos Place to store the position 337 * @return Zero on success, non-zero (with errno set) on failure 338 */ 339 int posix_fgetpos(FILE *restrict stream, posix_fpos_t *restrict pos) 340 { 341 off64_t ret = ftell(stream); 342 if (ret == -1) { 343 return errno; 344 } 345 pos->offset = ret; 346 return 0; 347 } 348 349 /** 350 * Reposition a file-position indicator in a stream. 351 * 352 * @param stream Stream to seek in. 353 * @param offset Direction and amount of bytes to seek. 354 * @param whence From where to seek. 355 * @return Zero on success, -1 otherwise. 356 */ 357 int posix_fseek(FILE *stream, long offset, int whence) 358 { 359 return fseek(stream, (off64_t) offset, whence); 360 } 361 362 /** 363 * Reposition a file-position indicator in a stream. 364 * 365 * @param stream Stream to seek in. 366 * @param offset Direction and amount of bytes to seek. 367 * @param whence From where to seek. 368 * @return Zero on success, -1 otherwise. 369 */ 370 int posix_fseeko(FILE *stream, posix_off_t offset, int whence) 371 { 372 return fseek(stream, (off64_t) offset, whence); 373 } 374 375 /** 376 * Discover current file offset in a stream. 377 * 378 * @param stream Stream for which the offset shall be retrieved. 379 * @return Current offset or -1 if not possible. 380 */ 381 long posix_ftell(FILE *stream) 382 { 383 return (long) ftell(stream); 384 } 385 386 /** 387 * Discover current file offset in a stream. 388 * 389 * @param stream Stream for which the offset shall be retrieved. 390 * @return Current offset or -1 if not possible. 391 */ 392 posix_off_t posix_ftello(FILE *stream) 393 { 394 return (posix_off_t) ftell(stream); 395 } 396 397 /** 398 * Print formatted output to the opened file. 399 * 400 * @param fildes File descriptor of the opened file. 401 * @param format Format description. 402 * @return Either the number of printed characters or negative value on error. 403 */ 404 int posix_dprintf(int fildes, const char *restrict format, ...) 405 { 406 va_list list; 407 va_start(list, format); 408 int result = posix_vdprintf(fildes, format, list); 409 va_end(list); 410 return result; 411 } 412 413 /** 414 * Write ordinary string to the opened file. 415 * 416 * @param str String to be written. 417 * @param size Size of the string (in bytes).. 418 * @param fd File descriptor of the opened file. 419 * @return The number of written characters. 420 */ 421 static int _dprintf_str_write(const char *str, size_t size, void *fd) 422 { 423 ssize_t wr = write(*(int *) fd, str, size); 424 return str_nlength(str, wr); 425 } 426 427 /** 428 * Write wide string to the opened file. 429 * 430 * @param str String to be written. 431 * @param size Size of the string (in bytes). 432 * @param fd File descriptor of the opened file. 433 * @return The number of written characters. 434 */ 435 static int _dprintf_wstr_write(const wchar_t *str, size_t size, void *fd) 436 { 437 size_t offset = 0; 438 size_t chars = 0; 439 size_t sz; 440 char buf[4]; 441 442 while (offset < size) { 443 sz = 0; 444 if (chr_encode(str[chars], buf, &sz, sizeof(buf)) != EOK) { 445 break; 446 } 447 448 if (write(*(int *) fd, buf, sz) != (ssize_t) sz) { 449 break; 450 } 451 452 chars++; 453 offset += sizeof(wchar_t); 454 } 455 456 return chars; 457 } 458 459 /** 460 * Print formatted output to the opened file. 461 * 462 * @param fildes File descriptor of the opened file. 463 * @param format Format description. 464 * @param ap Print arguments. 465 * @return Either the number of printed characters or negative value on error. 466 */ 467 int posix_vdprintf(int fildes, const char *restrict format, va_list ap) 468 { 469 printf_spec_t spec = { 470 .str_write = _dprintf_str_write, 471 .wstr_write = _dprintf_wstr_write, 472 .data = &fildes 473 }; 474 475 return printf_core(format, &spec, ap); 476 } 477 478 /** 479 * Print formatted output to the string. 480 * 481 * @param s Output string. 482 * @param format Format description. 483 * @return Either the number of printed characters (excluding null byte) or 484 * negative value on error. 485 */ 486 int posix_sprintf(char *s, const char *restrict format, ...) 487 { 488 va_list list; 489 va_start(list, format); 490 int result = posix_vsprintf(s, format, list); 491 va_end(list); 492 return result; 493 } 494 495 /** 496 * Print formatted output to the string. 497 * 498 * @param s Output string. 499 * @param format Format description. 500 * @param ap Print arguments. 501 * @return Either the number of printed characters (excluding null byte) or 502 * negative value on error. 503 */ 504 int posix_vsprintf(char *s, const char *restrict format, va_list ap) 505 { 506 return vsnprintf(s, STR_NO_LIMIT, format, ap); 507 } 508 509 /** 510 * Convert formatted input from the stream. 511 * 512 * @param stream Input stream. 513 * @param format Format description. 514 * @return The number of converted output items or EOF on failure. 515 */ 516 int posix_fscanf(FILE *restrict stream, const char *restrict format, ...) 517 { 518 va_list list; 519 va_start(list, format); 520 int result = posix_vfscanf(stream, format, list); 521 va_end(list); 522 return result; 523 } 524 525 /** 526 * Convert formatted input from the standard input. 527 * 528 * @param format Format description. 529 * @return The number of converted output items or EOF on failure. 530 */ 531 int posix_scanf(const char *restrict format, ...) 532 { 533 va_list list; 534 va_start(list, format); 535 int result = posix_vscanf(format, list); 536 va_end(list); 537 return result; 538 } 539 540 /** 541 * Convert formatted input from the standard input. 542 * 543 * @param format Format description. 544 * @param arg Output items. 545 * @return The number of converted output items or EOF on failure. 546 */ 547 int posix_vscanf(const char *restrict format, va_list arg) 548 { 549 return posix_vfscanf(stdin, format, arg); 550 } 551 552 /** 553 * Convert formatted input from the string. 554 * 555 * @param s Input string. 556 * @param format Format description. 557 * @return The number of converted output items or EOF on failure. 558 */ 559 int posix_sscanf(const char *restrict s, const char *restrict format, ...) 560 { 561 va_list list; 562 va_start(list, format); 563 int result = posix_vsscanf(s, format, list); 564 va_end(list); 565 return result; 566 } 567 568 /** 569 * Acquire file stream for the thread. 570 * 571 * @param file File stream to lock. 572 */ 573 void posix_flockfile(FILE *file) 574 { 575 /* dummy */ 576 } 577 578 /** 579 * Acquire file stream for the thread (non-blocking). 580 * 581 * @param file File stream to lock. 582 * @return Zero for success and non-zero if the lock cannot be acquired. 583 */ 584 int posix_ftrylockfile(FILE *file) 585 { 586 /* dummy */ 587 return 0; 588 } 589 590 /** 591 * Relinquish the ownership of the locked file stream. 592 * 593 * @param file File stream to unlock. 594 */ 595 void posix_funlockfile(FILE *file) 596 { 597 /* dummy */ 598 } 599 600 /** 601 * Get a byte from a stream (thread-unsafe). 602 * 603 * @param stream Input file stream. 604 * @return Either read byte or EOF. 605 */ 606 int posix_getc_unlocked(FILE *stream) 607 { 608 return getc(stream); 609 } 610 611 /** 612 * Get a byte from the standard input stream (thread-unsafe). 613 * 614 * @return Either read byte or EOF. 615 */ 616 int posix_getchar_unlocked(void) 617 { 618 return getchar(); 619 } 620 621 /** 622 * Put a byte on a stream (thread-unsafe). 623 * 624 * @param c Byte to output. 625 * @param stream Output file stream. 626 * @return Either written byte or EOF. 627 */ 628 int posix_putc_unlocked(int c, FILE *stream) 629 { 630 return putc(c, stream); 631 } 632 633 /** 634 * Put a byte on the standard output stream (thread-unsafe). 635 * 636 * @param c Byte to output. 637 * @return Either written byte or EOF. 638 */ 639 int posix_putchar_unlocked(int c) 640 { 641 return putchar(c); 642 } 643 644 /** 645 * Remove a file. 646 * 647 * @param path Pathname of the file that shall be removed. 648 * @return Zero on success, -1 otherwise. 649 */ 650 int posix_remove(const char *path) 651 { 652 // FIXME: unlink() and rmdir() seem to be equivalent at the moment, 653 // but that does not have to be true forever 654 return unlink(path); 655 } 656 657 /** 658 * 659 * @param s 141 660 * @return 142 661 */ 143 posix_off_t posix_ftello(FILE *stream) 144 { 145 // TODO 146 not_implemented(); 147 } 148 149 /** 150 * 151 * @param s 152 * @param format 153 * @param ... 154 * @return 155 */ 156 int posix_sprintf(char *s, const char *format, ...) 157 { 158 // TODO 159 not_implemented(); 160 } 161 162 /** 163 * 164 * @param s 165 * @param format 166 * @param ... 167 * @return 168 */ 169 int posix_vsprintf(char *s, const char *format, va_list ap) 662 char *posix_tmpnam(char *s) 170 663 { 171 664 // TODO: low priority, just a compile-time dependency of binutils … … 173 666 } 174 667 175 /**176 *177 * @param s178 * @param format179 * @param ...180 * @return181 */182 int posix_sscanf(const char *s, const char *format, ...)183 {184 // TODO185 not_implemented();186 }187 188 /**189 *190 * @param path191 * @return192 */193 int posix_remove(const char *path)194 {195 // TODO: low priority, just a compile-time dependency of binutils196 not_implemented();197 }198 199 /**200 *201 * @param s202 * @return203 */204 char *posix_tmpnam(char *s)205 {206 // TODO: low priority, just a compile-time dependency of binutils207 not_implemented();208 }209 210 668 /** @} 211 669 */
Note:
See TracChangeset
for help on using the changeset viewer.