Changeset 04803bf in mainline for uspace/lib/c/generic/io/io.c
- Timestamp:
- 2011-03-21T22:00:17Z (15 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 143932e3
- Parents:
- b50b5af2 (diff), 7308e84 (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 moved
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/c/generic/io/io.c
rb50b5af2 r04803bf 37 37 #include <fcntl.h> 38 38 #include <assert.h> 39 #include <str ing.h>39 #include <str.h> 40 40 #include <errno.h> 41 41 #include <bool.h> 42 42 #include <malloc.h> 43 #include <async.h> 43 44 #include <io/klog.h> 44 45 #include <vfs/vfs.h> 45 46 #include <ipc/devmap.h> 46 47 #include <adt/list.h> 47 48 #include "../private/io.h" 49 50 static void _ffillbuf(FILE *stream); 48 51 static void _fflushbuf(FILE *stream); 49 52 … … 57 60 .buf = NULL, 58 61 .buf_size = 0, 59 .buf_head = NULL 62 .buf_head = NULL, 63 .buf_tail = NULL, 64 .buf_state = _bs_empty 60 65 }; 61 66 … … 69 74 .buf = NULL, 70 75 .buf_size = BUFSIZ, 71 .buf_head = NULL 76 .buf_head = NULL, 77 .buf_tail = NULL, 78 .buf_state = _bs_empty 72 79 }; 73 80 … … 81 88 .buf = NULL, 82 89 .buf_size = 0, 83 .buf_head = NULL 90 .buf_head = NULL, 91 .buf_tail = NULL, 92 .buf_state = _bs_empty 84 93 }; 85 94 … … 179 188 stream->buf_size = size; 180 189 stream->buf_head = stream->buf; 190 stream->buf_tail = stream->buf; 191 stream->buf_state = _bs_empty; 181 192 } 182 193 … … 210 221 211 222 stream->buf_head = stream->buf; 223 stream->buf_tail = stream->buf; 212 224 return 0; 213 225 } … … 243 255 stream->klog = false; 244 256 stream->phone = -1; 257 stream->need_sync = false; 245 258 _setvbuf(stream); 246 259 … … 264 277 stream->klog = false; 265 278 stream->phone = -1; 279 stream->need_sync = false; 266 280 _setvbuf(stream); 267 281 … … 295 309 stream->klog = false; 296 310 stream->phone = -1; 311 stream->need_sync = false; 297 312 _setvbuf(stream); 298 313 … … 309 324 310 325 if (stream->phone >= 0) 311 ipc_hangup(stream->phone);326 async_hangup(stream->phone); 312 327 313 328 if (stream->fd >= 0) … … 331 346 } 332 347 333 /** Read from a stream .348 /** Read from a stream (unbuffered). 334 349 * 335 350 * @param buf Destination buffer. … … 337 352 * @param nmemb Number of records to read. 338 353 * @param stream Pointer to the stream. 339 * 340 */ 341 size_t fread(void *buf, size_t size, size_t nmemb, FILE *stream) 342 { 343 size_t left = size * nmemb; 344 size_t done = 0; 345 346 /* Make sure no data is pending write. */ 347 _fflushbuf(stream); 354 */ 355 static size_t _fread(void *buf, size_t size, size_t nmemb, FILE *stream) 356 { 357 size_t left, done; 358 359 if (size == 0 || nmemb == 0) 360 return 0; 361 362 left = size * nmemb; 363 done = 0; 348 364 349 365 while ((left > 0) && (!stream->error) && (!stream->eof)) { … … 363 379 } 364 380 381 /** Write to a stream (unbuffered). 382 * 383 * @param buf Source buffer. 384 * @param size Size of each record. 385 * @param nmemb Number of records to write. 386 * @param stream Pointer to the stream. 387 */ 365 388 static size_t _fwrite(const void *buf, size_t size, size_t nmemb, FILE *stream) 366 389 { 367 size_t left = size * nmemb; 368 size_t done = 0; 369 390 size_t left; 391 size_t done; 392 393 if (size == 0 || nmemb == 0) 394 return 0; 395 396 left = size * nmemb; 397 done = 0; 398 370 399 while ((left > 0) && (!stream->error)) { 371 400 ssize_t wr; … … 383 412 } 384 413 } 414 415 if (done > 0) 416 stream->need_sync = true; 385 417 386 418 return (done / size); 387 419 } 388 420 389 /** Drain stream buffer, do not sync stream. */ 421 /** Read some data in stream buffer. */ 422 static void _ffillbuf(FILE *stream) 423 { 424 ssize_t rc; 425 426 stream->buf_head = stream->buf_tail = stream->buf; 427 428 rc = read(stream->fd, stream->buf, stream->buf_size); 429 if (rc < 0) { 430 stream->error = true; 431 return; 432 } 433 434 if (rc == 0) { 435 stream->eof = true; 436 return; 437 } 438 439 stream->buf_head += rc; 440 stream->buf_state = _bs_read; 441 } 442 443 /** Write out stream buffer, do not sync stream. */ 390 444 static void _fflushbuf(FILE *stream) 391 445 { 392 446 size_t bytes_used; 393 447 394 448 if ((!stream->buf) || (stream->btype == _IONBF) || (stream->error)) 395 449 return; 396 397 bytes_used = stream->buf_head - stream->buf ;450 451 bytes_used = stream->buf_head - stream->buf_tail; 398 452 if (bytes_used == 0) 399 453 return; 400 401 (void) _fwrite(stream->buf, 1, bytes_used, stream); 454 455 /* If buffer has prefetched read data, we need to seek back. */ 456 if (stream->buf_state == _bs_read) 457 lseek(stream->fd, - (ssize_t) bytes_used, SEEK_CUR); 458 459 /* If buffer has unwritten data, we need to write them out. */ 460 if (stream->buf_state == _bs_write) 461 (void) _fwrite(stream->buf_tail, 1, bytes_used, stream); 462 402 463 stream->buf_head = stream->buf; 403 } 464 stream->buf_tail = stream->buf; 465 stream->buf_state = _bs_empty; 466 } 467 468 /** Read from a stream. 469 * 470 * @param dest Destination buffer. 471 * @param size Size of each record. 472 * @param nmemb Number of records to read. 473 * @param stream Pointer to the stream. 474 * 475 */ 476 size_t fread(void *dest, size_t size, size_t nmemb, FILE *stream) 477 { 478 uint8_t *dp; 479 size_t bytes_left; 480 size_t now; 481 size_t data_avail; 482 size_t total_read; 483 size_t i; 484 485 if (size == 0 || nmemb == 0) 486 return 0; 487 488 /* If not buffered stream, read in directly. */ 489 if (stream->btype == _IONBF) { 490 now = _fread(dest, size, nmemb, stream); 491 return now; 492 } 493 494 /* Make sure no data is pending write. */ 495 if (stream->buf_state == _bs_write) 496 _fflushbuf(stream); 497 498 /* Perform lazy allocation of stream buffer. */ 499 if (stream->buf == NULL) { 500 if (_fallocbuf(stream) != 0) 501 return 0; /* Errno set by _fallocbuf(). */ 502 } 503 504 bytes_left = size * nmemb; 505 total_read = 0; 506 dp = (uint8_t *) dest; 507 508 while ((!stream->error) && (!stream->eof) && (bytes_left > 0)) { 509 if (stream->buf_head == stream->buf_tail) 510 _ffillbuf(stream); 511 512 if (stream->error || stream->eof) 513 break; 514 515 data_avail = stream->buf_head - stream->buf_tail; 516 517 if (bytes_left > data_avail) 518 now = data_avail; 519 else 520 now = bytes_left; 521 522 for (i = 0; i < now; i++) { 523 dp[i] = stream->buf_tail[i]; 524 } 525 526 dp += now; 527 stream->buf_tail += now; 528 bytes_left -= now; 529 total_read += now; 530 } 531 532 return (total_read / size); 533 } 534 404 535 405 536 /** Write to a stream. … … 421 552 uint8_t b; 422 553 bool need_flush; 423 554 555 if (size == 0 || nmemb == 0) 556 return 0; 557 424 558 /* If not buffered stream, write out directly. */ 425 559 if (stream->btype == _IONBF) { … … 428 562 return now; 429 563 } 430 564 565 /* Make sure buffer contains no prefetched data. */ 566 if (stream->buf_state == _bs_read) 567 _fflushbuf(stream); 568 569 431 570 /* Perform lazy allocation of stream buffer. */ 432 571 if (stream->buf == NULL) { … … 468 607 } 469 608 609 if (total_written > 0) 610 stream->buf_state = _bs_write; 611 470 612 if (need_flush) 471 613 fflush(stream); … … 480 622 481 623 if (chr_encode(c, buf, &sz, STR_BOUNDS(1)) == EOK) { 482 size_t wr = fwrite(buf, sz, 1, stream);624 size_t wr = fwrite(buf, 1, sz, stream); 483 625 484 626 if (wr < sz) … … 522 664 } 523 665 666 char *fgets(char *str, int size, FILE *stream) 667 { 668 int c; 669 int idx; 670 671 idx = 0; 672 while (idx < size - 1) { 673 c = fgetc(stream); 674 if (c == EOF) 675 break; 676 677 str[idx++] = c; 678 679 if (c == '\n') 680 break; 681 } 682 683 if (ferror(stream)) 684 return NULL; 685 686 if (idx == 0) 687 return NULL; 688 689 str[idx] = '\0'; 690 return str; 691 } 692 524 693 int getchar(void) 525 694 { … … 527 696 } 528 697 529 int fseek(FILE *stream, long offset, int origin) 530 { 531 off_t rc = lseek(stream->fd, offset, origin); 532 if (rc == (off_t) (-1)) { 533 /* errno has been set by lseek. */ 698 int fseek(FILE *stream, off64_t offset, int whence) 699 { 700 off64_t rc; 701 702 _fflushbuf(stream); 703 704 rc = lseek(stream->fd, offset, whence); 705 if (rc == (off64_t) (-1)) { 706 /* errno has been set by lseek64. */ 534 707 return -1; 535 708 } 536 709 537 710 stream->eof = false; 538 539 711 return 0; 712 } 713 714 off64_t ftell(FILE *stream) 715 { 716 return lseek(stream->fd, 0, SEEK_CUR); 540 717 } 541 718 … … 554 731 } 555 732 556 if (stream->fd >= 0) 733 if (stream->fd >= 0 && stream->need_sync) { 734 /** 735 * Better than syncing always, but probably still not the 736 * right thing to do. 737 */ 738 stream->need_sync = false; 557 739 return fsync(stream->fd); 740 } 558 741 559 742 return ENOENT; … … 568 751 { 569 752 return stream->error; 753 } 754 755 void clearerr(FILE *stream) 756 { 757 stream->eof = false; 758 stream->error = false; 759 } 760 761 int fileno(FILE *stream) 762 { 763 if (stream->klog) { 764 errno = EBADF; 765 return -1; 766 } 767 768 return stream->fd; 570 769 } 571 770
Note:
See TracChangeset
for help on using the changeset viewer.