summaryrefslogtreecommitdiff
path: root/lib/libc
diff options
context:
space:
mode:
authorchristos <christos@NetBSD.org>2012-03-27 15:05:42 +0000
committerchristos <christos@NetBSD.org>2012-03-27 15:05:42 +0000
commitbaad00d0c072d37cba2aa3aad2bcbb15c7b00d0e (patch)
tree1ef0b1202c3bc828d646eb3f4204ad1ed3f19ceb /lib/libc
parentbae5d65144ba6010d073c3de6c63a476d6f792cf (diff)
- widen the internal read and write calls to match the syscalls
- add funopen2() which provides access to flush() and the wider calls. - make use of the new flush call in fmemopen()
Diffstat (limited to 'lib/libc')
-rw-r--r--lib/libc/stdio/Makefile.inc3
-rw-r--r--lib/libc/stdio/fflush.c13
-rw-r--r--lib/libc/stdio/findfp.c39
-rw-r--r--lib/libc/stdio/fmemopen.c50
-rw-r--r--lib/libc/stdio/freopen.c6
-rw-r--r--lib/libc/stdio/fseeko.c6
-rw-r--r--lib/libc/stdio/ftell.c6
-rw-r--r--lib/libc/stdio/ftello.c6
-rw-r--r--lib/libc/stdio/funopen.326
-rw-r--r--lib/libc/stdio/funopen.c96
-rw-r--r--lib/libc/stdio/fvwrite.c28
-rw-r--r--lib/libc/stdio/local.h6
-rw-r--r--lib/libc/stdio/refill.c7
-rw-r--r--lib/libc/stdio/sscanf.c8
-rw-r--r--lib/libc/stdio/stdio.c34
-rw-r--r--lib/libc/stdio/vfwprintf.c5
-rw-r--r--lib/libc/stdio/vsscanf.c8
-rw-r--r--lib/libc/stdio/vswscanf.c8
18 files changed, 253 insertions, 102 deletions
diff --git a/lib/libc/stdio/Makefile.inc b/lib/libc/stdio/Makefile.inc
index 23143606809..65e6762a392 100644
--- a/lib/libc/stdio/Makefile.inc
+++ b/lib/libc/stdio/Makefile.inc
@@ -1,5 +1,5 @@
# from: @(#)Makefile.inc 5.7 (Berkeley) 6/27/91
-# $NetBSD: Makefile.inc,v 1.40 2010/12/22 16:59:10 christos Exp $
+# $NetBSD: Makefile.inc,v 1.41 2012/03/27 15:05:42 christos Exp $
# stdio sources
.PATH: ${.CURDIR}/stdio
@@ -45,6 +45,7 @@ MLINKS+=fread.3 fwrite.3
MLINKS+=fseek.3 fgetpos.3 fseek.3 fseeko.3 fseek.3 fsetpos.3 fseek.3 ftell.3 \
fseek.3 ftello.3 fseek.3 rewind.3
MLINKS+=funopen.3 fropen.3 funopen.3 fwopen.3
+MLINKS+=funopen.3 funopen2.3 funopen.3 fropen2.3 funopen.3 fwopen2.3
MLINKS+=getc.3 fgetc.3 getc.3 getc_unlocked.3 getc.3 getchar.3 \
getc.3 getchar_unlocked.3 getc.3 getw.3
MLINKS+=getdelim.3 getline.3
diff --git a/lib/libc/stdio/fflush.c b/lib/libc/stdio/fflush.c
index d2ead657666..c9a317ed89c 100644
--- a/lib/libc/stdio/fflush.c
+++ b/lib/libc/stdio/fflush.c
@@ -1,4 +1,4 @@
-/* $NetBSD: fflush.c,v 1.17 2012/03/15 18:22:30 christos Exp $ */
+/* $NetBSD: fflush.c,v 1.18 2012/03/27 15:05:42 christos Exp $ */
/*-
* Copyright (c) 1990, 1993
@@ -37,7 +37,7 @@
#if 0
static char sccsid[] = "@(#)fflush.c 8.1 (Berkeley) 6/4/93";
#else
-__RCSID("$NetBSD: fflush.c,v 1.17 2012/03/15 18:22:30 christos Exp $");
+__RCSID("$NetBSD: fflush.c,v 1.18 2012/03/27 15:05:42 christos Exp $");
#endif
#endif /* LIBC_SCCS and not lint */
@@ -80,7 +80,8 @@ int
__sflush(FILE *fp)
{
unsigned char *p;
- int n, t;
+ size_t n;
+ ssize_t t;
_DIAGASSERT(fp != NULL);
@@ -92,8 +93,8 @@ __sflush(FILE *fp)
return 0;
ptrdiff_t tp = fp->_p - p;
- _DIAGASSERT(__type_fit(int, tp));
- n = (int)tp; /* write this much */
+ _DIAGASSERT(__type_fit(ssize_t, tp));
+ n = (ssize_t)tp; /* write this much */
/*
* Set these immediately to avoid problems with longjmp and to allow
@@ -109,5 +110,7 @@ __sflush(FILE *fp)
return EOF;
}
}
+ if (fp->_flush)
+ return (*fp->_flush)(fp->_cookie);
return 0;
}
diff --git a/lib/libc/stdio/findfp.c b/lib/libc/stdio/findfp.c
index 4b71afb69cb..b89ff4ab5d0 100644
--- a/lib/libc/stdio/findfp.c
+++ b/lib/libc/stdio/findfp.c
@@ -1,4 +1,4 @@
-/* $NetBSD: findfp.c,v 1.27 2012/03/15 18:22:30 christos Exp $ */
+/* $NetBSD: findfp.c,v 1.28 2012/03/27 15:05:42 christos Exp $ */
/*-
* Copyright (c) 1990, 1993
@@ -37,7 +37,7 @@
#if 0
static char sccsid[] = "@(#)findfp.c 8.2 (Berkeley) 1/4/94";
#else
-__RCSID("$NetBSD: findfp.c,v 1.27 2012/03/15 18:22:30 christos Exp $");
+__RCSID("$NetBSD: findfp.c,v 1.28 2012/03/27 15:05:42 christos Exp $");
#endif
#endif /* LIBC_SCCS and not lint */
@@ -56,13 +56,29 @@ int __sdidinit;
#define NDYNAMIC 10 /* add ten more whenever necessary */
-#define std(flags, file) \
-/* p r w flags file bf lfbsize cookie close */ \
- { NULL, 0, 0, flags, file, { NULL, 0 }, 0, __sF + file, __sclose, \
-/* read seek write ext up */ \
- __sread, __sseek, __swrite, { (void *)(__sFext + file), 0 }, NULL, \
-/* ur ubuf, nbuf lb blksize offset */ \
- 0, { '\0', '\0', '\0' }, { '\0' }, { NULL, 0 }, 0, (off_t)0 }
+#define std(flags, file) { \
+ ._p = NULL, \
+ ._r = 0, \
+ ._w = 0, \
+ ._flags = (flags), \
+ ._file = (file), \
+ ._bf = { ._base = NULL, ._size = 0 }, \
+ ._lbfsize = 0, \
+ ._cookie = __sF + (file), \
+ ._close = __sclose, \
+ ._read = __sread, \
+ ._seek = __sseek, \
+ ._write = __swrite, \
+ ._ext = { ._base = (void *)(__sFext + (file)), ._size = 0 }, \
+ ._up = NULL, \
+ ._ur = 0, \
+ ._ubuf = { [0] = '\0', [1] = '\0', [2] = '\0' }, \
+ ._nbuf = { [0] = '\0' }, \
+ ._flush = NULL, \
+ ._lb_unused = { '\0' }, \
+ ._blksize = 0, \
+ ._offset = (off_t)0, \
+}
/* the usual - (stdin + stdout + stderr) */
static FILE usual[FOPEN_MAX - 3];
@@ -99,8 +115,8 @@ moreglue(int n)
struct __sfileext *pext;
static FILE empty;
- g = (struct glue *)malloc(sizeof(*g) + ALIGNBYTES + n * sizeof(FILE)
- + n * sizeof(struct __sfileext));
+ g = malloc(sizeof(*g) + ALIGNBYTES + n * sizeof(FILE)
+ + n * sizeof(struct __sfileext));
if (g == NULL)
return NULL;
p = (FILE *)ALIGN((u_long)(g + 1));
@@ -129,6 +145,7 @@ __sfpinit(FILE *fp)
fp->_lbfsize = 0; /* not line buffered */
fp->_file = -1; /* no file */
/* fp->_cookie = <any>; */ /* caller sets cookie, _read/_write etc */
+ fp->_flush = NULL; /* default flush */
_UB(fp)._base = NULL; /* no ungetc buffer */
_UB(fp)._size = 0;
memset(WCIO_GET(fp), 0, sizeof(struct wchar_io_data));
diff --git a/lib/libc/stdio/fmemopen.c b/lib/libc/stdio/fmemopen.c
index 5daa8e5647c..9720c930b14 100644
--- a/lib/libc/stdio/fmemopen.c
+++ b/lib/libc/stdio/fmemopen.c
@@ -1,4 +1,4 @@
-/* $NetBSD: fmemopen.c,v 1.6 2012/01/22 18:36:17 christos Exp $ */
+/* $NetBSD: fmemopen.c,v 1.7 2012/03/27 15:05:42 christos Exp $ */
/*-
* Copyright (c)2007, 2010 Takehiko NOZAKI,
@@ -29,7 +29,7 @@
#include <sys/cdefs.h>
#if defined(LIBC_SCCS) && !defined(lint)
-__RCSID("$NetBSD: fmemopen.c,v 1.6 2012/01/22 18:36:17 christos Exp $");
+__RCSID("$NetBSD: fmemopen.c,v 1.7 2012/03/27 15:05:42 christos Exp $");
#endif /* LIBC_SCCS and not lint */
#include <assert.h>
@@ -46,11 +46,11 @@ struct fmemopen_cookie {
char *head, *tail, *cur, *eob;
};
-static int
-fmemopen_read(void *cookie, char *buf, int nbytes)
+static ssize_t
+fmemopen_read(void *cookie, void *buf, size_t nbytes)
{
struct fmemopen_cookie *p;
- char *s;
+ char *s, *b = buf;
_DIAGASSERT(cookie != NULL);
_DIAGASSERT(buf != NULL && nbytes > 0);
@@ -60,17 +60,18 @@ fmemopen_read(void *cookie, char *buf, int nbytes)
do {
if (p->cur == p->tail)
break;
- *buf++ = *p->cur++;
+ *b++ = *p->cur++;
} while (--nbytes > 0);
- return (int)(p->cur - s);
+ return (ssize_t)(p->cur - s);
}
-static int
-fmemopen_write(void *cookie, const char *buf, int nbytes)
+static ssize_t
+fmemopen_write(void *cookie, const void *buf, size_t nbytes)
{
struct fmemopen_cookie *p;
char *s;
+ const char *b = buf;
_DIAGASSERT(cookie != NULL);
_DIAGASSERT(buf != NULL && nbytes > 0);
@@ -81,20 +82,34 @@ fmemopen_write(void *cookie, const char *buf, int nbytes)
s = p->cur;
do {
if (p->cur == p->tail - 1) {
- if (*buf == '\0') {
+ if (*b == '\0') {
*p->cur++ = '\0';
goto ok;
}
break;
}
- *p->cur++ = *buf++;
+ *p->cur++ = *b++;
} while (--nbytes > 0);
*p->cur = '\0';
ok:
if (p->cur > p->eob)
p->eob = p->cur;
- return (int)(p->cur - s);
+ return (ssize_t)(p->cur - s);
+}
+
+static int
+fmemopen_flush(void *cookie)
+{
+ struct fmemopen_cookie *p;
+
+ _DIAGASSERT(cookie != NULL);
+
+ p = (struct fmemopen_cookie *)cookie;
+ if (p->cur >= p->tail)
+ return -1;
+ *p->cur = '\0';
+ return 0;
}
static off_t
@@ -184,12 +199,12 @@ fmemopen(void * __restrict buf, size_t size, const char * __restrict mode)
goto release;
}
*cookie->head = '\0';
- fp->_close = &fmemopen_close1;
+ fp->_close = fmemopen_close1;
} else {
cookie->head = (char *)buf;
if (oflags & O_TRUNC)
*cookie->head = '\0';
- fp->_close = &fmemopen_close0;
+ fp->_close = fmemopen_close0;
}
cookie->tail = cookie->head + size;
@@ -203,9 +218,10 @@ fmemopen(void * __restrict buf, size_t size, const char * __restrict mode)
cookie->cur = (oflags & O_APPEND) ? cookie->eob : cookie->head;
fp->_flags = flags;
- fp->_write = (flags & __SRD) ? NULL : &fmemopen_write;
- fp->_read = (flags & __SWR) ? NULL : &fmemopen_read;
- fp->_seek = &fmemopen_seek;
+ fp->_write = (flags & __SRD) ? NULL : fmemopen_write;
+ fp->_read = (flags & __SWR) ? NULL : fmemopen_read;
+ fp->_seek = fmemopen_seek;
+ fp->_flush = fmemopen_flush;
fp->_cookie = (void *)cookie;
return fp;
diff --git a/lib/libc/stdio/freopen.c b/lib/libc/stdio/freopen.c
index 2e090cfc183..f83f51aad9d 100644
--- a/lib/libc/stdio/freopen.c
+++ b/lib/libc/stdio/freopen.c
@@ -1,4 +1,4 @@
-/* $NetBSD: freopen.c,v 1.18 2012/03/15 18:22:30 christos Exp $ */
+/* $NetBSD: freopen.c,v 1.19 2012/03/27 15:05:42 christos Exp $ */
/*-
* Copyright (c) 1990, 1993
@@ -37,7 +37,7 @@
#if 0
static char sccsid[] = "@(#)freopen.c 8.1 (Berkeley) 6/4/93";
#else
-__RCSID("$NetBSD: freopen.c,v 1.18 2012/03/15 18:22:30 christos Exp $");
+__RCSID("$NetBSD: freopen.c,v 1.19 2012/03/27 15:05:42 christos Exp $");
#endif
#endif /* LIBC_SCCS and not lint */
@@ -93,7 +93,7 @@ freopen(const char *file, const char *mode, FILE *fp)
} else {
/* flush the stream; ANSI doesn't require this. */
if (fp->_flags & __SWR)
- (void) __sflush(fp);
+ (void)__sflush(fp);
/* if close is NULL, closing is a no-op, hence pointless */
isopen = fp->_close != NULL;
if ((wantfd = __sfileno(fp)) == -1 && isopen) {
diff --git a/lib/libc/stdio/fseeko.c b/lib/libc/stdio/fseeko.c
index 7ba016c08a4..ebeeaecdf15 100644
--- a/lib/libc/stdio/fseeko.c
+++ b/lib/libc/stdio/fseeko.c
@@ -1,4 +1,4 @@
-/* $NetBSD: fseeko.c,v 1.11 2012/03/15 18:22:30 christos Exp $ */
+/* $NetBSD: fseeko.c,v 1.12 2012/03/27 15:05:42 christos Exp $ */
/*-
* Copyright (c) 1990, 1993
@@ -34,7 +34,7 @@
#include <sys/cdefs.h>
#if defined(LIBC_SCCS) && !defined(lint)
-__RCSID("$NetBSD: fseeko.c,v 1.11 2012/03/15 18:22:30 christos Exp $");
+__RCSID("$NetBSD: fseeko.c,v 1.12 2012/03/27 15:05:42 christos Exp $");
#endif /* LIBC_SCCS and not lint */
#include "namespace.h"
@@ -97,7 +97,7 @@ fseeko(FILE *fp, off_t offset, int whence)
* we have to first find the current stream offset a la
* ftell (see ftell for details).
*/
- __sflush(fp); /* may adjust seek offset on append stream */
+ (void)__sflush(fp); /* may adjust seek offset on append stream */
if (fp->_flags & __SOFF)
curoff = fp->_offset;
else {
diff --git a/lib/libc/stdio/ftell.c b/lib/libc/stdio/ftell.c
index 1fd6e16c4b5..3e545f93855 100644
--- a/lib/libc/stdio/ftell.c
+++ b/lib/libc/stdio/ftell.c
@@ -1,4 +1,4 @@
-/* $NetBSD: ftell.c,v 1.19 2012/03/15 18:22:30 christos Exp $ */
+/* $NetBSD: ftell.c,v 1.20 2012/03/27 15:05:42 christos Exp $ */
/*-
* Copyright (c) 1990, 1993
@@ -37,7 +37,7 @@
#if 0
static char sccsid[] = "@(#)ftell.c 8.2 (Berkeley) 5/4/95";
#else
-__RCSID("$NetBSD: ftell.c,v 1.19 2012/03/15 18:22:30 christos Exp $");
+__RCSID("$NetBSD: ftell.c,v 1.20 2012/03/27 15:05:42 christos Exp $");
#endif
#endif /* LIBC_SCCS and not lint */
@@ -68,7 +68,7 @@ ftell(FILE *fp)
* Find offset of underlying I/O object, then
* adjust for buffered bytes.
*/
- __sflush(fp); /* may adjust seek offset on append stream */
+ (void)__sflush(fp); /* may adjust seek offset on append stream */
if (fp->_flags & __SOFF)
pos = fp->_offset;
else {
diff --git a/lib/libc/stdio/ftello.c b/lib/libc/stdio/ftello.c
index 3a5e6569c58..07578098fa9 100644
--- a/lib/libc/stdio/ftello.c
+++ b/lib/libc/stdio/ftello.c
@@ -1,4 +1,4 @@
-/* $NetBSD: ftello.c,v 1.6 2012/03/15 18:22:30 christos Exp $ */
+/* $NetBSD: ftello.c,v 1.7 2012/03/27 15:05:42 christos Exp $ */
/*-
* Copyright (c) 1990, 1993
@@ -34,7 +34,7 @@
#include <sys/cdefs.h>
#if defined(LIBC_SCCS) && !defined(lint)
-__RCSID("$NetBSD: ftello.c,v 1.6 2012/03/15 18:22:30 christos Exp $");
+__RCSID("$NetBSD: ftello.c,v 1.7 2012/03/27 15:05:42 christos Exp $");
#endif /* LIBC_SCCS and not lint */
#include "namespace.h"
@@ -69,7 +69,7 @@ ftello(FILE *fp)
* Find offset of underlying I/O object, then
* adjust for buffered bytes.
*/
- __sflush(fp); /* may adjust seek offset on append stream */
+ (void)__sflush(fp); /* may adjust seek offset on append stream */
if (fp->_flags & __SOFF)
pos = fp->_offset;
else {
diff --git a/lib/libc/stdio/funopen.3 b/lib/libc/stdio/funopen.3
index 57fd7c31d5a..1025b1e19a1 100644
--- a/lib/libc/stdio/funopen.3
+++ b/lib/libc/stdio/funopen.3
@@ -1,4 +1,4 @@
-.\" $NetBSD: funopen.3,v 1.18 2012/01/22 19:13:48 wiz Exp $
+.\" $NetBSD: funopen.3,v 1.19 2012/03/27 15:05:42 christos Exp $
.\"
.\" Copyright (c) 1990, 1991, 1993
.\" The Regents of the University of California. All rights reserved.
@@ -31,13 +31,16 @@
.\"
.\" @(#)funopen.3 8.1 (Berkeley) 6/9/93
.\"
-.Dd January 22, 2012
+.Dd March 16, 2012
.Dt FUNOPEN 3
.Os
.Sh NAME
.Nm funopen ,
+.Nm funopen2 ,
.Nm fropen ,
-.Nm fwopen
+.Nm fropen2 ,
+.Nm fwopen ,
+.Nm fwopen2
.Nd open a stream
.Sh LIBRARY
.Lb libc
@@ -45,10 +48,15 @@
.In stdio.h
.Ft FILE *
.Fn funopen "void *cookie" "int (*readfn)(void *, char *, int)" "int (*writefn)(void *, const char *, int)" "off_t (*seekfn)(void *, off_t, int)" "int (*closefn)(void *)"
+.Fn funopen2 "void *cookie" "ssize_t (*readfn)(void *, void *, size_t)" "ssize_t (*writefn)(void *, const void *, size_t)" "off_t (*seekfn)(void *, off_t, int)" "int (*flushfn)(void *)" "int (*closefn)(void *)"
.Ft FILE *
.Fn fropen "void *cookie" "int (*readfn)(void *, char *, int)"
.Ft FILE *
+.Fn fropen2 "void *cookie" "ssize_t (*readfn)(void *, void *, size_t)"
+.Ft FILE *
.Fn fwopen "void *cookie" "int (*writefn)(void *, const char *, int)"
+.Ft FILE *
+.Fn fwopen2 "void *cookie" "ssize_t (*writefn)(void *, const void *, size_t)"
.Sh DESCRIPTION
The
.Fn funopen
@@ -68,6 +76,14 @@ These
functions will be used to read, write, seek and
close the new stream.
.Pp
+The
+.Fn funopen2
+function provides sightly different read and write signatures, which match
+better the corresponding system calls, plus the ability to augment the
+streams default flushing function.
+If a flushing function is provided, then it is called after all data has
+been written to the stream.
+.Pp
In general, omitting a function means that any attempt to perform the
associated operation on the resulting stream will fail.
If the close function is omitted, closing the stream will flush
@@ -161,6 +177,10 @@ The
.Fn funopen
functions first appeared in
.Bx 4.4 .
+.The
+.Fn funopen2
+functions first appeared in
+.Nx 7 .
.Sh CAVEATS
All three functions are specific to
.Nx
diff --git a/lib/libc/stdio/funopen.c b/lib/libc/stdio/funopen.c
index a15d4a5aee1..06224e4607f 100644
--- a/lib/libc/stdio/funopen.c
+++ b/lib/libc/stdio/funopen.c
@@ -1,4 +1,4 @@
-/* $NetBSD: funopen.c,v 1.12 2012/03/15 18:22:30 christos Exp $ */
+/* $NetBSD: funopen.c,v 1.13 2012/03/27 15:05:42 christos Exp $ */
/*-
* Copyright (c) 1990, 1993
@@ -37,20 +37,23 @@
#if 0
static char sccsid[] = "@(#)funopen.c 8.1 (Berkeley) 6/4/93";
#else
-__RCSID("$NetBSD: funopen.c,v 1.12 2012/03/15 18:22:30 christos Exp $");
+__RCSID("$NetBSD: funopen.c,v 1.13 2012/03/27 15:05:42 christos Exp $");
#endif
#endif /* LIBC_SCCS and not lint */
#include <stdio.h>
#include <errno.h>
+#include <stdlib.h>
+#include <stddef.h>
#include "reentrant.h"
#include "local.h"
FILE *
-funopen(const void *cookie,
- int (*readfn)(void *, char *, int),
- int (*writefn)(void *, const char *, int),
+funopen2(const void *cookie,
+ ssize_t (*readfn)(void *, void *, size_t),
+ ssize_t (*writefn)(void *, const void *, size_t),
off_t (*seekfn)(void *, off_t, int),
+ int (*flushfn)(void *),
int (*closefn)(void *))
{
FILE *fp;
@@ -76,6 +79,89 @@ funopen(const void *cookie,
fp->_read = readfn;
fp->_write = writefn;
fp->_seek = seekfn;
+ fp->_flush = flushfn;
fp->_close = closefn;
return fp;
}
+
+typedef struct {
+ void *cookie;
+ int (*readfn)(void *, char *, int);
+ int (*writefn)(void *, const char *, int);
+ off_t (*seekfn)(void *, off_t, int);
+ int (*closefn)(void *);
+} dookie_t;
+
+static ssize_t
+creadfn(void *dookie, void *buf, size_t len)
+{
+ dookie_t *d = dookie;
+ if (len > INT_MAX)
+ len = INT_MAX;
+ return (*d->readfn)(d->cookie, buf, (int)len);
+}
+
+static ssize_t
+cwritefn(void *dookie, const void *buf, size_t len)
+{
+ dookie_t *d = dookie;
+ ssize_t nr;
+ size_t l = len;
+ const char *b = buf;
+
+ while (l) {
+ size_t nw = l > INT_MAX ? INT_MAX : l;
+ nr = (*d->writefn)(d->cookie, buf, (int)nw);
+ if (nr == -1) {
+ if (len == l)
+ return -1;
+ else
+ return len - l;
+ }
+ b += nr;
+ l -= nr;
+ }
+ return len;
+}
+
+static off_t
+cseekfn(void *dookie, off_t off, int whence)
+{
+ dookie_t *d = dookie;
+ return (*d->seekfn)(d->cookie, off, whence);
+}
+
+static int
+cclosefn(void *dookie)
+{
+ dookie_t *d = dookie;
+ void *c = d->cookie;
+ int (*cf)(void *) = d->closefn;
+ free(dookie);
+ return (*cf)(c);
+}
+
+FILE *
+funopen(const void *cookie,
+ int (*readfn)(void *, char *, int),
+ int (*writefn)(void *, const char *, int),
+ off_t (*seekfn)(void *, off_t, int),
+ int (*closefn)(void *))
+{
+ dookie_t *d;
+ FILE *fp;
+
+ if ((d = malloc(sizeof(*d))) == NULL)
+ return NULL;
+
+ d->cookie = __UNCONST(cookie);
+ d->readfn = readfn;
+ d->writefn = writefn;
+ d->seekfn = seekfn;
+ d->closefn = closefn;
+ fp = funopen2(d, creadfn, cwritefn, cseekfn, NULL, cclosefn);
+ if (fp != NULL)
+ return fp;
+ free(d);
+ return NULL;
+ }
diff --git a/lib/libc/stdio/fvwrite.c b/lib/libc/stdio/fvwrite.c
index 6e31e781186..a2619ac3d0c 100644
--- a/lib/libc/stdio/fvwrite.c
+++ b/lib/libc/stdio/fvwrite.c
@@ -1,4 +1,4 @@
-/* $NetBSD: fvwrite.c,v 1.24 2012/03/15 18:22:30 christos Exp $ */
+/* $NetBSD: fvwrite.c,v 1.25 2012/03/27 15:05:42 christos Exp $ */
/*-
* Copyright (c) 1990, 1993
@@ -37,7 +37,7 @@
#if 0
static char sccsid[] = "@(#)fvwrite.c 8.1 (Berkeley) 6/4/93";
#else
-__RCSID("$NetBSD: fvwrite.c,v 1.24 2012/03/15 18:22:30 christos Exp $");
+__RCSID("$NetBSD: fvwrite.c,v 1.25 2012/03/27 15:05:42 christos Exp $");
#endif
#endif /* LIBC_SCCS and not lint */
@@ -63,14 +63,15 @@ __sfvwrite(FILE *fp, struct __suio *uio)
size_t len;
char *p;
struct __siov *iov;
- int w, s;
+ int s;
+ ssize_t w;
char *nl;
size_t nlknown, nldist;
_DIAGASSERT(fp != NULL);
_DIAGASSERT(uio != NULL);
- if ((int)uio->uio_resid < 0) {
+ if ((ssize_t)uio->uio_resid < 0) {
errno = EINVAL;
return EOF;
}
@@ -102,8 +103,7 @@ __sfvwrite(FILE *fp, struct __suio *uio)
*/
do {
GETIOV(;);
- w = (*fp->_write)(fp->_cookie, p,
- (int)MIN(len, BUFSIZ));
+ w = (*fp->_write)(fp->_cookie, p, MIN(len, BUFSIZ));
if (w <= 0)
goto err;
p += w;
@@ -146,11 +146,11 @@ __sfvwrite(FILE *fp, struct __suio *uio)
w = fp->_w;
if (fp->_flags & __SSTR) {
if (len < (size_t)w)
- w = (int)len;
+ w = len;
COPY(w); /* copy MIN(fp->_w,len), */
- fp->_w -= w;
+ fp->_w -= (int)w;
fp->_p += w;
- w = (int)len; /* but pretend copied all */
+ w = len; /* but pretend copied all */
} else if (fp->_p > fp->_bf._base && len > (size_t)w) {
/* fill and flush */
COPY(w);
@@ -160,14 +160,14 @@ __sfvwrite(FILE *fp, struct __suio *uio)
goto err;
} else if (len >= (size_t)(w = fp->_bf._size)) {
/* write directly */
- w = (*fp->_write)(fp->_cookie, p, w);
+ w = (*fp->_write)(fp->_cookie, p, (size_t)w);
if (w <= 0)
goto err;
} else {
/* fill and done */
- w = (int)len;
+ w = len;
COPY(w);
- fp->_w -= w;
+ fp->_w -= (int)w;
fp->_p += w;
}
p += w;
@@ -199,13 +199,13 @@ __sfvwrite(FILE *fp, struct __suio *uio)
if (fflush(fp))
goto err;
} else if (s >= (w = fp->_bf._size)) {
- w = (*fp->_write)(fp->_cookie, p, w);
+ w = (*fp->_write)(fp->_cookie, p, (size_t)w);
if (w <= 0)
goto err;
} else {
w = s;
COPY(w);
- fp->_w -= w;
+ fp->_w -= (int)w;
fp->_p += w;
}
if ((nldist -= w) == 0) {
diff --git a/lib/libc/stdio/local.h b/lib/libc/stdio/local.h
index ef024ecccb2..42cd30fd01c 100644
--- a/lib/libc/stdio/local.h
+++ b/lib/libc/stdio/local.h
@@ -1,4 +1,4 @@
-/* $NetBSD: local.h,v 1.33 2012/03/15 13:23:10 christos Exp $ */
+/* $NetBSD: local.h,v 1.34 2012/03/27 15:05:42 christos Exp $ */
/*-
* Copyright (c) 1990, 1993
@@ -50,8 +50,8 @@ extern int __sflush(FILE *);
extern FILE *__sfp(void);
extern void __sfpinit(FILE *);
extern int __srefill(FILE *);
-extern int __sread(void *, char *, int);
-extern int __swrite(void *, char const *, int);
+extern ssize_t __sread(void *, void *, size_t);
+extern ssize_t __swrite(void *, const void *, size_t);
extern off_t __sseek(void *, off_t, int);
extern int __sclose(void *);
extern void __sinit(void);
diff --git a/lib/libc/stdio/refill.c b/lib/libc/stdio/refill.c
index b2335cb6a93..7988e7407ba 100644
--- a/lib/libc/stdio/refill.c
+++ b/lib/libc/stdio/refill.c
@@ -1,4 +1,4 @@
-/* $NetBSD: refill.c,v 1.15 2012/03/15 18:22:30 christos Exp $ */
+/* $NetBSD: refill.c,v 1.16 2012/03/27 15:05:42 christos Exp $ */
/*-
* Copyright (c) 1990, 1993
@@ -37,7 +37,7 @@
#if 0
static char sccsid[] = "@(#)refill.c 8.1 (Berkeley) 6/4/93";
#else
-__RCSID("$NetBSD: refill.c,v 1.15 2012/03/15 18:22:30 christos Exp $");
+__RCSID("$NetBSD: refill.c,v 1.16 2012/03/27 15:05:42 christos Exp $");
#endif
#endif /* LIBC_SCCS and not lint */
@@ -129,7 +129,8 @@ __srefill(FILE *fp)
rwlock_unlock(&__sfp_lock);
}
fp->_p = fp->_bf._base;
- fp->_r = (*fp->_read)(fp->_cookie, (char *)fp->_p, fp->_bf._size);
+ fp->_r = (int)(*fp->_read)(fp->_cookie, (char *)fp->_p,
+ (size_t)fp->_bf._size);
fp->_flags &= ~__SMOD; /* buffer contents are again pristine */
if (fp->_r <= 0) {
if (fp->_r == 0)
diff --git a/lib/libc/stdio/sscanf.c b/lib/libc/stdio/sscanf.c
index 629cb813fa4..fe339c99b7b 100644
--- a/lib/libc/stdio/sscanf.c
+++ b/lib/libc/stdio/sscanf.c
@@ -1,4 +1,4 @@
-/* $NetBSD: sscanf.c,v 1.19 2012/03/15 18:22:30 christos Exp $ */
+/* $NetBSD: sscanf.c,v 1.20 2012/03/27 15:05:42 christos Exp $ */
/*-
* Copyright (c) 1990, 1993
@@ -37,7 +37,7 @@
#if 0
static char sccsid[] = "@(#)sscanf.c 8.1 (Berkeley) 6/4/93";
#else
-__RCSID("$NetBSD: sscanf.c,v 1.19 2012/03/15 18:22:30 christos Exp $");
+__RCSID("$NetBSD: sscanf.c,v 1.20 2012/03/27 15:05:42 christos Exp $");
#endif
#endif /* LIBC_SCCS and not lint */
@@ -51,8 +51,8 @@ __RCSID("$NetBSD: sscanf.c,v 1.19 2012/03/15 18:22:30 christos Exp $");
#include "local.h"
/* ARGSUSED */
-static int
-eofread(void *cookie, char *buf, int len)
+static ssize_t
+eofread(void *cookie, void *buf, size_t len)
{
return 0;
diff --git a/lib/libc/stdio/stdio.c b/lib/libc/stdio/stdio.c
index 72a0a0bde3d..bf5bb095bbc 100644
--- a/lib/libc/stdio/stdio.c
+++ b/lib/libc/stdio/stdio.c
@@ -1,4 +1,4 @@
-/* $NetBSD: stdio.c,v 1.20 2012/03/20 01:42:59 christos Exp $ */
+/* $NetBSD: stdio.c,v 1.21 2012/03/27 15:05:42 christos Exp $ */
/*-
* Copyright (c) 1990, 1993
@@ -37,7 +37,7 @@
#if 0
static char sccsid[] = "@(#)stdio.c 8.1 (Berkeley) 6/4/93";
#else
-__RCSID("$NetBSD: stdio.c,v 1.20 2012/03/20 01:42:59 christos Exp $");
+__RCSID("$NetBSD: stdio.c,v 1.21 2012/03/27 15:05:42 christos Exp $");
#endif
#endif /* LIBC_SCCS and not lint */
@@ -56,37 +56,40 @@ __RCSID("$NetBSD: stdio.c,v 1.20 2012/03/20 01:42:59 christos Exp $");
* Small standard I/O/seek/close functions.
* These maintain the `known seek offset' for seek optimisation.
*/
-int
-__sread(void *cookie, char *buf, int n)
+ssize_t
+__sread(void *cookie, void *buf, size_t n)
{
FILE *fp = cookie;
ssize_t ret;
- _DIAGASSERT(fp != NULL);
+ _DIAGASSERT(cookie != NULL);
+ _DIAGASSERT(cookie == fp->_cookie);
_DIAGASSERT(buf != NULL);
- ret = read(__sfileno(fp), buf, (size_t)n);
+ ret = read(__sfileno(fp), buf, n);
/* if the read succeeded, update the current offset */
if (ret >= 0)
fp->_offset += ret;
else
fp->_flags &= ~__SOFF; /* paranoia */
- return (int)ret;
+ return ret;
}
-int
-__swrite(void *cookie, char const *buf, int n)
+ssize_t
+__swrite(void *cookie, const void *buf, size_t n)
{
FILE *fp = cookie;
_DIAGASSERT(cookie != NULL);
+ _DIAGASSERT(cookie == fp->_cookie);
_DIAGASSERT(buf != NULL);
if (fp->_flags & __SAPP)
- (void) lseek(__sfileno(fp), (off_t)0, SEEK_END);
+ if (lseek(__sfileno(fp), (off_t)0, SEEK_END) == (off_t)-1)
+ return -1;
fp->_flags &= ~__SOFF; /* in case FAPPEND mode is set */
- return (int)write(__sfileno(fp), buf, (size_t)n);
+ return write(__sfileno(fp), buf, n);
}
off_t
@@ -95,10 +98,11 @@ __sseek(void *cookie, off_t offset, int whence)
FILE *fp = cookie;
off_t ret;
- _DIAGASSERT(fp != NULL);
+ _DIAGASSERT(cookie != NULL);
+ _DIAGASSERT(cookie == fp->_cookie);
ret = lseek(__sfileno(fp), offset, whence);
- if (ret == -1L)
+ if (ret == (off_t)-1L)
fp->_flags &= ~__SOFF;
else {
fp->_flags |= __SOFF;
@@ -110,8 +114,10 @@ __sseek(void *cookie, off_t offset, int whence)
int
__sclose(void *cookie)
{
+ FILE *fp = cookie;
_DIAGASSERT(cookie != NULL);
+ _DIAGASSERT(cookie == fp->_cookie);
- return close(__sfileno((FILE *)cookie));
+ return close(__sfileno(fp));
}
diff --git a/lib/libc/stdio/vfwprintf.c b/lib/libc/stdio/vfwprintf.c
index 6e997a27757..e814253c0fd 100644
--- a/lib/libc/stdio/vfwprintf.c
+++ b/lib/libc/stdio/vfwprintf.c
@@ -1,4 +1,4 @@
-/* $NetBSD: vfwprintf.c,v 1.29 2012/03/21 14:20:47 christos Exp $ */
+/* $NetBSD: vfwprintf.c,v 1.30 2012/03/27 15:05:42 christos Exp $ */
/*-
* Copyright (c) 1990, 1993
@@ -38,7 +38,7 @@
static char sccsid[] = "@(#)vfprintf.c 8.1 (Berkeley) 6/4/93";
__FBSDID("$FreeBSD: src/lib/libc/stdio/vfwprintf.c,v 1.27 2007/01/09 00:28:08 imp Exp $");
#else
-__RCSID("$NetBSD: vfwprintf.c,v 1.29 2012/03/21 14:20:47 christos Exp $");
+__RCSID("$NetBSD: vfwprintf.c,v 1.30 2012/03/27 15:05:42 christos Exp $");
#endif
#endif /* LIBC_SCCS and not lint */
@@ -170,6 +170,7 @@ __sbprintf(FILE *fp, const CHAR_T *fmt, va_list ap)
fake._file = fp->_file;
fake._cookie = fp->_cookie;
fake._write = fp->_write;
+ fake._flush = fp->_flush;
/* set up the buffer */
fake._bf._base = fake._p = buf;
diff --git a/lib/libc/stdio/vsscanf.c b/lib/libc/stdio/vsscanf.c
index ae58b905347..9fb68a0acf3 100644
--- a/lib/libc/stdio/vsscanf.c
+++ b/lib/libc/stdio/vsscanf.c
@@ -1,4 +1,4 @@
-/* $NetBSD: vsscanf.c,v 1.18 2012/03/15 18:22:31 christos Exp $ */
+/* $NetBSD: vsscanf.c,v 1.19 2012/03/27 15:05:42 christos Exp $ */
/*-
* Copyright (c) 1990, 1993
@@ -37,7 +37,7 @@
#if 0
static char sccsid[] = "@(#)vsscanf.c 8.1 (Berkeley) 6/4/93";
#else
-__RCSID("$NetBSD: vsscanf.c,v 1.18 2012/03/15 18:22:31 christos Exp $");
+__RCSID("$NetBSD: vsscanf.c,v 1.19 2012/03/27 15:05:42 christos Exp $");
#endif
#endif /* LIBC_SCCS and not lint */
@@ -49,8 +49,8 @@ __RCSID("$NetBSD: vsscanf.c,v 1.18 2012/03/15 18:22:31 christos Exp $");
#include "local.h"
/* ARGSUSED */
-static int
-eofread(void *cookie, char *buf, int len)
+static ssize_t
+eofread(void *cookie, void *buf, size_t len)
{
return 0;
}
diff --git a/lib/libc/stdio/vswscanf.c b/lib/libc/stdio/vswscanf.c
index ed184add340..cb295e62c94 100644
--- a/lib/libc/stdio/vswscanf.c
+++ b/lib/libc/stdio/vswscanf.c
@@ -1,4 +1,4 @@
-/* $NetBSD: vswscanf.c,v 1.8 2012/03/15 18:22:31 christos Exp $ */
+/* $NetBSD: vswscanf.c,v 1.9 2012/03/27 15:05:42 christos Exp $ */
/*-
* Copyright (c) 1990, 1993
@@ -42,7 +42,7 @@
static char sccsid[] = "@(#)vsscanf.c 8.1 (Berkeley) 6/4/93";
__FBSDID("$FreeBSD: src/lib/libc/stdio/vswscanf.c,v 1.3 2004/04/07 09:55:05 tjr Exp $");
#else
-__RCSID("$NetBSD: vswscanf.c,v 1.8 2012/03/15 18:22:31 christos Exp $");
+__RCSID("$NetBSD: vswscanf.c,v 1.9 2012/03/27 15:05:42 christos Exp $");
#endif
#endif /* LIBC_SCCS and not lint */
@@ -56,9 +56,9 @@ __RCSID("$NetBSD: vswscanf.c,v 1.8 2012/03/15 18:22:31 christos Exp $");
#include "reentrant.h"
#include "local.h"
-static int
+static ssize_t
/*ARGSUSED*/
-eofread(void *cookie, char *buf, int len)
+eofread(void *cookie, void *buf, size_t len)
{
return 0;