os/ossrv/genericopenlibs/cstdlib/LSTDIO/FVWRITE.C
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
sl@0
     1
/* FVWRITE.C
sl@0
     2
 * 
sl@0
     3
 * Portions Copyright (c) 1990-2004 Nokia Corporation and/or its subsidiary(-ies).
sl@0
     4
 * All rights reserved.
sl@0
     5
 */
sl@0
     6
sl@0
     7
/* No user fns here.  Pesch 15apr92. */
sl@0
     8
sl@0
     9
/*
sl@0
    10
 * Copyright (c) 1990 The Regents of the University of California.
sl@0
    11
 * All rights reserved.
sl@0
    12
 *
sl@0
    13
 * Redistribution and use in source and binary forms are permitted
sl@0
    14
 * provided that the above copyright notice and this paragraph are
sl@0
    15
 * duplicated in all such forms and that any documentation,
sl@0
    16
 * advertising materials, and other materials related to such
sl@0
    17
 * distribution and use acknowledge that the software was developed
sl@0
    18
 * by the University of California, Berkeley.  The name of the
sl@0
    19
 * University may not be used to endorse or promote products derived
sl@0
    20
 * from this software without specific prior written permission.
sl@0
    21
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
sl@0
    22
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
sl@0
    23
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
sl@0
    24
 */
sl@0
    25
sl@0
    26
#include <stdio_r.h>
sl@0
    27
#include <string.h>
sl@0
    28
#include "LOCAL.H"
sl@0
    29
#include "FVWRITE.H"
sl@0
    30
sl@0
    31
#define	MIN(a, b) ((a) < (b) ? (a) : (b))
sl@0
    32
#define	COPY(n)	  (void) memmove((void *) fp->_p, (void *) p, (size_t) (n))
sl@0
    33
sl@0
    34
#define GETIOV(extra_work) \
sl@0
    35
  while (len == 0) \
sl@0
    36
    { \
sl@0
    37
      extra_work; \
sl@0
    38
      p = (const char*)iov->iov_base; \
sl@0
    39
      len = iov->iov_len; \
sl@0
    40
      iov++; \
sl@0
    41
    }
sl@0
    42
sl@0
    43
/*
sl@0
    44
 * Write some memory regions.  Return zero on success, EOF on error.
sl@0
    45
 *
sl@0
    46
 * This routine is large and unsightly, but most of the ugliness due
sl@0
    47
 * to the three different kinds of output buffering is handled here.
sl@0
    48
 */
sl@0
    49
sl@0
    50
int
sl@0
    51
