Ignore:
File:
1 edited

Legend:

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

    r59f388a re86a617a  
    3535#include <stdio.h>
    3636#include <unistd.h>
     37#include <fcntl.h>
    3738#include <assert.h>
    3839#include <str.h>
     
    4445#include <vfs/vfs.h>
    4546#include <vfs/vfs_sess.h>
    46 #include <vfs/inbox.h>
    4747#include <ipc/loc.h>
    4848#include <adt/list.h>
     
    5555static FILE stdin_null = {
    5656        .fd = -1,
    57         .pos = 0,
    5857        .error = true,
    5958        .eof = true,
     
    7069static FILE stdout_kio = {
    7170        .fd = -1,
    72         .pos = 0,
    7371        .error = false,
    7472        .eof = false,
     
    8583static FILE stderr_kio = {
    8684        .fd = -1,
    87         .pos = 0,
    8885        .error = false,
    8986        .eof = false,
     
    104101static LIST_INITIALIZE(files);
    105102
    106 void __stdio_init(void)
    107 {
    108         /* The first three standard file descriptors are assigned for compatibility.
    109          * This will probably be removed later.
    110          */
    111          
    112         int infd = inbox_get("stdin");
    113         if (infd >= 0) {
    114                 int stdinfd = vfs_clone(infd, -1, false);
    115                 assert(stdinfd == 0);
    116                 vfs_open(stdinfd, MODE_READ);
    117                 stdin = fdopen(stdinfd, "r");
     103void __stdio_init(int filc)
     104{
     105        if (filc > 0) {
     106                stdin = fdopen(0, "r");
    118107        } else {
    119108                stdin = &stdin_null;
     
    121110        }
    122111       
    123         int outfd = inbox_get("stdout");
    124         if (outfd >= 0) {
    125                 int stdoutfd = vfs_clone(outfd, -1, false);
    126                 assert(stdoutfd <= 1);
    127                 while (stdoutfd < 1)
    128                         stdoutfd = vfs_clone(outfd, -1, false);
    129                 vfs_open(stdoutfd, MODE_APPEND);
    130                 stdout = fdopen(stdoutfd, "a");
     112        if (filc > 1) {
     113                stdout = fdopen(1, "w");
    131114        } else {
    132115                stdout = &stdout_kio;
     
    134117        }
    135118       
    136         int errfd = inbox_get("stderr");
    137         if (errfd >= 0) {
    138                 int stderrfd = vfs_clone(errfd, -1, false);
    139                 assert(stderrfd <= 2);
    140                 while (stderrfd < 2)
    141                         stderrfd = vfs_clone(errfd, -1, false);
    142                 vfs_open(stderrfd, MODE_APPEND);
    143                 stderr = fdopen(stderrfd, "a");
     119        if (filc > 2) {
     120                stderr = fdopen(2, "w");
    144121        } else {
    145122                stderr = &stderr_kio;
     
    156133}
    157134
    158 static bool parse_mode(const char *fmode, int *mode, bool *create, bool *truncate)
     135static bool parse_mode(const char *mode, int *flags)
    159136{
    160137        /* Parse mode except first character. */
    161         const char *mp = fmode;
     138        const char *mp = mode;
    162139        if (*mp++ == 0) {
    163140                errno = EINVAL;
     
    179156                return false;
    180157        }
    181 
    182         *create = false;
    183         *truncate = false;
    184        
    185         /* Parse first character of fmode and determine mode for vfs_open(). */
    186         switch (fmode[0]) {
     158       
     159        /* Parse first character of mode and determine flags for open(). */
     160        switch (mode[0]) {
    187161        case 'r':
    188                 *mode = plus ? MODE_READ | MODE_WRITE : MODE_READ;
     162                *flags = plus ? O_RDWR : O_RDONLY;
    189163                break;
    190164        case 'w':
    191                 *mode = plus ? MODE_READ | MODE_WRITE : MODE_WRITE;
    192                 *create = true;
    193                 if (!plus)
    194                         *truncate = true;
     165                *flags = (O_TRUNC | O_CREAT) | (plus ? O_RDWR : O_WRONLY);
    195166                break;
    196167        case 'a':
     
    200171                        return false;
    201172                }
    202 
    203                 *mode = MODE_APPEND | (plus ? MODE_READ | MODE_WRITE : MODE_WRITE);
    204                 *create = true;
     173                *flags = (O_APPEND | O_CREAT) | (plus ? O_RDWR : O_WRONLY);
    205174                break;
    206175        default:
     
    276245 *
    277246 */
    278 FILE *fopen(const char *path, const char *fmode)
    279 {
    280         int mode;
    281         bool create;
    282         bool truncate;
    283 
    284         if (!parse_mode(fmode, &mode, &create, &truncate))
     247FILE *fopen(const char *path, const char *mode)
     248{
     249        int flags;
     250        if (!parse_mode(mode, &flags))
    285251                return NULL;
    286252       
     
    291257                return NULL;
    292258        }
    293 
    294         int flags = WALK_REGULAR;
    295         if (create)
    296                 flags |= WALK_MAY_CREATE;
    297         int file = vfs_lookup(path, flags);
    298         if (file < 0) {
    299                 errno = file;
     259       
     260        stream->fd = open(path, flags, 0666);
     261        if (stream->fd < 0) {
     262                /* errno was set by open() */
    300263                free(stream);
    301264                return NULL;
    302265        }
    303 
    304         int rc = vfs_open(file, mode);
    305         if (rc != EOK) {
    306                 errno = rc;
    307                 vfs_put(file);
    308                 free(stream);
    309                 return NULL;
    310         }
    311        
    312         if (truncate) {
    313                 rc = vfs_resize(file, 0);
    314                 if (rc != EOK) {
    315                         errno = rc;
    316                         vfs_put(file);
    317                         free(stream);
    318                         return NULL;
    319                 }
    320         }
    321 
    322         stream->fd = file;
    323         stream->pos = 0;
     266       
    324267        stream->error = false;
    325268        stream->eof = false;
     
    345288       
    346289        stream->fd = fd;
    347         stream->pos = 0;
    348290        stream->error = false;
    349291        stream->eof = false;
     
    370312       
    371313        if (stream->fd >= 0)
    372                 rc = vfs_put(stream->fd);
     314                rc = close(stream->fd);
    373315       
    374316        list_remove(&stream->link);
     
    431373static size_t _fread(void *buf, size_t size, size_t nmemb, FILE *stream)
    432374{
     375        size_t left, done;
     376
    433377        if (size == 0 || nmemb == 0)
    434378                return 0;
    435379
    436         ssize_t rd = vfs_read(stream->fd, &stream->pos, buf, size * nmemb);
    437         if (rd < 0) {
    438                 errno = rd;
    439                 stream->error = true;
    440                 rd = 0;
    441         } else if (rd == 0) {
    442                 stream->eof = true;
    443         }
    444        
    445         return (rd / size);
     380        left = size * nmemb;
     381        done = 0;
     382       
     383        while ((left > 0) && (!stream->error) && (!stream->eof)) {
     384                ssize_t rd = read(stream->fd, buf + done, left);
     385               
     386                if (rd < 0) {
     387                        /* errno was set by read() */
     388                        stream->error = true;
     389                } else if (rd == 0) {
     390                        stream->eof = true;
     391                } else {
     392                        left -= rd;
     393                        done += rd;
     394                }
     395        }
     396       
     397        return (done / size);
    446398}
    447399
     
    458410static size_t _fwrite(const void *buf, size_t size, size_t nmemb, FILE *stream)
    459411{
     412        size_t left;
     413        size_t done;
     414        int rc;
     415
    460416        if (size == 0 || nmemb == 0)
    461417                return 0;
    462418
    463         ssize_t wr;
    464         if (stream->kio) {
    465                 size_t nwritten;
    466                 wr = kio_write(buf, size * nmemb, &nwritten);
    467                 if (wr != EOK) {
     419        left = size * nmemb;
     420        done = 0;
     421
     422        while ((left > 0) && (!stream->error)) {
     423                ssize_t wr;
     424                size_t uwr;
     425               
     426                if (stream->kio) {
     427                        uwr = 0;
     428                        rc = kio_write(buf + done, left, &uwr);
     429                        if (rc != EOK)
     430                                errno = rc;
     431                } else {
     432                        wr = write(stream->fd, buf + done, left);
     433                        if (wr >= 0) {
     434                                uwr = (size_t)wr;
     435                                rc = EOK;
     436                        } else {
     437                                /* errno was set by write */
     438                                uwr = 0;
     439                                rc = errno;
     440                        }
     441                }
     442               
     443                if (rc != EOK) {
     444                        /* errno was set above */
    468445                        stream->error = true;
    469                         wr = 0;
    470446                } else {
    471                         wr = nwritten;
     447                        left -= uwr;
     448                        done += uwr;
    472449                }
    473         } else {
    474                 wr = vfs_write(stream->fd, &stream->pos, buf, size * nmemb);
    475                 if (wr < 0) {
    476                         errno = wr;
    477                         stream->error = true;
    478                         wr = 0;
    479                 }
    480         }
    481 
    482         if (wr > 0)
     450        }
     451
     452        if (done > 0)
    483453                stream->need_sync = true;
    484454       
    485         return (wr / size);
     455        return (done / size);
    486456}
    487457
     
    496466        stream->buf_head = stream->buf_tail = stream->buf;
    497467
    498         rc = vfs_read(stream->fd, &stream->pos, stream->buf, stream->buf_size);
     468        rc = read(stream->fd, stream->buf, stream->buf_size);
    499469        if (rc < 0) {
    500                 errno = rc;
     470                /* errno was set by read() */
    501471                stream->error = true;
    502472                return;
     
    523493
    524494        /* If buffer has prefetched read data, we need to seek back. */
    525         if (bytes_used > 0 && stream->buf_state == _bs_read)
    526                 stream->pos -= bytes_used;
     495        if (bytes_used > 0 && stream->buf_state == _bs_read) {
     496                off64_t rc;
     497                rc = lseek(stream->fd, - (ssize_t) bytes_used, SEEK_CUR);
     498                if (rc == (off64_t)-1) {
     499                        /* errno was set by lseek */
     500                        stream->error = 1;
     501                        return;
     502                }
     503        }
    527504
    528505        /* If buffer has unwritten data, we need to write them out. */
     
    796773int fseek(FILE *stream, off64_t offset, int whence)
    797774{
    798         int rc;
     775        off64_t rc;
    799776
    800777        if (stream->error)
    801                 return -1;
     778                return EOF;
    802779
    803780        _fflushbuf(stream);
    804781        if (stream->error) {
    805782                /* errno was set by _fflushbuf() */
    806                 return -1;
     783                return EOF;
    807784        }
    808785
    809786        stream->ungetc_chars = 0;
    810787
    811         struct stat st;
    812         switch (whence) {
    813         case SEEK_SET:
    814                 stream->pos = offset;
    815                 break;
    816         case SEEK_CUR:
    817                 stream->pos += offset;
    818                 break;
    819         case SEEK_END:
    820                 rc = vfs_stat(stream->fd, &st);
    821                 if (rc != EOK) {
    822                         errno = rc;
    823                         stream->error = true;
    824                         return -1;     
    825                 }
    826                 stream->pos = st.size + offset;
    827                 break;
     788        rc = lseek(stream->fd, offset, whence);
     789        if (rc == (off64_t) (-1)) {
     790                /* errno has been set by lseek() */
     791                return EOF;
    828792        }
    829793
     
    834798off64_t ftell(FILE *stream)
    835799{
    836         /* The native position is too large for the C99-ish interface. */
    837         if (stream->pos - stream->ungetc_chars > INT64_MAX)
    838                 return EOF;
    839 
     800        off64_t pos;
     801       
    840802        if (stream->error)
    841803                return EOF;
     
    847809        }
    848810
    849         return stream->pos - stream->ungetc_chars;
     811        pos = lseek(stream->fd, 0, SEEK_CUR);
     812        if (pos == (off64_t) -1) {
     813                /* errno was set by lseek */
     814                return (off64_t) -1;
     815        }
     816       
     817        return pos - stream->ungetc_chars;
    850818}
    851819
     
    872840       
    873841        if ((stream->fd >= 0) && (stream->need_sync)) {
    874                 int rc;
    875 
    876842                /**
    877843                 * Better than syncing always, but probably still not the
     
    879845                 */
    880846                stream->need_sync = false;
    881                 rc = vfs_sync(stream->fd);
    882                 if (rc != EOK) {
    883                         errno = rc;
     847                if (fsync(stream->fd) != 0) {
     848                        /* errno was set by fsync() */
    884849                        return EOF;
    885850                }
Note: See TracChangeset for help on using the changeset viewer.