- rewrote the file code so that streams manage low level file desc
(the code was written the other way around)
- reworked the flag handling code (now the stream._flag is closer to
what MS does)
- simplified temp files handling by using FILE_FLAG_DELETE_ON_CLOSE in
CreateFile
- fixed a couple of bugs
diff --git a/dlls/msvcrt/data.c b/dlls/msvcrt/data.c
index 36b75a5..fa11ed2 100644
--- a/dlls/msvcrt/data.c
+++ b/dlls/msvcrt/data.c
@@ -24,6 +24,7 @@
#include <math.h>
#include "msvcrt.h"
+#include "msvcrt/fcntl.h"
#include "msvcrt/stdlib.h"
#include "msvcrt/string.h"
@@ -285,7 +286,8 @@
MSVCRT___setlc_active = 0;
MSVCRT___unguarded_readlc_active = 0;
MSVCRT_timezone = 0;
-
+ MSVCRT__fmode = _O_TEXT;
+
MSVCRT___initenv= msvcrt_SnapshotOfEnvironmentA(NULL);
MSVCRT___winitenv= msvcrt_SnapshotOfEnvironmentW(NULL);
diff --git a/dlls/msvcrt/file.c b/dlls/msvcrt/file.c
index f450aaf..3d985a3 100644
--- a/dlls/msvcrt/file.c
+++ b/dlls/msvcrt/file.c
@@ -5,6 +5,7 @@
* Copyright 1996 Jukka Iivonen
* Copyright 1997,2000 Uwe Bonnes
* Copyright 2000 Jon Griffiths
+ * Copyright 2004 Eric Pouech
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -64,19 +65,30 @@
/* _access() bit flags FIXME: incomplete */
#define MSVCRT_W_OK 0x02
+/* values for xflag */
+#define WX_OPEN 0x01
+#define WX_ATEOF 0x02
+#define WX_DONTINHERIT 0x10
+#define WX_APPEND 0x20
+#define WX_TEXT 0x80
/* FIXME: Make this dynamic */
#define MSVCRT_MAX_FILES 257
-HANDLE MSVCRT_handles[MSVCRT_MAX_FILES];
-MSVCRT_FILE* MSVCRT_files[MSVCRT_MAX_FILES];
-int MSVCRT_flags[MSVCRT_MAX_FILES];
-char *MSVCRT_tempfiles[MSVCRT_MAX_FILES];
+static struct {
+ HANDLE handle;
+ unsigned char xflag;
+} MSVCRT_fdesc[MSVCRT_MAX_FILES];
+
MSVCRT_FILE MSVCRT__iob[3];
static int MSVCRT_fdstart = 3; /* first unallocated fd */
static int MSVCRT_fdend = 3; /* highest allocated fd */
+/* FIXME: make this dynamic */
+static MSVCRT_FILE* MSVCRT_fstreams[1024];
+static int MSVCRT_stream_idx;
+
/* INTERNAL: process umask */
static int MSVCRT_umask = 0;
@@ -113,33 +125,47 @@
buf->st_ctime = bufi64->st_ctime;
}
+static inline BOOL msvcrt_is_valid_fd(int fd)
+{
+ return fd >= 0 && fd < MSVCRT_fdend && (MSVCRT_fdesc[fd].xflag & WX_OPEN);
+}
+
/* INTERNAL: Get the HANDLE for a fd */
static HANDLE msvcrt_fdtoh(int fd)
{
- if (fd < 0 || fd >= MSVCRT_fdend ||
- MSVCRT_handles[fd] == INVALID_HANDLE_VALUE)
+ if (!msvcrt_is_valid_fd(fd))
{
WARN(":fd (%d) - no handle!\n",fd);
*MSVCRT___doserrno() = 0;
*MSVCRT__errno() = MSVCRT_EBADF;
return INVALID_HANDLE_VALUE;
}
- return MSVCRT_handles[fd];
+ if (MSVCRT_fdesc[fd].handle == INVALID_HANDLE_VALUE) FIXME("wtf\n");
+ return MSVCRT_fdesc[fd].handle;
}
/* INTERNAL: free a file entry fd */
static void msvcrt_free_fd(int fd)
{
- MSVCRT_handles[fd] = INVALID_HANDLE_VALUE;
- MSVCRT_files[fd] = 0;
- MSVCRT_flags[fd] = 0;
+ MSVCRT_fdesc[fd].handle = INVALID_HANDLE_VALUE;
+ MSVCRT_fdesc[fd].xflag = 0;
TRACE(":fd (%d) freed\n",fd);
- if (fd < 3)
- return; /* don't use 0,1,2 for user files */
- if (fd == MSVCRT_fdend - 1)
- MSVCRT_fdend--;
- if (fd < MSVCRT_fdstart)
- MSVCRT_fdstart = fd;
+ if (fd < 3) /* don't use 0,1,2 for user files */
+ {
+ switch (fd)
+ {
+ case 0: SetStdHandle(STD_INPUT_HANDLE, NULL); break;
+ case 1: SetStdHandle(STD_OUTPUT_HANDLE, NULL); break;
+ case 2: SetStdHandle(STD_ERROR_HANDLE, NULL); break;
+ }
+ }
+ else
+ {
+ if (fd == MSVCRT_fdend - 1)
+ MSVCRT_fdend--;
+ if (fd < MSVCRT_fdstart)
+ MSVCRT_fdstart = fd;
+ }
}
/* INTERNAL: Allocate an fd slot from a Win32 HANDLE */
@@ -153,46 +179,69 @@
WARN(":files exhausted!\n");
return -1;
}
- MSVCRT_handles[fd] = hand;
- MSVCRT_flags[fd] = flag;
+ MSVCRT_fdesc[fd].handle = hand;
+ MSVCRT_fdesc[fd].xflag = WX_OPEN;
+ if (flag & _O_NOINHERIT) MSVCRT_fdesc[fd].xflag |= WX_DONTINHERIT;
+ if (flag & _O_APPEND) MSVCRT_fdesc[fd].xflag |= WX_APPEND;
+ if (flag & _O_TEXT) MSVCRT_fdesc[fd].xflag |= WX_TEXT;
/* locate next free slot */
if (fd == MSVCRT_fdend)
MSVCRT_fdstart = ++MSVCRT_fdend;
else
while(MSVCRT_fdstart < MSVCRT_fdend &&
- MSVCRT_handles[MSVCRT_fdstart] != INVALID_HANDLE_VALUE)
+ MSVCRT_fdesc[MSVCRT_fdstart].handle != INVALID_HANDLE_VALUE)
MSVCRT_fdstart++;
+ switch (fd)
+ {
+ case 0: SetStdHandle(STD_INPUT_HANDLE, hand); break;
+ case 1: SetStdHandle(STD_OUTPUT_HANDLE, hand); break;
+ case 2: SetStdHandle(STD_ERROR_HANDLE, hand); break;
+ }
+
return fd;
}
/* INTERNAL: Allocate a FILE* for an fd slot
- * This is done lazily to avoid memory wastage for low level open/write
- * usage when a FILE* is not requested (but may be later).
*/
-static MSVCRT_FILE* msvcrt_alloc_fp(int fd)
+static MSVCRT_FILE* msvcrt_alloc_fp(void)
+{
+ int i;
+
+ for (i = 3; i < sizeof(MSVCRT_fstreams) / sizeof(MSVCRT_fstreams[0]); i++)
+ {
+ if (!MSVCRT_fstreams[i] || MSVCRT_fstreams[i]->_flag == 0)
+ {
+ if (!MSVCRT_fstreams[i])
+ {
+ if (!(MSVCRT_fstreams[i] = MSVCRT_calloc(sizeof(MSVCRT_FILE),1)))
+ return NULL;
+ if (i == MSVCRT_stream_idx) MSVCRT_stream_idx++;
+ }
+ return MSVCRT_fstreams[i];
+ }
+ }
+ return NULL;
+}
+
+/* INTERNAL: initialize a FILE* from an open fd */
+static int msvcrt_init_fp(MSVCRT_FILE* file, int fd, unsigned stream_flags)
{
TRACE(":fd (%d) allocating FILE*\n",fd);
- if (fd < 0 || fd >= MSVCRT_fdend ||
- MSVCRT_handles[fd] == INVALID_HANDLE_VALUE)
+ if (!msvcrt_is_valid_fd(fd))
{
WARN(":invalid fd %d\n",fd);
*MSVCRT___doserrno() = 0;
*MSVCRT__errno() = MSVCRT_EBADF;
- return NULL;
+ return -1;
}
- if (!MSVCRT_files[fd])
- {
- if ((MSVCRT_files[fd] = MSVCRT_calloc(sizeof(MSVCRT_FILE),1)))
- {
- MSVCRT_files[fd]->_file = fd;
- MSVCRT_files[fd]->_flag = MSVCRT_flags[fd];
- MSVCRT_files[fd]->_flag &= ~MSVCRT__IOAPPEND; /* mask out, see above */
- }
- }
- TRACE(":got FILE* (%p)\n",MSVCRT_files[fd]);
- return MSVCRT_files[fd];
+ memset(file, 0, sizeof(*file));
+ file->_file = fd;
+ file->_flag = stream_flags;
+
+ TRACE(":got FILE* (%p)\n",file);
+ return 0;
}
@@ -200,27 +249,34 @@
void msvcrt_init_io(void)
{
int i;
+
memset(MSVCRT__iob,0,3*sizeof(MSVCRT_FILE));
DuplicateHandle(GetCurrentProcess(), GetStdHandle(STD_INPUT_HANDLE),
- GetCurrentProcess(), &MSVCRT_handles[0], 0, FALSE, DUPLICATE_SAME_ACCESS);
- MSVCRT_flags[0] = MSVCRT__iob[0]._flag = MSVCRT__IOREAD;
+ GetCurrentProcess(), &MSVCRT_fdesc[0].handle, 0, FALSE, DUPLICATE_SAME_ACCESS);
+ MSVCRT_fdesc[0].xflag = WX_OPEN;
+ MSVCRT__iob[0]._flag = MSVCRT__IOREAD;
+ MSVCRT__iob[0]._tmpfname = NULL;
DuplicateHandle(GetCurrentProcess(), GetStdHandle(STD_OUTPUT_HANDLE),
- GetCurrentProcess(), &MSVCRT_handles[1], 0, FALSE, DUPLICATE_SAME_ACCESS);
- MSVCRT_flags[1] = MSVCRT__iob[1]._flag = MSVCRT__IOWRT;
+ GetCurrentProcess(), &MSVCRT_fdesc[0].handle, 0, FALSE, DUPLICATE_SAME_ACCESS);
+ MSVCRT_fdesc[1].xflag = WX_OPEN;
+ MSVCRT__iob[1]._flag = MSVCRT__IOWRT;
+ MSVCRT__iob[1]._tmpfname = NULL;
DuplicateHandle(GetCurrentProcess(), GetStdHandle(STD_ERROR_HANDLE),
- GetCurrentProcess(), &MSVCRT_handles[2], 0, FALSE, DUPLICATE_SAME_ACCESS);
- MSVCRT_flags[2] = MSVCRT__iob[2]._flag = MSVCRT__IOWRT;
+ GetCurrentProcess(), &MSVCRT_fdesc[2].handle, 0, FALSE, DUPLICATE_SAME_ACCESS);
+ MSVCRT_fdesc[2].xflag = WX_OPEN;
+ MSVCRT__iob[2]._flag = MSVCRT__IOWRT;
+ MSVCRT__iob[2]._tmpfname = NULL;
- TRACE(":handles (%p)(%p)(%p)\n",MSVCRT_handles[0],
- MSVCRT_handles[1],MSVCRT_handles[2]);
+ TRACE(":handles (%p)(%p)(%p)\n",MSVCRT_fdesc[0].handle,
+ MSVCRT_fdesc[1].handle,MSVCRT_fdesc[2].handle);
for (i = 0; i < 3; i++)
{
/* FILE structs for stdin/out/err are static and never deleted */
- MSVCRT_files[i] = &MSVCRT__iob[i];
+ MSVCRT_fstreams[i] = &MSVCRT__iob[i];
MSVCRT__iob[i]._file = i;
- MSVCRT_tempfiles[i] = NULL;
}
+ MSVCRT_stream_idx = 3;
}
/* INTERNAL: Flush stdio file buffer */
@@ -229,7 +285,8 @@
if(file->_bufsiz) {
int cnt=file->_ptr-file->_base;
if(cnt>0 && _write(file->_file, file->_base, cnt) != cnt) {
- return MSVCRT_EOF;
+ file->_flag |= MSVCRT__IOERR;
+ return MSVCRT_EOF;
}
file->_ptr=file->_base;
file->_cnt=file->_bufsiz;
@@ -429,17 +486,17 @@
{
int i, num_flushed = 0;
- for (i = 3; i < MSVCRT_fdend; i++)
- if (MSVCRT_handles[i] != INVALID_HANDLE_VALUE)
+ for (i = 3; i < MSVCRT_stream_idx; i++)
+ if (MSVCRT_fstreams[i] && MSVCRT_fstreams[i]->_flag)
{
#if 0
/* FIXME: flush, do not commit */
if (_commit(i) == -1)
- if (MSVCRT_files[i])
- MSVCRT_files[i]->_flag |= MSVCRT__IOERR;
+ if (MSVCRT_fstreams[i])
+ MSVCRT_fstreams[i]->_flag |= MSVCRT__IOERR;
#endif
- if(MSVCRT_files[i] && MSVCRT_files[i]->_flag & MSVCRT__IOWRT) {
- MSVCRT_fflush(MSVCRT_files[i]);
+ if(MSVCRT_fstreams[i]->_flag & MSVCRT__IOWRT) {
+ MSVCRT_fflush(MSVCRT_fstreams[i]);
num_flushed++;
}
}
@@ -472,20 +529,6 @@
TRACE(":fd (%d) handle (%p)\n",fd,hand);
if (hand == INVALID_HANDLE_VALUE)
return -1;
- /* flush stdio buffers */
- if(MSVCRT_files[fd]) {
- if(MSVCRT_files[fd]->_flag & MSVCRT__IOWRT)
- MSVCRT_fflush(MSVCRT_files[fd]);
-
- if(MSVCRT_files[fd]->_flag & MSVCRT__IOMYBUF)
- MSVCRT_free(MSVCRT_files[fd]->_base);
- }
-
- /* Don't free std FILE*'s, they are not dynamic */
- if (fd > 2 && MSVCRT_files[fd])
- MSVCRT_free(MSVCRT_files[fd]);
-
- msvcrt_free_fd(fd);
if (!CloseHandle(hand))
{
@@ -493,14 +536,7 @@
MSVCRT__set_errno(GetLastError());
return -1;
}
- if (MSVCRT_tempfiles[fd])
- {
- TRACE("deleting temporary file '%s'\n",MSVCRT_tempfiles[fd]);
- _unlink(MSVCRT_tempfiles[fd]);
- MSVCRT_free(MSVCRT_tempfiles[fd]);
- MSVCRT_tempfiles[fd] = NULL;
- }
-
+ msvcrt_free_fd(fd);
TRACE(":ok\n");
return 0;
}
@@ -538,7 +574,7 @@
*/
int _eof(int fd)
{
- DWORD curpos,endpos;
+ DWORD curpos,endpos,hcurpos,hendpos;
HANDLE hand = msvcrt_fdtoh(fd);
TRACE(":fd (%d) handle (%p)\n",fd,hand);
@@ -546,20 +582,17 @@
if (hand == INVALID_HANDLE_VALUE)
return -1;
- /* If we have a FILE* for this file, the EOF flag
- * will be set by the read()/write() functions.
- */
- if (MSVCRT_files[fd])
- return MSVCRT_flags[fd] & MSVCRT__IOEOF;
+ if (MSVCRT_fdesc[fd].xflag & WX_ATEOF) return TRUE;
/* Otherwise we do it the hard way */
- curpos = SetFilePointer(hand, 0, NULL, SEEK_CUR);
- endpos = SetFilePointer(hand, 0, NULL, FILE_END);
+ hcurpos = hendpos = 0;
+ curpos = SetFilePointer(hand, 0, &hcurpos, SEEK_CUR);
+ endpos = SetFilePointer(hand, 0, &hendpos, FILE_END);
- if (curpos == endpos)
+ if (curpos == endpos && hcurpos == hendpos)
return TRUE;
- SetFilePointer(hand, curpos, 0, FILE_BEGIN);
+ SetFilePointer(hand, curpos, &hcurpos, FILE_BEGIN);
return FALSE;
}
@@ -570,12 +603,10 @@
{
int num_closed = 0, i;
- for (i = 3; i < MSVCRT_fdend; i++)
- if (MSVCRT_handles[i] != INVALID_HANDLE_VALUE)
- {
- _close(i);
+ for (i = 3; i < MSVCRT_stream_idx; i++)
+ if (MSVCRT_fstreams[i] && MSVCRT_fstreams[i]->_flag &&
+ MSVCRT_fclose(MSVCRT_fstreams[i]))
num_closed++;
- }
TRACE(":closed (%d) handles\n",num_closed);
return num_closed;
@@ -614,27 +645,16 @@
(whence==SEEK_CUR)?"SEEK_CUR":
(whence==SEEK_END)?"SEEK_END":"UNKNOWN");
- if (((ret = SetFilePointer(hand, (long)offset, &hoffset,
- whence)) != INVALID_SET_FILE_POINTER) || !GetLastError())
+ ret = SetFilePointer(hand, (long)offset, &hoffset, whence);
+ if (ret != INVALID_SET_FILE_POINTER || !GetLastError())
{
- if (MSVCRT_files[fd])
- MSVCRT_files[fd]->_flag &= ~MSVCRT__IOEOF;
+ MSVCRT_fdesc[fd].xflag &= ~WX_ATEOF;
/* FIXME: What if we seek _to_ EOF - is EOF set? */
return ((__int64)hoffset << 32) | ret;
}
TRACE(":error-last error (%ld)\n",GetLastError());
- if (MSVCRT_files[fd])
- switch(GetLastError())
- {
- case ERROR_NEGATIVE_SEEK:
- case ERROR_SEEK_ON_DEVICE:
- MSVCRT__set_errno(GetLastError());
- MSVCRT_files[fd]->_flag |= MSVCRT__IOERR;
- break;
- default:
- break;
- }
+ MSVCRT__set_errno(GetLastError());
return -1;
}
@@ -741,14 +761,64 @@
MSVCRT_clearerr(file);
}
+static int msvcrt_get_flags(const char* mode, int *open_flags, int* stream_flags)
+{
+ int plus = strchr(mode, '+') != NULL;
+
+ switch(*mode++)
+ {
+ case 'R': case 'r':
+ *open_flags = plus ? _O_RDWR : _O_RDONLY;
+ *stream_flags = plus ? MSVCRT__IORW : MSVCRT__IOREAD;
+ break;
+ case 'W': case 'w':
+ *open_flags = _O_CREAT | _O_TRUNC | (plus ? _O_RDWR : _O_WRONLY);
+ *stream_flags = plus ? MSVCRT__IORW : MSVCRT__IOWRT;
+ break;
+ case 'A': case 'a':
+ *open_flags = _O_CREAT | _O_APPEND | (plus ? _O_RDWR : _O_WRONLY);
+ *stream_flags = plus ? MSVCRT__IORW : MSVCRT__IOWRT;
+ break;
+ default:
+ return -1;
+ }
+
+ while (*mode)
+ switch (*mode++)
+ {
+ case 'B': case 'b':
+ *open_flags |= _O_BINARY;
+ *open_flags &= ~_O_TEXT;
+ break;
+ case 'T': case 't':
+ *open_flags |= _O_TEXT;
+ *open_flags &= ~_O_BINARY;
+ break;
+ case '+':
+ break;
+ default:
+ FIXME(":unknown flag %c not supported\n",mode[-1]);
+ }
+ return 0;
+}
+
/*********************************************************************
* _fdopen (MSVCRT.@)
*/
MSVCRT_FILE* MSVCRT__fdopen(int fd, const char *mode)
{
- MSVCRT_FILE* file = msvcrt_alloc_fp(fd);
+ int open_flags, stream_flags;
+ MSVCRT_FILE* file;
- TRACE(":fd (%d) mode (%s) FILE* (%p)\n",fd,mode,file);
+ if (msvcrt_get_flags(mode, &open_flags, &stream_flags) == -1) return NULL;
+
+ if (!(file = msvcrt_alloc_fp())) return NULL;
+ if (msvcrt_init_fp(file, fd, stream_flags) == -1)
+ {
+ file->_flag = 0;
+ file = NULL;
+ }
+ else TRACE(":fd (%d) mode (%s) FILE* (%p)\n",fd,mode,file);
return file;
}
@@ -758,12 +828,28 @@
*/
MSVCRT_FILE* MSVCRT__wfdopen(int fd, const MSVCRT_wchar_t *mode)
{
- MSVCRT_FILE* file = msvcrt_alloc_fp(fd);
+ unsigned mlen = strlenW(mode);
+ char *modea = MSVCRT_calloc(mlen + 1, 1);
+ MSVCRT_FILE* file = NULL;
+ int open_flags, stream_flags;
- TRACE(":fd (%d) mode (%s) FILE* (%p)\n",fd,debugstr_w(mode),file);
- if (file)
- MSVCRT_rewind(file);
-
+ if (modea &&
+ WideCharToMultiByte(CP_ACP,0,mode,mlen,modea,mlen,NULL,NULL))
+ {
+ if (msvcrt_get_flags(modea, &open_flags, &stream_flags) == -1) return NULL;
+ if (!(file = msvcrt_alloc_fp())) return NULL;
+ if (msvcrt_init_fp(file, fd, stream_flags) == -1)
+ {
+ file->_flag = 0;
+ file = NULL;
+ }
+ else
+ {
+ if (file)
+ MSVCRT_rewind(file); /* FIXME: is this needed ??? */
+ TRACE(":fd (%d) mode (%s) FILE* (%p)\n",fd,debugstr_w(mode),file);
+ }
+ }
return file;
}
@@ -1012,7 +1098,7 @@
{
va_list ap;
int pmode;
- DWORD access = 0, creation = 0;
+ DWORD access = 0, creation = 0, attrib;
DWORD sharing;
int ioflag = 0, fd;
HANDLE hand;
@@ -1064,7 +1150,7 @@
creation = OPEN_EXISTING;
}
if (oflags & _O_APPEND)
- ioflag |= MSVCRT__IOAPPEND;
+ ioflag |= _O_APPEND;
if (oflags & _O_BINARY)
ioflag |= _O_BINARY;
@@ -1093,6 +1179,14 @@
ERR( "Unhandled shflags 0x%x\n", shflags );
return -1;
}
+ attrib = FILE_ATTRIBUTE_NORMAL;
+
+ if (oflags & _O_TEMPORARY)
+ {
+ attrib |= FILE_FLAG_DELETE_ON_CLOSE;
+ access |= DELETE;
+ sharing |= FILE_SHARE_DELETE;
+ }
if (oflags & ~(_O_BINARY|_O_TEXT|_O_APPEND|_O_TRUNC|_O_EXCL
|_O_CREAT|_O_RDWR|_O_WRONLY|_O_TEMPORARY|_O_NOINHERIT))
@@ -1102,8 +1196,7 @@
sa.lpSecurityDescriptor = NULL;
sa.bInheritHandle = (oflags & _O_NOINHERIT) ? FALSE : TRUE;
- hand = CreateFileA(path, access, sharing,
- &sa, creation, FILE_ATTRIBUTE_NORMAL, 0);
+ hand = CreateFileA(path, access, sharing, &sa, creation, attrib, 0);
if (hand == INVALID_HANDLE_VALUE) {
WARN(":failed-last error (%ld)\n",GetLastError());
@@ -1117,9 +1210,7 @@
if (fd > 0)
{
- if (oflags & _O_TEMPORARY)
- MSVCRT_tempfiles[fd] = _strdup(path);
- if (ioflag & MSVCRT__IOAPPEND)
+ if (oflags & _O_APPEND)
_lseek(fd, 0, FILE_END);
}
@@ -1226,11 +1317,13 @@
* text - it never sets _O_BINARY.
*/
/* FIXME: handle more flags */
- flags |= MSVCRT__IOREAD|MSVCRT__IOWRT;
- if ( !( flags & _O_TEXT ) ) flags |= _O_BINARY;
+ if (!(flags & (_O_BINARY | _O_TEXT)) && (*__p__fmode() & _O_BINARY))
+ flags |= _O_BINARY;
+ else
+ flags |= _O_TEXT;
fd = msvcrt_alloc_fd((HANDLE)hand,flags);
- TRACE(":handle (%ld) fd (%d) flags 0x%08x\n",hand,fd, flags);
+ TRACE(":handle (%ld) fd (%d) flags 0x%08x\n",hand,fd,flags);
return fd;
}
@@ -1241,10 +1334,10 @@
{
int num_removed = 0, i;
- for (i = 3; i < MSVCRT_fdend; i++)
- if (MSVCRT_tempfiles[i])
+ for (i = 3; i < MSVCRT_stream_idx; i++)
+ if (MSVCRT_fstreams[i] && MSVCRT_fstreams[i]->_tmpfname)
{
- _close(i);
+ MSVCRT_fclose(MSVCRT_fstreams[i]);
num_removed++;
}
@@ -1273,7 +1366,7 @@
*/
int _read(int fd, void *buf, unsigned int count)
{
- DWORD num_read, all_read =0;
+ DWORD num_read, all_read = 0;
char *bufstart = buf;
HANDLE hand = msvcrt_fdtoh(fd);
@@ -1287,28 +1380,22 @@
* So read big chunks, then remove the \r in memory and try reading
* the rest until the request is satisfied or EOF is met
*/
- while ( all_read < count)
+ while (all_read < count)
{
if (ReadFile(hand, bufstart+all_read, count - all_read, &num_read, NULL))
{
- if (num_read != (count- all_read))
+ if (num_read != (count - all_read))
{
TRACE(":EOF\n");
- if ( MSVCRT_files[fd])
- {
- MSVCRT_flags[fd] |= MSVCRT__IOEOF;
- /*
- MSVCRT_files[fd]->_flag |= MSVCRT__IOEOF;
- */
- }
- if ((MSVCRT_flags[fd]& _O_BINARY ) != _O_BINARY )
+ MSVCRT_fdesc[fd].xflag |= WX_ATEOF;
+ if (MSVCRT_fdesc[fd].xflag & WX_TEXT)
num_read -= remove_cr(bufstart+all_read,num_read);
all_read += num_read;
if (count > 4)
TRACE("%s\n",debugstr_an(buf,all_read));
return all_read;
}
- if ((MSVCRT_flags[fd]& _O_BINARY ) != _O_BINARY )
+ if (MSVCRT_fdesc[fd].xflag & WX_TEXT)
{
num_read -= remove_cr(bufstart+all_read,num_read);
}
@@ -1317,14 +1404,12 @@
else
{
TRACE(":failed-last error (%ld)\n",GetLastError());
- if (MSVCRT_files[fd])
- MSVCRT_files[fd]->_flag |= MSVCRT__IOERR;
return -1;
}
}
if (count > 4)
- TRACE("%s\n",debugstr_an(buf, all_read));
+ TRACE("(%lu), %s\n",all_read,debugstr_an(buf, all_read));
return all_read;
}
@@ -1334,9 +1419,13 @@
int MSVCRT__getw(MSVCRT_FILE* file)
{
int i;
- if (_read(file->_file, &i, sizeof(int)) != 1)
- return MSVCRT_EOF;
- return i;
+ switch (_read(file->_file, &i, sizeof(int)))
+ {
+ case 1: return i;
+ case 0: file->_flag |= MSVCRT__IOEOF; break;
+ default: file->_flag |= MSVCRT__IOERR; break;
+ }
+ return EOF;
}
/*********************************************************************
@@ -1344,11 +1433,13 @@
*/
int _setmode(int fd,int mode)
{
- int ret = MSVCRT_flags[fd] & (_O_TEXT | _O_BINARY);
+ int ret = MSVCRT_fdesc[fd].xflag & WX_TEXT ? _O_TEXT : _O_BINARY;
if (mode & (~(_O_TEXT|_O_BINARY)))
FIXME("fd (%d) mode (0x%08x) unknown\n",fd,mode);
- MSVCRT_flags[fd] &= ~(_O_TEXT|_O_BINARY);
- MSVCRT_flags[fd] |= mode & (_O_TEXT | _O_BINARY);
+ if ((mode & _O_TEXT) == _O_TEXT)
+ MSVCRT_fdesc[fd].xflag |= WX_TEXT;
+ else
+ MSVCRT_fdesc[fd].xflag &= WX_TEXT;
return ret;
}
@@ -1621,20 +1712,16 @@
}
/* If appending, go to EOF */
- if (MSVCRT_flags[fd] & MSVCRT__IOAPPEND)
+ if (MSVCRT_fdesc[fd].xflag & WX_APPEND)
_lseek(fd, 0, FILE_END);
- if (MSVCRT_flags[fd] & _O_BINARY)
+ if (!(MSVCRT_fdesc[fd].xflag & WX_TEXT))
{
if (WriteFile(hand, buf, count, &num_written, NULL)
&& (num_written == count))
return num_written;
TRACE(":failed-last error (%ld)\n",GetLastError());
- if (MSVCRT_files[fd])
- {
- MSVCRT_files[fd]->_flag |= MSVCRT__IOERR;
- *MSVCRT__errno() = MSVCRT_ENOSPC;
- }
+ *MSVCRT__errno() = MSVCRT_ENOSPC;
}
else
{
@@ -1676,14 +1763,10 @@
if ((WriteFile(hand, p, count+nr_lf, &num_written, NULL) == 0 ) || (num_written != count+nr_lf))
{
TRACE(":failed-last error (%ld) num_written %ld\n",GetLastError(),num_written);
- if (MSVCRT_files[fd])
- {
- MSVCRT_files[fd]->_flag |= MSVCRT__IOERR;
- *MSVCRT__errno() = MSVCRT_ENOSPC;
- if(nr_lf)
- MSVCRT_free(p);
- return s - buf_start;
- }
+ *MSVCRT__errno() = MSVCRT_ENOSPC;
+ if(nr_lf)
+ MSVCRT_free(p);
+ return s - buf_start;
}
else
{
@@ -1700,7 +1783,11 @@
*/
int MSVCRT__putw(int val, MSVCRT_FILE* file)
{
- return _write(file->_file, &val, sizeof(val)) == 1? val : MSVCRT_EOF;
+ int len;
+ len = _write(file->_file, &val, sizeof(val));
+ if (len == sizeof(val)) return val;
+ file->_flag |= MSVCRT__IOERR;
+ return MSVCRT_EOF;
}
/*********************************************************************
@@ -1711,7 +1798,21 @@
int r, flag;
flag = file->_flag;
+ if (file->_tmpfname)
+ {
+ MSVCRT_free(file->_tmpfname);
+ file->_tmpfname = NULL;
+ }
+ /* flush stdio buffers */
+ if(file->_flag & MSVCRT__IOWRT)
+ MSVCRT_fflush(file);
+ if(file->_flag & MSVCRT__IOMYBUF)
+ MSVCRT_free(file->_base);
+
r=_close(file->_file);
+
+ file->_flag = 0;
+
return ((r==MSVCRT_EOF) || (flag & MSVCRT__IOERR) ? MSVCRT_EOF : 0);
}
@@ -1736,7 +1837,6 @@
*/
int MSVCRT__filbuf(MSVCRT_FILE* file)
{
-
/* Allocate buffer if needed */
if(file->_bufsiz == 0 && !(file->_flag & MSVCRT__IONBF) ) {
msvcrt_alloc_buffer(file);
@@ -1750,17 +1850,18 @@
}
if(file->_flag & MSVCRT__IONBF) {
unsigned char c;
- if (_read(file->_file,&c,1) != 1) {
- file->_flag |= MSVCRT__IOEOF;
- return MSVCRT_EOF;
+ int r;
+ if ((r = _read(file->_file,&c,1)) != 1) {
+ file->_flag |= (r == 0) ? MSVCRT__IOEOF : MSVCRT__IOERR;
+ return MSVCRT_EOF;
}
return c;
} else {
file->_cnt = _read(file->_file, file->_base, file->_bufsiz);
- if(file->_cnt<0) file->_cnt = 0;
- if(!file->_cnt) {
- file->_flag |= MSVCRT__IOEOF;
- return MSVCRT_EOF;
+ if(file->_cnt<=0) {
+ file->_flag |= (file->_cnt == 0) ? MSVCRT__IOEOF : MSVCRT__IOERR;
+ file->_cnt = 0;
+ return MSVCRT_EOF;
}
file->_cnt--;
file->_ptr = file->_base+1;
@@ -1820,18 +1921,22 @@
/*********************************************************************
* fgetwc (MSVCRT.@)
*
- * In _O_TEXT mode, bultibyte characters are read from the file, dropping
+ * In _O_TEXT mode, multibyte characters are read from the file, dropping
* the CR from CR/LF combinations
*/
MSVCRT_wint_t MSVCRT_fgetwc(MSVCRT_FILE* file)
{
char c;
- if (file->_flag & _O_BINARY)
+ if (!(MSVCRT_fdesc[file->_file].xflag & WX_TEXT))
{
MSVCRT_wchar_t wc;
- if (_read(file->_file, &wc, sizeof(wc)) != sizeof(wc))
- return MSVCRT_WEOF;
+ int r;
+ if ((r = _read(file->_file, &wc, sizeof(wc))) != sizeof(wc))
+ {
+ file->_flag |= (r == 0) ? MSVCRT__IOEOF : MSVCRT__IOERR;
+ return MSVCRT_WEOF;
+ }
return wc;
}
c = MSVCRT_fgetc(file);
@@ -1925,7 +2030,11 @@
int res=msvcrt_flush_buffer(file);
if(!res) {
int pwritten = _write(file->_file, ptr, wrcnt);
- if (pwritten <= 0) pwritten=0;
+ if (pwritten <= 0)
+ {
+ file->_flag |= MSVCRT__IOERR;
+ pwritten=0;
+ }
written += pwritten;
}
}
@@ -1957,58 +2066,30 @@
MSVCRT_FILE* MSVCRT_fopen(const char *path, const char *mode)
{
MSVCRT_FILE* file;
- int flags = 0, plus = 0, fd;
- const char* search = mode;
+ int open_flags, stream_flags, fd;
TRACE("(%s,%s)\n",path,mode);
- while (*search)
- if (*search++ == '+')
- plus = 1;
-
/* map mode string to open() flags. "man fopen" for possibilities. */
- switch(*mode++)
- {
- case 'R': case 'r':
- flags = (plus ? _O_RDWR : _O_RDONLY);
- break;
- case 'W': case 'w':
- flags = _O_CREAT | _O_TRUNC | (plus ? _O_RDWR : _O_WRONLY);
- break;
- case 'A': case 'a':
- flags = _O_CREAT | _O_APPEND | (plus ? _O_RDWR : _O_WRONLY);
- break;
- default:
- return NULL;
- }
+ if (msvcrt_get_flags(mode, &open_flags, &stream_flags) == -1)
+ return NULL;
- while (*mode)
- switch (*mode++)
- {
- case 'B': case 'b':
- flags |= _O_BINARY;
- flags &= ~_O_TEXT;
- break;
- case 'T': case 't':
- flags |= _O_TEXT;
- flags &= ~_O_BINARY;
- break;
- case '+':
- break;
- default:
- FIXME(":unknown flag %c not supported\n",mode[-1]);
- }
-
- fd = _open(path, flags, _S_IREAD | _S_IWRITE);
+ fd = _open(path, open_flags, _S_IREAD | _S_IWRITE);
if (fd < 0)
return NULL;
- file = msvcrt_alloc_fp(fd);
+ if ((file = msvcrt_alloc_fp()) && msvcrt_init_fp(file, fd, stream_flags) != -1)
+ TRACE(":fd (%d) mode (%s) FILE* (%p)\n",fd,mode,file);
+ else if (file)
+ {
+ file->_flag = 0;
+ file = NULL;
+ }
+
TRACE(":got (%p)\n",file);
if (!file)
_close(fd);
-
return file;
}
@@ -2094,7 +2175,11 @@
return res?res : MSVCRT_fputc(c, file);
} else {
unsigned char cc=c;
- return _write(file->_file, &cc, 1) == 1? c : MSVCRT_EOF;
+ int len;
+ len = _write(file->_file, &cc, 1);
+ if (len == 1) return c;
+ file->_flag |= MSVCRT__IOERR;
+ return MSVCRT_EOF;
}
}
@@ -2113,6 +2198,7 @@
{ MSVCRT_size_t rcnt=size * nmemb;
MSVCRT_size_t read=0;
int pread=0;
+
/* first buffered data */
if(file->_cnt>0) {
int pcnt= (rcnt>file->_cnt)? file->_cnt:rcnt;
@@ -2121,21 +2207,27 @@
file->_ptr += pcnt;
read += pcnt ;
rcnt -= pcnt ;
- ptr = (char*)ptr + pcnt;
+ ptr = (char*)ptr + pcnt;
} else if(!(file->_flag & MSVCRT__IOREAD )) {
if(file->_flag & MSVCRT__IORW) {
file->_flag |= MSVCRT__IOREAD;
} else
- return 0;
+ return 0;
}
- if(rcnt) pread = _read(file->_file,ptr, rcnt);
- if (MSVCRT_flags[file->_file] & MSVCRT__IOEOF)
- /* expose feof condition in the flags
- MFC tests file->_flag for feof, and doesn't not call feof())
- */
- file->_flag |= MSVCRT__IOEOF;
- if (pread <= 0)
- pread = 0;
+ if(rcnt)
+ {
+ pread = _read(file->_file,ptr, rcnt);
+ /* expose feof condition in the flags
+ * MFC tests file->_flag for feof, and doesn't not call feof())
+ */
+ if (pread == 0)
+ file->_flag |= MSVCRT__IOEOF;
+ else if (pread == -1)
+ {
+ file->_flag |= MSVCRT__IOERR;
+ pread = 0;
+ }
+ }
read+=pread;
return read / size;
}
@@ -2146,49 +2238,30 @@
*/
MSVCRT_FILE* MSVCRT_freopen(const char *path, const char *mode,MSVCRT_FILE* file)
{
- MSVCRT_FILE* newfile;
- int fd;
+ int open_flags, stream_flags, fd;
TRACE(":path (%p) mode (%s) file (%p) fd (%d)\n",path,mode,file,file->_file);
if (!file || ((fd = file->_file) < 0) || fd > MSVCRT_fdend)
return NULL;
- if (fd > 2)
- {
-#if 0
- FIXME(":reopen on user file not implemented!\n");
- MSVCRT__set_errno(ERROR_CALL_NOT_IMPLEMENTED);
+ MSVCRT_fclose(file);
+
+ /* map mode string to open() flags. "man fopen" for possibilities. */
+ if (msvcrt_get_flags(mode, &open_flags, &stream_flags) == -1)
+ return NULL;
+
+ fd = _open(path, open_flags, _S_IREAD | _S_IWRITE);
+
+ if (fd < 0)
return NULL;
-#endif
- if(MSVCRT_fclose(file))
- return NULL;
- return MSVCRT_fopen(path, mode);
- }
-
- /* first, create the new file */
- if ((newfile = MSVCRT_fopen(path,mode)) == NULL)
- return NULL;
-
- if (fd < 3 && SetStdHandle(fd == 0 ? STD_INPUT_HANDLE :
- (fd == 1? STD_OUTPUT_HANDLE : STD_ERROR_HANDLE),
- MSVCRT_handles[newfile->_file]))
+ if (msvcrt_init_fp(file, fd, stream_flags) != -1)
{
- /* Redirecting std handle to file , copy over.. */
- MSVCRT_handles[fd] = MSVCRT_handles[newfile->_file];
- MSVCRT_flags[fd] = MSVCRT_flags[newfile->_file];
- memcpy(&MSVCRT__iob[fd], newfile, sizeof (MSVCRT_FILE));
- MSVCRT__iob[fd]._file = fd;
- /* And free up the resources allocated by fopen, but
- * not the HANDLE we copied. */
- MSVCRT_free(MSVCRT_files[fd]);
- msvcrt_free_fd(newfile->_file);
- return &MSVCRT__iob[fd];
+ file->_flag = 0;
+ WARN(":failed-last error (%ld)\n",GetLastError());
+ MSVCRT__set_errno(GetLastError());
+ return NULL;
}
-
- WARN(":failed-last error (%ld)\n",GetLastError());
- MSVCRT_fclose(newfile);
- MSVCRT__set_errno(GetLastError());
- return NULL;
+ return file;
}
/*********************************************************************
@@ -2233,7 +2306,7 @@
int MSVCRT_fputs(const char *s, MSVCRT_FILE* file)
{
size_t i, len = strlen(s);
- if (file->_flag & _O_BINARY)
+ if (!(MSVCRT_fdesc[file->_file].xflag & WX_TEXT))
return MSVCRT_fwrite(s,sizeof(*s),len,file) == len ? 0 : MSVCRT_EOF;
for (i=0; i<len; i++)
if (MSVCRT_fputc(s[i], file) == MSVCRT_EOF)
@@ -2247,7 +2320,7 @@
int MSVCRT_fputws(const MSVCRT_wchar_t *s, MSVCRT_FILE* file)
{
size_t i, len = strlenW(s);
- if (file->_flag & _O_BINARY)
+ if (!(MSVCRT_fdesc[file->_file].xflag & WX_TEXT))
return MSVCRT_fwrite(s,sizeof(*s),len,file) == len ? 0 : MSVCRT_EOF;
for (i=0; i<len; i++)
{
@@ -2464,10 +2537,19 @@
{
char *filename = MSVCRT_tmpnam(NULL);
int fd;
+ MSVCRT_FILE* file = NULL;
+
fd = _open(filename, _O_CREAT | _O_BINARY | _O_RDWR | _O_TEMPORARY);
- if (fd != -1)
- return msvcrt_alloc_fp(fd);
- return NULL;
+ if (fd != -1 && (file = msvcrt_alloc_fp()))
+ {
+ if (msvcrt_init_fp(file, fd, _O_RDWR) == -1)
+ {
+ file->_flag = 0;
+ file = NULL;
+ }
+ else file->_tmpfname = _strdup(filename);
+ }
+ return file;
}
/*********************************************************************
diff --git a/include/msvcrt/stdio.h b/include/msvcrt/stdio.h
index df92ca6..12af723 100644
--- a/include/msvcrt/stdio.h
+++ b/include/msvcrt/stdio.h
@@ -32,7 +32,6 @@
#define _IOERR 0x0020
#define _IOSTRG 0x0040
#define _IORW 0x0080
-#define _IOAPPEND 0x0200
#else
#define MSVCRT__IOREAD 0x0001
#define MSVCRT__IOWRT 0x0002
@@ -41,7 +40,6 @@
#define MSVCRT__IOERR 0x0020
#define MSVCRT__IOSTRG 0x0040
#define MSVCRT__IORW 0x0080
-#define MSVCRT__IOAPPEND 0x0200
#endif /* USE_MSVCRT_PREFIX */
#ifndef NULL