Merge "Switch to current upstream OpenBSD fwrite.c."

This commit is contained in:
Elliott Hughes 2014-05-04 03:20:31 +00:00 committed by Gerrit Code Review
commit 640b4a5a64
3 changed files with 27 additions and 34 deletions

View file

@ -223,7 +223,6 @@ libc_upstream_freebsd_src_files := \
upstream-freebsd/lib/libc/stdio/fclose.c \
upstream-freebsd/lib/libc/stdio/flags.c \
upstream-freebsd/lib/libc/stdio/fopen.c \
upstream-freebsd/lib/libc/stdio/fwrite.c \
upstream-freebsd/lib/libc/stdio/makebuf.c \
upstream-freebsd/lib/libc/stdio/mktemp.c \
upstream-freebsd/lib/libc/stdio/setvbuf.c \
@ -388,6 +387,7 @@ libc_upstream_openbsd_src_files := \
upstream-openbsd/lib/libc/stdio/fwalk.c \
upstream-openbsd/lib/libc/stdio/fwide.c \
upstream-openbsd/lib/libc/stdio/fwprintf.c \
upstream-openbsd/lib/libc/stdio/fwrite.c \
upstream-openbsd/lib/libc/stdio/fwscanf.c \
upstream-openbsd/lib/libc/stdio/getc.c \
upstream-openbsd/lib/libc/stdio/getchar.c \

View file

@ -1,4 +1,4 @@
/* $OpenBSD: fvwrite.h,v 1.5 2003/06/02 20:18:37 millert Exp $ */
/* $OpenBSD: fvwrite.h,v 1.6 2013/11/12 07:04:35 deraadt Exp $ */
/*-
* Copyright (c) 1990, 1993
@ -36,7 +36,7 @@
* I/O descriptors for __sfvwrite().
*/
struct __siov {
const void *iov_base;
void *iov_base;
size_t iov_len;
};
struct __suio {
@ -46,3 +46,4 @@ struct __suio {
};
extern int __sfvwrite(FILE *, struct __suio *);
wint_t __fputwc_unlock(wchar_t wc, FILE *fp);

View file

@ -1,3 +1,4 @@
/* $OpenBSD: fwrite.c,v 1.11 2014/05/01 16:40:36 deraadt Exp $ */
/*-
* Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
@ -30,67 +31,58 @@
* SUCH DAMAGE.
*/
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "@(#)fwrite.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "namespace.h"
#include <errno.h>
#include <stdint.h>
#include <stdio.h>
#include "un-namespace.h"
#include <stdlib.h>
#include <stdint.h>
#include <errno.h>
#include "local.h"
#include "fvwrite.h"
#include "libc_private.h"
#define MUL_NO_OVERFLOW (1UL << (sizeof(size_t) * 4))
/*
* Write `count' objects (each size `size') from memory to the given file.
* Return the number of whole objects written.
*/
size_t
fwrite(const void * __restrict buf, size_t size, size_t count, FILE * __restrict fp)
fwrite(const void *buf, size_t size, size_t count, FILE *fp)
{
size_t n;
struct __suio uio;
struct __siov iov;
int ret;
/*
* ANSI and SUSv2 require a return value of 0 if size or count are 0.
* Extension: Catch integer overflow
*/
if ((count == 0) || (size == 0))
return (0);
/*
* Check for integer overflow. As an optimization, first check that
* at least one of {count, size} is at least 2^16, since if both
* values are less than that, their product can't possible overflow
* (size_t is always at least 32 bits on FreeBSD).
*/
if (((count | size) > 0xFFFF) &&
(count > SIZE_MAX / size)) {
errno = EINVAL;
if ((size >= MUL_NO_OVERFLOW || count >= MUL_NO_OVERFLOW) &&
size > 0 && SIZE_MAX / size < count) {
errno = EOVERFLOW;
fp->_flags |= __SERR;
return (0);
}
n = count * size;
/*
* ANSI and SUSv2 require a return value of 0 if size or count are 0.
*/
if ((n = count * size) == 0)
return (0);
iov.iov_base = (void *)buf;
uio.uio_resid = iov.iov_len = n;
uio.uio_iov = &iov;
uio.uio_iovcnt = 1;
FLOCKFILE(fp);
ORIENT(fp, -1);
/*
* The usual case is success (__sfvwrite returns 0);
* skip the divide if this happens, since divides are
* generally slow and since this occurs whenever size==0.
*/
if (__sfvwrite(fp, &uio) != 0)
count = (n - uio.uio_resid) / size;
FLOCKFILE(fp);
_SET_ORIENTATION(fp, -1);
ret = __sfvwrite(fp, &uio);
FUNLOCKFILE(fp);
return (count);
if (ret == 0)
return (count);
return ((n - uio.uio_resid) / size);
}