implement funopen, fopencookie

Jeff Johnston jjohnstn@redhat.com
Thu May 31 23:23:00 GMT 2007


Eric, ok, assuming you have built and tested this patch for cygwin (I 
verified it for x86-linux).  One small change requested.  The 
declaration of funopen should use double-underscored argument names 
(e.g. __readfn instead of readfn).  The same goes for the fropen and 
fwopen macros; the argument names should be double-underscored.  I 
realize this was done long prior to your change, but please rectify this 
when you check in your patch.

-- Jeff J.

Eric Blake wrote:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
>
> This patch does a couple of things.  First, it fixes some reentrancy
> issues in stdio - before this patch, when one of the callback functions
> failed, it set only the global errno, rather than the explicit struct
> _reent->_errno field.  Note that fflush still has problems in this
> regards, and I still think that it is worth writing _fflush_r for the very
> reason that fflush can trigger the setting of errno, but I did not do it
> here because this patch was already getting big.
>
> Second, it adds two new functions, funopen from the BSD world, and
> fopencookie from the Linux world.  The two functions are identical in
> purpose, but different in signature, with a goal of letting a user specify
> custom callback routines.  With this interface in place, it becomes a much
> easier job to implement fmemopen (a FILE wrapper around a fixed-length
> string) and open_memstream (a FILE wrapper around a malloc'd, autogrowing
> string), two new functions that are slated for addition in the next
> revision of POSIX.  When either of these two interfaces is available, GNU
> autogen will use them for performance reasons (preference is given to
> fopencookie, because it allows a mode argument; to see it in action, look
> at
> http://cvs.savannah.gnu.org/viewvc/autogen/agen5/fmemopen.c?revision=4.13&root=autogen&view=markup).
>
> For platforms with large files, I intentionally did not write funopen vs.
> funopen64; rather, I tried to implement funopen so that it always handles
> large offsets.  Likewise for fopencookie.
>
> OK to apply?
>
> 2007-05-16  Eric Blake  <ebb9@byu.net>
>
> 	* libc/include/sys/reent.h (struct __sFILE, struct __sFILE64):
> 	Switch to reentrant callbacks.
> 	* libc/stdio/local.h (__sread, __swrite, __sseek, __sclose)
> 	(__sseek64, __swrite64): Fix prototypes.
> 	* libc/stdio/stdio.c (__sread, __swrite, __sseek, __sclose): Fix
> 	reentrancy.
> 	* libc/stdio64/stdio64.c (__sseek64_r, __swrite64_r): Delete.
> 	(__sseek64, __swrite64): Fix reentrancy.
> 	* libc/stdio/ftell.c (_ftell_r): Account for overflow, and fix
> 	reentrancy.
> 	* libc/stdio/fseek.c (_fseek_r): Likewise.
> 	* libc/stdio/fclose.c (_fclose_r): Fix reentrancy.
> 	* libc/stdio/freopen.c (_freopen_r): Likewise.
> 	* libc/stdio/fvwrite.c (__sfvwrite_r): Likewise.
> 	* libc/stdio/refill.c (__srefill_r): Likewise.
> 	* libc/stdio/siscanf.c (eofread): Likewise.
> 	* libc/stdio/sscanf.c (eofread): Likewise.
> 	* libc/stdio/vsiscanf.c (eofread1): Likewise.
> 	* libc/stdio/vsscanf.c (eofread1): Likewise.
> 	* libc/stdio64/freopen64.c (_freopen64_r): Likewise.
> 	* libc/stdio64/fseeko64.c (_fseeko64_r): Likewise.
> 	* libc/stdio64/ftello64.c (_ftello64_r): Likewise.
> 	* libc/stdio/fflush.c (fflush): Improve reentrancy, although more
> 	could be fixed.
> 	* libc/include/stdio.h (funopen): Fix declaration.
> 	(fopencookie): Declare.
> 	* libc/stdio/fopencookie.c (_fopencookie_r, fopencookie): New
> 	file.
> 	* libc/stdio/funopen.c (_funopen_r, funopen): New file.
> 	* libc/stdio/Makefile.am (ELIX_4_SOURCES, CHEWOUT_FILES): Build
> 	new files.
> 	* libc/stdio/Makefile: Regenerate.
>
> - --
> Don't work too hard, make some time for fun as well!
>
> Eric Blake             ebb9@byu.net
> -----BEGIN PGP SIGNATURE-----
> Version: GnuPG v1.4.5 (Cygwin)
> Comment: Public key at home.comcast.net/~ericblake/eblake.gpg
> Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org
>
> iD8DBQFGSwVr84KuGfSFAYARAmydAKC6Z/pxDe1AbHqPRTSVOKToofYL4QCeM/Jj
> i9qWtMx54Ey1/e40GNpVhhM=
> =hkAj
> -----END PGP SIGNATURE-----
>   
> ------------------------------------------------------------------------
>
> Index: libc/include/stdio.h
> ===================================================================
> RCS file: /cvs/src/src/newlib/libc/include/stdio.h,v
> retrieving revision 1.45
> diff -u -p -r1.45 stdio.h
> --- libc/include/stdio.h	4 May 2007 02:55:16 -0000	1.45
> +++ libc/include/stdio.h	16 May 2007 12:51:52 -0000
> @@ -480,15 +480,43 @@ int	_EXFUN(__swbuf_r, (struct _reent *, 
>   */
>  
>  #ifndef __STRICT_ANSI__
> +# ifdef __LARGE64_FILES
> +FILE	*_EXFUN(funopen,(const _PTR _cookie,
> +		int (*readfn)(_PTR _cookie, char *_buf, int _n),
> +		int (*writefn)(_PTR _cookie, const char *_buf, int _n),
> +		_fpos64_t (*seekfn)(_PTR _cookie, _fpos64_t _off, int _whence),
> +		int (*closefn)(_PTR _cookie)));
> +# else
>  FILE	*_EXFUN(funopen,(const _PTR _cookie,
>  		int (*readfn)(_PTR _cookie, char *_buf, int _n),
>  		int (*writefn)(_PTR _cookie, const char *_buf, int _n),
>  		fpos_t (*seekfn)(_PTR _cookie, fpos_t _off, int _whence),
>  		int (*closefn)(_PTR _cookie)));
> +# endif /* !__LARGE64_FILES */
>  
>  #define	fropen(cookie, fn) funopen(cookie, fn, (int (*)())0, (fpos_t (*)())0, (int (*)())0)
>  #define	fwopen(cookie, fn) funopen(cookie, (int (*)())0, fn, (fpos_t (*)())0, (int (*)())0)
> -#endif
> +
> +typedef ssize_t cookie_read_function_t(void *_cookie, char *_buf, size_t _n);
> +typedef ssize_t cookie_write_function_t(void *_cookie, const char *_buf, size_t _n);
> +# ifdef __LARGE64_FILES
> +typedef int cookie_seek_function_t(void *_cookie, _off64_t *_off, int _whence);
> +# else
> +typedef int cookie_seek_function_t(void *_cookie, off_t *_off, int _whence);
> +# endif /* !__LARGE64_FILES */
> +typedef int cookie_close_function_t(void *_cookie);
> +typedef struct
> +{
> +  /* These four struct member names are dictated by Linux; hopefully,
> +     they don't conflict with any macros.  */
> +  cookie_read_function_t  *read;
> +  cookie_write_function_t *write;
> +  cookie_seek_function_t  *seek;
> +  cookie_close_function_t *close;
> +} cookie_io_functions_t;
> +FILE *_EXFUN(fopencookie,(void *_cookie, const char *_mode,
> +                          cookie_io_functions_t _functions));
> +#endif /* ! __STRICT_ANSI__ */
>  
>  #ifndef __CUSTOM_FILE_IO__
>  /*
> Index: libc/include/sys/reent.h
> ===================================================================
> RCS file: /cvs/src/src/newlib/libc/include/sys/reent.h,v
> retrieving revision 1.37
> diff -u -p -r1.37 reent.h
> --- libc/include/sys/reent.h	1 Feb 2007 16:33:05 -0000	1.37
> +++ libc/include/sys/reent.h	16 May 2007 12:51:52 -0000
> @@ -181,11 +181,13 @@ struct __sFILE {
>    /* operations */
>    _PTR	_cookie;	/* cookie passed to io functions */
>  
> -  _READ_WRITE_RETURN_TYPE _EXFUN((*_read),(_PTR _cookie, char *_buf, int _n));
> -  _READ_WRITE_RETURN_TYPE _EXFUN((*_write),(_PTR _cookie, const char *_buf,
> -					    int _n));
> -  _fpos_t _EXFUN((*_seek),(_PTR _cookie, _fpos_t _offset, int _whence));
> -  int	_EXFUN((*_close),(_PTR _cookie));
> +  _READ_WRITE_RETURN_TYPE _EXFUN((*_read),(struct _reent *_data, _PTR _cookie,
> +					   char *_buf, int _n));
> +  _READ_WRITE_RETURN_TYPE _EXFUN((*_write),(struct _reent *_data, _PTR _cookie,
> +					    const char *_buf, int _n));
> +  _fpos_t _EXFUN((*_seek),(struct _reent *_data, _PTR _cookie, _fpos_t _offset,
> +			   int _whence));
> +  int	_EXFUN((*_close),(struct _reent *_data, _PTR _cookie));
>  
>    /* separate buffer for long sequences of ungetc() */
>    struct __sbuf _ub;	/* ungetc buffer */
> @@ -233,11 +235,13 @@ struct __sFILE64 {
>    /* operations */
>    _PTR	_cookie;	/* cookie passed to io functions */
>  
> -  _READ_WRITE_RETURN_TYPE _EXFUN((*_read),(_PTR _cookie, char *_buf, int _n));
> -  _READ_WRITE_RETURN_TYPE _EXFUN((*_write),(_PTR _cookie, const char *_buf,
> -					    int _n));
> -  _fpos_t _EXFUN((*_seek),(_PTR _cookie, _fpos_t _offset, int _whence));
> -  int	_EXFUN((*_close),(_PTR _cookie));
> +  _READ_WRITE_RETURN_TYPE _EXFUN((*_read),(struct _reent *_data, _PTR _cookie,
> +					   char *_buf, int _n));
> +  _READ_WRITE_RETURN_TYPE _EXFUN((*_write),(struct _reent *_data, _PTR _cookie,
> +					    const char *_buf, int _n));
> +  _fpos_t _EXFUN((*_seek),(struct _reent *_data, _PTR _cookie, _fpos_t _offset,
> +			   int _whence));
> +  int	_EXFUN((*_close),(struct _reent *_data, _PTR _cookie));
>  
>    /* separate buffer for long sequences of ungetc() */
>    struct __sbuf _ub;	/* ungetc buffer */
> @@ -256,7 +260,8 @@ struct __sFILE64 {
>    int   _flags2;        /* for future use */
>  
>    _off64_t _offset;     /* current lseek offset */
> -  _fpos64_t _EXFUN((*_seek64),(_PTR _cookie, _fpos64_t _offset, int _whence));
> +  _fpos64_t _EXFUN((*_seek64),(struct _reent *_data, _PTR _cookie,
> +			       _fpos64_t _offset, int _whence));
>  
>  #ifndef __SINGLE_THREAD__
>    _flock_t _lock;	/* for thread-safety locking */
> Index: libc/stdio/Makefile.am
> ===================================================================
> RCS file: /cvs/src/src/newlib/libc/stdio/Makefile.am,v
> retrieving revision 1.24
> diff -u -p -r1.24 Makefile.am
> --- libc/stdio/Makefile.am	4 May 2007 02:55:16 -0000	1.24
> +++ libc/stdio/Makefile.am	16 May 2007 12:51:52 -0000
> @@ -117,6 +117,8 @@ ELIX_4_SOURCES = \
>  	asnprintf.c		\
>  	diprintf.c		\
>  	dprintf.c		\
> +	fopencookie.c		\
> +	funopen.c		\
>  	vasniprintf.c		\
>  	vasnprintf.c
>  endif !ELIX_LEVEL_3
> @@ -179,6 +181,7 @@ CHEWOUT_FILES = \
>  	fileno.def		\
>  	fiprintf.def		\
>  	fopen.def		\
> +	fopencookie.def		\
>  	fputc.def		\
>  	fputs.def		\
>  	fread.def		\
> @@ -186,6 +189,7 @@ CHEWOUT_FILES = \
>  	fseek.def		\
>  	fsetpos.def		\
>  	ftell.def		\
> +	funopen.def		\
>  	fwrite.def		\
>  	getc.def		\
>  	getchar.def		\
> @@ -241,11 +245,13 @@ $(lpfx)fdopen.$(oext): local.h
>  $(lpfx)fflush.$(oext): local.h
>  $(lpfx)findfp.$(oext): local.h
>  $(lpfx)fopen.$(oext): local.h
> +$(lpfx)fopencookie.$(oext): local.h
>  $(lpfx)fputs.$(oext): fvwrite.h
>  $(lpfx)fread.$(oext): local.h
>  $(lpfx)freopen.$(oext): local.h
>  $(lpfx)fseek.$(oext): local.h
>  $(lpfx)ftell.$(oext): local.h
> +$(lpfx)funopen.$(oext): local.h
>  $(lpfx)fvwrite.$(oext): local.h fvwrite.h
>  $(lpfx)fwalk.$(oext): local.h
>  $(lpfx)fwrite.$(oext): local.h fvwrite.h
> Index: libc/stdio/Makefile.in
> ===================================================================
> RCS file: /cvs/src/src/newlib/libc/stdio/Makefile.in,v
> retrieving revision 1.35
> diff -u -p -r1.35 Makefile.in
> --- libc/stdio/Makefile.in	4 May 2007 02:55:16 -0000	1.35
> +++ libc/stdio/Makefile.in	16 May 2007 12:51:52 -0000
> @@ -108,6 +108,8 @@ am__objects_1 = lib_a-clearerr.$(OBJEXT)
>  @ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@	lib_a-asnprintf.$(OBJEXT) \
>  @ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@	lib_a-diprintf.$(OBJEXT) \
>  @ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@	lib_a-dprintf.$(OBJEXT) \
> +@ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@	lib_a-fopencookie.$(OBJEXT) \
> +@ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@	lib_a-funopen.$(OBJEXT) \
>  @ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@	lib_a-vasniprintf.$(OBJEXT) \
>  @ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@	lib_a-vasnprintf.$(OBJEXT)
>  @USE_LIBTOOL_FALSE@am_lib_a_OBJECTS = $(am__objects_1) \
> @@ -137,6 +139,8 @@ am__objects_4 = clearerr.lo fclose.lo fd
>  @ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@	asnprintf.lo \
>  @ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@	diprintf.lo \
>  @ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@	dprintf.lo \
> +@ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@	fopencookie.lo \
> +@ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@	funopen.lo \
>  @ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@	vasniprintf.lo \
>  @ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@	vasnprintf.lo
>  @USE_LIBTOOL_TRUE@am_libstdio_la_OBJECTS = $(am__objects_4) \
> @@ -403,6 +407,8 @@ GENERAL_SOURCES = \
>  @ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@	asnprintf.c		\
>  @ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@	diprintf.c		\
>  @ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@	dprintf.c		\
> +@ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@	fopencookie.c		\
> +@ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@	funopen.c		\
>  @ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@	vasniprintf.c		\
>  @ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@	vasnprintf.c
>  
> @@ -443,6 +449,7 @@ CHEWOUT_FILES = \
>  	fileno.def		\
>  	fiprintf.def		\
>  	fopen.def		\
> +	fopencookie.def		\
>  	fputc.def		\
>  	fputs.def		\
>  	fread.def		\
> @@ -450,6 +457,7 @@ CHEWOUT_FILES = \
>  	fseek.def		\
>  	fsetpos.def		\
>  	ftell.def		\
> +	funopen.def		\
>  	fwrite.def		\
>  	getc.def		\
>  	getchar.def		\
> @@ -1114,6 +1122,18 @@ lib_a-dprintf.o: dprintf.c
>  lib_a-dprintf.obj: dprintf.c
>  	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-dprintf.obj `if test -f 'dprintf.c'; then $(CYGPATH_W) 'dprintf.c'; else $(CYGPATH_W) '$(srcdir)/dprintf.c'; fi`
>  
> +lib_a-fopencookie.o: fopencookie.c
> +	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-fopencookie.o `test -f 'fopencookie.c' || echo '$(srcdir)/'`fopencookie.c
> +
> +lib_a-fopencookie.obj: fopencookie.c
> +	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-fopencookie.obj `if test -f 'fopencookie.c'; then $(CYGPATH_W) 'fopencookie.c'; else $(CYGPATH_W) '$(srcdir)/fopencookie.c'; fi`
> +
> +lib_a-funopen.o: funopen.c
> +	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-funopen.o `test -f 'funopen.c' || echo '$(srcdir)/'`funopen.c
> +
> +lib_a-funopen.obj: funopen.c
> +	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-funopen.obj `if test -f 'funopen.c'; then $(CYGPATH_W) 'funopen.c'; else $(CYGPATH_W) '$(srcdir)/funopen.c'; fi`
> +
>  lib_a-vasniprintf.o: vasniprintf.c
>  	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-vasniprintf.o `test -f 'vasniprintf.c' || echo '$(srcdir)/'`vasniprintf.c
>  
> @@ -1307,11 +1327,13 @@ $(lpfx)fdopen.$(oext): local.h
>  $(lpfx)fflush.$(oext): local.h
>  $(lpfx)findfp.$(oext): local.h
>  $(lpfx)fopen.$(oext): local.h
> +$(lpfx)fopencookie.$(oext): local.h
>  $(lpfx)fputs.$(oext): fvwrite.h
>  $(lpfx)fread.$(oext): local.h
>  $(lpfx)freopen.$(oext): local.h
>  $(lpfx)fseek.$(oext): local.h
>  $(lpfx)ftell.$(oext): local.h
> +$(lpfx)funopen.$(oext): local.h
>  $(lpfx)fvwrite.$(oext): local.h fvwrite.h
>  $(lpfx)fwalk.$(oext): local.h
>  $(lpfx)fwrite.$(oext): local.h fvwrite.h
> Index: libc/stdio/fclose.c
> ===================================================================
> RCS file: /cvs/src/src/newlib/libc/stdio/fclose.c,v
> retrieving revision 1.13
> diff -u -p -r1.13 fclose.c
> --- libc/stdio/fclose.c	15 Mar 2007 18:40:48 -0000	1.13
> +++ libc/stdio/fclose.c	16 May 2007 12:51:52 -0000
> @@ -90,7 +90,7 @@ _DEFUN(_fclose_r, (rptr, fp),
>       files to reposition file to last byte processed as opposed to
>       last byte read ahead into the buffer.  */
>    r = fflush (fp);
> -  if (fp->_close != NULL && (*fp->_close) (fp->_cookie) < 0)
> +  if (fp->_close != NULL && (*fp->_close) (rptr, fp->_cookie) < 0)
>      r = EOF;
>    if (fp->_flags & __SMBF)
>      _free_r (rptr, (char *) fp->_bf._base);
> Index: libc/stdio/fflush.c
> ===================================================================
> RCS file: /cvs/src/src/newlib/libc/stdio/fflush.c,v
> retrieving revision 1.9
> diff -u -p -r1.9 fflush.c
> --- libc/stdio/fflush.c	15 Mar 2007 21:32:13 -0000	1.9
> +++ libc/stdio/fflush.c	16 May 2007 12:51:52 -0000
> @@ -1,5 +1,5 @@
>  /*
> - * Copyright (c) 1990, 2006 The Regents of the University of California.
> + * Copyright (c) 1990 The Regents of the University of California.
>   * All rights reserved.
>   *
>   * Redistribution and use in source and binary forms are permitted
> @@ -90,7 +90,7 @@ _DEFUN(fflush, (fp),
>    t = fp->_flags;
>    if ((t & __SWR) == 0)
>      {
> -      _fpos_t _EXFUN((*seekfn), (_PTR, _fpos_t, int));
> +      _fpos_t _EXFUN((*seekfn), (struct _reent *, _PTR, _fpos_t, int));
>  
>        /* For a read stream, an fflush causes the next seek to be
>           unoptimized (i.e. forces a system-level seek).  This conforms
> @@ -114,7 +114,7 @@ _DEFUN(fflush, (fp),
>            else
>              {
>                /* We don't know current physical offset, so ask for it.  */
> -              curoff = (*seekfn) (fp->_cookie, (_fpos_t) 0, SEEK_CUR);
> +              curoff = (*seekfn) (_REENT, fp->_cookie, (_fpos_t) 0, SEEK_CUR);
>                if (curoff == -1L)
>                  {
>                    _funlockfile (fp);
> @@ -130,7 +130,7 @@ _DEFUN(fflush, (fp),
>                  curoff -= fp->_ur;
>              }
>            /* Now physically seek to after byte last read.  */
> -          if ((*seekfn)(fp->_cookie, curoff, SEEK_SET) != -1)
> +          if ((*seekfn)(_REENT, fp->_cookie, curoff, SEEK_SET) != -1)
>              {
>                /* Seek successful.  We can clear read buffer now.  */
>                fp->_flags &= ~__SNPT;
> @@ -161,7 +161,7 @@ _DEFUN(fflush, (fp),
>  
>    while (n > 0)
>      {
> -      t = (*fp->_write) (fp->_cookie, (char *) p, n);
> +      t = (*fp->_write) (_REENT, fp->_cookie, (char *) p, n);
>        if (t <= 0)
>  	{
>            fp->_flags |= __SERR;
> Index: libc/stdio/fopencookie.c
> ===================================================================
> RCS file: libc/stdio/fopencookie.c
> diff -N libc/stdio/fopencookie.c
> --- /dev/null	1 Jan 1970 00:00:00 -0000
> +++ libc/stdio/fopencookie.c	16 May 2007 12:51:52 -0000
> @@ -0,0 +1,248 @@
> +/* Copyright (C) 2007 Eric Blake
> + * Permission to use, copy, modify, and distribute this software
> + * is freely granted, provided that this notice is preserved.
> + */
> +
> +/*
> +FUNCTION
> +<<fopencookie>>---open a stream with custom callbacks
> +
> +INDEX
> +	fopencookie
> +
> +ANSI_SYNOPSIS
> +	#include <stdio.h>
> +	typedef ssize_t (*cookie_read_function_t)(void *_cookie, char *_buf,
> +						  size_t _n);
> +	typedef ssize_t (*cookie_write_function_t)(void *_cookie,
> +						   const char *_buf, size_t _n);
> +	typedef int (*cookie_seek_function_t)(void *_cookie, off_t *_off,
> +					      int _whence);
> +	typedef int (*cookie_close_function_t)(void *_cookie);
> +	typedef struct
> +	{
> +		cookie_read_function_t	*read;
> +		cookie_write_function_t *write;
> +		cookie_seek_function_t	*seek;
> +		cookie_close_function_t *close;
> +	} cookie_io_functions_t;
> +	FILE *fopencookie(const void *<[cookie]>, const char *<[mode]>,
> +			  cookie_io_functions_t <[functions]>);
> +
> +DESCRIPTION
> +<<fopencookie>> creates a <<FILE>> stream where I/O is performed using
> +custom callbacks.  The stream is opened with <[mode]> treated as in
> +<<fopen>>.  The callbacks <[functions.read]> and <[functions.write]>
> +may only be NULL when <[mode]> does not require them.
> +
> +<[functions.read]> should return -1 on failure, or else the number of
> +bytes read (0 on EOF).  It is similar to <<read>>, except that
> +<[cookie]> will be passed as the first argument.
> +
> +<[functions.write]> should return -1 on failure, or else the number of
> +bytes written.  It is similar to <<write>>, except that <[cookie]>
> +will be passed as the first argument.
> +
> +<[functions.seek]> should return -1 on failure, and 0 on success, with
> +*<[_off]> set to the current file position.  It is a cross between
> +<<lseek>> and <<fseek>>, with the <[_whence]> argument interpreted in
> +the same manner.  A NULL <[functions.seek]> makes the stream behave
> +similarly to a pipe in relation to stdio functions that require
> +positioning.
> +
> +<[functions.close]> should return -1 on failure, or 0 on success.  It
> +is similar to <<close>>, except that <[cookie]> will be passed as the
> +first argument.  A NULL <[functions.close]> merely flushes all data
> +then lets <<fclose>> succeed.  A failed close will still invalidate
> +the stream.
> +
> +Read and write I/O functions are allowed to change the underlying
> +buffer on fully buffered or line buffered streams by calling
> +<<setvbuf>>.  They are also not required to completely fill or empty
> +the buffer.  They are not, however, allowed to change streams from
> +unbuffered to buffered or to change the state of the line buffering
> +flag.  They must also be prepared to have read or write calls occur on
> +buffers other than the one most recently specified.
> +
> +RETURNS
> +The return value is an open FILE pointer on success.  On error,
> +<<NULL>> is returned, and <<errno>> will be set to EINVAL if a
> +function pointer is missing or <[mode]> is invalid, ENOMEM if the
> +stream cannot be created, or EMFILE if too many streams are already
> +open.
> +
> +PORTABILITY
> +This function is a newlib extension, copying the prototype from Linux.
> +It is not portable.  See also the <<funopen>> interface from BSD.
> +
> +Supporting OS subroutines required: <<sbrk>>.
> +*/
> +
> +#include <stdio.h>
> +#include <errno.h>
> +#include <sys/lock.h>
> +#include "local.h"
> +
> +typedef struct fccookie {
> +  void *cookie;
> +  cookie_read_function_t *readfn;
> +  cookie_write_function_t *writefn;
> +  cookie_seek_function_t *seekfn;
> +  cookie_close_function_t *closefn;
> +} fccookie;
> +
> +static _READ_WRITE_RETURN_TYPE
> +_DEFUN(fcreader, (ptr, cookie, buf, n),
> +       struct _reent *ptr _AND
> +       void *cookie _AND
> +       char *buf _AND
> +       int n)
> +{
> +  int result;
> +  fccookie *c = (fccookie *) cookie;
> +  errno = 0;
> +  if ((result = c->readfn (c->cookie, buf, n)) < 0 && errno)
> +    ptr->_errno = errno;
> +  return result;
> +}
> +
> +static _READ_WRITE_RETURN_TYPE
> +_DEFUN(fcwriter, (ptr, cookie, buf, n),
> +       struct _reent *ptr _AND
> +       void *cookie _AND
> +       const char *buf _AND
> +       int n)
> +{
> +  int result;
> +  fccookie *c = (fccookie *) cookie;
> +  errno = 0;
> +  if ((result = c->writefn (c->cookie, buf, n)) < 0 && errno)
> +    ptr->_errno = errno;
> +  return result;
> +}
> +
> +static _fpos_t
> +_DEFUN(fcseeker, (ptr, cookie, off, whence),
> +       struct _reent *ptr _AND
> +       void *cookie _AND
> +       _fpos_t pos _AND
> +       int whence)
> +{
> +  fccookie *c = (fccookie *) cookie;
> +#ifndef __LARGE64_FILES
> +  off_t offset = (off_t) pos;
> +#else /* __LARGE64_FILES */
> +  _off64_t offset = (_off64_t) pos;
> +#endif /* __LARGE64_FILES */
> +
> +  errno = 0;
> +  if (c->seekfn (c->cookie, &offset, whence) < 0 && errno)
> +    ptr->_errno = errno;
> +#ifdef __LARGE64_FILES
> +  else if ((_fpos_t)offset != offset)
> +    {
> +      ptr->_errno = EOVERFLOW;
> +      offset = -1;
> +    }
> +#endif /* __LARGE64_FILES */
> +  return (_fpos_t) offset;
> +}
> +
> +#ifdef __LARGE64_FILES
> +static _fpos64_t
> +_DEFUN(fcseeker64, (ptr, cookie, off, whence),
> +       struct _reent *ptr _AND
> +       void *cookie _AND
> +       _fpos64_t pos _AND
> +       int whence)
> +{
> +  _off64_t offset;
> +  fccookie *c = (fccookie *) cookie;
> +  errno = 0;
> +  if (c->seekfn (c->cookie, &offset, whence) < 0 && errno)
> +    ptr->_errno = errno;
> +  return (_fpos64_t) offset;
> +}
> +#endif /* __LARGE64_FILES */
> +
> +static int
> +_DEFUN(fccloser, (ptr, cookie),
> +       struct _reent *ptr _AND
> +       void *cookie)
> +{
> +  int result = 0;
> +  fccookie *c = (fccookie *) cookie;
> +  if (c->closefn)
> +    {
> +      errno = 0;
> +      if ((result = c->closefn (c->cookie)) < 0 && errno)
> +	ptr->_errno = errno;
> +    }
> +  _free_r (ptr, c);
> +  return result;
> +}
> +
> +FILE *
> +_DEFUN(_fopencookie_r, (ptr, cookie, mode, functions),
> +       struct _reent *ptr _AND
> +       void *cookie _AND
> +       const char *mode _AND
> +       cookie_io_functions_t functions)
> +{
> +  FILE *fp;
> +  fccookie *c;
> +  int flags;
> +  int dummy;
> +
> +  if ((flags = __sflags (ptr, mode, &dummy)) == 0)
> +    return NULL;
> +  if (((flags & (__SRD | __SRW)) && !functions.read)
> +      || ((flags & (__SWR | __SRW)) && !functions.write))
> +    {
> +      ptr->_errno = EINVAL;
> +      return NULL;
> +    }
> +  if ((fp = __sfp (ptr)) == NULL)
> +    return NULL;
> +  if ((c = (fccookie *) _malloc_r (ptr, sizeof *c)) == NULL)
> +    {
> +      __sfp_lock_acquire ();
> +      fp->_flags = 0;		/* release */
> +#ifndef __SINGLE_THREAD__
> +      __lock_close_recursive (fp->_lock);
> +#endif
> +      __sfp_lock_release ();
> +      return NULL;
> +    }
> +
> +  _flockfile (fp);
> +  fp->_file = -1;
> +  fp->_flags = flags;
> +  c->cookie = cookie;
> +  fp->_cookie = c;
> +  c->readfn = functions.read;
> +  fp->_read = fcreader;
> +  c->writefn = functions.write;
> +  fp->_write = fcwriter;
> +  c->seekfn = functions.seek;
> +  fp->_seek = functions.seek ? fcseeker : NULL;
> +#ifdef __LARGE64_FILES
> +  fp->_seek64 = functions.seek ? fcseeker64 : NULL;
> +  fp->_flags |= __SL64;
> +#endif
> +  c->closefn = functions.close;
> +  fp->_close = fccloser;
> +  _funlockfile (fp);
> +  return fp;
> +}
> +
> +#ifndef _REENT_ONLY
> +FILE *
> +_DEFUN(fopencookie, (cookie, mode, functions),
> +       void *cookie _AND
> +       const char *mode _AND
> +       cookie_io_functions_t functions)
> +{
> +  return _fopencookie_r (_REENT, cookie, mode, functions);
> +}
> +#endif /* !_REENT_ONLY */
> Index: libc/stdio/freopen.c
> ===================================================================
> RCS file: /cvs/src/src/newlib/libc/stdio/freopen.c,v
> retrieving revision 1.19
> diff -u -p -r1.19 freopen.c
> --- libc/stdio/freopen.c	15 Mar 2007 18:40:48 -0000	1.19
> +++ libc/stdio/freopen.c	16 May 2007 12:51:52 -0000
> @@ -130,7 +130,7 @@ _DEFUN(_freopen_r, (ptr, file, mode, fp)
>         * If file is NULL, the file should not be closed.
>         */
>        if (fp->_close != NULL && file != NULL)
> -	_CAST_VOID (*fp->_close) (fp->_cookie);
> +	_CAST_VOID (*fp->_close) (ptr, fp->_cookie);
>      }
>  
>    /*
> @@ -176,7 +176,7 @@ _DEFUN(_freopen_r, (ptr, file, mode, fp)
>          {
>            e = EBADF;
>            if (fp->_close != NULL)
> -            _CAST_VOID (*fp->_close) (fp->_cookie);
> +            _CAST_VOID (*fp->_close) (ptr, fp->_cookie);
>          }
>      }
>  
> Index: libc/stdio/fseek.c
> ===================================================================
> RCS file: /cvs/src/src/newlib/libc/stdio/fseek.c,v
> retrieving revision 1.16
> diff -u -p -r1.16 fseek.c
> --- libc/stdio/fseek.c	1 May 2007 23:03:36 -0000	1.16
> +++ libc/stdio/fseek.c	16 May 2007 12:51:52 -0000
> @@ -1,5 +1,5 @@
>  /*
> - * Copyright (c) 1990, 2007 The Regents of the University of California.
> + * Copyright (c) 1990 The Regents of the University of California.
>   * All rights reserved.
>   *
>   * Redistribution and use in source and binary forms are permitted
> @@ -122,7 +122,7 @@ _DEFUN(_fseek_r, (ptr, fp, offset, whenc
>         long offset        _AND
>         int whence)
>  {
> -  _fpos_t _EXFUN((*seekfn), (_PTR, _fpos_t, int));
> +  _fpos_t _EXFUN((*seekfn), (struct _reent *, _PTR, _fpos_t, int));
>    _fpos_t target;
>    _fpos_t curoff = 0;
>    size_t n;
> @@ -175,7 +175,7 @@ _DEFUN(_fseek_r, (ptr, fp, offset, whenc
>  	curoff = fp->_offset;
>        else
>  	{
> -	  curoff = (*seekfn) (fp->_cookie, (_fpos_t) 0, SEEK_CUR);
> +	  curoff = (*seekfn) (ptr, fp->_cookie, (_fpos_t) 0, SEEK_CUR);
>  	  if (curoff == -1L)
>  	    {
>  	      _funlockfile (fp);
> @@ -259,6 +259,11 @@ _DEFUN(_fseek_r, (ptr, fp, offset, whenc
>  	goto dumb;
>        target = st.st_size + offset;
>      }
> +  if ((long)target != target)
> +    {
> +      ptr->_errno = EOVERFLOW;
> +      return EOF;
> +    }
>  
>    if (!havepos)
>      {
> @@ -266,7 +271,7 @@ _DEFUN(_fseek_r, (ptr, fp, offset, whenc
>  	curoff = fp->_offset;
>        else
>  	{
> -	  curoff = (*seekfn) (fp->_cookie, 0L, SEEK_CUR);
> +	  curoff = (*seekfn) (ptr, fp->_cookie, 0L, SEEK_CUR);
>  	  if (curoff == POS_ERR)
>  	    goto dumb;
>  	}
> @@ -327,7 +332,7 @@ _DEFUN(_fseek_r, (ptr, fp, offset, whenc
>     */
>  
>    curoff = target & ~(fp->_blksize - 1);
> -  if ((*seekfn) (fp->_cookie, curoff, SEEK_SET) == POS_ERR)
> +  if ((*seekfn) (ptr, fp->_cookie, curoff, SEEK_SET) == POS_ERR)
>      goto dumb;
>    fp->_r = 0;
>    fp->_p = fp->_bf._base;
> @@ -351,7 +356,7 @@ _DEFUN(_fseek_r, (ptr, fp, offset, whenc
>     */
>  
>  dumb:
> -  if (fflush (fp) || (*seekfn) (fp->_cookie, offset, whence) == POS_ERR)
> +  if (fflush (fp) || (*seekfn) (ptr, fp->_cookie, offset, whence) == POS_ERR)
>      {
>        _funlockfile (fp);
>        return EOF;
> Index: libc/stdio/ftell.c
> ===================================================================
> RCS file: /cvs/src/src/newlib/libc/stdio/ftell.c,v
> retrieving revision 1.10
> diff -u -p -r1.10 ftell.c
> --- libc/stdio/ftell.c	26 Sep 2006 21:22:19 -0000	1.10
> +++ libc/stdio/ftell.c	16 May 2007 12:51:52 -0000
> @@ -125,7 +125,7 @@ _DEFUN(_ftell_r, (ptr, fp),
>      pos = fp->_offset;
>    else
>      {
> -      pos = (*fp->_seek) (fp->_cookie, (_fpos_t) 0, SEEK_CUR);
> +      pos = (*fp->_seek) (ptr, fp->_cookie, (_fpos_t) 0, SEEK_CUR);
>        if (pos == -1L)
>          {
>            _funlockfile (fp);
> @@ -154,6 +154,11 @@ _DEFUN(_ftell_r, (ptr, fp),
>      }
>  
>    _funlockfile (fp);
> +  if ((long)pos != pos)
> +    {
> +      pos = -1;
> +      ptr->_errno = EOVERFLOW;
> +    }
>    return pos;
>  }
>  
> Index: libc/stdio/funopen.c
> ===================================================================
> RCS file: libc/stdio/funopen.c
> diff -N libc/stdio/funopen.c
> --- /dev/null	1 Jan 1970 00:00:00 -0000
> +++ libc/stdio/funopen.c	16 May 2007 12:51:52 -0000
> @@ -0,0 +1,278 @@
> +/* Copyright (C) 2007 Eric Blake
> + * Permission to use, copy, modify, and distribute this software
> + * is freely granted, provided that this notice is preserved.
> + */
> +
> +/*
> +FUNCTION
> +<<funopen>>, <<fropen>>, <<fwopen>>---open a stream with custom callbacks
> +
> +INDEX
> +	funopen
> +INDEX
> +	fropen
> +INDEX
> +	fwopen
> +
> +ANSI_SYNOPSIS
> +	#include <stdio.h>
> +	FILE *funopen(const void *<[cookie]>,
> +	              int (*<[readfn]>) (void *cookie, char *buf, int n),
> +	              int (*<[writefn]>) (void *cookie, const char *buf, int n),
> +	              fpos_t (*<[seekfn]>) (void *cookie, fpos_t off, int whence),
> +	              int (*<[closefn]>) (void *cookie));
> +	FILE *fropen(const void *<[cookie]>,
> +	             int (*<[readfn]>) (void *cookie, char *buf, int n));
> +	FILE *fwopen(const void *<[cookie]>,
> +	             int (*<[writefn]>) (void *cookie, const char *buf, int n));
> +
> +DESCRIPTION
> +<<funopen>> creates a <<FILE>> stream where I/O is performed using
> +custom callbacks.  At least one of <[readfn]> and <[writefn]> must be
> +provided, which determines whether the stream behaves with mode <"r">,
> +<"w">, or <"r+">.
> +
> +<[readfn]> should return -1 on failure, or else the number of bytes
> +read (0 on EOF).  It is similar to <<read>>, except that <int> rather
> +than <size_t> bounds a transaction size, and <[cookie]> will be passed
> +as the first argument.  A NULL <[readfn]> makes attempts to read the
> +stream fail.
> +
> +<[writefn]> should return -1 on failure, or else the number of bytes
> +written.  It is similar to <<write>>, except that <int> rather than
> +<size_t> bounds a transaction size, and <[cookie]> will be passed as
> +the first argument.  A NULL <[writefn]> makes attempts to write the
> +stream fail.
> +
> +<[seekfn]> should return (fpos_t)-1 on failure, or else the current
> +file position.  It is similar to <<lseek>>, except that <[cookie]>
> +will be passed as the first argument.  A NULL <[seekfn]> makes the
> +stream behave similarly to a pipe in relation to stdio functions that
> +require positioning.  This implementation assumes fpos_t and off_t are
> +the same type.
> +
> +<[closefn]> should return -1 on failure, or 0 on success.  It is
> +similar to <<close>>, except that <[cookie]> will be passed as the
> +first argument.  A NULL <[closefn]> merely flushes all data then lets
> +<<fclose>> succeed.  A failed close will still invalidate the stream.
> +
> +Read and write I/O functions are allowed to change the underlying
> +buffer on fully buffered or line buffered streams by calling
> +<<setvbuf>>.  They are also not required to completely fill or empty
> +the buffer.  They are not, however, allowed to change streams from
> +unbuffered to buffered or to change the state of the line buffering
> +flag.  They must also be prepared to have read or write calls occur on
> +buffers other than the one most recently specified.
> +
> +The functions <<fropen>> and <<fwopen>> are convenience macros around
> +<<funopen>> that only use the specified callback.
> +
> +RETURNS
> +The return value is an open FILE pointer on success.  On error,
> +<<NULL>> is returned, and <<errno>> will be set to EINVAL if a
> +function pointer is missing, ENOMEM if the stream cannot be created,
> +or EMFILE if too many streams are already open.
> +
> +PORTABILITY
> +This function is a newlib extension, copying the prototype from BSD.
> +It is not portable.  See also the <<fopencookie>> interface from Linux.
> +
> +Supporting OS subroutines required: <<sbrk>>.
> +*/
> +
> +#include <stdio.h>
> +#include <errno.h>
> +#include <sys/lock.h>
> +#include "local.h"
> +
> +typedef int (*funread)(void *_cookie, char *_buf, int _n);
> +typedef int (*funwrite)(void *_cookie, const char *_buf, int _n);
> +#ifdef __LARGE64_FILES
> +typedef _fpos64_t (*funseek)(void *_cookie, _fpos64_t _off, int _whence);
> +#else
> +typedef fpos_t (*funseek)(void *_cookie, fpos_t _off, int _whence);
> +#endif
> +typedef int (*funclose)(void *_cookie);
> +
> +typedef struct funcookie {
> +  void *cookie;
> +  funread readfn;
> +  funwrite writefn;
> +  funseek seekfn;
> +  funclose closefn;
> +} funcookie;
> +
> +static _READ_WRITE_RETURN_TYPE
> +_DEFUN(funreader, (ptr, cookie, buf, n),
> +       struct _reent *ptr _AND
> +       void *cookie _AND
> +       char *buf _AND
> +       int n)
> +{
> +  int result;
> +  funcookie *c = (funcookie *) cookie;
> +  errno = 0;
> +  if ((result = c->readfn (c->cookie, buf, n)) < 0 && errno)
> +    ptr->_errno = errno;
> +  return result;
> +}
> +
> +static _READ_WRITE_RETURN_TYPE
> +_DEFUN(funwriter, (ptr, cookie, buf, n),
> +       struct _reent *ptr _AND
> +       void *cookie _AND
> +       const char *buf _AND
> +       int n)
> +{
> +  int result;
> +  funcookie *c = (funcookie *) cookie;
> +  errno = 0;
> +  if ((result = c->writefn (c->cookie, buf, n)) < 0 && errno)
> +    ptr->_errno = errno;
> +  return result;
> +}
> +
> +static _fpos_t
> +_DEFUN(funseeker, (ptr, cookie, off, whence),
> +       struct _reent *ptr _AND
> +       void *cookie _AND
> +       _fpos_t off _AND
> +       int whence)
> +{
> +  funcookie *c = (funcookie *) cookie;
> +#ifndef __LARGE64_FILES
> +  fpos_t result;
> +  errno = 0;
> +  if ((result = c->seekfn (c->cookie, (fpos_t) off, whence)) < 0 && errno)
> +    ptr->_errno = errno;
> +#else /* __LARGE64_FILES */
> +  _fpos64_t result;
> +  errno = 0;
> +  if ((result = c->seekfn (c->cookie, (_fpos64_t) off, whence)) < 0 && errno)
> +    ptr->_errno = errno;
> +  else if ((_fpos_t)result != result)
> +    {
> +      ptr->_errno = EOVERFLOW;
> +      result = -1;
> +    }
> +#endif /* __LARGE64_FILES */
> +  return result;
> +}
> +
> +#ifdef __LARGE64_FILES
> +static _fpos64_t
> +_DEFUN(funseeker64, (ptr, cookie, off, whence),
> +       struct _reent *ptr _AND
> +       void *cookie _AND
> +       _fpos64_t off _AND
> +       int whence)
> +{
> +  _fpos64_t result;
> +  funcookie *c = (funcookie *) cookie;
> +  errno = 0;
> +  if ((result = c->seekfn (c->cookie, off, whence)) < 0 && errno)
> +    ptr->_errno = errno;
> +  return result;
> +}
> +#endif /* __LARGE64_FILES */
> +
> +static int
> +_DEFUN(funcloser, (ptr, cookie),
> +       struct _reent *ptr _AND
> +       void *cookie)
> +{
> +  int result = 0;
> +  funcookie *c = (funcookie *) cookie;
> +  if (c->closefn)
> +    {
> +      errno = 0;
> +      if ((result = c->closefn (c->cookie)) < 0 && errno)
> +	ptr->_errno = errno;
> +    }
> +  _free_r (ptr, c);
> +  return result;
> +}
> +
> +FILE *
> +_DEFUN(_funopen_r, (ptr, cookie, readfn, writefn, seekfn, closefn),
> +       struct _reent *ptr _AND
> +       const void *cookie _AND
> +       funread readfn _AND
> +       funwrite writefn _AND
> +       funseek seekfn _AND
> +       funclose closefn)
> +{
> +  FILE *fp;
> +  funcookie *c;
> +
> +  if (!readfn && !writefn)
> +    {
> +      ptr->_errno = EINVAL;
> +      return NULL;
> +    }
> +  if ((fp = __sfp (ptr)) == NULL)
> +    return NULL;
> +  if ((c = (funcookie *) _malloc_r (ptr, sizeof *c)) == NULL)
> +    {
> +      __sfp_lock_acquire ();
> +      fp->_flags = 0;		/* release */
> +#ifndef __SINGLE_THREAD__
> +      __lock_close_recursive (fp->_lock);
> +#endif
> +      __sfp_lock_release ();
> +      return NULL;
> +    }
> +
> +  _flockfile (fp);
> +  fp->_file = -1;
> +  c->cookie = (void *) cookie; /* cast away const */
> +  fp->_cookie = c;
> +  if (readfn)
> +    {
> +      c->readfn = readfn;
> +      fp->_read = funreader;
> +      if (writefn)
> +	{
> +	  fp->_flags = __SRW;
> +	  c->writefn = writefn;
> +	  fp->_write = funwriter;
> +	}
> +      else
> +	{
> +	  fp->_flags = __SRD;
> +	  c->writefn = NULL;
> +	  fp->_write = NULL;
> +	}
> +    }
> +  else
> +    {
> +      fp->_flags = __SWR;
> +      c->writefn = writefn;
> +      fp->_write = funwriter;
> +      c->readfn = NULL;
> +      fp->_read = NULL;
> +    }
> +  c->seekfn = seekfn;
> +  fp->_seek = seekfn ? funseeker : NULL;
> +#ifdef __LARGE64_FILES
> +  fp->_seek64 = seekfn ? funseeker64 : NULL;
> +  fp->_flags |= __SL64;
> +#endif
> +  c->closefn = closefn;
> +  fp->_close = funcloser;
> +  _funlockfile (fp);
> +  return fp;
> +}
> +
> +#ifndef _REENT_ONLY
> +FILE *
> +_DEFUN(funopen, (cookie, readfn, writefn, seekfn, closefn),
> +       const void *cookie _AND
> +       funread readfn _AND
> +       funwrite writefn _AND
> +       funseek seekfn _AND
> +       funclose closefn)
> +{
> +  return _funopen_r (_REENT, cookie, readfn, writefn, seekfn, closefn);
> +}
> +#endif /* !_REENT_ONLY */
> Index: libc/stdio/fvwrite.c
> ===================================================================
> RCS file: /cvs/src/src/newlib/libc/stdio/fvwrite.c,v
> retrieving revision 1.12
> diff -u -p -r1.12 fvwrite.c
> --- libc/stdio/fvwrite.c	4 May 2007 02:55:16 -0000	1.12
> +++ libc/stdio/fvwrite.c	16 May 2007 12:51:52 -0000
> @@ -98,7 +98,7 @@ _DEFUN(__sfvwrite_r, (ptr, fp, uio),
>        do
>  	{
>  	  GETIOV (;);
> -	  w = (*fp->_write) (fp->_cookie, p, MIN (len, BUFSIZ));
> +	  w = (*fp->_write) (ptr, fp->_cookie, p, MIN (len, BUFSIZ));
>  	  if (w <= 0)
>  	    goto err;
>  	  p += w;
> @@ -191,7 +191,7 @@ _DEFUN(__sfvwrite_r, (ptr, fp, uio),
>  	  else if (len >= (w = fp->_bf._size))
>  	    {
>  	      /* write directly */
> -	      w = (*fp->_write) (fp->_cookie, p, w);
> +	      w = (*fp->_write) (ptr, fp->_cookie, p, w);
>  	      if (w <= 0)
>  		goto err;
>  	    }
> @@ -240,7 +240,7 @@ _DEFUN(__sfvwrite_r, (ptr, fp, uio),
>  	    }
>  	  else if (s >= (w = fp->_bf._size))
>  	    {
> -	      w = (*fp->_write) (fp->_cookie, p, w);
> +	      w = (*fp->_write) (ptr, fp->_cookie, p, w);
>  	      if (w <= 0)
>  		goto err;
>  	    }
> Index: libc/stdio/local.h
> ===================================================================
> RCS file: /cvs/src/src/newlib/libc/stdio/local.h,v
> retrieving revision 1.21
> diff -u -p -r1.21 local.h
> --- libc/stdio/local.h	1 May 2007 23:03:36 -0000	1.21
> +++ libc/stdio/local.h	16 May 2007 12:51:52 -0000
> @@ -34,10 +34,10 @@ extern int    _EXFUN(__svfiscanf_r,(stru
>  extern FILE  *_EXFUN(__sfp,(struct _reent *));
>  extern int    _EXFUN(__sflags,(struct _reent *,_CONST char*, int*));
>  extern int    _EXFUN(__srefill_r,(struct _reent *,FILE *));
> -extern _READ_WRITE_RETURN_TYPE _EXFUN(__sread,(_PTR, char *, int));
> -extern _READ_WRITE_RETURN_TYPE _EXFUN(__swrite,(_PTR, char _CONST *, int));
> -extern _fpos_t _EXFUN(__sseek,(_PTR, _fpos_t, int));
> -extern int    _EXFUN(__sclose,(_PTR));
> +extern _READ_WRITE_RETURN_TYPE _EXFUN(__sread,(struct _reent *, _PTR, char *, int));
> +extern _READ_WRITE_RETURN_TYPE _EXFUN(__swrite,(struct _reent *, _PTR, char _CONST *, int));
> +extern _fpos_t _EXFUN(__sseek,(struct _reent *, _PTR, _fpos_t, int));
> +extern int    _EXFUN(__sclose,(struct _reent *, _PTR));
>  extern int    _EXFUN(__stextmode,(int));
>  extern _VOID   _EXFUN(__sinit,(struct _reent *));
>  extern _VOID   _EXFUN(_cleanup_r,(struct _reent *));
> @@ -47,10 +47,8 @@ extern int    _EXFUN(_fwalk_reent,(struc
>  struct _glue * _EXFUN(__sfmoreglue,(struct _reent *,int n));
>  
>  #ifdef __LARGE64_FILES
> -extern _fpos64_t _EXFUN(__sseek64,(void *, _fpos64_t, int));
> -extern _fpos64_t _EXFUN(__sseek64_r,(struct _reent *, void *, _fpos64_t, int));
> -extern _READ_WRITE_RETURN_TYPE _EXFUN(__swrite64,(void *, char const *, int));
> -extern _READ_WRITE_RETURN_TYPE _EXFUN(__swrite64_r,(struct _reent *, void *,
> +extern _fpos64_t _EXFUN(__sseek64,(struct _reent *, void *, _fpos64_t, int));
> +extern _READ_WRITE_RETURN_TYPE _EXFUN(__swrite64,(struct _reent *, void *,
>                                        char const *, int));
>  #endif
>  
> Index: libc/stdio/refill.c
> ===================================================================
> RCS file: /cvs/src/src/newlib/libc/stdio/refill.c,v
> retrieving revision 1.9
> diff -u -p -r1.9 refill.c
> --- libc/stdio/refill.c	15 Mar 2007 18:40:48 -0000	1.9
> +++ libc/stdio/refill.c	16 May 2007 12:51:52 -0000
> @@ -104,7 +104,7 @@ _DEFUN(__srefill_r, (ptr, fp),
>    if (fp->_flags & (__SLBF | __SNBF))
>      _CAST_VOID _fwalk (_GLOBAL_REENT, lflush);
>    fp->_p = fp->_bf._base;
> -  fp->_r = (*fp->_read) (fp->_cookie, (char *) fp->_p, fp->_bf._size);
> +  fp->_r = (*fp->_read) (ptr, fp->_cookie, (char *) fp->_p, fp->_bf._size);
>    fp->_flags &= ~__SMOD;	/* buffer contents are again pristine */
>  #ifndef __CYGWIN__
>    if (fp->_r <= 0)
> Index: libc/stdio/siscanf.c
> ===================================================================
> RCS file: /cvs/src/src/newlib/libc/stdio/siscanf.c,v
> retrieving revision 1.2
> diff -u -p -r1.2 siscanf.c
> --- libc/stdio/siscanf.c	28 Oct 2005 21:38:59 -0000	1.2
> +++ libc/stdio/siscanf.c	16 May 2007 12:51:52 -0000
> @@ -112,7 +112,8 @@ Supporting OS subroutines required: <<cl
>  /* | ARGSUSED */
>  /*SUPPRESS 590*/
>  static _READ_WRITE_RETURN_TYPE
> -_DEFUN(eofread, (cookie, buf, len),
> +_DEFUN(eofread, (ptr, cookie, buf, len),
> +       struct _reent *ptr _AND
>         _PTR cookie _AND
>         char *buf   _AND
>         int len)
> Index: libc/stdio/sscanf.c
> ===================================================================
> RCS file: /cvs/src/src/newlib/libc/stdio/sscanf.c,v
> retrieving revision 1.10
> diff -u -p -r1.10 sscanf.c
> --- libc/stdio/sscanf.c	17 Apr 2007 20:53:24 -0000	1.10
> +++ libc/stdio/sscanf.c	16 May 2007 12:51:52 -0000
> @@ -393,7 +393,8 @@ Supporting OS subroutines required: <<cl
>  /* | ARGSUSED */
>  /*SUPPRESS 590*/
>  static _READ_WRITE_RETURN_TYPE
> -_DEFUN(eofread, (cookie, buf, len),
> +_DEFUN(eofread, (ptr, cookie, buf, len),
> +       struct _reent *ptr _AND
>         _PTR cookie _AND
>         char *buf   _AND
>         int len)
> Index: libc/stdio/stdio.c
> ===================================================================
> RCS file: /cvs/src/src/newlib/libc/stdio/stdio.c,v
> retrieving revision 1.7
> diff -u -p -r1.7 stdio.c
> --- libc/stdio/stdio.c	23 Apr 2004 20:01:55 -0000	1.7
> +++ libc/stdio/stdio.c	16 May 2007 12:51:52 -0000
> @@ -30,9 +30,10 @@
>   */
>  
>  _READ_WRITE_RETURN_TYPE
> -_DEFUN(__sread, (cookie, buf, n),
> -       _PTR cookie _AND
> -       char *buf   _AND
> +_DEFUN(__sread, (ptr, cookie, buf, n),
> +       struct _reent *ptr _AND
> +       void *cookie _AND
> +       char *buf _AND
>         int n)
>  {
>    register FILE *fp = (FILE *) cookie;
> @@ -44,7 +45,7 @@ _DEFUN(__sread, (cookie, buf, n),
>      oldmode = setmode (fp->_file, O_BINARY);
>  #endif
>  
> -  ret = _read_r (_REENT, fp->_file, buf, n);
> +  ret = _read_r (ptr, fp->_file, buf, n);
>  
>  #ifdef __SCLE
>    if (oldmode)
> @@ -61,9 +62,10 @@ _DEFUN(__sread, (cookie, buf, n),
>  }
>  
>  _READ_WRITE_RETURN_TYPE
> -_DEFUN(__swrite, (cookie, buf, n),
> -       _PTR cookie      _AND
> -       char _CONST *buf _AND
> +_DEFUN(__swrite, (ptr, cookie, buf, n),
> +       struct _reent *ptr _AND
> +       void *cookie _AND
> +       char const *buf _AND
>         int n)
>  {
>    register FILE *fp = (FILE *) cookie;
> @@ -73,7 +75,7 @@ _DEFUN(__swrite, (cookie, buf, n),
>  #endif
>  
>    if (fp->_flags & __SAPP)
> -    _CAST_VOID _lseek_r (_REENT, fp->_file, (_off_t) 0, SEEK_END);
> +    _CAST_VOID _lseek_r (ptr, fp->_file, (_off_t) 0, SEEK_END);
>    fp->_flags &= ~__SOFF;	/* in case O_APPEND mode is set */
>  
>  #ifdef __SCLE
> @@ -81,7 +83,7 @@ _DEFUN(__swrite, (cookie, buf, n),
>      oldmode = setmode (fp->_file, O_BINARY);
>  #endif
>  
> -  w = _write_r (_REENT, fp->_file, buf, n);
> +  w = _write_r (ptr, fp->_file, buf, n);
>  
>  #ifdef __SCLE
>    if (oldmode)
> @@ -92,15 +94,16 @@ _DEFUN(__swrite, (cookie, buf, n),
>  }
>  
>  _fpos_t
> -_DEFUN(__sseek, (cookie, offset, whence),
> -       _PTR cookie    _AND
> +_DEFUN(__sseek, (ptr, cookie, offset, whence),
> +       struct _reent *ptr _AND
> +       void *cookie _AND
>         _fpos_t offset _AND
>         int whence)
>  {
>    register FILE *fp = (FILE *) cookie;
>    register _off_t ret;
>  
> -  ret = _lseek_r (_REENT, fp->_file, (_off_t) offset, whence);
> +  ret = _lseek_r (ptr, fp->_file, (_off_t) offset, whence);
>    if (ret == -1L)
>      fp->_flags &= ~__SOFF;
>    else
> @@ -112,17 +115,18 @@ _DEFUN(__sseek, (cookie, offset, whence)
>  }
>  
>  int
> -_DEFUN(__sclose, (cookie),
> -       _PTR cookie)
> +_DEFUN(__sclose, (ptr, cookie),
> +       struct _reent *ptr _AND
> +       void *cookie)
>  {
>    FILE *fp = (FILE *) cookie;
>  
> -  return _close_r (_REENT, fp->_file);
> +  return _close_r (ptr, fp->_file);
>  }
>  
>  #ifdef __SCLE
>  int
> -_DEFUN(__stextmode, (fd), 
> +_DEFUN(__stextmode, (fd),
>         int fd)
>  {
>  #ifdef __CYGWIN__
> Index: libc/stdio/vsiscanf.c
> ===================================================================
> RCS file: /cvs/src/src/newlib/libc/stdio/vsiscanf.c,v
> retrieving revision 1.1
> diff -u -p -r1.1 vsiscanf.c
> --- libc/stdio/vsiscanf.c	24 Nov 2004 00:45:41 -0000	1.1
> +++ libc/stdio/vsiscanf.c	16 May 2007 12:51:52 -0000
> @@ -29,7 +29,8 @@
>  #include "local.h"
>  
>  static _READ_WRITE_RETURN_TYPE
> -_DEFUN(eofread1, (cookie, buf, len),
> +_DEFUN(eofread1, (ptr, cookie, buf, len),
> +       struct _reent *ptr _AND
>         _PTR cookie _AND
>         char *buf   _AND
>         int len)
> Index: libc/stdio/vsscanf.c
> ===================================================================
> RCS file: /cvs/src/src/newlib/libc/stdio/vsscanf.c,v
> retrieving revision 1.4
> diff -u -p -r1.4 vsscanf.c
> --- libc/stdio/vsscanf.c	16 Sep 2004 21:30:51 -0000	1.4
> +++ libc/stdio/vsscanf.c	16 May 2007 12:51:52 -0000
> @@ -29,7 +29,8 @@
>  #include "local.h"
>  
>  static _READ_WRITE_RETURN_TYPE
> -_DEFUN(eofread1, (cookie, buf, len),
> +_DEFUN(eofread1, (ptr, cookie, buf, len),
> +       struct _reent *_ptr _AND
>         _PTR cookie _AND
>         char *buf   _AND
>         int len)
> Index: libc/stdio64/freopen64.c
> ===================================================================
> RCS file: /cvs/src/src/newlib/libc/stdio64/freopen64.c,v
> retrieving revision 1.15
> diff -u -p -r1.15 freopen64.c
> --- libc/stdio64/freopen64.c	1 May 2007 23:03:36 -0000	1.15
> +++ libc/stdio64/freopen64.c	16 May 2007 12:51:52 -0000
> @@ -130,7 +130,7 @@ _DEFUN (_freopen64_r, (ptr, file, mode, 
>         * If file is NULL, the file should not be closed.
>         */
>        if (fp->_close != NULL && file != NULL)
> -	(void) (*fp->_close) (fp->_cookie);
> +	(void) (*fp->_close) (ptr, fp->_cookie);
>      }
>  
>    /*
> @@ -176,7 +176,7 @@ _DEFUN (_freopen64_r, (ptr, file, mode, 
>          {
>            e = EBADF;
>            if (fp->_close != NULL)
> -            (void) (*fp->_close) (fp->_cookie);
> +            (void) (*fp->_close) (ptr, fp->_cookie);
>          }
>      }
>  
> Index: libc/stdio64/fseeko64.c
> ===================================================================
> RCS file: /cvs/src/src/newlib/libc/stdio64/fseeko64.c,v
> retrieving revision 1.10
> diff -u -p -r1.10 fseeko64.c
> --- libc/stdio64/fseeko64.c	1 May 2007 23:03:36 -0000	1.10
> +++ libc/stdio64/fseeko64.c	16 May 2007 12:51:52 -0000
> @@ -104,7 +104,7 @@ _DEFUN (_fseeko64_r, (ptr, fp, offset, w
>       _off64_t offset _AND
>       int whence)
>  {
> -  _fpos64_t _EXFUN ((*seekfn), (void *, _fpos64_t, int));
> +  _fpos64_t _EXFUN ((*seekfn), (struct _reent *, void *, _fpos64_t, int));
>    _fpos64_t target, curoff;
>    size_t n;
>  
> @@ -155,7 +155,7 @@ _DEFUN (_fseeko64_r, (ptr, fp, offset, w
>  	curoff = fp->_offset;
>        else
>  	{
> -	  curoff = (*seekfn) (fp->_cookie, (_fpos64_t) 0, SEEK_CUR);
> +	  curoff = (*seekfn) (ptr, fp->_cookie, (_fpos64_t) 0, SEEK_CUR);
>  	  if (curoff == -1L)
>  	    {
>  	      _funlockfile(fp);
> @@ -238,7 +238,7 @@ _DEFUN (_fseeko64_r, (ptr, fp, offset, w
>  	curoff = fp->_offset;
>        else
>  	{
> -	  curoff = (*seekfn) (fp->_cookie, (_fpos64_t)0, SEEK_CUR);
> +	  curoff = (*seekfn) (ptr, fp->_cookie, (_fpos64_t)0, SEEK_CUR);
>  	  if (curoff == POS_ERR)
>  	    goto dumb;
>  	}
> @@ -299,7 +299,7 @@ _DEFUN (_fseeko64_r, (ptr, fp, offset, w
>     */
>  
>    curoff = target & ~((_fpos64_t)(fp->_blksize - 1));
> -  if ((*seekfn) (fp->_cookie, curoff, SEEK_SET) == POS_ERR)
> +  if ((*seekfn) (ptr, fp->_cookie, curoff, SEEK_SET) == POS_ERR)
>      goto dumb;
>    fp->_r = 0;
>    fp->_p = fp->_bf._base;
> @@ -323,7 +323,7 @@ _DEFUN (_fseeko64_r, (ptr, fp, offset, w
>     */
>  
>  dumb:
> -  if (fflush (fp) || (*seekfn) (fp->_cookie, offset, whence) == POS_ERR)
> +  if (fflush (fp) || (*seekfn) (ptr, fp->_cookie, offset, whence) == POS_ERR)
>      {
>        _funlockfile(fp);
>        return EOF;
> Index: libc/stdio64/ftello64.c
> ===================================================================
> RCS file: /cvs/src/src/newlib/libc/stdio64/ftello64.c,v
> retrieving revision 1.6
> diff -u -p -r1.6 ftello64.c
> --- libc/stdio64/ftello64.c	1 May 2007 23:03:36 -0000	1.6
> +++ libc/stdio64/ftello64.c	16 May 2007 12:51:52 -0000
> @@ -111,7 +111,7 @@ _DEFUN (_ftello64_r, (ptr, fp),
>      pos = fp->_offset;
>    else
>      {
> -      pos = (*fp->_seek64) (fp->_cookie, (_fpos64_t) 0, SEEK_CUR);
> +      pos = (*fp->_seek64) (ptr, fp->_cookie, (_fpos64_t) 0, SEEK_CUR);
>        if (pos == -1L)
>          {
>            _funlockfile(fp);
> Index: libc/stdio64/stdio64.c
> ===================================================================
> RCS file: /cvs/src/src/newlib/libc/stdio64/stdio64.c,v
> retrieving revision 1.2
> diff -u -p -r1.2 stdio64.c
> --- libc/stdio64/stdio64.c	22 Aug 2003 18:52:25 -0000	1.2
> +++ libc/stdio64/stdio64.c	16 May 2007 12:51:52 -0000
> @@ -26,11 +26,11 @@
>  
>  #ifdef __LARGE64_FILES
>  _fpos64_t
> -__sseek64_r (ptr, cookie, offset, whence)
> -     struct _reent *ptr;
> -     _PTR cookie;
> -     _fpos64_t offset;
> -     int whence;
> +_DEFUN(__sseek64, (ptr, cookie, offset, whence),
> +       struct _reent *ptr _AND
> +       void *cookie _AND
> +       _fpos64_t offset _AND
> +       int whence)
>  {
>    register FILE *fp = (FILE *) cookie;
>    register _off64_t ret;
> @@ -47,11 +47,11 @@ __sseek64_r (ptr, cookie, offset, whence
>  }
>  
>  _READ_WRITE_RETURN_TYPE
> -__swrite64_r (ptr, cookie, buf, n)
> -     struct _reent *ptr;
> -     _PTR cookie;
> -     char _CONST *buf;
> -     int n;
> +_DEFUN(__swrite64, (ptr, cookie, buf, n),
> +       struct _reent *ptr _AND
> +       void *cookie _AND
> +       char const *buf _AND
> +       int n)
>  {
>    register FILE *fp = (FILE *) cookie;
>    int w;
> @@ -78,26 +78,4 @@ __swrite64_r (ptr, cookie, buf, n)
>    return w;
>  }
>  
> -#ifndef _REENT_ONLY
> -_fpos64_t
> -__sseek64 (cookie, offset, whence)
> -     _PTR cookie;
> -     _fpos64_t offset;
> -     int whence;
> -{
> -  return __sseek64_r (_REENT, cookie, offset, whence);
> -}
> -
> -_READ_WRITE_RETURN_TYPE
> -__swrite64 (cookie, buf, n)
> -     _PTR cookie;
> -     char _CONST *buf;
> -     int n;
> -{
> -  return __swrite64_r (_REENT, cookie, buf, n);
> -}
> -
> -#endif /* !_REENT_ONLY */
> -
>  #endif /* __LARGE64_FILES */
> -
>   



More information about the Newlib mailing list