Ignore:
File:
1 edited

Legend:

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

    re86a617a r59f388a  
    3535#include <stdio.h>
    3636#include <unistd.h>
    37 #include <fcntl.h>
    3837#include <assert.h>
    3938#include <str.h>
     
    4544#include <vfs/vfs.h>
    4645#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,
    5758        .error = true,
    5859        .eof = true,
     
    6970static FILE stdout_kio = {
    7071        .fd = -1,
     72        .pos = 0,
    7173        .error = false,
    7274        .eof = false,
     
    8385static FILE stderr_kio = {
    8486        .fd = -1,
     87        .pos = 0,
    8588        .error = false,
    8689        .eof = false,
     
    101104static LIST_INITIALIZE(files);
    102105
    103 void __stdio_init(int filc)
    104 {
    105         if (filc > 0) {
    106                 stdin = fdopen(0, "r");
     106void __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");
    107118        } else {
    108119                stdin = &stdin_null;
     
    110121        }
    111122       
    112         if (filc > 1) {
    113                 stdout = fdopen(1, "w");
     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");
    114131        } else {
    115132                stdout = &stdout_kio;
     
    117134        }
    118135       
    119         if (filc > 2) {
    120                 stderr = fdopen(2, "w");
     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");
    121144        } else {
    122145                stderr = &stderr_kio;
     
    133156}
    134157
    135 static bool parse_mode(const char *mode, int *flags)
     158static bool parse_mode(const char *fmode, int *mode, bool *create, bool *truncate)
    136159{
    137160        /* Parse mode except first character. */
    138         const char *mp = mode;
     161        const char *mp = fmode;
    139162        if (*mp++ == 0) {
    140163                errno = EINVAL;
     
    156179                return false;
    157180        }
    158        
    159         /* Parse first character of mode and determine flags for open(). */
    160         switch (mode[0]) {
     181
     182        *create = false;
     183        *truncate = false;
     184       
     185        /* Parse first character of fmode and determine mode for vfs_open(). */
     186        switch (fmode[0]) {
    161187        case 'r':
    162                 *flags = plus ? O_RDWR : O_RDONLY;
     188                *mode = plus ? MODE_READ | MODE_WRITE : MODE_READ;
    163189                break;
    164190        case 'w':
    165                 *flags = (O_TRUNC | O_CREAT) | (plus ? O_RDWR : O_WRONLY);
     191                *mode = plus ? MODE_READ | MODE_WRITE : MODE_WRITE;
     192                *create = true;
     193                if (!plus)
     194                        *truncate = true;
    166195                break;
    167196        case 'a':
     
    171200                        return false;
    172201                }
    173                 *flags = (O_APPEND | O_CREAT) | (plus ? O_RDWR : O_WRONLY);
     202
     203                *mode = MODE_APPEND | (plus ? MODE_READ | MODE_WRITE : MODE_WRITE);
     204                *create = true;
    174205                break;
    175206        default:
     
    245276 *
    246277 */
    247 FILE *fopen(const char *path, const char *mode)
    248 {
    249         int flags;
    250         if (!parse_mode(mode, &flags))
     278FILE *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))
    251285                return NULL;
    252286       
     
    257291                return NULL;
    258292        }
    259        
    260         stream->fd = open(path, flags, 0666);
    261         if (stream->fd < 0) {
    262                 /* errno was set by open() */
     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;
    263300                free(stream);
    264301                return NULL;
    265302        }
    266        
     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;
    267324        stream->error = false;
    268325        stream->eof = false;
     
    288345       
    289346        stream->fd = fd;
     347        stream->pos = 0;
    290348        stream->error = false;
    291349        stream->eof = false;
     
    312370       
    313371        if (stream->fd >= 0)
    314                 rc = close(stream->fd);
     372                rc = vfs_put(stream->fd);
    315373       
    316374        list_remove(&stream->link);
     
    373431static size_t _fread(void *buf, size_t size, size_t nmemb, FILE *stream)
    374432{
    375         size_t left, done;
    376 
    377433        if (size == 0 || nmemb == 0)
    378434                return 0;
    379435
    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);
     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);
    398446}
    399447
     
    410458static size_t _fwrite(const void *buf, size_t size, size_t nmemb, FILE *stream)
    411459{
    412         size_t left;
    413         size_t done;
    414         int rc;
    415 
    416460        if (size == 0 || nmemb == 0)
    417461                return 0;
    418462
    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;
     463        ssize_t wr;
     464        if (stream->kio) {
     465                size_t nwritten;
     466                wr = kio_write(buf, size * nmemb, &nwritten);
     467                if (wr != EOK) {
     468                        stream->error = true;
     469                        wr = 0;
    431470                } 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                         }
     471                        wr = nwritten;
    441472                }
    442                
    443                 if (rc != EOK) {
    444                         /* errno was set above */
     473        } else {
     474                wr = vfs_write(stream->fd, &stream->pos, buf, size * nmemb);
     475                if (wr < 0) {
     476                        errno = wr;
    445477                        stream->error = true;
    446                 } else {
    447                         left -= uwr;
    448                         done += uwr;
     478                        wr = 0;
    449479                }
    450480        }
    451481
    452         if (done > 0)
     482        if (wr > 0)
    453483                stream->need_sync = true;
    454484       
    455         return (done / size);
     485        return (wr / size);
    456486}
    457487
     
    466496        stream->buf_head = stream->buf_tail = stream->buf;
    467497
    468         rc = read(stream->fd, stream->buf, stream->buf_size);
     498        rc = vfs_read(stream->fd, &stream->pos, stream->buf, stream->buf_size);
    469499        if (rc < 0) {
    470                 /* errno was set by read() */
     500                errno = rc;
    471501                stream->error = true;
    472502                return;
     
    493523
    494524        /* If buffer has prefetched read data, we need to seek back. */
    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         }
     525        if (bytes_used > 0 && stream->buf_state == _bs_read)
     526                stream->pos -= bytes_used;
    504527
    505528        /* If buffer has unwritten data, we need to write them out. */
     
    773796int fseek(FILE *stream, off64_t offset, int whence)
    774797{
    775         off64_t rc;
     798        int rc;
    776799
    777800        if (stream->error)
    778                 return EOF;
     801                return -1;
    779802
    780803        _fflushbuf(stream);
    781804        if (stream->error) {
    782805                /* errno was set by _fflushbuf() */
    783                 return EOF;
     806                return -1;
    784807        }
    785808
    786809        stream->ungetc_chars = 0;
    787810
    788         rc = lseek(stream->fd, offset, whence);
    789         if (rc == (off64_t) (-1)) {
    790                 /* errno has been set by lseek() */
    791                 return EOF;
     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;
    792828        }
    793829
     
    798834off64_t ftell(FILE *stream)
    799835{
    800         off64_t pos;
    801        
     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
    802840        if (stream->error)
    803841                return EOF;
     
    809847        }
    810848
    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;
     849        return stream->pos - stream->ungetc_chars;
    818850}
    819851
     
    840872       
    841873        if ((stream->fd >= 0) && (stream->need_sync)) {
     874                int rc;
     875
    842876                /**
    843877                 * Better than syncing always, but probably still not the
     
    845879                 */
    846880                stream->need_sync = false;
    847                 if (fsync(stream->fd) != 0) {
    848                         /* errno was set by fsync() */
     881                rc = vfs_sync(stream->fd);
     882                if (rc != EOK) {
     883                        errno = rc;
    849884                        return EOF;
    850885                }
Note: See TracChangeset for help on using the changeset viewer.