Changeset 2541


Ignore:
Timestamp:
Feb 7, 2006, 1:55:41 AM (20 years ago)
Author:
bird
Message:

Rewrote the freopen(NULL) code to use fcntl(,F_SETFL,) for updating the flags. This way it *works* and it supports switching on and off O_APPEND.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/libc-0.6/src/emx/src/lib/io/freopen.c

    r2536 r2541  
    1515#define TRUE    1
    1616
     17/**
     18 * Interprets the stream mode string.
     19 *
     20 * @returns the basic stream flags and *pmode set to the open mode.
     21 * @returns -1 and *pomode unset on failure.
     22 * @param   mode    The mode string.
     23 * @param   pomode  Where to store the open mode.
     24 */
     25static int _interpret_stream_mode(const char *mode, unsigned *pomode)
     26{
     27    int flags = 0;
     28    int omode = 0;
     29    char bt, ok;
     30
     31    switch (*mode)
     32      {
     33      case 'r':
     34        flags = _IOREAD;
     35        omode = O_RDONLY;
     36        break;
     37      case 'w':
     38        flags = _IOWRT;
     39        omode = O_WRONLY|O_CREAT|O_TRUNC;
     40        break;
     41      case 'a':
     42        flags = _IOWRT;
     43        omode = O_WRONLY|O_CREAT|O_APPEND;
     44        break;
     45      default:
     46        errno = EINVAL;
     47        return -1;
     48      }
     49
     50    ok = TRUE;
     51    bt = FALSE;
     52    while (ok && *++mode)
     53      {
     54        switch (*mode)
     55          {
     56          case 't':
     57            if (bt)
     58              ok = FALSE;
     59            else
     60              {
     61                bt = TRUE;
     62                omode |= O_TEXT;
     63              }
     64            break;
     65          case 'b':
     66            if (bt)
     67              ok = FALSE;
     68            else
     69              {
     70                bt = TRUE;
     71                omode |= O_BINARY;
     72              }
     73            break;
     74          case '+':
     75            if (flags & _IORW)
     76              ok = FALSE;
     77            else
     78              {
     79                omode &= ~(O_RDONLY|O_WRONLY);
     80                omode |= O_RDWR;
     81                flags &= ~(_IOREAD|_IOWRT);
     82                flags |= _IORW;
     83              }
     84            break;
     85          default:
     86            ok = FALSE;
     87            break;
     88          }
     89      }
     90    *pomode = omode;
     91    return flags;
     92}
     93
    1794FILE *_STD(freopen) (const char *fname, const char *mode, FILE *stream)
    1895{
    19   FILE *result;
     96  FILE *result = NULL;
    2097
    2198  STREAMV_LOCK;
     
    25102       * Change the stream mode.
    26103       */
    27       /** @todo freopen(NULL,,) isn't 100% right, but it'll do for now I hope */
    28       result = stream;
    29       if (result->_flags & _IOOPEN)
     104      if (stream->_flags & _IOOPEN)
    30105        {
    31           char bt, ok;
    32           int omode = 0;
    33 
    34           switch (*mode)
     106          int omode;
     107          int flags = _interpret_stream_mode(mode, &omode);
     108          if (flags != -1)
    35109            {
    36             case 'r':
    37               if (!(result->_flags & (_IORW | _IOREAD)))
     110              if (   ((flags & _IORW)   && !(stream->_flags & _IORW))
     111                  || ((flags & _IOREAD) && !(stream->_flags & (_IORW | _IOREAD)))
     112                  || ((flags & _IOWRT)  && !(stream->_flags & (_IORW | _IOWRT)))
     113                  )
     114                  errno = EINVAL;
     115              else
    38116                {
    39                   result = NULL;
    40                   errno = EINVAL;
     117                  if (!(stream->_flags & _IOSPECIAL))
     118                    {
     119                      /* flush it and set the new mode */
     120                      fflush(stream);
     121                      if (!fcntl(fileno(stream), F_SETFL, omode))
     122                        stream = stream;
     123                    }
     124                  else
     125                    errno = EBADF; /* doesn't support the mode. */
    41126                }
    42               omode = O_RDONLY;
    43               break;
    44             case 'w':
    45               if (!(result->_flags & (_IORW | _IOWRT)))
    46                 {
    47                   result = NULL;
    48                   errno = EINVAL;
    49                 }
    50               omode = O_WRONLY;
    51               break;
    52             case 'a':
    53               if (!(result->_flags & (_IORW | _IOWRT)))
    54                 {
    55                   result = NULL;
    56                   errno = EINVAL;
    57                 }
    58               omode = O_WRONLY | O_APPEND;
    59               break;
    60             default:
    61               errno = EINVAL;
    62               result = NULL;
    63               break;
    64             }
    65           ++mode; ok = TRUE; bt = FALSE;
    66           while (result && *mode != 0 && ok)
    67             {
    68               switch (*mode)
    69                 {
    70                 case 't':
    71                   if (bt)
    72                     ok = FALSE;
    73                   else
    74                     {
    75                       bt = TRUE;
    76                       omode |= O_TEXT;
    77                     }
    78                   break;
    79                 case 'b':
    80                   if (bt)
    81                     ok = FALSE;
    82                   else
    83                     {
    84                       bt = TRUE;
    85                       omode |= O_BINARY;
    86                     }
    87                   break;
    88                 case '+':
    89                    if (!(result->_flags & _IORW))
    90                      {
    91                        result = NULL;
    92                        errno = EINVAL;
    93                      }
    94                    omode &= ~(O_RDONLY|O_WRONLY);
    95                    omode |= O_RDWR;
    96                    break;
    97                 default:
    98                   ok = FALSE;
    99                   break;
    100                 }
    101               if (ok)
    102                   mode++;
    103             }
    104 
    105           /*
    106            * Was the mode ok And does this stream have a handle?
    107            */
    108           if (result && !(result->_flags & _IOSPECIAL))
    109             {
    110               /* flush it and set the new mode */
    111               fflush(result);
    112               int oldmode = setmode(fileno(result), omode);
    113               if (      oldmode == -1
    114                   ||    (omode & O_APPEND) != (oldmode & O_APPEND))
    115                 result = NULL;
    116127            }
    117128        }
    118129      else
    119         {
    120           errno = EBADF;
    121           result = NULL;
    122         }
     130        errno = EBADF;
    123131    }
    124132  else
Note: See TracChangeset for help on using the changeset viewer.