Prex Home / Browse Source - Prex Version: 0.9.0

root/usr/lib/libc/stdio/fvwrite.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. __sfvwrite

   1 /*-
   2  * Copyright (c) 1990, 1993
   3  *      The Regents of the University of California.  All rights reserved.
   4  *
   5  * This code is derived from software contributed to Berkeley by
   6  * Chris Torek.
   7  *
   8  * Redistribution and use in source and binary forms, with or without
   9  * modification, are permitted provided that the following conditions
  10  * are met:
  11  * 1. Redistributions of source code must retain the above copyright
  12  *    notice, this list of conditions and the following disclaimer.
  13  * 2. Redistributions in binary form must reproduce the above copyright
  14  *    notice, this list of conditions and the following disclaimer in the
  15  *    documentation and/or other materials provided with the distribution.
  16  * 3. Neither the name of the University nor the names of its contributors
  17  *    may be used to endorse or promote products derived from this software
  18  *    without specific prior written permission.
  19  *
  20  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  30  * SUCH DAMAGE.
  31  */
  32 
  33 #include <stdio.h>
  34 #include <string.h>
  35 #include "local.h"
  36 #include "fvwrite.h"
  37 
  38 /*
  39  * Write some memory regions.  Return zero on success, EOF on error.
  40  *
  41  * This routine is large and unsightly, but most of the ugliness due
  42  * to the three different kinds of output buffering is handled here.
  43  */
  44 int
  45 __sfvwrite(fp, uio)
  46         FILE *fp;
  47         struct __suio *uio;
  48 {
  49         size_t len;
  50         char *p;
  51         struct __siov *iov;
  52         int w, s;
  53         char *nl;
  54         int nlknown, nldist;
  55 
  56         if ((len = uio->uio_resid) == 0)
  57                 return (0);
  58         /* make sure we can write */
  59         if (cantwrite(fp))
  60                 return (EOF);
  61 
  62 #define MIN(a, b) ((a) < (b) ? (a) : (b))
  63 #define COPY(n)   (void)memcpy((void *)fp->_p, (void *)p, (size_t)(n))
  64 
  65         iov = uio->uio_iov;
  66         p = iov->iov_base;
  67         len = iov->iov_len;
  68         iov++;
  69 #define GETIOV(extra_work) \
  70         while (len == 0) { \
  71                 extra_work; \
  72                 p = iov->iov_base; \
  73                 len = iov->iov_len; \
  74                 iov++; \
  75         }
  76         if (fp->_flags & __SNBF) {
  77                 /*
  78                  * Unbuffered: write up to BUFSIZ bytes at a time.
  79                  */
  80                 do {
  81                         GETIOV(;);
  82                         w = __swrite(fp, p, MIN(len, BUFSIZ));
  83                         if (w <= 0)
  84                                 goto err;
  85                         p += w;
  86                         len -= w;
  87                 } while ((uio->uio_resid -= w) != 0);
  88         } else if ((fp->_flags & __SLBF) == 0) {
  89                 /*
  90                  * Fully buffered: fill partially full buffer, if any,
  91                  * and then flush.  If there is no partial buffer, write
  92                  * one _bf._size byte chunk directly (without copying).
  93                  *
  94                  * String output is a special case: write as many bytes
  95                  * as fit, but pretend we wrote everything.  This makes
  96                  * snprintf() return the number of bytes needed, rather
  97                  * than the number used, and avoids its write function
  98                  * (so that the write function can be invalid).
  99                  */
 100                 do {
 101                         GETIOV(;);
 102                         w = fp->_w;
 103                         if (fp->_flags & __SSTR) {
 104                                 if (len < w)
 105                                         w = len;
 106                                 COPY(w);        /* copy MIN(fp->_w,len), */
 107                                 fp->_w -= w;
 108                                 fp->_p += w;
 109                                 w = len;        /* but pretend copied all */
 110                         } else if (fp->_p > fp->_bf._base && len > w) {
 111                                 /* fill and flush */
 112                                 COPY(w);
 113                                 /* fp->_w -= w; */ /* unneeded */
 114                                 fp->_p += w;
 115                                 if (fflush(fp))
 116                                         goto err;
 117                         } else if (len >= (w = fp->_bf._size)) {
 118                                 /* write directly */
 119                                 w = __swrite(fp, p, w);
 120                                 if (w <= 0)
 121                                         goto err;
 122                         } else {
 123                                 /* fill and done */
 124                                 w = len;
 125                                 COPY(w);
 126                                 fp->_w -= w;
 127                                 fp->_p += w;
 128                         }
 129                         p += w;
 130                         len -= w;
 131                 } while ((uio->uio_resid -= w) != 0);
 132         } else {
 133                 /*
 134                  * Line buffered: like fully buffered, but we
 135                  * must check for newlines.  Compute the distance
 136                  * to the first newline (including the newline),
 137                  * or `infinity' if there is none, then pretend
 138                  * that the amount to write is MIN(len,nldist).
 139                  */
 140                 nlknown = 0;
 141                 nldist = 0;     /* XXX just to keep gcc happy */
 142                 do {
 143                         GETIOV(nlknown = 0);
 144                         if (!nlknown) {
 145                                 nl = memchr((void *)p, '\n', len);
 146                                 nldist = nl ? nl + 1 - p : len + 1;
 147                                 nlknown = 1;
 148                         }
 149                         s = MIN(len, nldist);
 150                         w = fp->_w + fp->_bf._size;
 151                         if (fp->_p > fp->_bf._base && s > w) {
 152                                 COPY(w);
 153                                 /* fp->_w -= w; */
 154                                 fp->_p += w;
 155                                 if (fflush(fp))
 156                                         goto err;
 157                         } else if (s >= (w = fp->_bf._size)) {
 158                                 w = __swrite(fp, p, w);
 159                                 if (w <= 0)
 160                                         goto err;
 161                         } else {
 162                                 w = s;
 163                                 COPY(w);
 164                                 fp->_w -= w;
 165                                 fp->_p += w;
 166                         }
 167                         if ((nldist -= w) == 0) {
 168                                 /* copied the newline: flush and forget */
 169                                 if (fflush(fp))
 170                                         goto err;
 171                                 nlknown = 0;
 172                         }
 173                         p += w;
 174                         len -= w;
 175                 } while ((uio->uio_resid -= w) != 0);
 176         }
 177         return (0);
 178 
 179 err:
 180         fp->_flags |= __SERR;
 181         return (EOF);
 182 }

/* [<][>][^][v][top][bottom][index][help] */