Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/posix/source/stdio.c

    r6afc9d7 re3c960e  
    5555#include "libc/sys/stat.h"
    5656
     57
     58/* not the best of solutions, but freopen and ungetc will eventually
     59 * need to be implemented in libc anyway
     60 */
     61#include "../../c/generic/private/stdio.h"
     62
    5763/** Clears the stream's error and end-of-file indicators.
    5864 *
     
    6167void posix_clearerr(FILE *stream)
    6268{
    63         clearerr(stream);
     69        stream->error = 0;
     70        stream->eof = 0;
    6471}
    6572
     
    94101int posix_fputs(const char *restrict s, FILE *restrict stream)
    95102{
    96         return fputs(s, stream);
     103        int rc = fputs(s, stream);
     104        if (rc == 0) {
     105                return EOF;
     106        } else {
     107                return 0;
     108        }
    97109}
    98110
     
    106118int posix_ungetc(int c, FILE *stream)
    107119{
    108         return ungetc(c, stream);
     120        uint8_t b = (uint8_t) c;
     121
     122        bool can_unget =
     123            /* Provided character is legal. */
     124            c != EOF &&
     125            /* Stream is consistent. */
     126            !stream->error &&
     127            /* Stream is buffered. */
     128            stream->btype != _IONBF &&
     129            /* Last operation on the stream was a read operation. */
     130            stream->buf_state == _bs_read &&
     131            /* Stream buffer is already allocated (i.e. there was already carried
     132             * out either write or read operation on the stream). This is probably
     133             * redundant check but let's be safe. */
     134            stream->buf != NULL &&
     135            /* There is still space in the stream to retreat. POSIX demands the
     136             * possibility to unget at least 1 character. It should be always
     137             * possible, assuming the last operation on the stream read at least 1
     138             * character, because the buffer is refilled in the lazily manner. */
     139            stream->buf_tail > stream->buf;
     140
     141        if (can_unget) {
     142                --stream->buf_tail;
     143                stream->buf_tail[0] = b;
     144                stream->eof = false;
     145                return (int) b;
     146        } else {
     147                return EOF;
     148        }
    109149}
    110150
     
    214254    const char *restrict mode, FILE *restrict stream)
    215255{
    216         return freopen(filename, mode, stream);
     256        assert(mode != NULL);
     257        assert(stream != NULL);
     258       
     259        if (filename == NULL) {
     260                /* POSIX allows this to be imlementation-defined. HelenOS currently
     261                 * does not support changing the mode. */
     262                // FIXME: handle mode change once it is supported
     263                return stream;
     264        }
     265       
     266        /* Open a new stream. */
     267        FILE* new = fopen(filename, mode);
     268        if (new == NULL) {
     269                fclose(stream);
     270                /* errno was set by fopen() */
     271                return NULL;
     272        }
     273       
     274        /* Close the original stream without freeing it (ignoring errors). */
     275        if (stream->buf != NULL) {
     276                fflush(stream);
     277        }
     278        if (stream->sess != NULL) {
     279                async_hangup(stream->sess);
     280        }
     281        if (stream->fd >= 0) {
     282                close(stream->fd);
     283        }
     284        list_remove(&stream->link);
     285       
     286        /* Move the new stream to the original location. */
     287        memcpy(stream, new, sizeof (FILE));
     288        free(new);
     289       
     290        /* Update references in the file list. */
     291        stream->link.next->prev = &stream->link;
     292        stream->link.prev->next = &stream->link;
     293       
     294        return stream;
    217295}
    218296
     
    315393int posix_fflush(FILE *stream)
    316394{
    317         return negerrno(fflush, stream);
     395        int rc = fflush(stream);
     396        if (rc < 0) {
     397                errno = -rc;
     398                return EOF;
     399        } else {
     400                return 0;
     401        }
    318402}
    319403
     
    345429{
    346430        ssize_t wr = write(*(int *) fd, str, size);
    347         if (wr < 0)
    348                 return errno;
    349431        return str_nlength(str, wr);
    350432}
     
    575657int posix_remove(const char *path)
    576658{
    577         return negerrno(remove, path);
     659        struct stat st;
     660        int rc = stat(path, &st);
     661       
     662        if (rc != EOK) {
     663                errno = -rc;
     664                return -1;
     665        }
     666       
     667        if (st.is_directory) {
     668                rc = rmdir(path);
     669        } else {
     670                rc = unlink(path);
     671        }
     672       
     673        if (rc != EOK) {
     674                errno = -rc;
     675                return -1;
     676        }
     677        return 0;
    578678}
    579679
     
    587687int posix_rename(const char *old, const char *new)
    588688{
    589         return negerrno(rename, old, new);
     689        return errnify(rename, old, new);
    590690}
    591691
Note: See TracChangeset for help on using the changeset viewer.