* protection, rather than locking the whole table for every change.
*/
static CRITICAL_SECTION file_cs;
+static CRITICAL_SECTION_DEBUG file_cs_debug =
+{
+ 0, 0, &file_cs,
+ { &file_cs_debug.ProcessLocksList, &file_cs_debug.ProcessLocksList },
+ 0, 0, { (DWORD_PTR)(__FILE__ ": file_cs") }
+};
+static CRITICAL_SECTION file_cs = { &file_cs_debug, -1, 0, 0, 0, 0 };
#define LOCK_FILES() do { EnterCriticalSection(&file_cs); } while (0)
#define UNLOCK_FILES() do { LeaveCriticalSection(&file_cs); } while (0)
unsigned int i;
ioinfo *fdinfo;
- InitializeCriticalSection(&file_cs);
- file_cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": file_cs");
GetStartupInfoA(&si);
if (si.cbReserved2 >= sizeof(unsigned int) && si.lpReserved2 != NULL)
{
if (get_ioinfo(fdstart)->handle == INVALID_HANDLE_VALUE) break;
}
- if(!__pioinfo[0])
- set_fd(INVALID_HANDLE_VALUE, 0, 3);
+ fdinfo = get_ioinfo(STDIN_FILENO);
+ if (!(fdinfo->wxflag & WX_OPEN) || fdinfo->handle == INVALID_HANDLE_VALUE) {
+ HANDLE h = GetStdHandle(STD_INPUT_HANDLE);
+ DWORD type = GetFileType(h);
- fdinfo = get_ioinfo(0);
- if (!(fdinfo->wxflag & WX_OPEN) || fdinfo->handle == INVALID_HANDLE_VALUE)
- {
- HANDLE std = GetStdHandle(STD_INPUT_HANDLE);
-#ifndef __REACTOS__
- if (std != INVALID_HANDLE_VALUE && DuplicateHandle(GetCurrentProcess(), std,
- GetCurrentProcess(), &fdinfo->handle,
- 0, TRUE, DUPLICATE_SAME_ACCESS))
-#else
- fdinfo->handle = std;
-#endif
- fdinfo->wxflag = WX_OPEN | WX_TEXT;
+ set_fd(h, WX_OPEN|WX_TEXT|((type&0xf)==FILE_TYPE_CHAR ? WX_NOSEEK : 0)
+ |((type&0xf)==FILE_TYPE_PIPE ? WX_PIPE : 0), STDIN_FILENO);
}
- fdinfo = get_ioinfo(1);
- if (!(fdinfo->wxflag & WX_OPEN) || fdinfo->handle == INVALID_HANDLE_VALUE)
- {
- HANDLE std = GetStdHandle(STD_OUTPUT_HANDLE);
-#ifndef __REACTOS__
- if (std != INVALID_HANDLE_VALUE && DuplicateHandle(GetCurrentProcess(), std,
- GetCurrentProcess(), &fdinfo->handle,
- 0, TRUE, DUPLICATE_SAME_ACCESS))
-#else
- fdinfo->handle = std;
-#endif
- fdinfo->wxflag = WX_OPEN | WX_TEXT;
+ fdinfo = get_ioinfo(STDOUT_FILENO);
+ if (!(fdinfo->wxflag & WX_OPEN) || fdinfo->handle == INVALID_HANDLE_VALUE) {
+ HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE);
+ DWORD type = GetFileType(h);
+
+ set_fd(h, WX_OPEN|WX_TEXT|((type&0xf)==FILE_TYPE_CHAR ? WX_NOSEEK : 0)
+ |((type&0xf)==FILE_TYPE_PIPE ? WX_PIPE : 0), STDOUT_FILENO);
}
- fdinfo = get_ioinfo(2);
- if (!(fdinfo->wxflag & WX_OPEN) || fdinfo->handle == INVALID_HANDLE_VALUE)
- {
- HANDLE std = GetStdHandle(STD_ERROR_HANDLE);
-#ifndef __REACTOS__
- if (std != INVALID_HANDLE_VALUE && DuplicateHandle(GetCurrentProcess(), std,
- GetCurrentProcess(), &fdinfo->handle,
- 0, TRUE, DUPLICATE_SAME_ACCESS))
-#else
- fdinfo->handle = std;
-#endif
- fdinfo->wxflag = WX_OPEN | WX_TEXT;
+ fdinfo = get_ioinfo(STDERR_FILENO);
+ if (!(fdinfo->wxflag & WX_OPEN) || fdinfo->handle == INVALID_HANDLE_VALUE) {
+ HANDLE h = GetStdHandle(STD_ERROR_HANDLE);
+ DWORD type = GetFileType(h);
+
+ set_fd(h, WX_OPEN|WX_TEXT|((type&0xf)==FILE_TYPE_CHAR ? WX_NOSEEK : 0)
+ |((type&0xf)==FILE_TYPE_PIPE ? WX_PIPE : 0), STDERR_FILENO);
}
- TRACE(":handles (%p)(%p)(%p)\n", get_ioinfo(0)->handle,
- get_ioinfo(1)->handle, get_ioinfo(2)->handle);
+ TRACE(":handles (%p)(%p)(%p)\n", get_ioinfo(STDIN_FILENO)->handle,
+ get_ioinfo(STDOUT_FILENO)->handle,
+ get_ioinfo(STDERR_FILENO)->handle);
memset(_iob,0,3*sizeof(FILE));
for (i = 0; i < 3; i++)
return 0;
}
+/*********************************************************************
+ * _isatty (MSVCRT.@)
+ */
+int CDECL _isatty(int fd)
+{
+ HANDLE hand = fdtoh(fd);
+
+ TRACE(":fd (%d) handle (%p)\n",fd,hand);
+ if (hand == INVALID_HANDLE_VALUE)
+ return 0;
+
+ return GetFileType(hand) == FILE_TYPE_CHAR? 1 : 0;
+}
+
/* INTERNAL: Allocate stdio file buffer */
-/*static*/ void alloc_buffer(FILE* file)
+/*static*/ BOOL alloc_buffer(FILE* file)
{
- file->_base = calloc(BUFSIZ,1);
- if(file->_base) {
- file->_bufsiz = BUFSIZ;
- file->_flag |= _IOMYBUF;
- } else {
- file->_base = (char*)(&file->_charbuf);
- /* put here 2 ??? */
- file->_bufsiz = sizeof(file->_charbuf);
- }
- file->_ptr = file->_base;
- file->_cnt = 0;
+ if((file->_file==STDOUT_FILENO || file->_file==STDERR_FILENO)
+ && _isatty(file->_file))
+ return FALSE;
+
+ file->_base = calloc(BUFSIZ,1);
+ if(file->_base) {
+ file->_bufsiz = BUFSIZ;
+ file->_flag |= _IOMYBUF;
+ } else {
+ file->_base = (char*)(&file->_charbuf);
+ /* put here 2 ??? */
+ file->_bufsiz = sizeof(file->_charbuf);
+ }
+ file->_ptr = file->_base;
+ file->_cnt = 0;
+ return TRUE;
}
/* INTERNAL: Convert integer to base32 string (0-9a-v), 0 becomes "" */
/* free everything on process exit */
void msvcrt_free_io(void)
{
- int i;
+ unsigned int i;
+ int j;
+ _flushall();
_fcloseall();
- /* The Win32 _fcloseall() function explicitly doesn't close stdin,
- * stdout, and stderr (unlike GNU), so we need to fclose() them here
- * or they won't get flushed.
- */
- fclose(&_iob[0]);
- fclose(&_iob[1]);
- fclose(&_iob[2]);
for(i=0; i<sizeof(__pioinfo)/sizeof(__pioinfo[0]); i++)
free(__pioinfo[i]);
+ for(j=0; j<stream_idx; j++)
+ {
+ FILE *file = get_file(j);
+ if(file<_iob || file>=_iob+_IOB_ENTRIES)
+ {
+ ((file_crit*)file)->crit.DebugInfo->Spare[0] = 0;
+ DeleteCriticalSection(&((file_crit*)file)->crit);
+ }
+ }
+
for(i=0; i<sizeof(fstream)/sizeof(fstream[0]); i++)
free(fstream[i]);
- file_cs.DebugInfo->Spare[0] = 0;
DeleteCriticalSection(&file_cs);
}
return (intptr_t)hand;
}
-/*********************************************************************
- * _isatty (MSVCRT.@)
- */
-int CDECL _isatty(int fd)
-{
- HANDLE hand = fdtoh(fd);
-
- TRACE(":fd (%d) handle (%p)\n",fd,hand);
- if (hand == INVALID_HANDLE_VALUE)
- return 0;
-
- return GetFileType(hand) == FILE_TYPE_CHAR? 1 : 0;
-}
-
/*********************************************************************
* _mktemp (MSVCRT.@)
*/
return num_removed;
}
+static inline int get_utf8_char_len(char ch)
+{
+ if((ch&0xf8) == 0xf0)
+ return 4;
+ else if((ch&0xf0) == 0xe0)
+ return 3;
+ else if((ch&0xe0) == 0xc0)
+ return 2;
+ return 1;
+}
+
+/*********************************************************************
+ * (internal) read_utf8
+ */
+static int read_utf8(int fd, wchar_t *buf, unsigned int count)
+{
+ ioinfo *fdinfo = get_ioinfo(fd);
+ HANDLE hand = fdinfo->handle;
+ char min_buf[4], *readbuf, lookahead;
+ DWORD readbuf_size, pos=0, num_read=1, char_len, i, j;
+
+ /* make the buffer big enough to hold at least one character */
+ /* read bytes have to fit to output and lookahead buffers */
+ count /= 2;
+ readbuf_size = count < 4 ? 4 : count;
+ if(readbuf_size<=4 || !(readbuf = malloc(readbuf_size))) {
+ readbuf_size = 4;
+ readbuf = min_buf;
+ }
+
+ if(fdinfo->lookahead[0] != '\n') {
+ readbuf[pos++] = fdinfo->lookahead[0];
+ fdinfo->lookahead[0] = '\n';
+
+ if(fdinfo->lookahead[1] != '\n') {
+ readbuf[pos++] = fdinfo->lookahead[1];
+ fdinfo->lookahead[1] = '\n';
+
+ if(fdinfo->lookahead[2] != '\n') {
+ readbuf[pos++] = fdinfo->lookahead[2];
+ fdinfo->lookahead[2] = '\n';
+ }
+ }
+ }
+
+ /* NOTE: this case is broken in native dll, reading
+ * sometimes fails when small buffer is passed
+ */
+ if(count < 4) {
+ if(!pos && !ReadFile(hand, readbuf, 1, &num_read, NULL)) {
+ if (GetLastError() == ERROR_BROKEN_PIPE) {
+ fdinfo->wxflag |= WX_ATEOF;
+ return 0;
+ }else {
+ _dosmaperr(GetLastError());
+ return -1;
+ }
+ }else if(!num_read) {
+ fdinfo->wxflag |= WX_ATEOF;
+ return 0;
+ }else {
+ pos++;
+ }
+
+ char_len = get_utf8_char_len(readbuf[0]);
+ if(char_len>pos) {
+ if(ReadFile(hand, readbuf+pos, char_len-pos, &num_read, NULL))
+ pos += num_read;
+ }
+
+ if(readbuf[0] == '\n')
+ fdinfo->wxflag |= WX_READNL;
+ else
+ fdinfo->wxflag &= ~WX_READNL;
+
+ if(readbuf[0] == 0x1a) {
+ fdinfo->wxflag |= WX_ATEOF;
+ return 0;
+ }
+
+ if(readbuf[0] == '\r') {
+ if(!ReadFile(hand, &lookahead, 1, &num_read, NULL) || num_read!=1)
+ buf[0] = '\r';
+ else if(lookahead == '\n')
+ buf[0] = '\n';
+ else {
+ buf[0] = '\r';
+ if(fdinfo->wxflag & (WX_PIPE | WX_NOSEEK))
+ fdinfo->lookahead[0] = lookahead;
+ else
+ SetFilePointer(fdinfo->handle, -1, NULL, FILE_CURRENT);
+ }
+ return 2;
+ }
+
+ if(!(num_read = MultiByteToWideChar(CP_UTF8, 0, readbuf, pos, buf, count))) {
+ _dosmaperr(GetLastError());
+ return -1;
+ }
+
+ return num_read*2;
+ }
+
+ if(!ReadFile(hand, readbuf+pos, readbuf_size-pos, &num_read, NULL)) {
+ if(pos) {
+ num_read = 0;
+ }else if(GetLastError() == ERROR_BROKEN_PIPE) {
+ fdinfo->wxflag |= WX_ATEOF;
+ if (readbuf != min_buf) free(readbuf);
+ return 0;
+ }else {
+ _dosmaperr(GetLastError());
+ if (readbuf != min_buf) free(readbuf);
+ return -1;
+ }
+ }else if(!pos && !num_read) {
+ fdinfo->wxflag |= WX_ATEOF;
+ if (readbuf != min_buf) free(readbuf);
+ return 0;
+ }
+
+ pos += num_read;
+ if(readbuf[0] == '\n')
+ fdinfo->wxflag |= WX_READNL;
+ else
+ fdinfo->wxflag &= ~WX_READNL;
+
+ /* Find first byte of last character (may be incomplete) */
+ for(i=pos-1; i>0 && i>pos-4; i--)
+ if((readbuf[i]&0xc0) != 0x80)
+ break;
+ char_len = get_utf8_char_len(readbuf[i]);
+ if(char_len+i <= pos)
+ i += char_len;
+
+ if(fdinfo->wxflag & (WX_PIPE | WX_NOSEEK)) {
+ if(i < pos)
+ fdinfo->lookahead[0] = readbuf[i];
+ if(i+1 < pos)
+ fdinfo->lookahead[1] = readbuf[i+1];
+ if(i+2 < pos)
+ fdinfo->lookahead[2] = readbuf[i+2];
+ }else if(i < pos) {
+ SetFilePointer(fdinfo->handle, i-pos, NULL, FILE_CURRENT);
+ }
+ pos = i;
+
+ for(i=0, j=0; i<pos; i++) {
+ if(readbuf[i] == 0x1a) {
+ fdinfo->wxflag |= WX_ATEOF;
+ break;
+ }
+
+ /* strip '\r' if followed by '\n' */
+ if(readbuf[i] == '\r' && i+1==pos) {
+ if(fdinfo->lookahead[0] != '\n' || !ReadFile(hand, &lookahead, 1, &num_read, NULL) || !num_read) {
+ readbuf[j++] = '\r';
+ }else if(lookahead == '\n' && j==0) {
+ readbuf[j++] = '\n';
+ }else {
+ if(lookahead != '\n')
+ readbuf[j++] = '\r';
+
+ if(fdinfo->wxflag & (WX_PIPE | WX_NOSEEK))
+ fdinfo->lookahead[0] = lookahead;
+ else
+ SetFilePointer(fdinfo->handle, -1, NULL, FILE_CURRENT);
+ }
+ }else if(readbuf[i]!='\r' || readbuf[i+1]!='\n') {
+ readbuf[j++] = readbuf[i];
+ }
+ }
+ pos = j;
+
+ if(!(num_read = MultiByteToWideChar(CP_UTF8, 0, readbuf, pos, buf, count))) {
+ _dosmaperr(GetLastError());
+ if (readbuf != min_buf) free(readbuf);
+ return -1;
+ }
+
+ if (readbuf != min_buf) free(readbuf);
+ return num_read*2;
+}
+
/*********************************************************************
* (internal) read_i
*
*/
static int read_i(int fd, void *buf, unsigned int count)
{
- DWORD num_read;
- char *bufstart = buf;
- HANDLE hand = fdtoh(fd);
- ioinfo *fdinfo = get_ioinfo(fd);
+ DWORD num_read, utf16;
+ char *bufstart = buf;
+ HANDLE hand = fdtoh(fd);
+ ioinfo *fdinfo = get_ioinfo(fd);
- if (count == 0)
- return 0;
+ if (count == 0)
+ return 0;
- if (fdinfo->wxflag & WX_READEOF) {
- fdinfo->wxflag |= WX_ATEOF;
- TRACE("already at EOF, returning 0\n");
- return 0;
- }
- /* Don't trace small reads, it gets *very* annoying */
- if (count > 4)
- TRACE(":fd (%d) handle (%p) buf (%p) len (%d)\n",fd,hand,buf,count);
- if (hand == INVALID_HANDLE_VALUE)
- return -1;
+ if (fdinfo->wxflag & WX_ATEOF) {
+ TRACE("already at EOF, returning 0\n");
+ return 0;
+ }
+ /* Don't trace small reads, it gets *very* annoying */
+ if (count > 4)
+ TRACE(":fd (%d) handle (%p) buf (%p) len (%d)\n",fd,hand,buf,count);
+ if (hand == INVALID_HANDLE_VALUE)
+ {
+ *_errno() = EBADF;
+ return -1;
+ }
- /* Reading single bytes in O_TEXT mode makes things slow
- * So read big chunks
- */
- if (ReadFile(hand, bufstart, count, &num_read, NULL))
+ utf16 = (fdinfo->exflag & EF_UTF16) != 0;
+ if (((fdinfo->exflag&EF_UTF8) || utf16) && count&1)
{
+ *_errno() = EINVAL;
+ return -1;
+ }
+
+ if((fdinfo->wxflag&WX_TEXT) && (fdinfo->exflag&EF_UTF8))
+ return read_utf8(fd, buf, count);
+
+ if (fdinfo->lookahead[0]!='\n' || ReadFile(hand, bufstart, count, &num_read, NULL))
+ {
+ if (fdinfo->lookahead[0] != '\n')
+ {
+ bufstart[0] = fdinfo->lookahead[0];
+ fdinfo->lookahead[0] = '\n';
+
+ if (utf16)
+ {
+ bufstart[1] = fdinfo->lookahead[1];
+ fdinfo->lookahead[1] = '\n';
+ }
+
+ if(count>1+utf16 && ReadFile(hand, bufstart+1+utf16, count-1-utf16, &num_read, NULL))
+ num_read += 1+utf16;
+ else
+ num_read = 1+utf16;
+ }
+
+ if(utf16 && (num_read&1))
+ {
+ /* msvcr90 uses uninitialized value from the buffer in this case */
+ /* msvcrt ignores additional data */
+ ERR("got odd number of bytes in UTF16 mode\n");
+ num_read--;
+ }
+
if (count != 0 && num_read == 0)
{
- fdinfo->wxflag |= (WX_ATEOF|WX_READEOF);
+ fdinfo->wxflag |= WX_ATEOF;
TRACE(":EOF %s\n",debugstr_an(buf,num_read));
}
else if (fdinfo->wxflag & WX_TEXT)
{
DWORD i, j;
- if (bufstart[num_read-1] == '\r')
+
+ if (bufstart[0]=='\n' && (!utf16 || bufstart[1]==0))
+ fdinfo->wxflag |= WX_READNL;
+ else
+ fdinfo->wxflag &= ~WX_READNL;
+
+ for (i=0, j=0; i<num_read; i+=1+utf16)
{
- if(count == 1)
+ /* in text mode, a ctrl-z signals EOF */
+ if (bufstart[i]==0x1a && (!utf16 || bufstart[i+1]==0))
{
- fdinfo->wxflag &= ~WX_READCR;
- ReadFile(hand, bufstart, 1, &num_read, NULL);
+ fdinfo->wxflag |= WX_ATEOF;
+ TRACE(":^Z EOF %s\n",debugstr_an(buf,num_read));
+ break;
}
- else
+
+ /* in text mode, strip \r if followed by \n */
+ if (bufstart[i]=='\r' && (!utf16 || bufstart[i+1]==0) && i+1+utf16==num_read)
{
- fdinfo->wxflag |= WX_READCR;
- num_read--;
+ char lookahead[2];
+ DWORD len;
+
+ lookahead[1] = '\n';
+ if (ReadFile(hand, lookahead, 1+utf16, &len, NULL) && len)
+ {
+ if(lookahead[0]=='\n' && (!utf16 || lookahead[1]==0) && j==0)
+ {
+ bufstart[j++] = '\n';
+ if(utf16) bufstart[j++] = 0;
+ }
+ else
+ {
+ if(lookahead[0]!='\n' || (utf16 && lookahead[1]!=0))
+ {
+ bufstart[j++] = '\r';
+ if(utf16) bufstart[j++] = 0;
+ }
+
+ if (fdinfo->wxflag & (WX_PIPE | WX_NOSEEK))
+ {
+ if (lookahead[0]=='\n' && (!utf16 || !lookahead[1]))
+ {
+ bufstart[j++] = '\n';
+ if (utf16) bufstart[j++] = 0;
+ }
+ else
+ {
+ fdinfo->lookahead[0] = lookahead[0];
+ fdinfo->lookahead[1] = lookahead[1];
+ }
+ }
+ else
+ SetFilePointer(fdinfo->handle, -1-utf16, NULL, FILE_CURRENT);
+ }
+ }
+ else
+ {
+ bufstart[j++] = '\r';
+ if(utf16) bufstart[j++] = 0;
+ }
}
- }
- else
- fdinfo->wxflag &= ~WX_READCR;
- for (i=0, j=0; i<num_read; i++)
- {
- /* in text mode, a ctrl-z signals EOF */
- if (bufstart[i] == 0x1a)
+ else if((bufstart[i]!='\r' || (utf16 && bufstart[i+1]!=0))
+ || (bufstart[i+1+utf16]!='\n' || (utf16 && bufstart[i+3]!=0)))
{
- fdinfo->wxflag |= (WX_ATEOF|WX_READEOF);
- TRACE(":^Z EOF %s\n",debugstr_an(buf,num_read));
- break;
+ bufstart[j++] = bufstart[i];
+ if(utf16) bufstart[j++] = bufstart[i+1];
}
- /* in text mode, strip \r if followed by \n.
- * BUG: should save state across calls somehow, so CR LF that
- * straddles buffer boundary gets recognized properly?
- */
- if ((bufstart[i] != '\r')
- || ((i+1) < num_read && bufstart[i+1] != '\n'))
- bufstart[j++] = bufstart[i];
}
num_read = j;
}
if (GetLastError() == ERROR_BROKEN_PIPE)
{
TRACE(":end-of-pipe\n");
- fdinfo->wxflag |= (WX_ATEOF|WX_READEOF);
+ fdinfo->wxflag |= WX_ATEOF;
return 0;
}
else
}
}
- if (count > 4)
- TRACE("(%u), %s\n",num_read,debugstr_an(buf, num_read));
- return num_read;
+ if (count > 4)
+ TRACE("(%u), %s\n",num_read,debugstr_an(buf, num_read));
+ return num_read;
}
/*********************************************************************
/*********************************************************************
* fgetwc (MSVCRT.@)
- *
- * In _O_TEXT mode, multibyte characters are read from the file, dropping
- * the CR from CR/LF combinations
*/
wint_t CDECL fgetwc(FILE* file)
{
- int c;
+ wint_t ret;
+ int ch;
- _lock_file(file);
- if (!(get_ioinfo(file->_file)->wxflag & WX_TEXT))
- {
- wchar_t wc;
- unsigned int i;
- int j;
- char *chp, *wcp;
- wcp = (char *)&wc;
- for(i=0; i<sizeof(wc); i++)
- {
- if (file->_cnt>0)
- {
- file->_cnt--;
- chp = file->_ptr++;
- wcp[i] = *chp;
- }
- else
- {
- j = _filbuf(file);
- if(file->_cnt<=0)
- {
- file->_flag |= (file->_cnt == 0) ? _IOEOF : _IOERR;
- file->_cnt = 0;
+ _lock_file(file);
- _unlock_file(file);
- return WEOF;
- }
- wcp[i] = j;
- }
- }
+ if((get_ioinfo(file->_file)->exflag & (EF_UTF8 | EF_UTF16))
+ || !(get_ioinfo(file->_file)->wxflag & WX_TEXT)) {
+ char *p;
- _unlock_file(file);
- return wc;
- }
+ for(p=(char*)&ret; (wint_t*)p<&ret+1; p++) {
+ ch = fgetc(file);
+ if(ch == EOF) {
+ ret = WEOF;
+ break;
+ }
+ *p = (char)ch;
+ }
+ }else {
+ char mbs[MB_LEN_MAX];
+ int len = 0;
+
+ ch = fgetc(file);
+ if(ch != EOF) {
+ mbs[0] = (char)ch;
+ if(isleadbyte((unsigned char)mbs[0])) {
+ ch = fgetc(file);
+ if(ch != EOF) {
+ mbs[1] = (char)ch;
+ len = 2;
+ }
+ }else {
+ len = 1;
+ }
+ }
- c = fgetc(file);
- if ((__mb_cur_max > 1) && isleadbyte(c))
- {
- FIXME("Treat Multibyte characters\n");
+ if(!len || mbtowc(&ret, mbs, len)==-1)
+ ret = WEOF;
}
- _unlock_file(file);
- if (c == EOF)
- return WEOF;
- else
- return (wint_t)c;
+ _unlock_file(file);
+ return ret;
}
/*********************************************************************
int CDECL fopen_s(FILE** pFile,
const char *filename, const char *mode)
{
- if (!MSVCRT_CHECK_PMT(pFile != NULL) || !MSVCRT_CHECK_PMT(filename != NULL) ||
- !MSVCRT_CHECK_PMT(mode != NULL)) {
- *_errno() = EINVAL;
- return EINVAL;
- }
+ if (!MSVCRT_CHECK_PMT(pFile != NULL)) return EINVAL;
+ if (!MSVCRT_CHECK_PMT(filename != NULL)) return EINVAL;
+ if (!MSVCRT_CHECK_PMT(mode != NULL)) return EINVAL;
*pFile = fopen(filename, mode);
while(rcnt>0)
{
int i;
- /* Fill the buffer on small reads.
- * TODO: Use a better buffering strategy.
- */
- if (!file->_cnt && size*nmemb <= BUFSIZ/2 && !(file->_flag & _IONBF)) {
- if (file->_bufsiz == 0) {
- alloc_buffer(file);
- }
+ if (!file->_cnt && rcnt<BUFSIZ && !(file->_flag & _IONBF)
+ && (file->_bufsiz != 0 || alloc_buffer(file))) {
file->_cnt = _read(file->_file, file->_base, file->_bufsiz);
file->_ptr = file->_base;
i = ((unsigned int)file->_cnt<rcnt) ? file->_cnt : rcnt;
file->_cnt -= i;
file->_ptr += i;
}
+ } else if (rcnt > UINT_MAX) {
+ i = _read(file->_file, ptr, UINT_MAX);
+ } else if (rcnt < BUFSIZ) {
+ i = _read(file->_file, ptr, rcnt);
} else {
- i = _read(file->_file,ptr, rcnt);
+ i = _read(file->_file, ptr, rcnt - BUFSIZ/2);
}
pread += i;
rcnt -= i;
return EOF;
_lock_file(file);
- if(file->_bufsiz == 0) {
- alloc_buffer(file);
+ if(file->_bufsiz == 0 && alloc_buffer(file))
file->_ptr++;
- }
if(file->_ptr>file->_base) {
file->_ptr--;
- *file->_ptr=c;
+ if(file->_flag & _IOSTRG) {
+ if(*file->_ptr != c) {
+ file->_ptr++;
+ _unlock_file(file);
+ return EOF;
+ }
+ }else {
+ *file->_ptr = c;
+ }
file->_cnt++;
clearerr(file);
_unlock_file(file);