Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset fd4b636 in mainline


Ignore:
Timestamp:
2011-07-27T21:28:19Z (10 years ago)
Author:
Jiří Zárevúcky <zarevucky.jiri@…>
Branches:
lfn, master
Children:
58115ae
Parents:
f215bb5
Message:

Complete implementation of freopen().

File:
1 edited

Legend:

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

    rf215bb5 rfd4b636  
    5050#include "libc/str.h"
    5151#include "libc/malloc.h"
     52#include "libc/adt/list.h"
     53#include "libc/sys/stat.h"
    5254
    5355
     
    252254        assert(mode != NULL);
    253255        assert(stream != NULL);
    254 
     256       
     257        /* Retieve the node. */
     258        struct stat st;
     259        int rc;
     260       
    255261        if (filename == NULL) {
    256                 // TODO
    257                
    258                 /* print error to stderr as well, to avoid hard to find problems
    259                  * with buggy apps that expect this to work
    260                  */
    261                 fprintf(stderr,
    262                     "ERROR: Application wants to use freopen() to change mode of opened stream.\n"
    263                     "       libposix does not support that yet, the application may function improperly.\n");
    264                 errno = ENOTSUP;
     262                rc = fstat(stream->fd, &st);
     263        } else {
     264                rc = stat(filename, &st);
     265        }
     266       
     267        if (rc != EOK) {
     268                fclose(stream);
     269                errno = -rc;
    265270                return NULL;
    266271        }
    267 
    268         FILE* copy = malloc(sizeof(FILE));
    269         if (copy == NULL) {
    270                 errno = ENOMEM;
     272       
     273        fdi_node_t node = {
     274                .fs_handle = st.fs_handle,
     275                .devmap_handle = st.devmap_handle,
     276                .index = st.index
     277        };
     278       
     279        /* Open a new stream. */
     280        FILE* new = fopen_node(&node, mode);
     281        if (new == NULL) {
     282                fclose(stream);
     283                /* fopen_node() sets errno. */
    271284                return NULL;
    272285        }
    273         memcpy(copy, stream, sizeof(FILE));
    274         fclose(copy); /* copy is now freed */
    275        
    276         copy = fopen(filename, mode); /* open new stream */
    277         if (copy == NULL) {
    278                 /* fopen() sets errno */
    279                 return NULL;
    280         }
    281        
    282         /* move the new stream to the original location */
    283         memcpy(stream, copy, sizeof (FILE));
    284         free(copy);
    285        
    286         /* update references in the file list */
     286       
     287        /* Close the original stream without freeing it (ignoring errors). */
     288        if (stream->buf != NULL) {
     289                fflush(stream);
     290        }
     291        if (stream->sess != NULL) {
     292                async_hangup(stream->sess);
     293        }
     294        if (stream->fd >= 0) {
     295                close(stream->fd);
     296        }
     297        list_remove(&stream->link);
     298       
     299        /* Move the new stream to the original location. */
     300        memcpy(stream, new, sizeof (FILE));
     301        free(new);
     302       
     303        /* Update references in the file list. */
    287304        stream->link.next->prev = &stream->link;
    288305        stream->link.prev->next = &stream->link;
Note: See TracChangeset for help on using the changeset viewer.