Ignore:
File:
1 edited

Legend:

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

    r6afc9d7 rfdf97f6  
    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
     
    230308        }
    231309}
     310
     311struct _posix_fpos {
     312        off64_t offset;
     313};
    232314
    233315/** Restores stream a to position previously saved with fgetpos().
     
    315397int posix_fflush(FILE *stream)
    316398{
    317         return negerrno(fflush, stream);
     399        int rc = fflush(stream);
     400        if (rc < 0) {
     401                errno = -rc;
     402                return EOF;
     403        } else {
     404                return 0;
     405        }
    318406}
    319407
     
    345433{
    346434        ssize_t wr = write(*(int *) fd, str, size);
    347         if (wr < 0)
    348                 return errno;
    349435        return str_nlength(str, wr);
    350436}
     
    575661int posix_remove(const char *path)
    576662{
    577         return negerrno(remove, path);
     663        struct stat st;
     664        int rc = stat(path, &st);
     665       
     666        if (rc != EOK) {
     667                errno = -rc;
     668                return -1;
     669        }
     670       
     671        if (st.is_directory) {
     672                rc = rmdir(path);
     673        } else {
     674                rc = unlink(path);
     675        }
     676       
     677        if (rc != EOK) {
     678                errno = -rc;
     679                return -1;
     680        }
     681        return 0;
    578682}
    579683
     
    587691int posix_rename(const char *old, const char *new)
    588692{
    589         return negerrno(rename, old, new);
     693        return errnify(rename, old, new);
    590694}
    591695
Note: See TracChangeset for help on using the changeset viewer.