📄 fflush.c
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// This source code is licensed under Microsoft Shared Source License
// Version 1.0 for Windows CE.
// For a copy of the license visit http://go.microsoft.com/fwlink/?LinkId=3223.
//
/***
*fflush.c - flush a stream buffer
*
*
*Purpose:
* defines fflush() - flush the buffer on a stream
* _flushall() - flush all stream buffers
*
*******************************************************************************/
#include <cruntime.h>
#include <stdio.h>
#include <file2.h>
#include <mtdll.h>
#include <internal.h>
#include <dbgint.h>
/* Values passed to flsall() to distinguish between _flushall() and
* fflush(NULL) behavior
*/
#define FLUSHALL 1
#define FFLUSHNULL 0
/* Core routine for fflush(NULL) and flushall()
*/
static int __cdecl flsall(int);
/***
*int fflush(stream) - flush the buffer on a stream
*
*Purpose:
* if file open for writing and buffered, flush the buffer. if problems
* flushing the buffer, set the stream flag to error
* Always flushes the stdio stream and forces a commit to disk if file
* was opened in commit mode.
*
*Entry:
* FILEX *stream - stream to flush
*
*Exit:
* returns 0 if flushed successfully, or no buffer to flush
* returns EOF and sets file error flag if fails.
* FILEX struct entries affected: _ptr, _cnt, _flag.
*
*Exceptions:
*
*******************************************************************************/
int __cdecl fflush (
REG1 FILEX *stream
)
{
int rc;
if(!CheckStdioInit())
return EOF;
/* if stream is NULL, flush all streams
*/
if ( stream == NULL )
return(flsall(FFLUSHNULL));
if (! _lock_validate_str(stream))
return EOF;
rc = _fflush_lk(stream);
_unlock_str(stream);
return(rc);
}
/***
*_fflush_lk() - Flush the buffer on a stream (stream is already locked)
*
*Purpose:
* Core flush routine; assumes stream lock is held by caller.
*
* [See fflush() above for more information.]
*
*Entry:
* [See fflush()]
*Exit:
* [See fflush()]
*
*Exceptions:
*
*******************************************************************************/
int __cdecl _fflush_lk (
REG1 FILEX *str
)
{
if (_flush(str) != 0)
{
/* _flush failed, don't attempt to commit */
return(EOF);
}
/* lowio commit to ensure data is written to disk */
if (str->_flag & _IOCOMMIT)
{
return (_commit(str) ? 0 : EOF);
}
return 0;
}
/***
*int _flush(stream) - flush the buffer on a single stream
*
*Purpose:
* If file open for writing and buffered, flush the buffer. If
* problems flushing the buffer, set the stream flag to error.
* Multi-thread version assumes stream lock is held by caller.
*
*Entry:
* FILEX* stream - stream to flush
*
*Exit:
* Returns 0 if flushed successfully, or if no buffer to flush.,
* Returns EOF and sets file error flag if fails.
* File struct entries affected: _ptr, _cnt, _flag.
*
*Exceptions:
*
*******************************************************************************/
int __cdecl _flush (
FILEX *str
)
{
REG1 FILEX *stream;
REG2 int rc = 0; /* assume good return */
REG3 int nchar;
/* Init pointer to stream */
stream = str;
if ((stream->_flag & (_IOREAD | _IOWRT)) == _IOWRT && bigbuf(stream)
&& (nchar = stream->_ptr - stream->_base) > 0)
{
if ( _write(stream, stream->_base, nchar) == nchar ) {
/* if this is a read/write file, clear _IOWRT so that
* next operation can be a read
*/
if ( _IORW & stream->_flag )
stream->_flag &= ~_IOWRT;
}
else {
stream->_flag |= _IOERR;
rc = EOF;
}
}
stream->_ptr = stream->_base;
stream->_cnt = 0;
return(rc);
}
/***
*int _flushall() - flush all output buffers
*
*Purpose:
* flushes all the output buffers to the file, clears all input buffers.
*
*Entry:
* None.
*
*Exit:
* returns number of open streams
*
*Exceptions:
*
*******************************************************************************/
int __cdecl _flushall (
void
)
{
return(flsall(FLUSHALL));
}
/***
*static int flsall(flushflag) - flush all output buffers
*
*Purpose:
* Flushes all the output buffers to the file and, if FLUSHALL is passed,
* clears all input buffers. Core routine for both fflush(NULL) and
* flushall().
*
* MTHREAD Note: All the locking/unlocking required for both fflush(NULL)
* and flushall() is performed in this routine.
*
*Entry:
* int flushflag - flag indicating the exact semantics, there are two
* legal values: FLUSHALL and FFLUSHNULL
*
*Exit:
* if flushflag == FFLUSHNULL then flsbuf returns:
0, if successful
* EOF, if an error occurs while flushing one of the streams
*
* if flushflag == FLUSHALL then flsbuf returns the number of streams
* successfully flushed
*
*Exceptions:
*
*******************************************************************************/
static int __cdecl flsall (
int flushflag
)
{
REG1 int i;
int count = 0;
int errcode = 0;
if(!CheckStdioInit())
return EOF;
EnterCriticalSection(&csIobScanLock); // protects the __piob table
for ( i = 0 ; i < _nstream ; i++ ) {
if ( (__piob[i] != NULL) && (inuse(__piob[i])) ) {
/*
* lock the stream. this is not done until testing
* the stream is in use to avoid unnecessarily creating
* a lock for every stream. the price is having to
* retest the stream after the lock has been asserted.
*/
_lock_str2(i, __piob[i]);
/*
* if the stream is STILL in use (it may have been
* closed before the lock was asserted), see about
* flushing it.
*/
if ( inuse(__piob[i]) ) {
if ( flushflag == FLUSHALL ) {
/*
* FLUSHALL functionality: fflush the read or
* write stream and, if successful, update the
* count of flushed streams
*/
if ( _fflush_lk(__piob[i]) != EOF )
/* update count of successfully flushed
* streams
*/
count++;
}
else if ( (flushflag == FFLUSHNULL) &&
(__piob[i]->_flag & _IOWRT) ) {
/*
* FFLUSHNULL functionality: fflush the write
* stream and kept track of the error, if one
* occurs
*/
if ( _fflush_lk(__piob[i]) == EOF )
errcode = EOF;
}
}
_unlock_str2(i, __piob[i]);
}
}
LeaveCriticalSection(&csIobScanLock);
if ( flushflag == FLUSHALL )
return(count);
else
return(errcode);
}
/***
*int _fcloseall() - close all open streams
*
*Purpose:
* Closes all streams currently open except for stdin/out/err/aux/prn.
* tmpfile() files are among those closed.
*
*Entry:
* None.
*
*Exit:
* returns number of streams closed if OK
* returns EOF if fails.
*
*Exceptions:
*
*******************************************************************************/
int __cdecl _fcloseall (
void
)
{
REG2 int count = 0;
int i;
if(!CheckStdioInit())
return EOF;
EnterCriticalSection(&csIobScanLock); // protects the __piob table
for ( i = 3 ; i < _nstream ; i++ ) {
if ( __piob[i] != NULL )
{
//if the stream is in use, close it
if ( inuse(__piob[i] ) && (fclose( __piob[i] ) != EOF) )
count++;
DeleteCriticalSection( &(__piob[i]->lock) );
_free_crt( __piob[i] );
__piob[i] = NULL;
}
}
LeaveCriticalSection(&csIobScanLock);
return(count);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -