int __cdecl _flush ( FILE *str ) { REG1 FILE *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(_fileno(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 fflush(FILE *stream) { int rc = 0; int count; int written; if (!stream) stream = stdout; if ((stream->flag & (_IORD | _IOWR)) == _IOWR && bigbuf(stream) && (count = stream->ptr - stream->base) > 0) { if (stream->flag & _IOCRLF) { written = write_translated(fileno(stream), stream->base, count); } else { written = write(fileno(stream), stream->base, count); } if (written == count) { // If this is a read/write file, clear _IOWR so that next operation can be a read if (stream->flag & _IORW) stream->flag &= ~_IOWR; } else { stream->flag |= _IOERR; rc = EOF; } } stream->ptr = stream->base; stream->cnt = 0; return rc; }
long ftell(FILE *stream) { long filepos; if (stream->cnt < 0) stream->cnt = 0; if ((filepos = tell(fileno(stream))) < 0L) return -1; if (!bigbuf(stream)) return filepos - stream->cnt; if (stream->flag & _IORD) { filepos -= stream->cnt; } else if (stream->flag & _IOWR) { filepos += (stream->ptr - stream->base); } return filepos; }
size_t fwrite(const void *buffer, size_t size, size_t num, FILE *stream) { const char *data; // Point to where data comes from next unsigned total; // Total bytes to write unsigned count; // Num bytes left to write unsigned bufsize; // Size of stream buffer unsigned nbytes; // Number of bytes to write now unsigned nwritten; // Number of bytes written int c; // A temp char // Initialize local vars data = buffer; count = total = size * num; if (count == 0) return 0; if (anybuf(stream)) { // Already has buffer, use its size bufsize = stream->bufsiz; } else { // Assume will get BUFSIZ buffer bufsize = BUFSIZ; } // Here is the main loop -- we go through here until we're done while (count != 0) { // If the buffer is big and has room, copy data to buffer if (bigbuf(stream) && stream->cnt != 0) { // How much do we want? nbytes = (count < (unsigned) stream->cnt) ? count : stream->cnt; memcpy(stream->ptr, data, nbytes); // Update stream and amount of data written count -= nbytes; stream->cnt -= nbytes; stream->ptr += nbytes; data += nbytes; } else if (count >= bufsize) { // If we have more than bufsize chars to write, write // data by calling write with an integral number of // bufsiz blocks. If we reach here and we have a big // buffer, it must be full so flush it. if (bigbuf(stream)) { if (fflush(stream)) { // Error, stream flags set -- we're out of here return (total - count) / size; } } // Calc chars to write -- (count / bufsize) * bufsize nbytes = bufsize ? (count - count % bufsize) : count; if (stream->flag & _IOCRLF) { nwritten = write_translated(fileno(stream), (char *) data, nbytes); } else { nwritten = write(fileno(stream), data, nbytes); } if ((int) nwritten < 0) { // Error -- out of here stream->flag |= _IOERR; return (total - count) / size; } // Update count and data to reflect write count -= nwritten; data += nwritten; if (nwritten < nbytes) { // Error -- out of here stream->flag |= _IOERR; return (total - count) / size; } } else { // Buffer full and not enough chars to do direct write, so do a flsbuf. c = *data; if (flsbuf(c, stream) == EOF) { // Error or eof, stream flags set by _flsbuf return (total - count) / size; } // flsbuf wrote a char -- update count ++data; --count; // Update buffer size bufsize = stream->bufsiz > 0 ? stream->bufsiz : 1; } } // We finished successfully, so just return num return num; }
int flsbuf(int ch, FILE *stream) { int count; int written; int fh; char chbuf; fh = fileno(stream); if (!(stream->flag & (_IOWR | _IORW)) || (stream->flag & _IOSTR)) { stream->flag |= _IOERR; return -1; } if (stream->flag & _IORD) { stream->cnt = 0; if (stream->flag & _IOEOF) { stream->ptr = stream->base; stream->flag &= ~_IORD; } else { stream->flag |= _IOERR; return -1; } } stream->flag |= _IOWR; stream->flag &= ~_IOEOF; written = count = stream->cnt = 0; // Get a buffer for this stream, if necessary if (!anybuf(stream)) getbuf(stream); // If big buffer is assigned to stream if (bigbuf(stream)) { count = stream->ptr - stream->base; stream->ptr = stream->base + 1; stream->cnt = stream->bufsiz - 1; if (count > 0) { if (stream->flag & _IOCRLF) { written = write_translated(fh, stream->base, count); } else { written = write(fh, stream->base, count); } } *stream->base = (char) ch; } else { // Perform single character output (either _IONBF or no buffering) count = 1; chbuf = (char) ch; if (stream->flag & _IOCRLF) { written = write_translated(fh, &chbuf, count); } else { written = write(fh, &chbuf, count); } } // See if the write was successful. if (written != count) { stream->flag |= _IOERR; return -1; } return ch & 0xff; }
int __cdecl _flswbuf ( int ch, FILE *str ) #endif /* _UNICODE */ { REG1 FILE *stream; REG2 int charcount; REG3 int written; int fh; _ASSERTE(str != NULL); /* Init file handle and pointers */ stream = str; fh = _fileno(stream); if (!(stream->_flag & (_IOWRT|_IORW))) { errno = EBADF; stream->_flag |= _IOERR; return(_TEOF); } else if ((stream->_flag & _IOSTRG)) { errno = ERANGE; stream->_flag |= _IOERR; return(_TEOF); } /* Check that _IOREAD is not set or, if it is, then so is _IOEOF. Note that _IOREAD and IOEOF both being set implies switching from read to write at end-of-file, which is allowed by ANSI. Note that resetting the _cnt and _ptr fields amounts to doing an fflush() on the stream in this case. Note also that the _cnt field has to be reset to 0 for the error path as well (i.e., _IOREAD set but _IOEOF not set) as well as the non-error path. */ if (stream->_flag & _IOREAD) { stream->_cnt = 0; if (stream->_flag & _IOEOF) { stream->_ptr = stream->_base; stream->_flag &= ~_IOREAD; } else { stream->_flag |= _IOERR; return(_TEOF); } } stream->_flag |= _IOWRT; stream->_flag &= ~_IOEOF; written = charcount = stream->_cnt = 0; /* Get a buffer for this stream, if necessary. */ if (!anybuf(stream)) { /* Do NOT get a buffer if (1) stream is stdout/stderr, and (2) stream is NOT a tty. [If stdout/stderr is a tty, we do NOT set up single char buffering. This is so that later temporary buffering will not be thwarted by the _IONBF bit being set (see _stbuf/_ftbuf usage).] */ if (!( ((stream==stdout) || (stream==stderr)) && (_isatty(fh)) )) _getbuf(stream); } /* end !anybuf() */ /* If big buffer is assigned to stream... */ if (bigbuf(stream)) { _ASSERTE(("inconsistent IOB fields", stream->_ptr - stream->_base >= 0)); charcount = (int)(stream->_ptr - stream->_base); stream->_ptr = stream->_base + sizeof(TCHAR); stream->_cnt = stream->_bufsiz - (int)sizeof(TCHAR); if (charcount > 0) written = _write(fh, stream->_base, charcount); else if (_osfile_safe(fh) & FAPPEND) { if( _lseeki64(fh,0L,SEEK_END)==-1) { stream->_flag |= _IOERR; return(_TEOF); } } #ifndef _UNICODE *stream->_base = (char)ch; #else /* _UNICODE */ *(wchar_t *)(stream->_base) = (wchar_t)(ch & 0xffff); #endif /* _UNICODE */ } /* Perform single character output (either _IONBF or no buffering) */ else { charcount = sizeof(TCHAR); #ifndef _UNICODE written = _write(fh, &ch, charcount); #else /* _UNICODE */ { char mbc[4]; *(wchar_t *)mbc = (wchar_t)(ch & 0xffff); written = _write(fh, mbc, charcount); } #endif /* _UNICODE */ } /* See if the _write() was successful. */ if (written != charcount) { stream->_flag |= _IOERR; return(_TEOF); } #ifndef _UNICODE return(ch & 0xff); #else /* _UNICODE */ return(ch & 0xffff); #endif /* _UNICODE */ }
int __cdecl _fflush_lk ( REG1 FILE *str ) { #else /* _MT */ int __cdecl fflush ( REG1 FILE *str ) { /* if stream is NULL, flush all streams */ if ( str == NULL ) { return(flsall(FFLUSHNULL)); } #endif /* _MT */ 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(_fileno(str)) ? EOF : 0); } 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: * FILE* 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 ( FILE *str ) { REG1 FILE *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(_fileno(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); }
/* define the normal version */ #ifdef _MT size_t __cdecl _fwrite_lk ( #else /* _MT */ size_t __cdecl fwrite ( #endif /* _MT */ const void *buffer, size_t size, size_t num, FILE *stream ) { const char *data; /* point to where data comes from next */ unsigned total; /* total bytes to write */ unsigned count; /* num bytes left to write */ unsigned bufsize; /* size of stream buffer */ unsigned nbytes; /* number of bytes to write now */ unsigned nwritten; /* number of bytes written */ int c; /* a temp char */ /* initialize local vars */ data = buffer; count = total = size * num; if (0 == count) return 0; if (anybuf(stream)) /* already has buffer, use its size */ bufsize = stream->_bufsiz; else #if defined (_M_M68K) || defined (_M_MPPC) /* assume will get BUFSIZ buffer */ bufsize = BUFSIZ; #else /* defined (_M_M68K) || defined (_M_MPPC) */ /* assume will get _INTERNAL_BUFSIZ buffer */ bufsize = _INTERNAL_BUFSIZ; #endif /* defined (_M_M68K) || defined (_M_MPPC) */ /* here is the main loop -- we go through here until we're done */ while (count != 0) { /* if the buffer is big and has room, copy data to buffer */ if (bigbuf(stream) && stream->_cnt != 0) { /* how much do we want? */ nbytes = (count < (unsigned)stream->_cnt) ? count : stream->_cnt; memcpy(stream->_ptr, data, nbytes); /* update stream and amt of data written */ count -= nbytes; stream->_cnt -= nbytes; stream->_ptr += nbytes; data += nbytes; } else if (count >= bufsize) { /* If we have more than bufsize chars to write, write data by calling write with an integral number of bufsiz blocks. If we reach here and we have a big buffer, it must be full so _flush it. */ if (bigbuf(stream)) { if (_flush(stream)) { /* error, stream flags set -- we're out of here */ return (total - count) / size; } } /* calc chars to read -- (count/bufsize) * bufsize */ nbytes = ( bufsize ? (count - count % bufsize) : count ); nwritten = _write(_fileno(stream), data, nbytes); if (nwritten == (unsigned)EOF) { /* error -- out of here */ stream->_flag |= _IOERR; return (total - count) / size; } /* update count and data to reflect write */ count -= nwritten; data += nwritten; if (nwritten < nbytes) { /* error -- out of here */ stream->_flag |= _IOERR; return (total - count) / size; } } else { /* buffer full and not enough chars to do direct write, so do a _flsbuf. */ c = *data; /* _flsbuf write one char, this is it */ if (_flsbuf(c, stream) == EOF) { /* error or eof, stream flags set by _flsbuf */ return (total - count) / size; } /* _flsbuf wrote a char -- update count */ ++data; --count; /* update buffer size */ bufsize = stream->_bufsiz > 0 ? stream->_bufsiz : 1; } } /* we finished successfully, so just return num */ return num; }
long __cdecl _ftell_nolock( FILE* str ) { REG1 FILE* stream; unsigned int offset; long filepos; REG2 char* p; char* max; int fd; unsigned int rdcnt; _VALIDATE_RETURN((str != NULL), EINVAL, (-1L)); /* Init stream pointer and file descriptor */ stream = str; fd = _fileno(stream); if (stream->_cnt < 0) { stream->_cnt = 0; } if ((filepos = _lseek(fd, 0L, SEEK_CUR)) < 0L) { return (-1L); } if (!bigbuf(stream)) { /* _IONBF or no buffering designated */ return (filepos - stream->_cnt); } offset = (unsigned)(stream->_ptr - stream->_base); if (stream->_flag & (_IOWRT | _IOREAD)) { if (_osfile(fd) & FTEXT) for (p = stream->_base; p < stream->_ptr; p++) if (*p == '\n') { /* adjust for '\r' */ offset++; } } else if (!(stream->_flag & _IORW)) { errno = EINVAL; return (-1L); } if (filepos == 0L) { return ((long)offset); } if (stream->_flag & _IOREAD) /* go to preceding sector */ if (stream->_cnt == 0) { /* filepos holds correct location */ offset = 0; } else { /* Subtract out the number of unread bytes left in the buffer. [We can't simply use _iob[]._bufsiz because the last read may have hit EOF and, thus, the buffer was not completely filled.] */ rdcnt = stream->_cnt + (unsigned)(stream->_ptr - stream->_base); /* If text mode, adjust for the cr/lf substitution. If binary mode, we're outta here. */ if (_osfile(fd) & FTEXT) { /* (1) If we're not at eof, simply copy _bufsiz onto rdcnt to get the # of untranslated chars read. (2) If we're at eof, we must look through the buffer expanding the '\n' chars one at a time. */ /* [NOTE: Performance issue -- it is faster to do the two _lseek() calls than to blindly go through and expand the '\n' chars regardless of whether we're at eof or not.] */ if (_lseek(fd, 0L, SEEK_END) == filepos) { max = stream->_base + rdcnt; for (p = stream->_base; p < max; p++) if (*p == '\n') /* adjust for '\r' */ { rdcnt++; } /* If last byte was ^Z, the lowio read didn't tell us about it. Check flag and bump count, if necessary. */ if (stream->_flag & _IOCTRLZ) { ++rdcnt; } } else { if (_lseek(fd, filepos, SEEK_SET) < 0) { return (-1); } /* We want to set rdcnt to the number of bytes originally read into the stream buffer (before crlf->lf translation). In most cases, this will just be _bufsiz. However, the buffer size may have been changed, due to fseek optimization, at the END of the last _filbuf call. */ if ((rdcnt <= _SMALL_BUFSIZ) && (stream->_flag & _IOMYBUF) && !(stream->_flag & _IOSETVBUF)) { /* The translated contents of the buffer is small and we are not at eof. The buffer size must have been set to _SMALL_BUFSIZ during the last _filbuf call. */ rdcnt = _SMALL_BUFSIZ; } else { rdcnt = stream->_bufsiz; } /* If first byte in untranslated buffer was a '\n', assume it was preceeded by a '\r' which was discarded by the previous read operation and count the '\n'. */ if (_osfile(fd) & FCRLF) { ++rdcnt; } } } /* end if FTEXT */ filepos -= (long)rdcnt; } /* end else stream->_cnt != 0 */ return (filepos + (long)offset); }