+++ /dev/null
-/*\r
- Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.<BR>\r
- This program and the accompanying materials are licensed and made available\r
- under the terms and conditions of the BSD License that accompanies this\r
- distribution. The full text of the license may be found at\r
- http://opensource.org/licenses/bsd-license.\r
-\r
- THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
- WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-\r
- * Copyright (c) 1990, 1993\r
- * The Regents of the University of California. All rights reserved.\r
- *\r
- * This code is derived from software contributed to Berkeley by\r
- * Chris Torek.\r
- *\r
- * Redistribution and use in source and binary forms, with or without\r
- * modification, are permitted provided that the following conditions\r
- * are met:\r
- * 1. Redistributions of source code must retain the above copyright\r
- * notice, this list of conditions and the following disclaimer.\r
- * 2. Redistributions in binary form must reproduce the above copyright\r
- * notice, this list of conditions and the following disclaimer in the\r
- * documentation and/or other materials provided with the distribution.\r
- * 3. Neither the name of the University nor the names of its contributors\r
- * may be used to endorse or promote products derived from this software\r
- * without specific prior written permission.\r
- *\r
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND\r
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\r
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\r
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE\r
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\r
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\r
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\r
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\r
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\r
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\r
- * SUCH DAMAGE.\r
-\r
- NetBSD: fvwrite.c,v 1.16.2.1 2007/05/07 19:49:09 pavel Exp\r
- fvwrite.c 8.1 (Berkeley) 6/4/93\r
-*/\r
-#include <LibConfig.h>\r
-#include <sys/EfiCdefs.h>\r
-\r
-#include <assert.h>\r
-#include <errno.h>\r
-#include <stdio.h>\r
-#include <stdlib.h>\r
-#include <string.h>\r
-#include "reentrant.h"\r
-#include "local.h"\r
-#include "fvwrite.h"\r
-\r
-/*\r
- * Write some memory regions. Return zero on success, EOF on error.\r
- *\r
- * This routine is large and unsightly, but most of the ugliness due\r
- * to the three different kinds of output buffering is handled here.\r
- */\r
-int\r
-__sfvwrite(FILE *fp, struct __suio *uio)\r
-{\r
- size_t len;\r
- char *p;\r
- struct __siov *iov;\r
- int w, s;\r
- char *nl;\r
- int nlknown, nldist;\r
-\r
- _DIAGASSERT(fp != NULL);\r
- _DIAGASSERT(uio != NULL);\r
- if(fp == NULL) {\r
- errno = EINVAL;\r
- return (EOF);\r
- }\r
-\r
- if ((len = uio->uio_resid) == 0)\r
- return (0);\r
- /* make sure we can write */\r
- if (cantwrite(fp)) {\r
- errno = EBADF;\r
- return (EOF);\r
- }\r
-\r
-//#define MIN(a, b) ((a) < (b) ? (a) : (b))\r
-#define COPY(n) (void)memcpy((void *)fp->_p, (void *)p, (size_t)(n))\r
-\r
- iov = uio->uio_iov;\r
- p = iov->iov_base;\r
- len = iov->iov_len;\r
- iov++;\r
-#define GETIOV(extra_work) \\r
- while (len == 0) { \\r
- extra_work; \\r
- p = iov->iov_base; \\r
- len = iov->iov_len; \\r
- iov++; \\r
- }\r
- if (fp->_flags & __SNBF) {\r
- /*\r
- * Unbuffered: write up to BUFSIZ bytes at a time.\r
- */\r
- do {\r
- GETIOV(;);\r
- w = (*fp->_write)(fp->_cookie, p,\r
- (int)MIN(len, BUFSIZ));\r
- if (w < 0)\r
- goto err;\r
- p += w;\r
- len -= w;\r
- } while ((uio->uio_resid -= w) > 0);\r
- uio->uio_resid = 0; // Just in case it went negative such as when NL is expanded to CR NL\r
- } else if ((fp->_flags & __SLBF) == 0) {\r
- /*\r
- * Fully buffered: fill partially full buffer, if any,\r
- * and then flush. If there is no partial buffer, write\r
- * one _bf._size byte chunk directly (without copying).\r
- *\r
- * String output is a special case: write as many bytes\r
- * as fit, but pretend we wrote everything. This makes\r
- * snprintf() return the number of bytes needed, rather\r
- * than the number used, and avoids its write function\r
- * (so that the write function can be invalid).\r
- */\r
- do {\r
- GETIOV(;);\r
- if ((fp->_flags & (__SALC | __SSTR)) ==\r
- (__SALC | __SSTR) && fp->_w < (int)len) {\r
- size_t blen = fp->_p - fp->_bf._base;\r
- unsigned char *_base;\r
- int _size;\r
-\r
- /* Allocate space exponentially. */\r
- _size = fp->_bf._size;\r
- do {\r
- _size = (_size << 1) + 1;\r
- } while (_size < (int)(blen + len));\r
- _base = realloc(fp->_bf._base,\r
- (size_t)(_size + 1));\r
- if (_base == NULL)\r
- goto err;\r
- fp->_w += _size - fp->_bf._size;\r
- fp->_bf._base = _base;\r
- fp->_bf._size = _size;\r
- fp->_p = _base + blen;\r
- }\r
- w = fp->_w;\r
- if (fp->_flags & __SSTR) {\r
- if (len < (size_t)w)\r
- w = (int)len;\r
- COPY(w); /* copy MIN(fp->_w,len), */\r
- fp->_w -= w;\r
- fp->_p += w;\r
- w = (int)len; /* but pretend copied all */\r
- } else if (fp->_p > fp->_bf._base && len > (size_t)w) {\r
- /* fill and flush */\r
- COPY(w);\r
- /* fp->_w -= w; */ /* unneeded */\r
- fp->_p += w;\r
- if (fflush(fp))\r
- goto err;\r
- } else if (len >= (size_t)(w = fp->_bf._size)) {\r
- /* write directly */\r
- w = (*fp->_write)(fp->_cookie, p, w);\r
- if (w <= 0)\r
- goto err;\r
- } else {\r
- /* fill and done */\r
- w = (int)len;\r
- COPY(w);\r
- fp->_w -= w;\r
- fp->_p += w;\r
- }\r
- p += w;\r
- len -= w;\r
- } while ((uio->uio_resid -= w) != 0);\r
- } else {\r
- /*\r
- * Line buffered: like fully buffered, but we\r
- * must check for newlines. Compute the distance\r
- * to the first newline (including the newline),\r
- * or `infinity' if there is none, then pretend\r
- * that the amount to write is MIN(len,nldist).\r
- */\r
- nlknown = 0;\r
- nldist = 0; /* XXX just to keep gcc happy */\r
- do {\r
- GETIOV(nlknown = 0);\r
- if (!nlknown) {\r
- nl = memchr((void *)p, '\n', len); // Divide the string at the first '\n'\r
- nldist = (int)(nl ? nl + 1 - p : len + 1);\r
- nlknown = 1;\r
- }\r
- s = (int)(MIN((int)len, nldist));\r
- w = fp->_w + fp->_bf._size;\r
- if (fp->_p > fp->_bf._base && s > w) {\r
- COPY(w);\r
- /* fp->_w -= w; */\r
- fp->_p += w;\r
- if (fflush(fp))\r
- goto err;\r
- } else if (s >= (w = fp->_bf._size)) {\r
- w = (*fp->_write)(fp->_cookie, p, w);\r
- if (w <= 0)\r
- goto err;\r
- } else {\r
- w = s;\r
- COPY(w);\r
- fp->_w -= w;\r
- fp->_p += w;\r
- }\r
- if ((nldist -= w) == 0) {\r
- /* copied the newline: flush and forget */\r
- if (fflush(fp))\r
- goto err;\r
- nlknown = 0;\r
- }\r
- p += w;\r
- len -= w;\r
- } while ((uio->uio_resid -= w) != 0);\r
- }\r
- return (0);\r
-\r
-err:\r
- fp->_flags |= __SERR;\r
- return (EOF);\r
-}\r