https://git.reactos.org/?p=reactos.git;a=commitdiff;h=9eb1eae28cd216025f5ed…
commit 9eb1eae28cd216025f5eda2cb549578939f2e446
Author: Thomas Faber <thomas.faber(a)reactos.org>
AuthorDate: Sun Mar 25 15:31:50 2018 +0200
Commit: Thomas Faber <thomas.faber(a)reactos.org>
CommitDate: Mon Mar 26 13:00:06 2018 +0200
[CRT] Update file descriptor handling to match Wine (2/7). CORE-14504
Import Wine commits by Piotr Caban:
* 4508e665c07 msvcrt: Use fd critical section in _commit.
* afc6962a24a msvcrt: Use fd critical section in _close.
* 9a4cfbc3edc msvcrt: Use fd critical section in _eof.
* ffdd16cc0d7 msvcrt: Use fd critical section in _locking.
* fa6de597700 msvcrt: Use fd critical section in _lseeki64.
* f2f45d5fe67 msvcrt: Use fd critical section in _chsize_s.
---
sdk/lib/crt/stdio/file.c | 157 ++++++++++++++++++++++++++++-------------------
1 file changed, 93 insertions(+), 64 deletions(-)
diff --git a/sdk/lib/crt/stdio/file.c b/sdk/lib/crt/stdio/file.c
index 3c7c01ac78..878f3b13d1 100644
--- a/sdk/lib/crt/stdio/file.c
+++ b/sdk/lib/crt/stdio/file.c
@@ -182,13 +182,16 @@ static inline ioinfo* get_ioinfo_nolock(int fd)
static inline ioinfo* get_ioinfo(int fd)
{
- ioinfo *ret = NULL;
- if(fd < MSVCRT_MAX_FILES)
- ret = __pioinfo[fd/MSVCRT_FD_BLOCK_SIZE];
- if(!ret)
- return &__badioinfo;
+ ioinfo *ret = get_ioinfo_nolock(fd);
+ if(ret->exflag & EF_CRIT_INIT)
+ EnterCriticalSection(&ret->crit);
+ return ret;
+}
- return ret + (fd%MSVCRT_FD_BLOCK_SIZE);
+static inline void release_ioinfo(ioinfo *info)
+{
+ if(info->exflag & EF_CRIT_INIT)
+ LeaveCriticalSection(&info->crit);
}
static inline FILE* msvcrt_get_file(int i)
@@ -814,27 +817,36 @@ int CDECL _wunlink(const wchar_t *path)
*/
int CDECL _commit(int fd)
{
- HANDLE hand = fdtoh(fd);
-
- TRACE(":fd (%d) handle (%p)\n",fd,hand);
- if (hand == INVALID_HANDLE_VALUE)
- return -1;
+ ioinfo *info = get_ioinfo(fd);
+ int ret;
- if (!FlushFileBuffers(hand))
- {
- if (GetLastError() == ERROR_INVALID_HANDLE)
+ TRACE(":fd (%d) handle (%p)\n", fd, info->handle);
+ if (info->handle == INVALID_HANDLE_VALUE)
+ ret = -1;
+ else if (!FlushFileBuffers(info->handle))
{
- /* FlushFileBuffers fails for console handles
- * so we ignore this error.
- */
- return 0;
+ if (GetLastError() == ERROR_INVALID_HANDLE)
+ {
+ /* FlushFileBuffers fails for console handles
+ * so we ignore this error.
+ */
+ ret = 0;
+ }
+ else
+ {
+ TRACE(":failed-last error (%d)\n",GetLastError());
+ _dosmaperr(GetLastError());
+ ret = -1;
+ }
}
- TRACE(":failed-last error (%d)\n",GetLastError());
- _dosmaperr(GetLastError());
- return -1;
- }
- TRACE(":ok\n");
- return 0;
+ else
+ {
+ TRACE(":ok\n");
+ ret = 0;
+ }
+
+ release_ioinfo(info);
+ return ret;
}
/* _flushall calls fflush which calls _flushall */
@@ -907,27 +919,24 @@ int CDECL fflush(FILE* file)
*/
int CDECL _close(int fd)
{
- HANDLE hand;
+ ioinfo *info = get_ioinfo(fd);
int ret;
LOCK_FILES();
- hand = fdtoh(fd);
- TRACE(":fd (%d) handle (%p)\n",fd,hand);
- if (hand == INVALID_HANDLE_VALUE)
- ret = -1;
- else if (!CloseHandle(hand))
- {
- WARN(":failed-last error (%d)\n",GetLastError());
- _dosmaperr(GetLastError());
+ TRACE(":fd (%d) handle (%p)\n", fd, info->handle);
+ if (!(info->wxflag & WX_OPEN)) {
ret = -1;
- }
- else
- {
+ } else {
+ ret = CloseHandle(info->handle) ? 0 : -1;
msvcrt_free_fd(fd);
- ret = 0;
+ if (ret) {
+ WARN(":failed-last error (%d)\n",GetLastError());
+ _dosmaperr(GetLastError());
+ ret = -1;
+ }
}
UNLOCK_FILES();
- TRACE(":ok\n");
+ release_ioinfo(info);
return ret;
}
@@ -1004,29 +1013,38 @@ int CDECL _dup(int od)
*/
int CDECL _eof(int fd)
{
+ ioinfo *info = get_ioinfo(fd);
DWORD curpos,endpos;
LONG hcurpos,hendpos;
- HANDLE hand = fdtoh(fd);
- TRACE(":fd (%d) handle (%p)\n",fd,hand);
+ TRACE(":fd (%d) handle (%p)\n", fd, info->handle);
- if (hand == INVALID_HANDLE_VALUE)
+ if (info->handle == INVALID_HANDLE_VALUE)
+ {
+ release_ioinfo(info);
return -1;
+ }
- if (get_ioinfo_nolock(fd)->wxflag & WX_ATEOF) return TRUE;
+ if (info->wxflag & WX_ATEOF)
+ {
+ release_ioinfo(info);
+ return TRUE;
+ }
/* Otherwise we do it the hard way */
hcurpos = hendpos = 0;
- curpos = SetFilePointer(hand, 0, &hcurpos, FILE_CURRENT);
- endpos = SetFilePointer(hand, 0, &hendpos, FILE_END);
+ curpos = SetFilePointer(info->handle, 0, &hcurpos, FILE_CURRENT);
+ endpos = SetFilePointer(info->handle, 0, &hendpos, FILE_END);
if (curpos == endpos && hcurpos == hendpos)
{
/* FIXME: shouldn't WX_ATEOF be set here? */
+ release_ioinfo(info);
return TRUE;
}
- SetFilePointer(hand, curpos, &hcurpos, FILE_BEGIN);
+ SetFilePointer(info->handle, curpos, &hcurpos, FILE_BEGIN);
+ release_ioinfo(info);
return FALSE;
}
@@ -1092,15 +1110,20 @@ void msvcrt_free_io(void)
*/
__int64 CDECL _lseeki64(int fd, __int64 offset, int whence)
{
- HANDLE hand = fdtoh(fd);
+ ioinfo *info = get_ioinfo(fd);
LARGE_INTEGER ofs;
- TRACE(":fd (%d) handle (%p)\n",fd,hand);
- if (hand == INVALID_HANDLE_VALUE)
+ TRACE(":fd (%d) handle (%p)\n", fd, info->handle);
+
+ if (info->handle == INVALID_HANDLE_VALUE)
+ {
+ release_ioinfo(info);
return -1;
+ }
if (whence < 0 || whence > 2)
{
+ release_ioinfo(info);
*_errno() = EINVAL;
return -1;
}
@@ -1114,14 +1137,16 @@ __int64 CDECL _lseeki64(int fd, __int64 offset, int whence)
/* The MoleBox protection scheme expects msvcrt to use SetFilePointer only,
* so a LARGE_INTEGER offset cannot be passed directly via SetFilePointerEx. */
ofs.QuadPart = offset;
- if ((ofs.u.LowPart = SetFilePointer(hand, ofs.u.LowPart, &ofs.u.HighPart, whence))
!= INVALID_SET_FILE_POINTER ||
+ if ((ofs.u.LowPart = SetFilePointer(info->handle, ofs.u.LowPart,
&ofs.u.HighPart, whence)) != INVALID_SET_FILE_POINTER ||
GetLastError() == ERROR_SUCCESS)
{
- get_ioinfo_nolock(fd)->wxflag &= ~(WX_ATEOF|WX_READEOF);
+ info->wxflag &= ~(WX_ATEOF|WX_READEOF);
/* FIXME: What if we seek _to_ EOF - is EOF set? */
+ release_ioinfo(info);
return ofs.QuadPart;
}
+ release_ioinfo(info);
TRACE(":error-last error (%d)\n",GetLastError());
_dosmaperr(GetLastError());
return -1;
@@ -1167,16 +1192,20 @@ void CDECL _unlock_file(FILE *file)
*/
int CDECL _locking(int fd, int mode, LONG nbytes)
{
+ ioinfo *info = get_ioinfo(fd);
BOOL ret;
DWORD cur_locn;
- HANDLE hand = fdtoh(fd);
- TRACE(":fd (%d) handle (%p)\n",fd,hand);
- if (hand == INVALID_HANDLE_VALUE)
+ TRACE(":fd (%d) handle (%p)\n", fd, info->handle);
+ if (info->handle == INVALID_HANDLE_VALUE)
+ {
+ release_ioinfo(info);
return -1;
+ }
if (mode < 0 || mode > 4)
{
+ release_ioinfo(info);
*_errno() = EINVAL;
return -1;
}
@@ -1189,8 +1218,9 @@ int CDECL _locking(int fd, int mode, LONG nbytes)
(mode==_LK_NBRLCK)?"_LK_NBRLCK":
"UNKNOWN");
- if ((cur_locn = SetFilePointer(hand, 0L, NULL, SEEK_CUR)) == INVALID_SET_FILE_POINTER)
+ if ((cur_locn = SetFilePointer(info->handle, 0L, NULL, SEEK_CUR)) ==
INVALID_SET_FILE_POINTER)
{
+ release_ioinfo(info);
FIXME ("Seek failed\n");
*_errno() = EINVAL; /* FIXME */
return -1;
@@ -1201,16 +1231,17 @@ int CDECL _locking(int fd, int mode, LONG nbytes)
ret = 1; /* just to satisfy gcc */
while (nretry--)
{
- ret = LockFile(hand, cur_locn, 0L, nbytes, 0L);
+ ret = LockFile(info->handle, cur_locn, 0L, nbytes, 0L);
if (ret) break;
Sleep(1);
}
}
else if (mode == _LK_UNLCK)
- ret = UnlockFile(hand, cur_locn, 0L, nbytes, 0L);
+ ret = UnlockFile(info->handle, cur_locn, 0L, nbytes, 0L);
else
- ret = LockFile(hand, cur_locn, 0L, nbytes, 0L);
+ ret = LockFile(info->handle, cur_locn, 0L, nbytes, 0L);
/* FIXME - what about error settings? */
+ release_ioinfo(info);
return ret ? 0 : -1;
}
@@ -1259,18 +1290,16 @@ int CDECL fseek(FILE* file, long offset, int whence)
*/
int CDECL _chsize_s(int fd, __int64 size)
{
+ ioinfo *info;
__int64 cur, pos;
- HANDLE handle;
BOOL ret = FALSE;
TRACE("(fd=%d, size=%s)\n", fd, wine_dbgstr_longlong(size));
if (!MSVCRT_CHECK_PMT(size >= 0)) return EINVAL;
- LOCK_FILES();
-
- handle = fdtoh(fd);
- if (handle != INVALID_HANDLE_VALUE)
+ info = get_ioinfo(fd);
+ if (info->handle != INVALID_HANDLE_VALUE)
{
/* save the current file pointer */
cur = _lseeki64(fd, 0, SEEK_CUR);
@@ -1279,7 +1308,7 @@ int CDECL _chsize_s(int fd, __int64 size)
pos = _lseeki64(fd, size, SEEK_SET);
if (pos >= 0)
{
- ret = SetEndOfFile(handle);
+ ret = SetEndOfFile(info->handle);
if (!ret) _dosmaperr(GetLastError());
}
@@ -1288,7 +1317,7 @@ int CDECL _chsize_s(int fd, __int64 size)
}
}
- UNLOCK_FILES();
+ release_ioinfo(info);
return ret ? 0 : *_errno();
}