__sfvwrite (register FILE *fp,register struct __suio *uio)
sl@0
    52
{
sl@0
    53
  register size_t len;
sl@0
    54
  register const char *p;
sl@0
    55
  register struct __siov *iov;
sl@0
    56
  register int w, s;
sl@0
    57
  char *nl;
sl@0
    58
  int nlknown, nldist = -1;
sl@0
    59
sl@0
    60
  if ((len = uio->uio_resid) == 0)
sl@0
    61
    return 0;
sl@0
    62
sl@0
    63
  /* make sure we can write */
sl@0
    64
  if (cantwrite (fp))
sl@0
    65
    return EOF;
sl@0
    66
sl@0
    67
  iov = uio->uio_iov;
sl@0
    68
  len = 0;
sl@0
    69
  if (fp->_flags & __SNBF)
sl@0
    70
    {
sl@0
    71
      /*
sl@0
    72
       * Unbuffered: write up to BUFSIZ bytes at a time.
sl@0
    73
       */
sl@0
    74
      do
sl@0
    75
	{
sl@0
    76
	  GETIOV (;);
sl@0
    77
	  w = (*fp->_write) (fp->_cookie, p, MIN (len, BUFSIZ));
sl@0
    78
	  if (w <= 0)
sl@0
    79
	    goto err;
sl@0
    80
	  p += w;
sl@0
    81
	  len -= w;
sl@0
    82
	}
sl@0
    83
      while ((uio->uio_resid -= w) != 0);
sl@0
    84
    }
sl@0
    85
  else if ((fp->_flags & __SLBF) == 0)
sl@0
    86
    {
sl@0
    87
      /*
sl@0
    88
       * Fully buffered: fill partially full buffer, if any,
sl@0
    89
       * and then flush.  If there is no partial buffer, write
sl@0
    90
       * one _bf._size byte chunk directly (without copying).
sl@0
    91
       *
sl@0
    92
       * String output is a special case: write as many bytes
sl@0
    93
       * as fit, but pretend we wrote everything.  This makes
sl@0
    94
       * snprintf() return the number of bytes needed, rather
sl@0
    95
       * than the number used, and avoids its write function
sl@0
    96
       * (so that the write function can be invalid).
sl@0
    97
       */
sl@0
    98
      do
sl@0
    99
	{
sl@0
   100
	  GETIOV (;);
sl@0
   101
	  w = fp->_w;
sl@0
   102
	  if (fp->_flags & __SSTR)
sl@0
   103
	    {
sl@0
   104
	      if ((int)len < w)
sl@0
   105
		w = len;
sl@0
   106
	      COPY (w);		/* copy MIN(fp->_w,len), */
sl@0
   107
	      fp->_w -= w;
sl@0
   108
	      fp->_p += w;
sl@0
   109
	      w = len;		/* but pretend copied all */
sl@0
   110
	    }
sl@0
   111
	  else if (fp->_p > fp->_bf._base && (int)len > w)
sl@0
   112
	    {
sl@0
   113
	      /* fill and flush */
sl@0
   114
	      COPY (w);
sl@0
   115
	      /* fp->_w -= w; *//* unneeded */
sl@0
   116
	      fp->_p += w;
sl@0
   117
	      if (fflush (fp))
sl@0
   118
		goto err;
sl@0
   119
	    }
sl@0
   120
	  else if ((int)len >= (w = fp->_bf._size))
sl@0
   121
	    {
sl@0
   122
	      /* write directly */
sl@0
   123
	      w = (*fp->_write) (fp->_cookie, p, w);
sl@0
   124
	      if (w <= 0)
sl@0
   125
		goto err;
sl@0
   126
	    }
sl@0
   127
	  else
sl@0
   128
	    {
sl@0
   129
	      /* fill and done */
sl@0
   130
	      w = len;
sl@0
   131
	      COPY (w);
sl@0
   132
	      fp->_w -= w;
sl@0
   133
	      fp->_p += w;
sl@0
   134
	    }
sl@0
   135
	  p += w;
sl@0
   136
	  len -= w;
sl@0
   137
	}
sl@0
   138
      while ((uio->uio_resid -= w) != 0);
sl@0
   139
    }
sl@0
   140
  else
sl@0
   141
    {
sl@0
   142
      /*
sl@0
   143
       * Line buffered: like fully buffered, but we
sl@0
   144
       * must check for newlines.  Compute the distance
sl@0
   145
       * to the first newline (including the newline),
sl@0
   146
       * or `infinity' if there is none, then pretend
sl@0
   147
       * that the amount to write is MIN(len,nldist).
sl@0
   148
       */
sl@0
   149
      nlknown = 0;
sl@0
   150
      do
sl@0
   151
	{
sl@0
   152
	  GETIOV (nlknown = 0);
sl@0
   153
	  if (!nlknown)
sl@0
   154
	    {
sl@0
   155
	      nl = (char *)memchr ((void *) p, '\n', len);
sl@0
   156
	      nldist = nl ? nl + 1 - p : len + 1;
sl@0
   157
	      nlknown = 1;
sl@0
   158
	    }
sl@0
   159
	  s = MIN ((int)len, nldist);
sl@0
   160
	  w = fp->_w + fp->_bf._size;
sl@0
   161
	  if (fp->_p > fp->_bf._base && s > w)
sl@0
   162
	    {
sl@0
   163
	      COPY (w);
sl@0
   164
	      /* fp->_w -= w; */
sl@0
   165
	      fp->_p += w;
sl@0
   166
	      if (fflush (fp))
sl@0
   167
		goto err;
sl@0
   168
	    }
sl@0
   169
	  else if (s >= (w = fp->_bf._size))
sl@0
   170
	    {
sl@0
   171
	      w = (*fp->_write) (fp->_cookie, p, w);
sl@0
   172
	      if (w <= 0)
sl@0
   173
		goto err;
sl@0
   174
	    }
sl@0
   175
	  else
sl@0
   176
	    {
sl@0
   177
	      w = s;
sl@0
   178
	      COPY (w);
sl@0
   179
	      fp->_w -= w;
sl@0
   180
	      fp->_p += w;
sl@0
   181
	    }
sl@0
   182
	  if ((nldist -= w) == 0)
sl@0
   183
	    {
sl@0
   184
	      /* copied the newline: flush and forget */
sl@0
   185
	      if (fflush (fp))
sl@0
   186
		goto err;
sl@0
   187
	      nlknown = 0;
sl@0
   188
	    }
sl@0
   189
	  p += w;
sl@0
   190
	  len -= w;
sl@0
   191
	}
sl@0
   192
      while ((uio->uio_resid -= w) != 0);
sl@0
   193
    }
sl@0
   194
  return 0;
sl@0
   195
sl@0
   196
err:
sl@0
   197
  fp->_flags |= __SERR;
sl@0
   198
  return EOF;
sl@0
   199
}