Changeset facebd56 in mainline
- Timestamp:
- 2010-03-12T21:59:09Z (15 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 2070570, e2b73d4f
- Parents:
- 5782081
- Location:
- uspace/lib/libc
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/libc/generic/io/io.c
r5782081 rfacebd56 46 46 #include <adt/list.h> 47 47 48 static void _ffillbuf(FILE *stream); 48 49 static void _fflushbuf(FILE *stream); 49 50 … … 57 58 .buf = NULL, 58 59 .buf_size = 0, 59 .buf_head = NULL 60 .buf_head = NULL, 61 .buf_tail = NULL, 62 .buf_state = _bs_empty 60 63 }; 61 64 … … 69 72 .buf = NULL, 70 73 .buf_size = BUFSIZ, 71 .buf_head = NULL 74 .buf_head = NULL, 75 .buf_tail = NULL, 76 .buf_state = _bs_empty 72 77 }; 73 78 … … 81 86 .buf = NULL, 82 87 .buf_size = 0, 83 .buf_head = NULL 88 .buf_head = NULL, 89 .buf_tail = NULL, 90 .buf_state = _bs_empty 84 91 }; 85 92 … … 179 186 stream->buf_size = size; 180 187 stream->buf_head = stream->buf; 188 stream->buf_tail = stream->buf; 189 stream->buf_state = _bs_empty; 181 190 } 182 191 … … 210 219 211 220 stream->buf_head = stream->buf; 221 stream->buf_tail = stream->buf; 212 222 return 0; 213 223 } … … 243 253 stream->klog = false; 244 254 stream->phone = -1; 255 stream->need_sync = false; 245 256 _setvbuf(stream); 246 257 … … 264 275 stream->klog = false; 265 276 stream->phone = -1; 277 stream->need_sync = false; 266 278 _setvbuf(stream); 267 279 … … 295 307 stream->klog = false; 296 308 stream->phone = -1; 309 stream->need_sync = false; 297 310 _setvbuf(stream); 298 311 … … 331 344 } 332 345 333 /** Read from a stream .346 /** Read from a stream (unbuffered). 334 347 * 335 348 * @param buf Destination buffer. … … 337 350 * @param nmemb Number of records to read. 338 351 * @param stream Pointer to the stream. 339 * 340 */ 341 size_t fread(void *buf, size_t size, size_t nmemb, FILE *stream) 352 */ 353 static size_t _fread(void *buf, size_t size, size_t nmemb, FILE *stream) 342 354 { 343 355 size_t left, done; … … 345 357 if (size == 0 || nmemb == 0) 346 358 return 0; 347 348 /* Make sure no data is pending write. */349 _fflushbuf(stream);350 359 351 360 left = size * nmemb; … … 368 377 } 369 378 379 /** Write to a stream (unbuffered). 380 * 381 * @param buf Source buffer. 382 * @param size Size of each record. 383 * @param nmemb Number of records to write. 384 * @param stream Pointer to the stream. 385 */ 370 386 static size_t _fwrite(const void *buf, size_t size, size_t nmemb, FILE *stream) 371 387 { … … 394 410 } 395 411 } 412 413 if (done > 0) 414 stream->need_sync = true; 396 415 397 416 return (done / size); 398 417 } 399 418 400 /** Drain stream buffer, do not sync stream. */ 419 /** Read some data in stream buffer. */ 420 static void _ffillbuf(FILE *stream) 421 { 422 ssize_t rc; 423 424 stream->buf_head = stream->buf_tail = stream->buf; 425 426 rc = read(stream->fd, stream->buf, stream->buf_size); 427 if (rc < 0) { 428 stream->error = true; 429 return; 430 } 431 432 if (rc == 0) { 433 stream->eof = true; 434 return; 435 } 436 437 stream->buf_head += rc; 438 stream->buf_state = _bs_read; 439 } 440 441 /** Write out stream buffer, do not sync stream. */ 401 442 static void _fflushbuf(FILE *stream) 402 443 { 403 444 size_t bytes_used; 404 445 405 446 if ((!stream->buf) || (stream->btype == _IONBF) || (stream->error)) 406 447 return; 407 408 bytes_used = stream->buf_head - stream->buf ;448 449 bytes_used = stream->buf_head - stream->buf_tail; 409 450 if (bytes_used == 0) 410 451 return; 411 412 (void) _fwrite(stream->buf, 1, bytes_used, stream); 452 453 /* If buffer has prefetched read data, we need to seek back. */ 454 if (stream->buf_state == _bs_read) 455 lseek(stream->fd, - (ssize_t) bytes_used, SEEK_CUR); 456 457 /* If buffer has unwritten data, we need to write them out. */ 458 if (stream->buf_state == _bs_write) 459 (void) _fwrite(stream->buf_tail, 1, bytes_used, stream); 460 413 461 stream->buf_head = stream->buf; 414 } 462 stream->buf_tail = stream->buf; 463 stream->buf_state = _bs_empty; 464 } 465 466 /** Read from a stream. 467 * 468 * @param dest Destination buffer. 469 * @param size Size of each record. 470 * @param nmemb Number of records to read. 471 * @param stream Pointer to the stream. 472 * 473 */ 474 size_t fread(void *dest, size_t size, size_t nmemb, FILE *stream) 475 { 476 uint8_t *dp; 477 size_t bytes_left; 478 size_t now; 479 size_t data_avail; 480 size_t total_read; 481 size_t i; 482 483 if (size == 0 || nmemb == 0) 484 return 0; 485 486 /* If not buffered stream, read in directly. */ 487 if (stream->btype == _IONBF) { 488 now = _fread(dest, size, nmemb, stream); 489 return now; 490 } 491 492 /* Make sure no data is pending write. */ 493 if (stream->buf_state == _bs_write) 494 _fflushbuf(stream); 495 496 /* Perform lazy allocation of stream buffer. */ 497 if (stream->buf == NULL) { 498 if (_fallocbuf(stream) != 0) 499 return 0; /* Errno set by _fallocbuf(). */ 500 } 501 502 bytes_left = size * nmemb; 503 total_read = 0; 504 dp = (uint8_t *) dest; 505 506 while ((!stream->error) && (!stream->eof) && (bytes_left > 0)) { 507 if (stream->buf_head == stream->buf_tail) 508 _ffillbuf(stream); 509 510 if (stream->error || stream->eof) 511 break; 512 513 data_avail = stream->buf_head - stream->buf_tail; 514 515 if (bytes_left > data_avail) 516 now = data_avail; 517 else 518 now = bytes_left; 519 520 for (i = 0; i < now; i++) { 521 dp[i] = stream->buf_tail[i]; 522 } 523 524 dp += now; 525 stream->buf_tail += now; 526 bytes_left -= now; 527 total_read += now; 528 } 529 530 return (total_read / size); 531 } 532 415 533 416 534 /** Write to a stream. … … 442 560 return now; 443 561 } 444 562 563 /* Make sure buffer contains no prefetched data. */ 564 if (stream->buf_state == _bs_read) 565 _fflushbuf(stream); 566 567 445 568 /* Perform lazy allocation of stream buffer. */ 446 569 if (stream->buf == NULL) { … … 482 605 } 483 606 607 if (total_written > 0) 608 stream->buf_state = _bs_write; 609 484 610 if (need_flush) 485 611 fflush(stream); … … 570 696 int fseek(FILE *stream, off64_t offset, int whence) 571 697 { 572 off64_t rc = lseek(stream->fd, offset, whence); 698 off64_t rc; 699 700 _fflushbuf(stream); 701 702 rc = lseek(stream->fd, offset, whence); 573 703 if (rc == (off64_t) (-1)) { 574 704 /* errno has been set by lseek64. */ 575 705 return -1; 576 706 } 577 707 578 708 stream->eof = false; 579 580 709 return 0; 581 710 } … … 600 729 } 601 730 602 if (stream->fd >= 0) 731 if (stream->fd >= 0 && stream->need_sync) { 732 /** 733 * Better than syncing always, but probably still not the 734 * right thing to do. 735 */ 736 stream->need_sync = false; 603 737 return fsync(stream->fd); 738 } 604 739 605 740 return ENOENT; -
uspace/lib/libc/include/stdio.h
r5782081 rfacebd56 75 75 }; 76 76 77 enum _buffer_state { 78 /** Buffer is empty */ 79 _bs_empty, 80 81 /** Buffer contains data to be written */ 82 _bs_write, 83 84 /** Buffer contains prefetched data for reading */ 85 _bs_read 86 }; 87 77 88 typedef struct { 78 89 /** Linked list pointer. */ … … 94 105 int phone; 95 106 107 /** 108 * Non-zero if the stream needs sync on fflush(). XXX change 109 * console semantics so that sync is not needed. 110 */ 111 int need_sync; 112 96 113 /** Buffering type */ 97 114 enum _buffer_type btype; 115 98 116 /** Buffer */ 99 117 uint8_t *buf; 118 100 119 /** Buffer size */ 101 120 size_t buf_size; 121 122 /** Buffer state */ 123 enum _buffer_state buf_state; 124 102 125 /** Buffer I/O pointer */ 103 126 uint8_t *buf_head; 127 128 /** Points to end of occupied space when in read mode. */ 129 uint8_t *buf_tail; 104 130 } FILE; 105 131
Note:
See TracChangeset
for help on using the changeset viewer.