204 lines
6.9 KiB
C
204 lines
6.9 KiB
C
|
/***
|
||
|
*setvbuf.c - set buffer size for a stream
|
||
|
*
|
||
|
* Copyright (c) 1985-2001, Microsoft Corporation. All rights reserved.
|
||
|
*
|
||
|
*Purpose:
|
||
|
* defines setvbuf() - set the buffering mode and size for a stream.
|
||
|
*
|
||
|
*Revision History:
|
||
|
* 09-19-83 RN initial version
|
||
|
* 06-26-85 TC modified to allow user defined buffers of various sizes
|
||
|
* 06-24-86 DFW kludged to fix incompatability with Xenix values of
|
||
|
* _IOFBF, _IOLBF
|
||
|
* 02-09-87 JCR added "buffer=&(_iob2[fileno(stream)]._charbuf);"
|
||
|
* to handle _IONBF case
|
||
|
* 02-25-87 JCR added support for default buffer and IBMC20-condition
|
||
|
* code
|
||
|
* 04-13-87 JCR changed type of szie from int to size_t (unsigned int)
|
||
|
* and changed a related comparison
|
||
|
* 06-29-87 JCR Took out the _OLD_IOFBF/_OLD_IOLBF kludge for MSC.
|
||
|
* Should be taken out for IBM too...
|
||
|
* 09-28-87 JCR Corrected _iob2 indexing (now uses _iob_index() macro).
|
||
|
* 11-02-87 JCR Multi-thread support
|
||
|
* 12-11-87 JCR Added "_LOAD_DS" to declaration
|
||
|
* 05-27-88 PHG Merged DLL and normal versions
|
||
|
* 06-06-88 JCR Optimized _iob2 references
|
||
|
* 06-14-88 JCR Use near pointer to reference _iob[] entries
|
||
|
* 08-09-88 JCR Buffer size can't be greater than INT_MAX
|
||
|
* 08-25-88 GJF Don't use FP_OFF() macro for the 386
|
||
|
* 08-18-89 GJF Clean up, now specific to OS/2 2.0 (i.e., 386 flat
|
||
|
* model). Also fixed copyright and indents.
|
||
|
* 02-15-90 GJF _iob[], _iob2[] merge. Also, cleanup, a little tuning
|
||
|
* and fixed copyright.
|
||
|
* 03-19-90 GJF Made calling type _CALLTYPE1, added #include
|
||
|
* <cruntime.h> and removed #include <register.h>.
|
||
|
* 05-29-90 SBM Use _flush, not [_]fflush[_lk]
|
||
|
* 07-23-90 SBM Replaced <assertm.h> by <assert.h>
|
||
|
* 10-03-90 GJF New-style function declarator.
|
||
|
* 04-06-93 SKS Replace _CRTAPI* with __cdecl
|
||
|
* 04-27-93 CFW Change _IONBF size to 2 bytes to hold wide char.
|
||
|
* 06-22-93 GJF Set _IOSETVBUF (new) to indicate user-specified
|
||
|
* buffering (in addition to setting _IOYOURBUF or
|
||
|
* _IOMYBUF).
|
||
|
* 11-12-93 GJF Return failure if size == 1 (instead of putting
|
||
|
* 0 into stream->_bufsiz, preventing any i/o)
|
||
|
* 04-05-94 GJF #ifdef-ed out _cflush reference for msvcrt*.dll, it
|
||
|
* is unnecessary.
|
||
|
* 01-10-95 CFW Debug CRT allocs.
|
||
|
* 02-06-94 CFW assert -> _ASSERTE.
|
||
|
* 02-20-95 GJF Merged in Mac version.
|
||
|
* 03-07-95 GJF _[un]lock_str macros now take FILE * arg.
|
||
|
* 03-02-98 GJF Exception-safe locking.
|
||
|
* 01-04-99 GJF Changes for 64-bit size_t.
|
||
|
* 05-17-99 PML Remove all Macintosh support.
|
||
|
*
|
||
|
*******************************************************************************/
|
||
|
|
||
|
#include <cruntime.h>
|
||
|
#include <stdio.h>
|
||
|
#include <file2.h>
|
||
|
#include <malloc.h>
|
||
|
#include <internal.h>
|
||
|
#include <mtdll.h>
|
||
|
#include <limits.h>
|
||
|
#include <dbgint.h>
|
||
|
|
||
|
/***
|
||
|
*int setvbuf(stream, buffer, type, size) - set buffering for a file
|
||
|
*
|
||
|
*Purpose:
|
||
|
* Controls buffering and buffer size for the specified stream. The
|
||
|
* array pointed to by buf is used as a buffer, unless NULL, in which
|
||
|
* case we'll allocate a buffer automatically. type specifies the type
|
||
|
* of buffering: _IONBF = no buffer, _IOFBF = buffered, _IOLBF = same
|
||
|
* as _IOFBF.
|
||
|
*
|
||
|
*Entry:
|
||
|
* FILE *stream - stream to control buffer on
|
||
|
* char *buffer - pointer to buffer to use (NULL means auto allocate)
|
||
|
* int type - type of buffering (_IONBF, _IOFBF or _IOLBF)
|
||
|
* size_t size - size of buffer
|
||
|
*
|
||
|
*Exit:
|
||
|
* return 0 if successful
|
||
|
* returns non-zero if fails
|
||
|
*
|
||
|
*Exceptions:
|
||
|
*
|
||
|
*******************************************************************************/
|
||
|
|
||
|
int __cdecl setvbuf (
|
||
|
FILE *str,
|
||
|
char *buffer,
|
||
|
int type,
|
||
|
size_t size
|
||
|
)
|
||
|
{
|
||
|
REG1 FILE *stream;
|
||
|
int retval=0; /* assume good return */
|
||
|
|
||
|
_ASSERTE(str != NULL);
|
||
|
|
||
|
/*
|
||
|
* (1) Make sure type is one of the three legal values.
|
||
|
* (2) If we are buffering, make sure size is greater than 0.
|
||
|
*/
|
||
|
if ( (type != _IONBF) && ((size < 2) || (size > INT_MAX) ||
|
||
|
((type != _IOFBF) && (type != _IOLBF))) )
|
||
|
return(-1);
|
||
|
|
||
|
/*
|
||
|
* force size to be even by masking down to the nearest multiple
|
||
|
* of 2
|
||
|
*/
|
||
|
size &= (size_t)~1;
|
||
|
|
||
|
/*
|
||
|
* Init stream pointers
|
||
|
*/
|
||
|
stream = str;
|
||
|
|
||
|
#ifdef _MT
|
||
|
/*
|
||
|
* Lock the file
|
||
|
*/
|
||
|
_lock_str(stream);
|
||
|
__try {
|
||
|
#endif
|
||
|
|
||
|
/*
|
||
|
* Flush the current buffer and free it, if it is ours.
|
||
|
*/
|
||
|
_flush(stream);
|
||
|
_freebuf(stream);
|
||
|
|
||
|
/*
|
||
|
* Clear a bunch of bits in stream->_flag (all bits related to
|
||
|
* buffering and those which used to be in stream2->_flag2). Most
|
||
|
* of these should never be set when setvbuf() is called, but it
|
||
|
* doesn't cost anything to be safe.
|
||
|
*/
|
||
|
stream->_flag &= ~(_IOMYBUF | _IOYOURBUF | _IONBF |
|
||
|
_IOSETVBUF | _IOFEOF | _IOFLRTN | _IOCTRLZ);
|
||
|
|
||
|
/*
|
||
|
* CASE 1: No Buffering.
|
||
|
*/
|
||
|
if (type & _IONBF) {
|
||
|
stream->_flag |= _IONBF;
|
||
|
buffer = (char *)&(stream->_charbuf);
|
||
|
size = 2;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* NOTE: Cases 2 and 3 (below) cover type == _IOFBF or type == _IOLBF
|
||
|
* Line buffering is treated as the same as full buffering, so the
|
||
|
* _IOLBF bit in stream->_flag is never set. Finally, since _IOFBF is
|
||
|
* defined to be 0, full buffering is simply assumed whenever _IONBF
|
||
|
* is not set.
|
||
|
*/
|
||
|
|
||
|
/*
|
||
|
* CASE 2: Default Buffering -- Allocate a buffer for the user.
|
||
|
*/
|
||
|
else if ( buffer == NULL ) {
|
||
|
if ( (buffer = _malloc_crt(size)) == NULL ) {
|
||
|
#ifndef CRTDLL
|
||
|
/*
|
||
|
* force library pre-termination procedure (placed here
|
||
|
* because the code path should almost never be hit)
|
||
|
*/
|
||
|
_cflush++;
|
||
|
#endif /* CRTDLL */
|
||
|
retval = -1;
|
||
|
goto done;
|
||
|
}
|
||
|
stream->_flag |= _IOMYBUF | _IOSETVBUF;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* CASE 3: User Buffering -- Use the buffer supplied by the user.
|
||
|
*/
|
||
|
else {
|
||
|
stream->_flag |= _IOYOURBUF | _IOSETVBUF;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Common return for all cases.
|
||
|
*/
|
||
|
stream->_bufsiz = (int)size;
|
||
|
stream->_ptr = stream->_base = buffer;
|
||
|
stream->_cnt = 0;
|
||
|
done:
|
||
|
|
||
|
#ifdef _MT
|
||
|
; }
|
||
|
__finally {
|
||
|
_unlock_str(stream);
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
return(retval);
|
||
|
}
|