Changeset 04803bf in mainline for uspace/lib/c/generic/io/io.c


Ignore:
Timestamp:
2011-03-21T22:00:17Z (15 years ago)
Author:
Jiri Svoboda <jiri@…>
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.
Message:

Merge mainline changes (needs fixes).

File:
1 moved

Legend:

Unmodified
Added
Removed
  • uspace/lib/c/generic/io/io.c

    rb50b5af2 r04803bf  
    3737#include <fcntl.h>
    3838#include <assert.h>
    39 #include <string.h>
     39#include <str.h>
    4040#include <errno.h>
    4141#include <bool.h>
    4242#include <malloc.h>
     43#include <async.h>
    4344#include <io/klog.h>
    4445#include <vfs/vfs.h>
    4546#include <ipc/devmap.h>
    4647#include <adt/list.h>
    47 
     48#include "../private/io.h"
     49
     50static void _ffillbuf(FILE *stream);
    4851static void _fflushbuf(FILE *stream);
    4952
     
    5760        .buf = NULL,
    5861        .buf_size = 0,
    59         .buf_head = NULL
     62        .buf_head = NULL,
     63        .buf_tail = NULL,
     64        .buf_state = _bs_empty
    6065};
    6166
     
    6974        .buf = NULL,
    7075        .buf_size = BUFSIZ,
    71         .buf_head = NULL
     76        .buf_head = NULL,
     77        .buf_tail = NULL,
     78        .buf_state = _bs_empty
    7279};
    7380
     
    8188        .buf = NULL,
    8289        .buf_size = 0,
    83         .buf_head = NULL
     90        .buf_head = NULL,
     91        .buf_tail = NULL,
     92        .buf_state = _bs_empty
    8493};
    8594
     
    179188        stream->buf_size = size;
    180189        stream->buf_head = stream->buf;
     190        stream->buf_tail = stream->buf;
     191        stream->buf_state = _bs_empty;
    181192}
    182193
     
    210221       
    211222        stream->buf_head = stream->buf;
     223        stream->buf_tail = stream->buf;
    212224        return 0;
    213225}
     
    243255        stream->klog = false;
    244256        stream->phone = -1;
     257        stream->need_sync = false;
    245258        _setvbuf(stream);
    246259       
     
    264277        stream->klog = false;
    265278        stream->phone = -1;
     279        stream->need_sync = false;
    266280        _setvbuf(stream);
    267281       
     
    295309        stream->klog = false;
    296310        stream->phone = -1;
     311        stream->need_sync = false;
    297312        _setvbuf(stream);
    298313       
     
    309324       
    310325        if (stream->phone >= 0)
    311                 ipc_hangup(stream->phone);
     326                async_hangup(stream->phone);
    312327       
    313328        if (stream->fd >= 0)
     
    331346}
    332347
    333 /** Read from a stream.
     348/** Read from a stream (unbuffered).
    334349 *
    335350 * @param buf    Destination buffer.
     
    337352 * @param nmemb  Number of records to read.
    338353 * @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 */
     355static 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;
    348364       
    349365        while ((left > 0) && (!stream->error) && (!stream->eof)) {
     
    363379}
    364380
     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 */
    365388static size_t _fwrite(const void *buf, size_t size, size_t nmemb, FILE *stream)
    366389{
    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
    370399        while ((left > 0) && (!stream->error)) {
    371400                ssize_t wr;
     
    383412                }
    384413        }
     414
     415        if (done > 0)
     416                stream->need_sync = true;
    385417       
    386418        return (done / size);
    387419}
    388420
    389 /** Drain stream buffer, do not sync stream. */
     421/** Read some data in stream buffer. */
     422static 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. */
    390444static void _fflushbuf(FILE *stream)
    391445{
    392446        size_t bytes_used;
    393        
     447
    394448        if ((!stream->buf) || (stream->btype == _IONBF) || (stream->error))
    395449                return;
    396        
    397         bytes_used = stream->buf_head - stream->buf;
     450
     451        bytes_used = stream->buf_head - stream->buf_tail;
    398452        if (bytes_used == 0)
    399453                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
    402463        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 */
     476size_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
    404535
    405536/** Write to a stream.
     
    421552        uint8_t b;
    422553        bool need_flush;
    423        
     554
     555        if (size == 0 || nmemb == 0)
     556                return 0;
     557
    424558        /* If not buffered stream, write out directly. */
    425559        if (stream->btype == _IONBF) {
     
    428562                return now;
    429563        }
    430        
     564
     565        /* Make sure buffer contains no prefetched data. */
     566        if (stream->buf_state == _bs_read)
     567                _fflushbuf(stream);
     568
     569
    431570        /* Perform lazy allocation of stream buffer. */
    432571        if (stream->buf == NULL) {
     
    468607        }
    469608       
     609        if (total_written > 0)
     610                stream->buf_state = _bs_write;
     611
    470612        if (need_flush)
    471613                fflush(stream);
     
    480622       
    481623        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);
    483625               
    484626                if (wr < sz)
     
    522664}
    523665
     666char *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
    524693int getchar(void)
    525694{
     
    527696}
    528697
    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. */
     698int 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. */
    534707                return -1;
    535708        }
    536        
     709
    537710        stream->eof = false;
    538        
    539711        return 0;
     712}
     713
     714off64_t ftell(FILE *stream)
     715{
     716        return lseek(stream->fd, 0, SEEK_CUR);
    540717}
    541718
     
    554731        }
    555732       
    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;
    557739                return fsync(stream->fd);
     740        }
    558741       
    559742        return ENOENT;
     
    568751{
    569752        return stream->error;
     753}
     754
     755void clearerr(FILE *stream)
     756{
     757        stream->eof = false;
     758        stream->error = false;
     759}
     760
     761int fileno(FILE *stream)
     762{
     763        if (stream->klog) {
     764                errno = EBADF;
     765                return -1;
     766        }
     767       
     768        return stream->fd;
    570769}
    571770
Note: See TracChangeset for help on using the changeset viewer.