mirror of
https://github.com/reactos/reactos.git
synced 2025-04-04 20:50:41 +00:00
[crt]
partial sync of file.c with wine 1.7.11 svn path=/trunk/; revision=61885
This commit is contained in:
parent
ac3145e072
commit
ab7ef6db66
1 changed files with 213 additions and 19 deletions
|
@ -89,15 +89,25 @@ int *__p___mb_cur_max(void);
|
|||
#define WX_APPEND 0x20
|
||||
#define WX_TEXT 0x80
|
||||
|
||||
/* values for exflag - it's used differently in msvcr90.dll*/
|
||||
#define EF_UTF8 0x01
|
||||
#define EF_UTF16 0x02
|
||||
#define EF_CRIT_INIT 0x04
|
||||
#define EF_UNK_UNICODE 0x08
|
||||
|
||||
static char utf8_bom[3] = { 0xef, 0xbb, 0xbf };
|
||||
static char utf16_bom[2] = { 0xff, 0xfe };
|
||||
|
||||
/* FIXME: this should be allocated dynamically */
|
||||
#define MAX_FILES 2048
|
||||
#define FD_BLOCK_SIZE 64
|
||||
|
||||
/* ioinfo structure size is different in msvcrXX.dll's */
|
||||
typedef struct {
|
||||
HANDLE handle;
|
||||
unsigned char wxflag;
|
||||
char unk1;
|
||||
BOOL crit_init;
|
||||
int exflag;
|
||||
CRITICAL_SECTION crit;
|
||||
} ioinfo;
|
||||
|
||||
|
@ -734,10 +744,8 @@ int CDECL _wunlink(const wchar_t *path)
|
|||
/* _flushall calls fflush which calls _flushall */
|
||||
int CDECL fflush(FILE* file);
|
||||
|
||||
/*********************************************************************
|
||||
* _flushall (MSVCRT.@)
|
||||
*/
|
||||
int CDECL _flushall(void)
|
||||
/* INTERNAL: Flush all stream buffer */
|
||||
static int flush_all_buffers(int mask)
|
||||
{
|
||||
int i, num_flushed = 0;
|
||||
FILE *file;
|
||||
|
@ -748,8 +756,8 @@ int CDECL _flushall(void)
|
|||
|
||||
if (file->_flag)
|
||||
{
|
||||
if(file->_flag & _IOWRT) {
|
||||
fflush(file);
|
||||
if(file->_flag & mask) {
|
||||
fflush(file);
|
||||
num_flushed++;
|
||||
}
|
||||
}
|
||||
|
@ -760,22 +768,41 @@ int CDECL _flushall(void)
|
|||
return num_flushed;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* _flushall (MSVCRT.@)
|
||||
*/
|
||||
int CDECL _flushall(void)
|
||||
{
|
||||
return flush_all_buffers(_IOWRT | _IOREAD);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* fflush (MSVCRT.@)
|
||||
*/
|
||||
int CDECL fflush(FILE* file)
|
||||
{
|
||||
if(!file) {
|
||||
_flushall();
|
||||
flush_all_buffers(_IOWRT);
|
||||
} else if(file->_flag & _IOWRT) {
|
||||
int res;
|
||||
|
||||
_lock_file(file);
|
||||
res = flush_buffer(file);
|
||||
/* FIXME
|
||||
if(!res && (file->_flag & _IOCOMMIT))
|
||||
res = _commit(file->_file) ? EOF : 0;
|
||||
*/
|
||||
_unlock_file(file);
|
||||
|
||||
return res;
|
||||
}
|
||||
} else if(file->_flag & _IOREAD) {
|
||||
_lock_file(file);
|
||||
file->_cnt = 0;
|
||||
file->_ptr = file->_base;
|
||||
_unlock_file(file);
|
||||
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1220,7 +1247,9 @@ void CDECL rewind(FILE* file)
|
|||
static int get_flags(const wchar_t* mode, int *open_flags, int* stream_flags)
|
||||
{
|
||||
int plus = strchrW(mode, '+') != NULL;
|
||||
|
||||
|
||||
while(*mode == ' ') mode++;
|
||||
|
||||
switch(*mode++)
|
||||
{
|
||||
case 'R': case 'r':
|
||||
|
@ -1241,23 +1270,97 @@ static int get_flags(const wchar_t* mode, int *open_flags, int* stream_flags)
|
|||
return -1;
|
||||
}
|
||||
|
||||
while (*mode)
|
||||
/* FIXME */
|
||||
/* *stream_flags |= MSVCRT__commode; */
|
||||
|
||||
while (*mode && *mode!=',')
|
||||
switch (*mode++)
|
||||
{
|
||||
case 'B': case 'b':
|
||||
*open_flags |= _O_BINARY;
|
||||
*open_flags &= ~_O_TEXT;
|
||||
break;
|
||||
case 'T': case 't':
|
||||
case 't':
|
||||
*open_flags |= _O_TEXT;
|
||||
*open_flags &= ~_O_BINARY;
|
||||
break;
|
||||
case 'D':
|
||||
*open_flags |= _O_TEMPORARY;
|
||||
break;
|
||||
case 'T':
|
||||
*open_flags |= _O_SHORT_LIVED;
|
||||
break;
|
||||
/* FIXME
|
||||
case 'c':
|
||||
*stream_flags |= _IOCOMMIT;
|
||||
break;
|
||||
case 'n':
|
||||
*stream_flags &= ~_IOCOMMIT;
|
||||
break;
|
||||
*/
|
||||
case 'N':
|
||||
*open_flags |= _O_NOINHERIT;
|
||||
break;
|
||||
case '+':
|
||||
case ' ':
|
||||
case 'a':
|
||||
case 'w':
|
||||
break;
|
||||
case 'S':
|
||||
case 'R':
|
||||
FIXME("ignoring cache optimization flag: %c\n", mode[-1]);
|
||||
break;
|
||||
default:
|
||||
FIXME(":unknown flag %c not supported\n",mode[-1]);
|
||||
ERR("incorrect mode flag: %c\n", mode[-1]);
|
||||
break;
|
||||
}
|
||||
|
||||
if(*mode == ',')
|
||||
{
|
||||
static const WCHAR ccs[] = {'c','c','s'};
|
||||
static const WCHAR utf8[] = {'u','t','f','-','8'};
|
||||
static const WCHAR utf16le[] = {'u','t','f','-','1','6','l','e'};
|
||||
static const WCHAR unicode[] = {'u','n','i','c','o','d','e'};
|
||||
|
||||
mode++;
|
||||
while(*mode == ' ') mode++;
|
||||
if(!MSVCRT_CHECK_PMT(!strncmpW(ccs, mode, sizeof(ccs)/sizeof(ccs[0]))))
|
||||
return -1;
|
||||
mode += sizeof(ccs)/sizeof(ccs[0]);
|
||||
while(*mode == ' ') mode++;
|
||||
if(!MSVCRT_CHECK_PMT(*mode == '='))
|
||||
return -1;
|
||||
mode++;
|
||||
while(*mode == ' ') mode++;
|
||||
|
||||
if(!strncmpiW(utf8, mode, sizeof(utf8)/sizeof(utf8[0])))
|
||||
{
|
||||
*open_flags |= _O_U8TEXT;
|
||||
mode += sizeof(utf8)/sizeof(utf8[0]);
|
||||
}
|
||||
else if(!strncmpiW(utf16le, mode, sizeof(utf16le)/sizeof(utf16le[0])))
|
||||
{
|
||||
*open_flags |= _O_U16TEXT;
|
||||
mode += sizeof(utf16le)/sizeof(utf16le[0]);
|
||||
}
|
||||
else if(!strncmpiW(unicode, mode, sizeof(unicode)/sizeof(unicode[0])))
|
||||
{
|
||||
*open_flags |= _O_WTEXT;
|
||||
mode += sizeof(unicode)/sizeof(unicode[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
_invalid_parameter(NULL, NULL, NULL, 0, 0);
|
||||
*_errno() = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
while(*mode == ' ') mode++;
|
||||
}
|
||||
|
||||
if(!MSVCRT_CHECK_PMT(*mode == 0))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1446,19 +1549,23 @@ wchar_t * CDECL _wmktemp(wchar_t *pattern)
|
|||
int wxflags = 0;
|
||||
unsigned unsupp; /* until we support everything */
|
||||
|
||||
if (oflags & _O_APPEND) wxflags |= WX_APPEND;
|
||||
if (oflags & _O_BINARY) {/* Nothing to do */}
|
||||
else if (oflags & _O_TEXT) wxflags |= WX_TEXT;
|
||||
else if (*__p__fmode() & _O_BINARY) {/* Nothing to do */}
|
||||
if (oflags & _O_APPEND) wxflags |= WX_APPEND;
|
||||
if (oflags & _O_BINARY) {/* Nothing to do */}
|
||||
else if (oflags & _O_TEXT) wxflags |= WX_TEXT;
|
||||
else if (oflags & _O_WTEXT) wxflags |= WX_TEXT;
|
||||
else if (oflags & _O_U16TEXT) wxflags |= WX_TEXT;
|
||||
else if (oflags & _O_U8TEXT) wxflags |= WX_TEXT;
|
||||
else if (*__p__fmode() & _O_BINARY) {/* Nothing to do */}
|
||||
else wxflags |= WX_TEXT; /* default to TEXT*/
|
||||
if (oflags & _O_NOINHERIT) wxflags |= WX_DONTINHERIT;
|
||||
if (oflags & _O_NOINHERIT) wxflags |= WX_DONTINHERIT;
|
||||
|
||||
if ((unsupp = oflags & ~(
|
||||
_O_BINARY|_O_TEXT|_O_APPEND|
|
||||
_O_TRUNC|_O_EXCL|_O_CREAT|
|
||||
_O_RDWR|_O_WRONLY|_O_TEMPORARY|
|
||||
_O_NOINHERIT|
|
||||
_O_SEQUENTIAL|_O_RANDOM|_O_SHORT_LIVED
|
||||
_O_SEQUENTIAL|_O_RANDOM|_O_SHORT_LIVED|
|
||||
_O_WTEXT|_O_U16TEXT|_O_U8TEXT
|
||||
)))
|
||||
ERR(":unsupported oflags 0x%04x\n",unsupp);
|
||||
|
||||
|
@ -1639,6 +1746,29 @@ int CDECL _sopen( const char *path, int oflags, int shflags, ... )
|
|||
return fd;
|
||||
}
|
||||
|
||||
static int check_bom(HANDLE h, int oflags, BOOL seek)
|
||||
{
|
||||
char bom[sizeof(utf8_bom)];
|
||||
DWORD r;
|
||||
|
||||
oflags &= ~(_O_WTEXT|_O_U16TEXT|_O_U8TEXT);
|
||||
|
||||
if (!ReadFile(h, bom, sizeof(utf8_bom), &r, NULL))
|
||||
return oflags;
|
||||
|
||||
if (r==sizeof(utf8_bom) && !memcmp(bom, utf8_bom, sizeof(utf8_bom))) {
|
||||
oflags |= _O_U8TEXT;
|
||||
}else if (r>=sizeof(utf16_bom) && !memcmp(bom, utf16_bom, sizeof(utf16_bom))) {
|
||||
if (seek && r>2)
|
||||
SetFilePointer(h, 2, NULL, FILE_BEGIN);
|
||||
oflags |= _O_U16TEXT;
|
||||
}else if (seek) {
|
||||
SetFilePointer(h, 0, NULL, FILE_BEGIN);
|
||||
}
|
||||
|
||||
return oflags;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* _wsopen_s (MSVCRT.@)
|
||||
*/
|
||||
|
@ -1722,6 +1852,21 @@ int CDECL _wsopen_s( int *fd, const wchar_t* path, int oflags, int shflags, int
|
|||
sa.lpSecurityDescriptor = NULL;
|
||||
sa.bInheritHandle = (oflags & _O_NOINHERIT) ? FALSE : TRUE;
|
||||
|
||||
if ((oflags&(_O_WTEXT|_O_U16TEXT|_O_U8TEXT))
|
||||
&& (creation==OPEN_ALWAYS || creation==OPEN_EXISTING)
|
||||
&& !(access&GENERIC_READ))
|
||||
{
|
||||
hand = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE,
|
||||
&sa, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
|
||||
if (hand != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
oflags = check_bom(hand, oflags, FALSE);
|
||||
CloseHandle(hand);
|
||||
}
|
||||
else
|
||||
oflags &= ~(_O_WTEXT|_O_U16TEXT|_O_U8TEXT);
|
||||
}
|
||||
|
||||
hand = CreateFileW(path, access, sharing, &sa, creation, attrib, 0);
|
||||
|
||||
if (hand == INVALID_HANDLE_VALUE) {
|
||||
|
@ -1730,7 +1875,56 @@ int CDECL _wsopen_s( int *fd, const wchar_t* path, int oflags, int shflags, int
|
|||
return *_errno();
|
||||
}
|
||||
|
||||
if (oflags & (_O_WTEXT|_O_U16TEXT|_O_U8TEXT))
|
||||
{
|
||||
if ((access & GENERIC_WRITE) && (creation==CREATE_NEW
|
||||
|| creation==CREATE_ALWAYS || creation==TRUNCATE_EXISTING
|
||||
|| (creation==OPEN_ALWAYS && GetLastError()==ERROR_ALREADY_EXISTS)))
|
||||
{
|
||||
if (oflags & _O_U8TEXT)
|
||||
{
|
||||
DWORD written = 0, tmp;
|
||||
|
||||
while(written!=sizeof(utf8_bom) && WriteFile(hand, (char*)utf8_bom+written,
|
||||
sizeof(utf8_bom)-written, &tmp, NULL))
|
||||
written += tmp;
|
||||
if (written != sizeof(utf8_bom)) {
|
||||
WARN("error writing BOM\n");
|
||||
CloseHandle(hand);
|
||||
*_errno() = GetLastError();
|
||||
return *_errno();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DWORD written = 0, tmp;
|
||||
|
||||
while(written!=sizeof(utf16_bom) && WriteFile(hand, (char*)utf16_bom+written,
|
||||
sizeof(utf16_bom)-written, &tmp, NULL))
|
||||
written += tmp;
|
||||
if (written != sizeof(utf16_bom))
|
||||
{
|
||||
WARN("error writing BOM\n");
|
||||
CloseHandle(hand);
|
||||
*_errno() = GetLastError();
|
||||
return *_errno();
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (access & GENERIC_READ)
|
||||
oflags = check_bom(hand, oflags, TRUE);
|
||||
}
|
||||
|
||||
*fd = alloc_fd(hand, wxflag);
|
||||
if (*fd == -1)
|
||||
return *_errno();
|
||||
|
||||
if (oflags & _O_WTEXT)
|
||||
get_ioinfo(*fd)->exflag |= EF_UTF16|EF_UNK_UNICODE;
|
||||
else if (oflags & _O_U16TEXT)
|
||||
get_ioinfo(*fd)->exflag |= EF_UTF16;
|
||||
else if (oflags & _O_U8TEXT)
|
||||
get_ioinfo(*fd)->exflag |= EF_UTF8;
|
||||
|
||||
TRACE(":fd (%d) handle (%p)\n", *fd, hand);
|
||||
return 0;
|
||||
|
|
Loading…
Reference in a new issue