1c2c66affSColin Finck /* 2c2c66affSColin Finck * PROJECT: ReactOS CRT library 3c2c66affSColin Finck * LICENSE: LGPL - See COPYING in the top level directory 4c2c66affSColin Finck * FILE: lib/sdk/crt/stdio/file.c 5c2c66affSColin Finck * PURPOSE: File CRT functions 6c2c66affSColin Finck * PROGRAMMERS: Wine team 7c2c66affSColin Finck * Ported to ReactOS by Aleksey Bragin (aleksey@reactos.org) 8c2c66affSColin Finck */ 9c2c66affSColin Finck 10c2c66affSColin Finck /********************************************* 11c2c66affSColin Finck * This file contains ReactOS changes!! 12c2c66affSColin Finck * Don't blindly sync it with Wine code! 13c2c66affSColin Finck * 14c2c66affSColin Finck * If you break Unicode output on the console again, please update this counter: 15c2c66affSColin Finck * int hours_wasted_on_this = 42; 16c2c66affSColin Finck *********************************************/ 17c2c66affSColin Finck 18c2c66affSColin Finck /* 19c2c66affSColin Finck * msvcrt.dll file functions 20c2c66affSColin Finck * 21c2c66affSColin Finck * Copyright 1996,1998 Marcus Meissner 22c2c66affSColin Finck * Copyright 1996 Jukka Iivonen 23c2c66affSColin Finck * Copyright 1997,2000 Uwe Bonnes 24c2c66affSColin Finck * Copyright 2000 Jon Griffiths 25c2c66affSColin Finck * Copyright 2004 Eric Pouech 26c2c66affSColin Finck * Copyright 2004 Juan Lang 27c2c66affSColin Finck * 28c2c66affSColin Finck * This library is free software; you can redistribute it and/or 29c2c66affSColin Finck * modify it under the terms of the GNU Lesser General Public 30c2c66affSColin Finck * License as published by the Free Software Foundation; either 31c2c66affSColin Finck * version 2.1 of the License, or (at your option) any later version. 32c2c66affSColin Finck * 33c2c66affSColin Finck * This library is distributed in the hope that it will be useful, 34c2c66affSColin Finck * but WITHOUT ANY WARRANTY; without even the implied warranty of 35c2c66affSColin Finck * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 36c2c66affSColin Finck * Lesser General Public License for more details. 37c2c66affSColin Finck * 38c2c66affSColin Finck * You should have received a copy of the GNU Lesser General Public 39c2c66affSColin Finck * License along with this library; if not, write to the Free Software 40c2c66affSColin Finck * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 41c2c66affSColin Finck * 42c2c66affSColin Finck * TODO 43c2c66affSColin Finck * Use the file flag hints O_SEQUENTIAL, O_RANDOM, O_SHORT_LIVED 44c2c66affSColin Finck */ 45c2c66affSColin Finck 46c2c66affSColin Finck #include <precomp.h> 47c2c66affSColin Finck #include "wine/unicode.h" 48c529e727SThomas Faber #include "internal/wine/msvcrt.h" 49c2c66affSColin Finck 50c2c66affSColin Finck #include <sys/utime.h> 51c2c66affSColin Finck #include <direct.h> 52c2c66affSColin Finck 53c2c66affSColin Finck int *__p__fmode(void); 54c2c66affSColin Finck int *__p___mb_cur_max(void); 55c2c66affSColin Finck 56c2c66affSColin Finck extern int _commode; 57c2c66affSColin Finck 58c2c66affSColin Finck #ifndef _IOCOMMIT 59c2c66affSColin Finck #define _IOCOMMIT 0x4000 60c2c66affSColin Finck #endif 61c2c66affSColin Finck 62c2c66affSColin Finck #ifdef feof 63c2c66affSColin Finck #undef feof 64c2c66affSColin Finck #endif 65c2c66affSColin Finck #ifdef _fileno 66c2c66affSColin Finck #undef _fileno 67c2c66affSColin Finck #endif 68c2c66affSColin Finck #ifdef ferror 69c2c66affSColin Finck #undef ferror 70c2c66affSColin Finck #endif 71c2c66affSColin Finck #ifdef clearerr 72c2c66affSColin Finck #undef clearerr 73c2c66affSColin Finck #endif 74c2c66affSColin Finck 75c2c66affSColin Finck #undef getc 76c2c66affSColin Finck #undef getwc 77c2c66affSColin Finck #undef getchar 78c2c66affSColin Finck #undef getwchar 79c2c66affSColin Finck #undef putc 80c2c66affSColin Finck #undef putwc 81c2c66affSColin Finck #undef putchar 82c2c66affSColin Finck #undef putwchar 83c2c66affSColin Finck 84c2c66affSColin Finck #undef vprintf 85c2c66affSColin Finck #undef vwprintf 86c2c66affSColin Finck 87c2c66affSColin Finck /* _access() bit flags FIXME: incomplete */ 88c2c66affSColin Finck /* defined in crt/io.h */ 89c2c66affSColin Finck 90c2c66affSColin Finck /* values for wxflag in file descriptor */ 91c2c66affSColin Finck #define WX_OPEN 0x01 92c2c66affSColin Finck #define WX_ATEOF 0x02 93c2c66affSColin Finck #define WX_READNL 0x04 /* read started with \n */ 94c2c66affSColin Finck #define WX_READEOF 0x04 /* like ATEOF, but for underlying file rather than buffer */ 95c2c66affSColin Finck #define WX_PIPE 0x08 96c2c66affSColin Finck #define WX_READCR 0x08 /* underlying file is at \r */ 97c2c66affSColin Finck #define WX_DONTINHERIT 0x10 98c2c66affSColin Finck #define WX_APPEND 0x20 99c2c66affSColin Finck #define WX_TTY 0x40 100c2c66affSColin Finck #define WX_TEXT 0x80 101c2c66affSColin Finck 102c2c66affSColin Finck /* values for exflag - it's used differently in msvcr90.dll*/ 103c2c66affSColin Finck #define EF_UTF8 0x01 104c2c66affSColin Finck #define EF_UTF16 0x02 10525064fdfSThomas Faber #define EF_CRIT_INIT 0x04 106c2c66affSColin Finck #define EF_UNK_UNICODE 0x08 107c2c66affSColin Finck 108c2c66affSColin Finck static char utf8_bom[3] = { 0xef, 0xbb, 0xbf }; 109c2c66affSColin Finck static char utf16_bom[2] = { 0xff, 0xfe }; 110c2c66affSColin Finck 111c2c66affSColin Finck /* FIXME: this should be allocated dynamically */ 112c2c66affSColin Finck #define MSVCRT_MAX_FILES 2048 113c2c66affSColin Finck #define MSVCRT_FD_BLOCK_SIZE 32 114c2c66affSColin Finck 115c2c66affSColin Finck #define MSVCRT_INTERNAL_BUFSIZ 4096 116c2c66affSColin Finck 117c2c66affSColin Finck /********************************************************************* 118c2c66affSColin Finck * __pioinfo (MSVCRT.@) 119c2c66affSColin Finck * array of pointers to ioinfo arrays [32] 120c2c66affSColin Finck */ 121c2c66affSColin Finck ioinfo * __pioinfo[MSVCRT_MAX_FILES/MSVCRT_FD_BLOCK_SIZE] = { 0 }; 122c2c66affSColin Finck 123c2c66affSColin Finck /********************************************************************* 124c2c66affSColin Finck * __badioinfo (MSVCRT.@) 125c2c66affSColin Finck */ 126c2c66affSColin Finck ioinfo __badioinfo = { INVALID_HANDLE_VALUE, WX_TEXT }; 127c2c66affSColin Finck 128c2c66affSColin Finck typedef struct { 129c2c66affSColin Finck FILE file; 130c2c66affSColin Finck CRITICAL_SECTION crit; 131c2c66affSColin Finck } file_crit; 132c2c66affSColin Finck 133c2c66affSColin Finck FILE _iob[_IOB_ENTRIES] = { { 0 } }; 134c2c66affSColin Finck static file_crit* MSVCRT_fstream[MSVCRT_MAX_FILES/MSVCRT_FD_BLOCK_SIZE] = { NULL }; 135c2c66affSColin Finck static int MSVCRT_max_streams = 512, MSVCRT_stream_idx; 136c2c66affSColin Finck 137c2c66affSColin Finck /* INTERNAL: process umask */ 138c2c66affSColin Finck static int MSVCRT_umask = 0; 139c2c66affSColin Finck 140c2c66affSColin Finck /* INTERNAL: static data for tmpnam and _wtmpname functions */ 141c2c66affSColin Finck static int tmpnam_unique; 142c2c66affSColin Finck 1436aa8e3ccSThomas Faber /* This critical section protects the MSVCRT_fstreams table 1446aa8e3ccSThomas Faber * and MSVCRT_stream_idx from race conditions. It also 1456aa8e3ccSThomas Faber * protects fd critical sections creation code. 146c2c66affSColin Finck */ 147c2c66affSColin Finck static CRITICAL_SECTION MSVCRT_file_cs; 148c2c66affSColin Finck static CRITICAL_SECTION_DEBUG MSVCRT_file_cs_debug = 149c2c66affSColin Finck { 150c2c66affSColin Finck 0, 0, &MSVCRT_file_cs, 151c2c66affSColin Finck { &MSVCRT_file_cs_debug.ProcessLocksList, &MSVCRT_file_cs_debug.ProcessLocksList }, 152c2c66affSColin Finck 0, 0, { (DWORD_PTR)(__FILE__ ": MSVCRT_file_cs") } 153c2c66affSColin Finck }; 154c2c66affSColin Finck static CRITICAL_SECTION MSVCRT_file_cs = { &MSVCRT_file_cs_debug, -1, 0, 0, 0, 0 }; 155c2c66affSColin Finck #define LOCK_FILES() do { EnterCriticalSection(&MSVCRT_file_cs); } while (0) 156c2c66affSColin Finck #define UNLOCK_FILES() do { LeaveCriticalSection(&MSVCRT_file_cs); } while (0) 157c2c66affSColin Finck 158c2c66affSColin Finck static inline ioinfo* get_ioinfo_nolock(int fd) 159c2c66affSColin Finck { 160c2c66affSColin Finck ioinfo *ret = NULL; 161c2c66affSColin Finck if(fd>=0 && fd<MSVCRT_MAX_FILES) 162c2c66affSColin Finck ret = __pioinfo[fd/MSVCRT_FD_BLOCK_SIZE]; 163c2c66affSColin Finck if(!ret) 164c2c66affSColin Finck return &__badioinfo; 165c2c66affSColin Finck 166c2c66affSColin Finck return ret + (fd%MSVCRT_FD_BLOCK_SIZE); 167c2c66affSColin Finck } 168c2c66affSColin Finck 1696aa8e3ccSThomas Faber static inline void init_ioinfo_cs(ioinfo *info) 1706aa8e3ccSThomas Faber { 1716aa8e3ccSThomas Faber if(!(info->exflag & EF_CRIT_INIT)) { 1726aa8e3ccSThomas Faber LOCK_FILES(); 1736aa8e3ccSThomas Faber if(!(info->exflag & EF_CRIT_INIT)) { 1746aa8e3ccSThomas Faber InitializeCriticalSection(&info->crit); 1756aa8e3ccSThomas Faber info->exflag |= EF_CRIT_INIT; 1766aa8e3ccSThomas Faber } 1776aa8e3ccSThomas Faber UNLOCK_FILES(); 1786aa8e3ccSThomas Faber } 1796aa8e3ccSThomas Faber } 1806aa8e3ccSThomas Faber 181*c8719ee8SHervé Poussineau ioinfo* get_ioinfo(int fd) 182c2c66affSColin Finck { 1839eb1eae2SThomas Faber ioinfo *ret = get_ioinfo_nolock(fd); 184bffd8201SThomas Faber if(ret == &__badioinfo) 185bffd8201SThomas Faber return ret; 1866aa8e3ccSThomas Faber init_ioinfo_cs(ret); 1879eb1eae2SThomas Faber EnterCriticalSection(&ret->crit); 1889eb1eae2SThomas Faber return ret; 1899eb1eae2SThomas Faber } 190c2c66affSColin Finck 19127b79867SThomas Faber static inline BOOL alloc_pioinfo_block(int fd) 19227b79867SThomas Faber { 19327b79867SThomas Faber ioinfo *block; 19427b79867SThomas Faber int i; 19527b79867SThomas Faber 19627b79867SThomas Faber if(fd<0 || fd>=MSVCRT_MAX_FILES) 19727b79867SThomas Faber { 19827b79867SThomas Faber *_errno() = ENFILE; 19927b79867SThomas Faber return FALSE; 20027b79867SThomas Faber } 20127b79867SThomas Faber 20227b79867SThomas Faber block = calloc(MSVCRT_FD_BLOCK_SIZE, sizeof(ioinfo)); 20327b79867SThomas Faber if(!block) 20427b79867SThomas Faber { 20527b79867SThomas Faber WARN(":out of memory!\n"); 20627b79867SThomas Faber *_errno() = ENOMEM; 20727b79867SThomas Faber return FALSE; 20827b79867SThomas Faber } 20927b79867SThomas Faber for(i=0; i<MSVCRT_FD_BLOCK_SIZE; i++) 21027b79867SThomas Faber block[i].handle = INVALID_HANDLE_VALUE; 21127b79867SThomas Faber if(InterlockedCompareExchangePointer((void**)&__pioinfo[fd/MSVCRT_FD_BLOCK_SIZE], block, NULL)) 21227b79867SThomas Faber free(block); 21327b79867SThomas Faber return TRUE; 21427b79867SThomas Faber } 21527b79867SThomas Faber 21627b79867SThomas Faber static inline ioinfo* get_ioinfo_alloc_fd(int fd) 21727b79867SThomas Faber { 2186aa8e3ccSThomas Faber ioinfo *ret; 21927b79867SThomas Faber 22027b79867SThomas Faber ret = get_ioinfo(fd); 22127b79867SThomas Faber if(ret != &__badioinfo) 22227b79867SThomas Faber return ret; 22327b79867SThomas Faber 22427b79867SThomas Faber if(!alloc_pioinfo_block(fd)) 22527b79867SThomas Faber return &__badioinfo; 22627b79867SThomas Faber 2276aa8e3ccSThomas Faber return get_ioinfo(fd); 2286aa8e3ccSThomas Faber } 22927b79867SThomas Faber 2306aa8e3ccSThomas Faber static inline ioinfo* get_ioinfo_alloc(int *fd) 23127b79867SThomas Faber { 2326aa8e3ccSThomas Faber int i; 2336aa8e3ccSThomas Faber 2346aa8e3ccSThomas Faber *fd = -1; 2356aa8e3ccSThomas Faber for(i=0; i<MSVCRT_MAX_FILES; i++) 23627b79867SThomas Faber { 2376aa8e3ccSThomas Faber ioinfo *info = get_ioinfo_nolock(i); 2386aa8e3ccSThomas Faber 2396aa8e3ccSThomas Faber if(info == &__badioinfo) 2406aa8e3ccSThomas Faber { 2416aa8e3ccSThomas Faber if(!alloc_pioinfo_block(i)) 2426aa8e3ccSThomas Faber return &__badioinfo; 2436aa8e3ccSThomas Faber info = get_ioinfo_nolock(i); 2446aa8e3ccSThomas Faber } 2456aa8e3ccSThomas Faber 2466aa8e3ccSThomas Faber init_ioinfo_cs(info); 24727b79867SThomas Faber if(TryEnterCriticalSection(&info->crit)) 24827b79867SThomas Faber { 24927b79867SThomas Faber if(info->handle == INVALID_HANDLE_VALUE) 25027b79867SThomas Faber { 2516aa8e3ccSThomas Faber *fd = i; 2526aa8e3ccSThomas Faber return info; 25327b79867SThomas Faber } 25427b79867SThomas Faber LeaveCriticalSection(&info->crit); 25527b79867SThomas Faber } 25627b79867SThomas Faber } 25727b79867SThomas Faber 2586aa8e3ccSThomas Faber WARN(":files exhausted!\n"); 2596aa8e3ccSThomas Faber *_errno() = ENFILE; 2606aa8e3ccSThomas Faber return &__badioinfo; 26127b79867SThomas Faber } 26227b79867SThomas Faber 263*c8719ee8SHervé Poussineau void release_ioinfo(ioinfo *info) 2649eb1eae2SThomas Faber { 265bffd8201SThomas Faber if(info!=&__badioinfo && info->exflag & EF_CRIT_INIT) 2669eb1eae2SThomas Faber LeaveCriticalSection(&info->crit); 267c2c66affSColin Finck } 268c2c66affSColin Finck 269c2c66affSColin Finck static inline FILE* msvcrt_get_file(int i) 270c2c66affSColin Finck { 271c2c66affSColin Finck file_crit *ret; 272c2c66affSColin Finck 273c2c66affSColin Finck if(i >= MSVCRT_max_streams) 274c2c66affSColin Finck return NULL; 275c2c66affSColin Finck 276c2c66affSColin Finck if(i < _IOB_ENTRIES) 277c2c66affSColin Finck return &_iob[i]; 278c2c66affSColin Finck 279c2c66affSColin Finck ret = MSVCRT_fstream[i/MSVCRT_FD_BLOCK_SIZE]; 280c2c66affSColin Finck if(!ret) { 281c2c66affSColin Finck MSVCRT_fstream[i/MSVCRT_FD_BLOCK_SIZE] = calloc(MSVCRT_FD_BLOCK_SIZE, sizeof(file_crit)); 282c2c66affSColin Finck if(!MSVCRT_fstream[i/MSVCRT_FD_BLOCK_SIZE]) { 283c2c66affSColin Finck ERR("out of memory\n"); 284c2c66affSColin Finck *_errno() = ENOMEM; 285c2c66affSColin Finck return NULL; 286c2c66affSColin Finck } 287c2c66affSColin Finck 288c2c66affSColin Finck ret = MSVCRT_fstream[i/MSVCRT_FD_BLOCK_SIZE] + (i%MSVCRT_FD_BLOCK_SIZE); 289c2c66affSColin Finck } else 290c2c66affSColin Finck ret += i%MSVCRT_FD_BLOCK_SIZE; 291c2c66affSColin Finck 292c2c66affSColin Finck return &ret->file; 293c2c66affSColin Finck } 294c2c66affSColin Finck 295c2c66affSColin Finck /* INTERNAL: free a file entry fd */ 296c2c66affSColin Finck static void msvcrt_free_fd(int fd) 297c2c66affSColin Finck { 298bffd8201SThomas Faber ioinfo *fdinfo = get_ioinfo(fd); 299c2c66affSColin Finck 300c2c66affSColin Finck if(fdinfo != &__badioinfo) 301c2c66affSColin Finck { 302c2c66affSColin Finck fdinfo->handle = INVALID_HANDLE_VALUE; 303c2c66affSColin Finck fdinfo->wxflag = 0; 304c2c66affSColin Finck } 305c2c66affSColin Finck TRACE(":fd (%d) freed\n",fd); 306c2c66affSColin Finck 307c2c66affSColin Finck if (fd < 3) 308c2c66affSColin Finck { 309c2c66affSColin Finck switch (fd) 310c2c66affSColin Finck { 311c2c66affSColin Finck case 0: 312c2c66affSColin Finck SetStdHandle(STD_INPUT_HANDLE, 0); 313c2c66affSColin Finck break; 314c2c66affSColin Finck case 1: 315c2c66affSColin Finck SetStdHandle(STD_OUTPUT_HANDLE, 0); 316c2c66affSColin Finck break; 317c2c66affSColin Finck case 2: 318c2c66affSColin Finck SetStdHandle(STD_ERROR_HANDLE, 0); 319c2c66affSColin Finck break; 320c2c66affSColin Finck } 321c2c66affSColin Finck } 322bffd8201SThomas Faber release_ioinfo(fdinfo); 323c2c66affSColin Finck } 324c2c66affSColin Finck 32527b79867SThomas Faber static void msvcrt_set_fd(ioinfo *fdinfo, HANDLE hand, int flag) 326c2c66affSColin Finck { 327c2c66affSColin Finck fdinfo->handle = hand; 328c2c66affSColin Finck fdinfo->wxflag = WX_OPEN | (flag & (WX_DONTINHERIT | WX_APPEND | WX_TEXT | WX_PIPE | WX_TTY)); 329c2c66affSColin Finck fdinfo->lookahead[0] = '\n'; 330c2c66affSColin Finck fdinfo->lookahead[1] = '\n'; 331c2c66affSColin Finck fdinfo->lookahead[2] = '\n'; 33227b79867SThomas Faber fdinfo->exflag &= EF_CRIT_INIT; 333c2c66affSColin Finck 33427b79867SThomas Faber switch (fdinfo-__pioinfo[0]) 335c2c66affSColin Finck { 336c2c66affSColin Finck case 0: SetStdHandle(STD_INPUT_HANDLE, hand); break; 337c2c66affSColin Finck case 1: SetStdHandle(STD_OUTPUT_HANDLE, hand); break; 338c2c66affSColin Finck case 2: SetStdHandle(STD_ERROR_HANDLE, hand); break; 339c2c66affSColin Finck } 340c2c66affSColin Finck } 341c2c66affSColin Finck 342c2c66affSColin Finck /* INTERNAL: Allocate an fd slot from a Win32 HANDLE */ 343c2c66affSColin Finck /*static*/ int msvcrt_alloc_fd(HANDLE hand, int flag) 344c2c66affSColin Finck { 34527b79867SThomas Faber int fd; 3466aa8e3ccSThomas Faber ioinfo *info = get_ioinfo_alloc(&fd); 347c2c66affSColin Finck 34827b79867SThomas Faber TRACE(":handle (%p) allocating fd (%d)\n", hand, fd); 34927b79867SThomas Faber 35027b79867SThomas Faber if(info == &__badioinfo) 35127b79867SThomas Faber return -1; 35227b79867SThomas Faber 35327b79867SThomas Faber msvcrt_set_fd(info, hand, flag); 35427b79867SThomas Faber release_ioinfo(info); 35527b79867SThomas Faber return fd; 356c2c66affSColin Finck } 357c2c66affSColin Finck 358c2c66affSColin Finck /* INTERNAL: Allocate a FILE* for an fd slot */ 359c2c66affSColin Finck /* caller must hold the files lock */ 360c2c66affSColin Finck static FILE* msvcrt_alloc_fp(void) 361c2c66affSColin Finck { 362c2c66affSColin Finck int i; 363c2c66affSColin Finck FILE *file; 364c2c66affSColin Finck 365c2c66affSColin Finck for (i = 3; i < MSVCRT_max_streams; i++) 366c2c66affSColin Finck { 367c2c66affSColin Finck file = msvcrt_get_file(i); 368c2c66affSColin Finck if (!file) 369c2c66affSColin Finck return NULL; 370c2c66affSColin Finck 371c2c66affSColin Finck if (file->_flag == 0) 372c2c66affSColin Finck { 373c2c66affSColin Finck if (i == MSVCRT_stream_idx) MSVCRT_stream_idx++; 374c2c66affSColin Finck return file; 375c2c66affSColin Finck } 376c2c66affSColin Finck } 377c2c66affSColin Finck 378c2c66affSColin Finck return NULL; 379c2c66affSColin Finck } 380c2c66affSColin Finck 381c2c66affSColin Finck /* INTERNAL: initialize a FILE* from an open fd */ 382c2c66affSColin Finck static int msvcrt_init_fp(FILE* file, int fd, unsigned stream_flags) 383c2c66affSColin Finck { 384c2c66affSColin Finck TRACE(":fd (%d) allocating FILE*\n",fd); 38553864fccSThomas Faber if (!(get_ioinfo_nolock(fd)->wxflag & WX_OPEN)) 386c2c66affSColin Finck { 387c2c66affSColin Finck WARN(":invalid fd %d\n",fd); 388c2c66affSColin Finck *__doserrno() = 0; 389c2c66affSColin Finck *_errno() = EBADF; 390c2c66affSColin Finck return -1; 391c2c66affSColin Finck } 392c2c66affSColin Finck file->_ptr = file->_base = NULL; 393c2c66affSColin Finck file->_cnt = 0; 394c2c66affSColin Finck file->_file = fd; 395c2c66affSColin Finck file->_flag = stream_flags; 396c2c66affSColin Finck file->_tmpfname = NULL; 397c2c66affSColin Finck 398c2c66affSColin Finck if(file<_iob || file>=_iob+_IOB_ENTRIES) 399c2c66affSColin Finck InitializeCriticalSection(&((file_crit*)file)->crit); 400c2c66affSColin Finck 401c2c66affSColin Finck TRACE(":got FILE* (%p)\n",file); 402c2c66affSColin Finck return 0; 403c2c66affSColin Finck } 404c2c66affSColin Finck 405c2c66affSColin Finck /* INTERNAL: Create an inheritance data block (for spawned process) 406c2c66affSColin Finck * The inheritance block is made of: 407c2c66affSColin Finck * 00 int nb of file descriptor (NBFD) 408c2c66affSColin Finck * 04 char file flags (wxflag): repeated for each fd 409c2c66affSColin Finck * 4+NBFD HANDLE file handle: repeated for each fd 410c2c66affSColin Finck */ 411c2c66affSColin Finck unsigned create_io_inherit_block(WORD *size, BYTE **block) 412c2c66affSColin Finck { 41327b79867SThomas Faber int fd, last_fd; 414c2c66affSColin Finck char* wxflag_ptr; 415c2c66affSColin Finck HANDLE* handle_ptr; 416c2c66affSColin Finck ioinfo* fdinfo; 417c2c66affSColin Finck 41827b79867SThomas Faber for (last_fd=MSVCRT_MAX_FILES-1; last_fd>=0; last_fd--) 41927b79867SThomas Faber if (get_ioinfo_nolock(last_fd)->handle != INVALID_HANDLE_VALUE) 42027b79867SThomas Faber break; 42127b79867SThomas Faber last_fd++; 42227b79867SThomas Faber 42327b79867SThomas Faber *size = sizeof(unsigned) + (sizeof(char) + sizeof(HANDLE)) * last_fd; 424c2c66affSColin Finck *block = calloc(1, *size); 425c2c66affSColin Finck if (!*block) 426c2c66affSColin Finck { 427c2c66affSColin Finck *size = 0; 428c2c66affSColin Finck return FALSE; 429c2c66affSColin Finck } 430c2c66affSColin Finck wxflag_ptr = (char*)*block + sizeof(unsigned); 43127b79867SThomas Faber handle_ptr = (HANDLE*)(wxflag_ptr + last_fd); 432c2c66affSColin Finck 43327b79867SThomas Faber *(unsigned*)*block = last_fd; 43427b79867SThomas Faber for (fd = 0; fd < last_fd; fd++) 435c2c66affSColin Finck { 436c2c66affSColin Finck /* to be inherited, we need it to be open, and that DONTINHERIT isn't set */ 437bffd8201SThomas Faber fdinfo = get_ioinfo(fd); 438c2c66affSColin Finck if ((fdinfo->wxflag & (WX_OPEN | WX_DONTINHERIT)) == WX_OPEN) 439c2c66affSColin Finck { 440c2c66affSColin Finck *wxflag_ptr = fdinfo->wxflag; 441c2c66affSColin Finck *handle_ptr = fdinfo->handle; 442c2c66affSColin Finck } 443c2c66affSColin Finck else 444c2c66affSColin Finck { 445c2c66affSColin Finck *wxflag_ptr = 0; 446c2c66affSColin Finck *handle_ptr = INVALID_HANDLE_VALUE; 447c2c66affSColin Finck } 448bffd8201SThomas Faber release_ioinfo(fdinfo); 449c2c66affSColin Finck wxflag_ptr++; handle_ptr++; 450c2c66affSColin Finck } 451c2c66affSColin Finck return TRUE; 452c2c66affSColin Finck } 453c2c66affSColin Finck 454c2c66affSColin Finck /* INTERNAL: Set up all file descriptors, 455c2c66affSColin Finck * as well as default streams (stdin, stderr and stdout) 456c2c66affSColin Finck */ 457c2c66affSColin Finck void msvcrt_init_io(void) 458c2c66affSColin Finck { 459c2c66affSColin Finck STARTUPINFOA si; 460c2c66affSColin Finck unsigned int i; 461c2c66affSColin Finck ioinfo *fdinfo; 462c2c66affSColin Finck 463c2c66affSColin Finck GetStartupInfoA(&si); 464c2c66affSColin Finck if (si.cbReserved2 >= sizeof(unsigned int) && si.lpReserved2 != NULL) 465c2c66affSColin Finck { 466c2c66affSColin Finck BYTE* wxflag_ptr; 467c2c66affSColin Finck HANDLE* handle_ptr; 468c2c66affSColin Finck unsigned int count; 469c2c66affSColin Finck 470c2c66affSColin Finck count = *(unsigned*)si.lpReserved2; 471c2c66affSColin Finck wxflag_ptr = si.lpReserved2 + sizeof(unsigned); 472c2c66affSColin Finck handle_ptr = (HANDLE*)(wxflag_ptr + count); 473c2c66affSColin Finck 474c2c66affSColin Finck count = min(count, (si.cbReserved2 - sizeof(unsigned)) / (sizeof(HANDLE) + 1)); 475c2c66affSColin Finck count = min(count, MSVCRT_MAX_FILES); 476c2c66affSColin Finck for (i = 0; i < count; i++) 477c2c66affSColin Finck { 478c2c66affSColin Finck if ((*wxflag_ptr & WX_OPEN) && *handle_ptr != INVALID_HANDLE_VALUE) 47927b79867SThomas Faber { 48027b79867SThomas Faber fdinfo = get_ioinfo_alloc_fd(i); 48127b79867SThomas Faber if(fdinfo != &__badioinfo) 48227b79867SThomas Faber msvcrt_set_fd(fdinfo, *handle_ptr, *wxflag_ptr); 48327b79867SThomas Faber release_ioinfo(fdinfo); 48427b79867SThomas Faber } 485c2c66affSColin Finck 486c2c66affSColin Finck wxflag_ptr++; handle_ptr++; 487c2c66affSColin Finck } 488c2c66affSColin Finck } 489c2c66affSColin Finck 49027b79867SThomas Faber fdinfo = get_ioinfo_alloc_fd(STDIN_FILENO); 491c2c66affSColin Finck if (!(fdinfo->wxflag & WX_OPEN) || fdinfo->handle == INVALID_HANDLE_VALUE) { 492c2c66affSColin Finck HANDLE h = GetStdHandle(STD_INPUT_HANDLE); 493c2c66affSColin Finck DWORD type = GetFileType(h); 494c2c66affSColin Finck 49527b79867SThomas Faber msvcrt_set_fd(fdinfo, h, WX_OPEN|WX_TEXT|((type&0xf)==FILE_TYPE_CHAR ? WX_TTY : 0) 49627b79867SThomas Faber |((type&0xf)==FILE_TYPE_PIPE ? WX_PIPE : 0)); 497c2c66affSColin Finck } 49827b79867SThomas Faber release_ioinfo(fdinfo); 499c2c66affSColin Finck 50027b79867SThomas Faber fdinfo = get_ioinfo_alloc_fd(STDOUT_FILENO); 501c2c66affSColin Finck if (!(fdinfo->wxflag & WX_OPEN) || fdinfo->handle == INVALID_HANDLE_VALUE) { 502c2c66affSColin Finck HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE); 503c2c66affSColin Finck DWORD type = GetFileType(h); 504c2c66affSColin Finck 50527b79867SThomas Faber msvcrt_set_fd(fdinfo, h, WX_OPEN|WX_TEXT|((type&0xf)==FILE_TYPE_CHAR ? WX_TTY : 0) 50627b79867SThomas Faber |((type&0xf)==FILE_TYPE_PIPE ? WX_PIPE : 0)); 507c2c66affSColin Finck } 50827b79867SThomas Faber release_ioinfo(fdinfo); 509c2c66affSColin Finck 51027b79867SThomas Faber fdinfo = get_ioinfo_alloc_fd(STDERR_FILENO); 511c2c66affSColin Finck if (!(fdinfo->wxflag & WX_OPEN) || fdinfo->handle == INVALID_HANDLE_VALUE) { 512c2c66affSColin Finck HANDLE h = GetStdHandle(STD_ERROR_HANDLE); 513c2c66affSColin Finck DWORD type = GetFileType(h); 514c2c66affSColin Finck 51527b79867SThomas Faber msvcrt_set_fd(fdinfo, h, WX_OPEN|WX_TEXT|((type&0xf)==FILE_TYPE_CHAR ? WX_TTY : 0) 51627b79867SThomas Faber |((type&0xf)==FILE_TYPE_PIPE ? WX_PIPE : 0)); 517c2c66affSColin Finck } 51827b79867SThomas Faber release_ioinfo(fdinfo); 519c2c66affSColin Finck 52025064fdfSThomas Faber TRACE(":handles (%p)(%p)(%p)\n", get_ioinfo_nolock(STDIN_FILENO)->handle, 52125064fdfSThomas Faber get_ioinfo_nolock(STDOUT_FILENO)->handle, 52225064fdfSThomas Faber get_ioinfo_nolock(STDERR_FILENO)->handle); 523c2c66affSColin Finck 524c2c66affSColin Finck memset(_iob,0,3*sizeof(FILE)); 525c2c66affSColin Finck for (i = 0; i < 3; i++) 526c2c66affSColin Finck { 527c2c66affSColin Finck /* FILE structs for stdin/out/err are static and never deleted */ 528c2c66affSColin Finck _iob[i]._file = i; 529c2c66affSColin Finck _iob[i]._tmpfname = NULL; 530c2c66affSColin Finck _iob[i]._flag = (i == 0) ? _IOREAD : _IOWRT; 531c2c66affSColin Finck } 532c2c66affSColin Finck MSVCRT_stream_idx = 3; 533c2c66affSColin Finck } 534c2c66affSColin Finck 535c2c66affSColin Finck /* INTERNAL: Flush stdio file buffer */ 536c2c66affSColin Finck static int msvcrt_flush_buffer(FILE* file) 537c2c66affSColin Finck { 538c2c66affSColin Finck if((file->_flag & (_IOREAD|_IOWRT)) == _IOWRT && 539c2c66affSColin Finck file->_flag & (_IOMYBUF|_USERBUF)) { 540c2c66affSColin Finck int cnt=file->_ptr-file->_base; 541c2c66affSColin Finck if(cnt>0 && _write(file->_file, file->_base, cnt) != cnt) { 542c2c66affSColin Finck file->_flag |= _IOERR; 543c2c66affSColin Finck return EOF; 544c2c66affSColin Finck } 545c2c66affSColin Finck 546c2c66affSColin Finck if(file->_flag & _IORW) 547c2c66affSColin Finck file->_flag &= ~_IOWRT; 548c2c66affSColin Finck 549c2c66affSColin Finck #ifdef __REACTOS__ /* CORE-11949 */ 550c2c66affSColin Finck file->_ptr=file->_base; 551c2c66affSColin Finck file->_cnt=0; 552c2c66affSColin Finck #endif 553c2c66affSColin Finck } 554c2c66affSColin Finck 555c2c66affSColin Finck #ifndef __REACTOS__ /* CORE-11949 */ 556c2c66affSColin Finck file->_ptr=file->_base; 557c2c66affSColin Finck file->_cnt=0; 558c2c66affSColin Finck #endif 559c2c66affSColin Finck return 0; 560c2c66affSColin Finck } 561c2c66affSColin Finck 562c2c66affSColin Finck /********************************************************************* 563c2c66affSColin Finck * _isatty (MSVCRT.@) 564c2c66affSColin Finck */ 565c2c66affSColin Finck int CDECL _isatty(int fd) 566c2c66affSColin Finck { 567c2c66affSColin Finck TRACE(":fd (%d)\n",fd); 568c2c66affSColin Finck 569c2c66affSColin Finck return get_ioinfo_nolock(fd)->wxflag & WX_TTY; 570c2c66affSColin Finck } 571c2c66affSColin Finck 572c2c66affSColin Finck /* INTERNAL: Allocate stdio file buffer */ 573c2c66affSColin Finck /*static*/ BOOL msvcrt_alloc_buffer(FILE* file) 574c2c66affSColin Finck { 575c2c66affSColin Finck if((file->_file==STDOUT_FILENO || file->_file==STDERR_FILENO) 576c2c66affSColin Finck && _isatty(file->_file)) 577c2c66affSColin Finck return FALSE; 578c2c66affSColin Finck 579c2c66affSColin Finck file->_base = calloc(1, MSVCRT_INTERNAL_BUFSIZ); 580c2c66affSColin Finck if(file->_base) { 581c2c66affSColin Finck file->_bufsiz = MSVCRT_INTERNAL_BUFSIZ; 582c2c66affSColin Finck file->_flag |= _IOMYBUF; 583c2c66affSColin Finck } else { 584c2c66affSColin Finck file->_base = (char*)(&file->_charbuf); 585c2c66affSColin Finck file->_bufsiz = 2; 586c2c66affSColin Finck file->_flag |= _IONBF; 587c2c66affSColin Finck } 588c2c66affSColin Finck file->_ptr = file->_base; 589c2c66affSColin Finck file->_cnt = 0; 590c2c66affSColin Finck return TRUE; 591c2c66affSColin Finck } 592c2c66affSColin Finck 593c2c66affSColin Finck /* INTERNAL: Allocate temporary buffer for stdout and stderr */ 594c2c66affSColin Finck static BOOL add_std_buffer(FILE *file) 595c2c66affSColin Finck { 596c2c66affSColin Finck static char buffers[2][BUFSIZ]; 597c2c66affSColin Finck 598c2c66affSColin Finck if((file->_file!=STDOUT_FILENO && file->_file!=STDERR_FILENO) 599c2c66affSColin Finck || (file->_flag & (_IONBF | _IOMYBUF | _USERBUF)) 600c2c66affSColin Finck || !_isatty(file->_file)) 601c2c66affSColin Finck return FALSE; 602c2c66affSColin Finck 603c2c66affSColin Finck file->_ptr = file->_base = buffers[file->_file == STDOUT_FILENO ? 0 : 1]; 604c2c66affSColin Finck file->_bufsiz = file->_cnt = BUFSIZ; 605c2c66affSColin Finck file->_flag |= _USERBUF; 606c2c66affSColin Finck return TRUE; 607c2c66affSColin Finck } 608c2c66affSColin Finck 609c2c66affSColin Finck /* INTERNAL: Removes temporary buffer from stdout or stderr */ 610c2c66affSColin Finck /* Only call this function when add_std_buffer returned TRUE */ 611c2c66affSColin Finck static void remove_std_buffer(FILE *file) 612c2c66affSColin Finck { 613c2c66affSColin Finck msvcrt_flush_buffer(file); 614c2c66affSColin Finck file->_ptr = file->_base = NULL; 615c2c66affSColin Finck file->_bufsiz = file->_cnt = 0; 616c2c66affSColin Finck file->_flag &= ~_USERBUF; 617c2c66affSColin Finck } 618c2c66affSColin Finck 619c2c66affSColin Finck /* INTERNAL: Convert integer to base32 string (0-9a-v), 0 becomes "" */ 620c2c66affSColin Finck static int msvcrt_int_to_base32(int num, char *str) 621c2c66affSColin Finck { 622c2c66affSColin Finck char *p; 623c2c66affSColin Finck int n = num; 624c2c66affSColin Finck int digits = 0; 625c2c66affSColin Finck 626c2c66affSColin Finck while (n != 0) 627c2c66affSColin Finck { 628c2c66affSColin Finck n >>= 5; 629c2c66affSColin Finck digits++; 630c2c66affSColin Finck } 631c2c66affSColin Finck p = str + digits; 632c2c66affSColin Finck *p = 0; 633c2c66affSColin Finck while (--p >= str) 634c2c66affSColin Finck { 635c2c66affSColin Finck *p = (num & 31) + '0'; 636c2c66affSColin Finck if (*p > '9') 637c2c66affSColin Finck *p += ('a' - '0' - 10); 638c2c66affSColin Finck num >>= 5; 639c2c66affSColin Finck } 640c2c66affSColin Finck 641c2c66affSColin Finck return digits; 642c2c66affSColin Finck } 643c2c66affSColin Finck 644c2c66affSColin Finck /* INTERNAL: wide character version of msvcrt_int_to_base32 */ 645c2c66affSColin Finck static int msvcrt_int_to_base32_w(int num, wchar_t *str) 646c2c66affSColin Finck { 647c2c66affSColin Finck wchar_t *p; 648c2c66affSColin Finck int n = num; 649c2c66affSColin Finck int digits = 0; 650c2c66affSColin Finck 651c2c66affSColin Finck while (n != 0) 652c2c66affSColin Finck { 653c2c66affSColin Finck n >>= 5; 654c2c66affSColin Finck digits++; 655c2c66affSColin Finck } 656c2c66affSColin Finck p = str + digits; 657c2c66affSColin Finck *p = 0; 658c2c66affSColin Finck while (--p >= str) 659c2c66affSColin Finck { 660c2c66affSColin Finck *p = (num & 31) + '0'; 661c2c66affSColin Finck if (*p > '9') 662c2c66affSColin Finck *p += ('a' - '0' - 10); 663c2c66affSColin Finck num >>= 5; 664c2c66affSColin Finck } 665c2c66affSColin Finck 666c2c66affSColin Finck return digits; 667c2c66affSColin Finck } 668c2c66affSColin Finck 669c2c66affSColin Finck /* INTERNAL: Create a wide string from an ascii string */ 670c2c66affSColin Finck wchar_t *msvcrt_wstrdupa(const char *str) 671c2c66affSColin Finck { 672c2c66affSColin Finck const unsigned int len = strlen(str) + 1 ; 673c2c66affSColin Finck wchar_t *wstr = malloc(len* sizeof (wchar_t)); 674c2c66affSColin Finck if (!wstr) 675c2c66affSColin Finck return NULL; 676c2c66affSColin Finck MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED,str,len,wstr,len); 677c2c66affSColin Finck return wstr; 678c2c66affSColin Finck } 679c2c66affSColin Finck 680c2c66affSColin Finck /********************************************************************* 681c2c66affSColin Finck * __iob_func(MSVCRT.@) 682c2c66affSColin Finck */ 683c2c66affSColin Finck FILE * CDECL __iob_func(void) 684c2c66affSColin Finck { 685c2c66affSColin Finck return &_iob[0]; 686c2c66affSColin Finck } 687c2c66affSColin Finck 688c2c66affSColin Finck /********************************************************************* 689c2c66affSColin Finck * _access (MSVCRT.@) 690c2c66affSColin Finck */ 691c2c66affSColin Finck int CDECL _access(const char *filename, int mode) 692c2c66affSColin Finck { 693c2c66affSColin Finck DWORD attr = GetFileAttributesA(filename); 694c2c66affSColin Finck 695c2c66affSColin Finck TRACE("(%s,%d) %d\n",filename,mode,attr); 696c2c66affSColin Finck 697c2c66affSColin Finck if (!filename || attr == INVALID_FILE_ATTRIBUTES) 698c2c66affSColin Finck { 699c2c66affSColin Finck _dosmaperr(GetLastError()); 700c2c66affSColin Finck return -1; 701c2c66affSColin Finck } 702c2c66affSColin Finck if ((attr & FILE_ATTRIBUTE_READONLY) && (mode & W_OK)) 703c2c66affSColin Finck { 704c2c66affSColin Finck _set_errno(ERROR_ACCESS_DENIED); 705c2c66affSColin Finck return -1; 706c2c66affSColin Finck } 707c2c66affSColin Finck return 0; 708c2c66affSColin Finck } 709c2c66affSColin Finck 710c2c66affSColin Finck /********************************************************************* 711c2c66affSColin Finck * _access_s (MSVCRT.@) 712c2c66affSColin Finck */ 713c2c66affSColin Finck int CDECL _access_s(const char *filename, int mode) 714c2c66affSColin Finck { 715c2c66affSColin Finck if (!MSVCRT_CHECK_PMT(filename != NULL) || 716c2c66affSColin Finck !MSVCRT_CHECK_PMT((mode & ~(R_OK | W_OK)) == 0)) 717c2c66affSColin Finck { 718c2c66affSColin Finck _set_errno(EINVAL); 719c2c66affSColin Finck return -1; 720c2c66affSColin Finck } 721c2c66affSColin Finck 722c2c66affSColin Finck return _access(filename, mode); 723c2c66affSColin Finck } 724c2c66affSColin Finck 725c2c66affSColin Finck /********************************************************************* 726c2c66affSColin Finck * _waccess (MSVCRT.@) 727c2c66affSColin Finck */ 728c2c66affSColin Finck int CDECL _waccess(const wchar_t *filename, int mode) 729c2c66affSColin Finck { 730c2c66affSColin Finck DWORD attr = GetFileAttributesW(filename); 731c2c66affSColin Finck 732c2c66affSColin Finck TRACE("(%s,%d) %d\n",debugstr_w(filename),mode,attr); 733c2c66affSColin Finck 734c2c66affSColin Finck if (!filename || attr == INVALID_FILE_ATTRIBUTES) 735c2c66affSColin Finck { 736c2c66affSColin Finck _dosmaperr(GetLastError()); 737c2c66affSColin Finck return -1; 738c2c66affSColin Finck } 739c2c66affSColin Finck if ((attr & FILE_ATTRIBUTE_READONLY) && (mode & W_OK)) 740c2c66affSColin Finck { 741c2c66affSColin Finck _set_errno(ERROR_ACCESS_DENIED); 742c2c66affSColin Finck return -1; 743c2c66affSColin Finck } 744c2c66affSColin Finck return 0; 745c2c66affSColin Finck } 746c2c66affSColin Finck 747c2c66affSColin Finck /********************************************************************* 748c2c66affSColin Finck * _waccess_s (MSVCRT.@) 749c2c66affSColin Finck */ 750c2c66affSColin Finck int CDECL _waccess_s(const wchar_t *filename, int mode) 751c2c66affSColin Finck { 752c2c66affSColin Finck if (!MSVCRT_CHECK_PMT(filename != NULL) || 753c2c66affSColin Finck !MSVCRT_CHECK_PMT((mode & ~(R_OK | W_OK)) == 0)) 754c2c66affSColin Finck { 755c2c66affSColin Finck *_errno() = EINVAL; 756c2c66affSColin Finck return -1; 757c2c66affSColin Finck } 758c2c66affSColin Finck 759c2c66affSColin Finck return _waccess(filename, mode); 760c2c66affSColin Finck } 761c2c66affSColin Finck 762c2c66affSColin Finck /********************************************************************* 763c2c66affSColin Finck * _chmod (MSVCRT.@) 764c2c66affSColin Finck */ 765c2c66affSColin Finck int CDECL _chmod(const char *path, int flags) 766c2c66affSColin Finck { 767c2c66affSColin Finck DWORD oldFlags = GetFileAttributesA(path); 768c2c66affSColin Finck 769c2c66affSColin Finck if (oldFlags != INVALID_FILE_ATTRIBUTES) 770c2c66affSColin Finck { 771c2c66affSColin Finck DWORD newFlags = (flags & _S_IWRITE)? oldFlags & ~FILE_ATTRIBUTE_READONLY: 772c2c66affSColin Finck oldFlags | FILE_ATTRIBUTE_READONLY; 773c2c66affSColin Finck 774c2c66affSColin Finck if (newFlags == oldFlags || SetFileAttributesA(path, newFlags)) 775c2c66affSColin Finck return 0; 776c2c66affSColin Finck } 777c2c66affSColin Finck _dosmaperr(GetLastError()); 778c2c66affSColin Finck return -1; 779c2c66affSColin Finck } 780c2c66affSColin Finck 781c2c66affSColin Finck /********************************************************************* 782c2c66affSColin Finck * _wchmod (MSVCRT.@) 783c2c66affSColin Finck */ 784c2c66affSColin Finck int CDECL _wchmod(const wchar_t *path, int flags) 785c2c66affSColin Finck { 786c2c66affSColin Finck DWORD oldFlags = GetFileAttributesW(path); 787c2c66affSColin Finck 788c2c66affSColin Finck if (oldFlags != INVALID_FILE_ATTRIBUTES) 789c2c66affSColin Finck { 790c2c66affSColin Finck DWORD newFlags = (flags & _S_IWRITE)? oldFlags & ~FILE_ATTRIBUTE_READONLY: 791c2c66affSColin Finck oldFlags | FILE_ATTRIBUTE_READONLY; 792c2c66affSColin Finck 793c2c66affSColin Finck if (newFlags == oldFlags || SetFileAttributesW(path, newFlags)) 794c2c66affSColin Finck return 0; 795c2c66affSColin Finck } 796c2c66affSColin Finck _dosmaperr(GetLastError()); 797c2c66affSColin Finck return -1; 798c2c66affSColin Finck } 799c2c66affSColin Finck 800c2c66affSColin Finck /********************************************************************* 801c2c66affSColin Finck * _unlink (MSVCRT.@) 802c2c66affSColin Finck */ 803c2c66affSColin Finck int CDECL _unlink(const char *path) 804c2c66affSColin Finck { 805c2c66affSColin Finck TRACE("%s\n",debugstr_a(path)); 806c2c66affSColin Finck if(DeleteFileA(path)) 807c2c66affSColin Finck return 0; 808c2c66affSColin Finck TRACE("failed (%d)\n",GetLastError()); 809c2c66affSColin Finck _dosmaperr(GetLastError()); 810c2c66affSColin Finck return -1; 811c2c66affSColin Finck } 812c2c66affSColin Finck 813c2c66affSColin Finck /********************************************************************* 814c2c66affSColin Finck * _wunlink (MSVCRT.@) 815c2c66affSColin Finck */ 816c2c66affSColin Finck int CDECL _wunlink(const wchar_t *path) 817c2c66affSColin Finck { 818c2c66affSColin Finck TRACE("(%s)\n",debugstr_w(path)); 819c2c66affSColin Finck if(DeleteFileW(path)) 820c2c66affSColin Finck return 0; 821c2c66affSColin Finck TRACE("failed (%d)\n",GetLastError()); 822c2c66affSColin Finck _dosmaperr(GetLastError()); 823c2c66affSColin Finck return -1; 824c2c66affSColin Finck } 825c2c66affSColin Finck 826c2c66affSColin Finck /********************************************************************* 827c2c66affSColin Finck * _commit (MSVCRT.@) 828c2c66affSColin Finck */ 829c2c66affSColin Finck int CDECL _commit(int fd) 830c2c66affSColin Finck { 8319eb1eae2SThomas Faber ioinfo *info = get_ioinfo(fd); 8329eb1eae2SThomas Faber int ret; 833c2c66affSColin Finck 8349eb1eae2SThomas Faber TRACE(":fd (%d) handle (%p)\n", fd, info->handle); 8359eb1eae2SThomas Faber if (info->handle == INVALID_HANDLE_VALUE) 8369eb1eae2SThomas Faber ret = -1; 8379eb1eae2SThomas Faber else if (!FlushFileBuffers(info->handle)) 838c2c66affSColin Finck { 839c2c66affSColin Finck if (GetLastError() == ERROR_INVALID_HANDLE) 840c2c66affSColin Finck { 841c2c66affSColin Finck /* FlushFileBuffers fails for console handles 842c2c66affSColin Finck * so we ignore this error. 843c2c66affSColin Finck */ 8449eb1eae2SThomas Faber ret = 0; 845c2c66affSColin Finck } 8469eb1eae2SThomas Faber else 8479eb1eae2SThomas Faber { 848c2c66affSColin Finck TRACE(":failed-last error (%d)\n",GetLastError()); 849c2c66affSColin Finck _dosmaperr(GetLastError()); 8509eb1eae2SThomas Faber ret = -1; 851c2c66affSColin Finck } 8529eb1eae2SThomas Faber } 8539eb1eae2SThomas Faber else 8549eb1eae2SThomas Faber { 855c2c66affSColin Finck TRACE(":ok\n"); 8569eb1eae2SThomas Faber ret = 0; 8579eb1eae2SThomas Faber } 8589eb1eae2SThomas Faber 8599eb1eae2SThomas Faber release_ioinfo(info); 8609eb1eae2SThomas Faber return ret; 861c2c66affSColin Finck } 862c2c66affSColin Finck 863c2c66affSColin Finck /* _flushall calls fflush which calls _flushall */ 864c2c66affSColin Finck int CDECL fflush(FILE* file); 865c2c66affSColin Finck 866c2c66affSColin Finck /* INTERNAL: Flush all stream buffer */ 867c2c66affSColin Finck static int msvcrt_flush_all_buffers(int mask) 868c2c66affSColin Finck { 869c2c66affSColin Finck int i, num_flushed = 0; 870c2c66affSColin Finck FILE *file; 871c2c66affSColin Finck 872c2c66affSColin Finck LOCK_FILES(); 873c2c66affSColin Finck for (i = 0; i < MSVCRT_stream_idx; i++) { 874c2c66affSColin Finck file = msvcrt_get_file(i); 875c2c66affSColin Finck 876c2c66affSColin Finck if (file->_flag) 877c2c66affSColin Finck { 878c2c66affSColin Finck if(file->_flag & mask) { 879c2c66affSColin Finck fflush(file); 880c2c66affSColin Finck num_flushed++; 881c2c66affSColin Finck } 882c2c66affSColin Finck } 883c2c66affSColin Finck } 884c2c66affSColin Finck UNLOCK_FILES(); 885c2c66affSColin Finck 886c2c66affSColin Finck TRACE(":flushed (%d) handles\n",num_flushed); 887c2c66affSColin Finck return num_flushed; 888c2c66affSColin Finck } 889c2c66affSColin Finck 890c2c66affSColin Finck /********************************************************************* 891c2c66affSColin Finck * _flushall (MSVCRT.@) 892c2c66affSColin Finck */ 893c2c66affSColin Finck int CDECL _flushall(void) 894c2c66affSColin Finck { 895c2c66affSColin Finck return msvcrt_flush_all_buffers(_IOWRT | _IOREAD); 896c2c66affSColin Finck } 897c2c66affSColin Finck 898c2c66affSColin Finck /********************************************************************* 899c2c66affSColin Finck * fflush (MSVCRT.@) 900c2c66affSColin Finck */ 901c2c66affSColin Finck int CDECL fflush(FILE* file) 902c2c66affSColin Finck { 903c2c66affSColin Finck if(!file) { 904c2c66affSColin Finck msvcrt_flush_all_buffers(_IOWRT); 905c2c66affSColin Finck } else if(file->_flag & _IOWRT) { 906c2c66affSColin Finck int res; 907c2c66affSColin Finck 908c2c66affSColin Finck _lock_file(file); 909c2c66affSColin Finck res = msvcrt_flush_buffer(file); 910c2c66affSColin Finck /* FIXME 911c2c66affSColin Finck if(!res && (file->_flag & _IOCOMMIT)) 912c2c66affSColin Finck res = _commit(file->_file) ? EOF : 0; 913c2c66affSColin Finck */ 914c2c66affSColin Finck _unlock_file(file); 915c2c66affSColin Finck 916c2c66affSColin Finck return res; 917c2c66affSColin Finck } else if(file->_flag & _IOREAD) { 918c2c66affSColin Finck _lock_file(file); 919c2c66affSColin Finck file->_cnt = 0; 920c2c66affSColin Finck file->_ptr = file->_base; 921c2c66affSColin Finck _unlock_file(file); 922c2c66affSColin Finck 923c2c66affSColin Finck return 0; 924c2c66affSColin Finck } 925c2c66affSColin Finck return 0; 926c2c66affSColin Finck } 927c2c66affSColin Finck 928c2c66affSColin Finck /********************************************************************* 929c2c66affSColin Finck * _close (MSVCRT.@) 930c2c66affSColin Finck */ 931c2c66affSColin Finck int CDECL _close(int fd) 932c2c66affSColin Finck { 9339eb1eae2SThomas Faber ioinfo *info = get_ioinfo(fd); 934c2c66affSColin Finck int ret; 935c2c66affSColin Finck 9369eb1eae2SThomas Faber TRACE(":fd (%d) handle (%p)\n", fd, info->handle); 9379eb1eae2SThomas Faber if (!(info->wxflag & WX_OPEN)) { 938c2c66affSColin Finck ret = -1; 9392765bddfSThomas Faber } else if (fd == STDOUT_FILENO && 9402765bddfSThomas Faber info->handle == get_ioinfo_nolock(STDERR_FILENO)->handle) { 9412765bddfSThomas Faber msvcrt_free_fd(fd); 9422765bddfSThomas Faber ret = 0; 9432765bddfSThomas Faber } else if (fd == STDERR_FILENO && 9442765bddfSThomas Faber info->handle == get_ioinfo_nolock(STDOUT_FILENO)->handle) { 9452765bddfSThomas Faber msvcrt_free_fd(fd); 9462765bddfSThomas Faber ret = 0; 9479eb1eae2SThomas Faber } else { 9489eb1eae2SThomas Faber ret = CloseHandle(info->handle) ? 0 : -1; 9499eb1eae2SThomas Faber msvcrt_free_fd(fd); 9509eb1eae2SThomas Faber if (ret) { 951c2c66affSColin Finck WARN(":failed-last error (%d)\n",GetLastError()); 952c2c66affSColin Finck _dosmaperr(GetLastError()); 953c2c66affSColin Finck ret = -1; 954c2c66affSColin Finck } 955c2c66affSColin Finck } 9569eb1eae2SThomas Faber release_ioinfo(info); 957c2c66affSColin Finck return ret; 958c2c66affSColin Finck } 959c2c66affSColin Finck 960c2c66affSColin Finck /********************************************************************* 961c2c66affSColin Finck * _dup2 (MSVCRT.@) 962c2c66affSColin Finck * NOTES 963c2c66affSColin Finck * MSDN isn't clear on this point, but the remarks for _pipe 964c2c66affSColin Finck * indicate file descriptors duplicated with _dup and _dup2 are always 965c2c66affSColin Finck * inheritable. 966c2c66affSColin Finck */ 967c2c66affSColin Finck int CDECL _dup2(int od, int nd) 968c2c66affSColin Finck { 969bffd8201SThomas Faber ioinfo *info_od, *info_nd; 970c2c66affSColin Finck int ret; 971c2c66affSColin Finck 972c2c66affSColin Finck TRACE("(od=%d, nd=%d)\n", od, nd); 973bffd8201SThomas Faber 974bffd8201SThomas Faber if (od < nd) 975bffd8201SThomas Faber { 976bffd8201SThomas Faber info_od = get_ioinfo(od); 97727b79867SThomas Faber info_nd = get_ioinfo_alloc_fd(nd); 978bffd8201SThomas Faber } 979bffd8201SThomas Faber else 980bffd8201SThomas Faber { 98127b79867SThomas Faber info_nd = get_ioinfo_alloc_fd(nd); 982bffd8201SThomas Faber info_od = get_ioinfo(od); 983bffd8201SThomas Faber } 984bffd8201SThomas Faber 98527b79867SThomas Faber if (info_nd == &__badioinfo) 98627b79867SThomas Faber { 98727b79867SThomas Faber ret = -1; 98827b79867SThomas Faber } 98927b79867SThomas Faber else if (info_od->wxflag & WX_OPEN) 990c2c66affSColin Finck { 991c2c66affSColin Finck HANDLE handle; 992c2c66affSColin Finck 993bffd8201SThomas Faber if (DuplicateHandle(GetCurrentProcess(), info_od->handle, 994c2c66affSColin Finck GetCurrentProcess(), &handle, 0, TRUE, DUPLICATE_SAME_ACCESS)) 995c2c66affSColin Finck { 996bffd8201SThomas Faber int wxflag = info_od->wxflag & ~_O_NOINHERIT; 997c2c66affSColin Finck 998bffd8201SThomas Faber if (info_nd->wxflag & WX_OPEN) 999c2c66affSColin Finck _close(nd); 100027b79867SThomas Faber 100127b79867SThomas Faber msvcrt_set_fd(info_nd, handle, wxflag); 1002c2c66affSColin Finck /* _dup2 returns 0, not nd, on success */ 1003c2c66affSColin Finck ret = 0; 1004c2c66affSColin Finck } 1005c2c66affSColin Finck else 1006c2c66affSColin Finck { 1007c2c66affSColin Finck ret = -1; 1008c2c66affSColin Finck _dosmaperr(GetLastError()); 1009c2c66affSColin Finck } 1010c2c66affSColin Finck } 1011c2c66affSColin Finck else 1012c2c66affSColin Finck { 1013c2c66affSColin Finck *_errno() = EBADF; 1014c2c66affSColin Finck ret = -1; 1015c2c66affSColin Finck } 1016bffd8201SThomas Faber 1017bffd8201SThomas Faber release_ioinfo(info_od); 1018bffd8201SThomas Faber release_ioinfo(info_nd); 1019c2c66affSColin Finck return ret; 1020c2c66affSColin Finck } 1021c2c66affSColin Finck 1022c2c66affSColin Finck /********************************************************************* 1023c2c66affSColin Finck * _dup (MSVCRT.@) 1024c2c66affSColin Finck */ 1025c2c66affSColin Finck int CDECL _dup(int od) 1026c2c66affSColin Finck { 1027c2c66affSColin Finck int fd, ret; 10286aa8e3ccSThomas Faber ioinfo *info = get_ioinfo_alloc(&fd); 1029c2c66affSColin Finck 1030c2c66affSColin Finck if (_dup2(od, fd) == 0) 1031c2c66affSColin Finck ret = fd; 1032c2c66affSColin Finck else 1033c2c66affSColin Finck ret = -1; 10346aa8e3ccSThomas Faber release_ioinfo(info); 1035c2c66affSColin Finck return ret; 1036c2c66affSColin Finck } 1037c2c66affSColin Finck 1038c2c66affSColin Finck /********************************************************************* 1039c2c66affSColin Finck * _eof (MSVCRT.@) 1040c2c66affSColin Finck */ 1041c2c66affSColin Finck int CDECL _eof(int fd) 1042c2c66affSColin Finck { 10439eb1eae2SThomas Faber ioinfo *info = get_ioinfo(fd); 1044c2c66affSColin Finck DWORD curpos,endpos; 1045c2c66affSColin Finck LONG hcurpos,hendpos; 1046c2c66affSColin Finck 10479eb1eae2SThomas Faber TRACE(":fd (%d) handle (%p)\n", fd, info->handle); 1048c2c66affSColin Finck 10499eb1eae2SThomas Faber if (info->handle == INVALID_HANDLE_VALUE) 10509eb1eae2SThomas Faber { 10519eb1eae2SThomas Faber release_ioinfo(info); 1052c2c66affSColin Finck return -1; 10539eb1eae2SThomas Faber } 1054c2c66affSColin Finck 10559eb1eae2SThomas Faber if (info->wxflag & WX_ATEOF) 10569eb1eae2SThomas Faber { 10579eb1eae2SThomas Faber release_ioinfo(info); 10589eb1eae2SThomas Faber return TRUE; 10599eb1eae2SThomas Faber } 1060c2c66affSColin Finck 1061c2c66affSColin Finck /* Otherwise we do it the hard way */ 1062c2c66affSColin Finck hcurpos = hendpos = 0; 10639eb1eae2SThomas Faber curpos = SetFilePointer(info->handle, 0, &hcurpos, FILE_CURRENT); 10649eb1eae2SThomas Faber endpos = SetFilePointer(info->handle, 0, &hendpos, FILE_END); 1065c2c66affSColin Finck 1066c2c66affSColin Finck if (curpos == endpos && hcurpos == hendpos) 1067c2c66affSColin Finck { 1068c2c66affSColin Finck /* FIXME: shouldn't WX_ATEOF be set here? */ 10699eb1eae2SThomas Faber release_ioinfo(info); 1070c2c66affSColin Finck return TRUE; 1071c2c66affSColin Finck } 1072c2c66affSColin Finck 10739eb1eae2SThomas Faber SetFilePointer(info->handle, curpos, &hcurpos, FILE_BEGIN); 10749eb1eae2SThomas Faber release_ioinfo(info); 1075c2c66affSColin Finck return FALSE; 1076c2c66affSColin Finck } 1077c2c66affSColin Finck 1078c2c66affSColin Finck /********************************************************************* 1079c2c66affSColin Finck * _fcloseall (MSVCRT.@) 1080c2c66affSColin Finck */ 1081c2c66affSColin Finck int CDECL _fcloseall(void) 1082c2c66affSColin Finck { 1083c2c66affSColin Finck int num_closed = 0, i; 1084c2c66affSColin Finck FILE *file; 1085c2c66affSColin Finck 1086c2c66affSColin Finck LOCK_FILES(); 1087c2c66affSColin Finck for (i = 3; i < MSVCRT_stream_idx; i++) { 1088c2c66affSColin Finck file = msvcrt_get_file(i); 1089c2c66affSColin Finck 1090c2c66affSColin Finck if (file->_flag && !fclose(file)) 1091c2c66affSColin Finck num_closed++; 1092c2c66affSColin Finck } 1093c2c66affSColin Finck UNLOCK_FILES(); 1094c2c66affSColin Finck 1095c2c66affSColin Finck TRACE(":closed (%d) handles\n",num_closed); 1096c2c66affSColin Finck return num_closed; 1097c2c66affSColin Finck } 1098c2c66affSColin Finck 1099c2c66affSColin Finck /* free everything on process exit */ 1100c2c66affSColin Finck void msvcrt_free_io(void) 1101c2c66affSColin Finck { 1102c2c66affSColin Finck unsigned int i; 1103c2c66affSColin Finck int j; 1104c2c66affSColin Finck 1105c2c66affSColin Finck _flushall(); 1106c2c66affSColin Finck _fcloseall(); 1107c2c66affSColin Finck 1108c2c66affSColin Finck for(i=0; i<sizeof(__pioinfo)/sizeof(__pioinfo[0]); i++) 110925064fdfSThomas Faber { 111025064fdfSThomas Faber if(!__pioinfo[i]) 111125064fdfSThomas Faber continue; 111225064fdfSThomas Faber 111325064fdfSThomas Faber for(j=0; j<MSVCRT_FD_BLOCK_SIZE; j++) 111425064fdfSThomas Faber { 111525064fdfSThomas Faber if(__pioinfo[i][j].exflag & EF_CRIT_INIT) 111625064fdfSThomas Faber DeleteCriticalSection(&__pioinfo[i][j].crit); 111725064fdfSThomas Faber } 1118c2c66affSColin Finck free(__pioinfo[i]); 111925064fdfSThomas Faber } 1120c2c66affSColin Finck 1121c2c66affSColin Finck for(j=0; j<MSVCRT_stream_idx; j++) 1122c2c66affSColin Finck { 1123c2c66affSColin Finck FILE *file = msvcrt_get_file(j); 1124c2c66affSColin Finck if(file<_iob || file>=_iob+_IOB_ENTRIES) 1125c2c66affSColin Finck { 1126c2c66affSColin Finck ((file_crit*)file)->crit.DebugInfo->Spare[0] = 0; 1127c2c66affSColin Finck DeleteCriticalSection(&((file_crit*)file)->crit); 1128c2c66affSColin Finck } 1129c2c66affSColin Finck } 1130c2c66affSColin Finck 1131c2c66affSColin Finck for(i=0; i<sizeof(MSVCRT_fstream)/sizeof(MSVCRT_fstream[0]); i++) 1132c2c66affSColin Finck free(MSVCRT_fstream[i]); 1133c2c66affSColin Finck } 1134c2c66affSColin Finck 1135c2c66affSColin Finck /********************************************************************* 1136c2c66affSColin Finck * _lseeki64 (MSVCRT.@) 1137c2c66affSColin Finck */ 1138c2c66affSColin Finck __int64 CDECL _lseeki64(int fd, __int64 offset, int whence) 1139c2c66affSColin Finck { 11409eb1eae2SThomas Faber ioinfo *info = get_ioinfo(fd); 1141c2c66affSColin Finck LARGE_INTEGER ofs; 1142c2c66affSColin Finck 11439eb1eae2SThomas Faber TRACE(":fd (%d) handle (%p)\n", fd, info->handle); 11449eb1eae2SThomas Faber 11459eb1eae2SThomas Faber if (info->handle == INVALID_HANDLE_VALUE) 11469eb1eae2SThomas Faber { 11479eb1eae2SThomas Faber release_ioinfo(info); 1148c2c66affSColin Finck return -1; 11499eb1eae2SThomas Faber } 1150c2c66affSColin Finck 1151c2c66affSColin Finck if (whence < 0 || whence > 2) 1152c2c66affSColin Finck { 11539eb1eae2SThomas Faber release_ioinfo(info); 1154c2c66affSColin Finck *_errno() = EINVAL; 1155c2c66affSColin Finck return -1; 1156c2c66affSColin Finck } 1157c2c66affSColin Finck 1158c2c66affSColin Finck TRACE(":fd (%d) to %s pos %s\n", 1159c2c66affSColin Finck fd,wine_dbgstr_longlong(offset), 1160c2c66affSColin Finck (whence==SEEK_SET)?"SEEK_SET": 1161c2c66affSColin Finck (whence==SEEK_CUR)?"SEEK_CUR": 1162c2c66affSColin Finck (whence==SEEK_END)?"SEEK_END":"UNKNOWN"); 1163c2c66affSColin Finck 1164c2c66affSColin Finck /* The MoleBox protection scheme expects msvcrt to use SetFilePointer only, 1165c2c66affSColin Finck * so a LARGE_INTEGER offset cannot be passed directly via SetFilePointerEx. */ 1166c2c66affSColin Finck ofs.QuadPart = offset; 11679eb1eae2SThomas Faber if ((ofs.u.LowPart = SetFilePointer(info->handle, ofs.u.LowPart, &ofs.u.HighPart, whence)) != INVALID_SET_FILE_POINTER || 1168c2c66affSColin Finck GetLastError() == ERROR_SUCCESS) 1169c2c66affSColin Finck { 11709eb1eae2SThomas Faber info->wxflag &= ~(WX_ATEOF|WX_READEOF); 1171c2c66affSColin Finck /* FIXME: What if we seek _to_ EOF - is EOF set? */ 1172c2c66affSColin Finck 11739eb1eae2SThomas Faber release_ioinfo(info); 1174c2c66affSColin Finck return ofs.QuadPart; 1175c2c66affSColin Finck } 11769eb1eae2SThomas Faber release_ioinfo(info); 1177c2c66affSColin Finck TRACE(":error-last error (%d)\n",GetLastError()); 1178c2c66affSColin Finck _dosmaperr(GetLastError()); 1179c2c66affSColin Finck return -1; 1180c2c66affSColin Finck } 1181c2c66affSColin Finck 1182c2c66affSColin Finck /********************************************************************* 1183c2c66affSColin Finck * _lseek (MSVCRT.@) 1184c2c66affSColin Finck */ 1185c2c66affSColin Finck LONG CDECL _lseek(int fd, LONG offset, int whence) 1186c2c66affSColin Finck { 1187c2c66affSColin Finck return (LONG)_lseeki64(fd, offset, whence); 1188c2c66affSColin Finck } 1189c2c66affSColin Finck 1190c2c66affSColin Finck /********************************************************************* 1191c2c66affSColin Finck * _lock_file (MSVCRT.@) 1192c2c66affSColin Finck */ 1193c2c66affSColin Finck void CDECL _lock_file(FILE *file) 1194c2c66affSColin Finck { 1195c2c66affSColin Finck if(file>=_iob && file<_iob+_IOB_ENTRIES) 1196c2c66affSColin Finck _lock(_STREAM_LOCKS+(file-_iob)); 1197c2c66affSColin Finck /* ReactOS: string streams dont need to be locked */ 1198c2c66affSColin Finck else if(!(file->_flag & _IOSTRG)) 1199c2c66affSColin Finck EnterCriticalSection(&((file_crit*)file)->crit); 1200c2c66affSColin Finck } 1201c2c66affSColin Finck 1202c2c66affSColin Finck /********************************************************************* 1203c2c66affSColin Finck * _unlock_file (MSVCRT.@) 1204c2c66affSColin Finck */ 1205c2c66affSColin Finck void CDECL _unlock_file(FILE *file) 1206c2c66affSColin Finck { 1207c2c66affSColin Finck if(file>=_iob && file<_iob+_IOB_ENTRIES) 1208c2c66affSColin Finck _unlock(_STREAM_LOCKS+(file-_iob)); 1209c2c66affSColin Finck /* ReactOS: string streams dont need to be locked */ 1210c2c66affSColin Finck else if(!(file->_flag & _IOSTRG)) 1211c2c66affSColin Finck LeaveCriticalSection(&((file_crit*)file)->crit); 1212c2c66affSColin Finck 1213c2c66affSColin Finck } 1214c2c66affSColin Finck 1215c2c66affSColin Finck /********************************************************************* 1216c2c66affSColin Finck * _locking (MSVCRT.@) 1217c2c66affSColin Finck * 1218c2c66affSColin Finck * This is untested; the underlying LockFile doesn't work yet. 1219c2c66affSColin Finck */ 1220c2c66affSColin Finck int CDECL _locking(int fd, int mode, LONG nbytes) 1221c2c66affSColin Finck { 12229eb1eae2SThomas Faber ioinfo *info = get_ioinfo(fd); 1223c2c66affSColin Finck BOOL ret; 1224c2c66affSColin Finck DWORD cur_locn; 1225c2c66affSColin Finck 12269eb1eae2SThomas Faber TRACE(":fd (%d) handle (%p)\n", fd, info->handle); 12279eb1eae2SThomas Faber if (info->handle == INVALID_HANDLE_VALUE) 12289eb1eae2SThomas Faber { 12299eb1eae2SThomas Faber release_ioinfo(info); 1230c2c66affSColin Finck return -1; 12319eb1eae2SThomas Faber } 1232c2c66affSColin Finck 1233c2c66affSColin Finck if (mode < 0 || mode > 4) 1234c2c66affSColin Finck { 12359eb1eae2SThomas Faber release_ioinfo(info); 1236c2c66affSColin Finck *_errno() = EINVAL; 1237c2c66affSColin Finck return -1; 1238c2c66affSColin Finck } 1239c2c66affSColin Finck 1240c2c66affSColin Finck TRACE(":fd (%d) by 0x%08x mode %s\n", 1241c2c66affSColin Finck fd,nbytes,(mode==_LK_UNLCK)?"_LK_UNLCK": 1242c2c66affSColin Finck (mode==_LK_LOCK)?"_LK_LOCK": 1243c2c66affSColin Finck (mode==_LK_NBLCK)?"_LK_NBLCK": 1244c2c66affSColin Finck (mode==_LK_RLCK)?"_LK_RLCK": 1245c2c66affSColin Finck (mode==_LK_NBRLCK)?"_LK_NBRLCK": 1246c2c66affSColin Finck "UNKNOWN"); 1247c2c66affSColin Finck 12482765bddfSThomas Faber if ((cur_locn = SetFilePointer(info->handle, 0L, NULL, FILE_CURRENT)) == INVALID_SET_FILE_POINTER) 1249c2c66affSColin Finck { 12509eb1eae2SThomas Faber release_ioinfo(info); 1251c2c66affSColin Finck FIXME ("Seek failed\n"); 1252c2c66affSColin Finck *_errno() = EINVAL; /* FIXME */ 1253c2c66affSColin Finck return -1; 1254c2c66affSColin Finck } 1255c2c66affSColin Finck if (mode == _LK_LOCK || mode == _LK_RLCK) 1256c2c66affSColin Finck { 1257c2c66affSColin Finck int nretry = 10; 1258c2c66affSColin Finck ret = 1; /* just to satisfy gcc */ 1259c2c66affSColin Finck while (nretry--) 1260c2c66affSColin Finck { 12619eb1eae2SThomas Faber ret = LockFile(info->handle, cur_locn, 0L, nbytes, 0L); 1262c2c66affSColin Finck if (ret) break; 1263c2c66affSColin Finck Sleep(1); 1264c2c66affSColin Finck } 1265c2c66affSColin Finck } 1266c2c66affSColin Finck else if (mode == _LK_UNLCK) 12679eb1eae2SThomas Faber ret = UnlockFile(info->handle, cur_locn, 0L, nbytes, 0L); 1268c2c66affSColin Finck else 12699eb1eae2SThomas Faber ret = LockFile(info->handle, cur_locn, 0L, nbytes, 0L); 1270c2c66affSColin Finck /* FIXME - what about error settings? */ 12719eb1eae2SThomas Faber release_ioinfo(info); 1272c2c66affSColin Finck return ret ? 0 : -1; 1273c2c66affSColin Finck } 1274c2c66affSColin Finck 1275c2c66affSColin Finck /********************************************************************* 1276c2c66affSColin Finck * _fseeki64 (MSVCRT.@) 1277c2c66affSColin Finck */ 1278c2c66affSColin Finck int CDECL _fseeki64(FILE* file, __int64 offset, int whence) 1279c2c66affSColin Finck { 1280c2c66affSColin Finck int ret; 1281c2c66affSColin Finck 1282c2c66affSColin Finck _lock_file(file); 1283c2c66affSColin Finck /* Flush output if needed */ 1284c2c66affSColin Finck if(file->_flag & _IOWRT) 1285c2c66affSColin Finck msvcrt_flush_buffer(file); 1286c2c66affSColin Finck 1287c2c66affSColin Finck if(whence == SEEK_CUR && file->_flag & _IOREAD ) { 1288c2c66affSColin Finck whence = SEEK_SET; 1289c2c66affSColin Finck offset += _ftelli64(file); 1290c2c66affSColin Finck } 1291c2c66affSColin Finck 1292c2c66affSColin Finck /* Discard buffered input */ 1293c2c66affSColin Finck file->_cnt = 0; 1294c2c66affSColin Finck file->_ptr = file->_base; 1295c2c66affSColin Finck /* Reset direction of i/o */ 1296c2c66affSColin Finck if(file->_flag & _IORW) { 1297c2c66affSColin Finck file->_flag &= ~(_IOREAD|_IOWRT); 1298c2c66affSColin Finck } 1299c2c66affSColin Finck /* Clear end of file flag */ 1300c2c66affSColin Finck file->_flag &= ~_IOEOF; 1301c2c66affSColin Finck ret = (_lseeki64(file->_file,offset,whence) == -1)?-1:0; 1302c2c66affSColin Finck 1303c2c66affSColin Finck _unlock_file(file); 1304c2c66affSColin Finck return ret; 1305c2c66affSColin Finck } 1306c2c66affSColin Finck 1307c2c66affSColin Finck /********************************************************************* 1308c2c66affSColin Finck * fseek (MSVCRT.@) 1309c2c66affSColin Finck */ 1310c2c66affSColin Finck int CDECL fseek(FILE* file, long offset, int whence) 1311c2c66affSColin Finck { 1312c2c66affSColin Finck return _fseeki64( file, offset, whence ); 1313c2c66affSColin Finck } 1314c2c66affSColin Finck 1315c2c66affSColin Finck /********************************************************************* 1316c2c66affSColin Finck * _chsize_s (MSVCRT.@) 1317c2c66affSColin Finck */ 1318c2c66affSColin Finck int CDECL _chsize_s(int fd, __int64 size) 1319c2c66affSColin Finck { 13209eb1eae2SThomas Faber ioinfo *info; 1321c2c66affSColin Finck __int64 cur, pos; 1322c2c66affSColin Finck BOOL ret = FALSE; 1323c2c66affSColin Finck 1324c2c66affSColin Finck TRACE("(fd=%d, size=%s)\n", fd, wine_dbgstr_longlong(size)); 1325c2c66affSColin Finck 1326c2c66affSColin Finck if (!MSVCRT_CHECK_PMT(size >= 0)) return EINVAL; 1327c2c66affSColin Finck 13289eb1eae2SThomas Faber info = get_ioinfo(fd); 13299eb1eae2SThomas Faber if (info->handle != INVALID_HANDLE_VALUE) 1330c2c66affSColin Finck { 1331c2c66affSColin Finck /* save the current file pointer */ 1332c2c66affSColin Finck cur = _lseeki64(fd, 0, SEEK_CUR); 1333c2c66affSColin Finck if (cur >= 0) 1334c2c66affSColin Finck { 1335c2c66affSColin Finck pos = _lseeki64(fd, size, SEEK_SET); 1336c2c66affSColin Finck if (pos >= 0) 1337c2c66affSColin Finck { 13389eb1eae2SThomas Faber ret = SetEndOfFile(info->handle); 1339c2c66affSColin Finck if (!ret) _dosmaperr(GetLastError()); 1340c2c66affSColin Finck } 1341c2c66affSColin Finck 1342c2c66affSColin Finck /* restore the file pointer */ 1343c2c66affSColin Finck _lseeki64(fd, cur, SEEK_SET); 1344c2c66affSColin Finck } 1345c2c66affSColin Finck } 1346c2c66affSColin Finck 13479eb1eae2SThomas Faber release_ioinfo(info); 1348c2c66affSColin Finck return ret ? 0 : *_errno(); 1349c2c66affSColin Finck } 1350c2c66affSColin Finck 1351c2c66affSColin Finck /********************************************************************* 1352c2c66affSColin Finck * _chsize (MSVCRT.@) 1353c2c66affSColin Finck */ 1354c2c66affSColin Finck int CDECL _chsize(int fd, long size) 1355c2c66affSColin Finck { 1356c2c66affSColin Finck /* _chsize_s returns errno on failure but _chsize should return -1 */ 1357c2c66affSColin Finck return _chsize_s( fd, size ) == 0 ? 0 : -1; 1358c2c66affSColin Finck } 1359c2c66affSColin Finck 1360c2c66affSColin Finck /********************************************************************* 1361c2c66affSColin Finck * clearerr (MSVCRT.@) 1362c2c66affSColin Finck */ 1363c2c66affSColin Finck void CDECL clearerr(FILE* file) 1364c2c66affSColin Finck { 1365c2c66affSColin Finck TRACE(":file (%p) fd (%d)\n",file,file->_file); 1366c2c66affSColin Finck 1367c2c66affSColin Finck _lock_file(file); 1368c2c66affSColin Finck file->_flag &= ~(_IOERR | _IOEOF); 1369c2c66affSColin Finck _unlock_file(file); 1370c2c66affSColin Finck } 1371c2c66affSColin Finck 1372c2c66affSColin Finck /********************************************************************* 1373c2c66affSColin Finck * rewind (MSVCRT.@) 1374c2c66affSColin Finck */ 1375c2c66affSColin Finck void CDECL rewind(FILE* file) 1376c2c66affSColin Finck { 1377c2c66affSColin Finck TRACE(":file (%p) fd (%d)\n",file,file->_file); 1378c2c66affSColin Finck 1379c2c66affSColin Finck _lock_file(file); 1380c2c66affSColin Finck fseek(file, 0L, SEEK_SET); 1381c2c66affSColin Finck clearerr(file); 1382c2c66affSColin Finck _unlock_file(file); 1383c2c66affSColin Finck } 1384c2c66affSColin Finck 1385c2c66affSColin Finck static int msvcrt_get_flags(const wchar_t* mode, int *open_flags, int* stream_flags) 1386c2c66affSColin Finck { 1387c2c66affSColin Finck int plus = strchrW(mode, '+') != NULL; 1388c2c66affSColin Finck 1389c2c66affSColin Finck TRACE("%s\n", debugstr_w(mode)); 1390c2c66affSColin Finck 1391c2c66affSColin Finck while(*mode == ' ') mode++; 1392c2c66affSColin Finck 1393c2c66affSColin Finck switch(*mode++) 1394c2c66affSColin Finck { 1395c2c66affSColin Finck case 'R': case 'r': 1396c2c66affSColin Finck *open_flags = plus ? _O_RDWR : _O_RDONLY; 1397c2c66affSColin Finck *stream_flags = plus ? _IORW : _IOREAD; 1398c2c66affSColin Finck break; 1399c2c66affSColin Finck case 'W': case 'w': 1400c2c66affSColin Finck *open_flags = _O_CREAT | _O_TRUNC | (plus ? _O_RDWR : _O_WRONLY); 1401c2c66affSColin Finck *stream_flags = plus ? _IORW : _IOWRT; 1402c2c66affSColin Finck break; 1403c2c66affSColin Finck case 'A': case 'a': 1404c2c66affSColin Finck *open_flags = _O_CREAT | _O_APPEND | (plus ? _O_RDWR : _O_WRONLY); 1405c2c66affSColin Finck *stream_flags = plus ? _IORW : _IOWRT; 1406c2c66affSColin Finck break; 1407c2c66affSColin Finck default: 1408c2c66affSColin Finck MSVCRT_INVALID_PMT(0, EINVAL); 1409c2c66affSColin Finck return -1; 1410c2c66affSColin Finck } 1411c2c66affSColin Finck 1412c2c66affSColin Finck *stream_flags |= _commode; 1413c2c66affSColin Finck 1414c2c66affSColin Finck while (*mode && *mode!=',') 1415c2c66affSColin Finck switch (*mode++) 1416c2c66affSColin Finck { 1417c2c66affSColin Finck case 'B': case 'b': 1418c2c66affSColin Finck *open_flags |= _O_BINARY; 1419c2c66affSColin Finck *open_flags &= ~_O_TEXT; 1420c2c66affSColin Finck break; 1421c2c66affSColin Finck case 't': 1422c2c66affSColin Finck *open_flags |= _O_TEXT; 1423c2c66affSColin Finck *open_flags &= ~_O_BINARY; 1424c2c66affSColin Finck break; 1425c2c66affSColin Finck case 'D': 1426c2c66affSColin Finck *open_flags |= _O_TEMPORARY; 1427c2c66affSColin Finck break; 1428c2c66affSColin Finck case 'T': 1429c2c66affSColin Finck *open_flags |= _O_SHORT_LIVED; 1430c2c66affSColin Finck break; 1431c2c66affSColin Finck case 'c': 1432c2c66affSColin Finck *stream_flags |= _IOCOMMIT; 1433c2c66affSColin Finck break; 1434c2c66affSColin Finck case 'n': 1435c2c66affSColin Finck *stream_flags &= ~_IOCOMMIT; 1436c2c66affSColin Finck break; 1437c2c66affSColin Finck case 'N': 1438c2c66affSColin Finck *open_flags |= _O_NOINHERIT; 1439c2c66affSColin Finck break; 1440c2c66affSColin Finck case '+': 1441c2c66affSColin Finck case ' ': 1442c2c66affSColin Finck case 'a': 1443c2c66affSColin Finck case 'w': 1444c2c66affSColin Finck break; 1445c2c66affSColin Finck case 'S': 1446c2c66affSColin Finck case 'R': 1447c2c66affSColin Finck FIXME("ignoring cache optimization flag: %c\n", mode[-1]); 1448c2c66affSColin Finck break; 1449c2c66affSColin Finck default: 1450c2c66affSColin Finck ERR("incorrect mode flag: %c\n", mode[-1]); 1451c2c66affSColin Finck break; 1452c2c66affSColin Finck } 1453c2c66affSColin Finck 1454c2c66affSColin Finck if(*mode == ',') 1455c2c66affSColin Finck { 1456c2c66affSColin Finck static const WCHAR ccs[] = {'c','c','s'}; 1457c2c66affSColin Finck static const WCHAR utf8[] = {'u','t','f','-','8'}; 1458c2c66affSColin Finck static const WCHAR utf16le[] = {'u','t','f','-','1','6','l','e'}; 1459c2c66affSColin Finck static const WCHAR unicode[] = {'u','n','i','c','o','d','e'}; 1460c2c66affSColin Finck 1461c2c66affSColin Finck mode++; 1462c2c66affSColin Finck while(*mode == ' ') mode++; 1463c2c66affSColin Finck if(!MSVCRT_CHECK_PMT(!strncmpW(ccs, mode, sizeof(ccs)/sizeof(ccs[0])))) 1464c2c66affSColin Finck return -1; 1465c2c66affSColin Finck mode += sizeof(ccs)/sizeof(ccs[0]); 1466c2c66affSColin Finck while(*mode == ' ') mode++; 1467c2c66affSColin Finck if(!MSVCRT_CHECK_PMT(*mode == '=')) 1468c2c66affSColin Finck return -1; 1469c2c66affSColin Finck mode++; 1470c2c66affSColin Finck while(*mode == ' ') mode++; 1471c2c66affSColin Finck 1472c2c66affSColin Finck if(!strncmpiW(utf8, mode, sizeof(utf8)/sizeof(utf8[0]))) 1473c2c66affSColin Finck { 1474c2c66affSColin Finck *open_flags |= _O_U8TEXT; 1475c2c66affSColin Finck mode += sizeof(utf8)/sizeof(utf8[0]); 1476c2c66affSColin Finck } 1477c2c66affSColin Finck else if(!strncmpiW(utf16le, mode, sizeof(utf16le)/sizeof(utf16le[0]))) 1478c2c66affSColin Finck { 1479c2c66affSColin Finck *open_flags |= _O_U16TEXT; 1480c2c66affSColin Finck mode += sizeof(utf16le)/sizeof(utf16le[0]); 1481c2c66affSColin Finck } 1482c2c66affSColin Finck else if(!strncmpiW(unicode, mode, sizeof(unicode)/sizeof(unicode[0]))) 1483c2c66affSColin Finck { 1484c2c66affSColin Finck *open_flags |= _O_WTEXT; 1485c2c66affSColin Finck mode += sizeof(unicode)/sizeof(unicode[0]); 1486c2c66affSColin Finck } 1487c2c66affSColin Finck else 1488c2c66affSColin Finck { 1489c2c66affSColin Finck MSVCRT_INVALID_PMT(0, EINVAL); 1490c2c66affSColin Finck return -1; 1491c2c66affSColin Finck } 1492c2c66affSColin Finck 1493c2c66affSColin Finck while(*mode == ' ') mode++; 1494c2c66affSColin Finck } 1495c2c66affSColin Finck 1496c2c66affSColin Finck if(!MSVCRT_CHECK_PMT(*mode == 0)) 1497c2c66affSColin Finck return -1; 1498c2c66affSColin Finck return 0; 1499c2c66affSColin Finck } 1500c2c66affSColin Finck 1501c2c66affSColin Finck /********************************************************************* 1502c2c66affSColin Finck * _fdopen (MSVCRT.@) 1503c2c66affSColin Finck */ 1504c2c66affSColin Finck FILE* CDECL _fdopen(int fd, const char *mode) 1505c2c66affSColin Finck { 1506c2c66affSColin Finck FILE *ret; 1507c2c66affSColin Finck wchar_t *modeW = NULL; 1508c2c66affSColin Finck 1509c2c66affSColin Finck if (mode && !(modeW = msvcrt_wstrdupa(mode))) return NULL; 1510c2c66affSColin Finck 1511c2c66affSColin Finck ret = _wfdopen(fd, modeW); 1512c2c66affSColin Finck 1513c2c66affSColin Finck free(modeW); 1514c2c66affSColin Finck return ret; 1515c2c66affSColin Finck } 1516c2c66affSColin Finck 1517c2c66affSColin Finck /********************************************************************* 1518c2c66affSColin Finck * _wfdopen (MSVCRT.@) 1519c2c66affSColin Finck */ 1520c2c66affSColin Finck FILE* CDECL _wfdopen(int fd, const wchar_t *mode) 1521c2c66affSColin Finck { 1522c2c66affSColin Finck int open_flags, stream_flags; 1523c2c66affSColin Finck FILE* file; 1524c2c66affSColin Finck 1525c2c66affSColin Finck if (msvcrt_get_flags(mode, &open_flags, &stream_flags) == -1) return NULL; 1526c2c66affSColin Finck 1527c2c66affSColin Finck LOCK_FILES(); 1528c2c66affSColin Finck if (!(file = msvcrt_alloc_fp())) 1529c2c66affSColin Finck file = NULL; 1530c2c66affSColin Finck else if (msvcrt_init_fp(file, fd, stream_flags) == -1) 1531c2c66affSColin Finck { 1532c2c66affSColin Finck file->_flag = 0; 1533c2c66affSColin Finck file = NULL; 1534c2c66affSColin Finck } 1535c2c66affSColin Finck else TRACE(":fd (%d) mode (%s) FILE* (%p)\n", fd, debugstr_w(mode), file); 1536c2c66affSColin Finck UNLOCK_FILES(); 1537c2c66affSColin Finck 1538c2c66affSColin Finck return file; 1539c2c66affSColin Finck } 1540c2c66affSColin Finck 1541c2c66affSColin Finck /********************************************************************* 1542c2c66affSColin Finck * _filelength (MSVCRT.@) 1543c2c66affSColin Finck */ 1544c2c66affSColin Finck LONG CDECL _filelength(int fd) 1545c2c66affSColin Finck { 1546c2c66affSColin Finck LONG curPos = _lseek(fd, 0, SEEK_CUR); 1547c2c66affSColin Finck if (curPos != -1) 1548c2c66affSColin Finck { 1549c2c66affSColin Finck LONG endPos = _lseek(fd, 0, SEEK_END); 1550c2c66affSColin Finck if (endPos != -1) 1551c2c66affSColin Finck { 1552c2c66affSColin Finck if (endPos != curPos) 1553c2c66affSColin Finck _lseek(fd, curPos, SEEK_SET); 1554c2c66affSColin Finck return endPos; 1555c2c66affSColin Finck } 1556c2c66affSColin Finck } 1557c2c66affSColin Finck return -1; 1558c2c66affSColin Finck } 1559c2c66affSColin Finck 1560c2c66affSColin Finck /********************************************************************* 1561c2c66affSColin Finck * _filelengthi64 (MSVCRT.@) 1562c2c66affSColin Finck */ 1563c2c66affSColin Finck __int64 CDECL _filelengthi64(int fd) 1564c2c66affSColin Finck { 1565c2c66affSColin Finck __int64 curPos = _lseeki64(fd, 0, SEEK_CUR); 1566c2c66affSColin Finck if (curPos != -1) 1567c2c66affSColin Finck { 1568c2c66affSColin Finck __int64 endPos = _lseeki64(fd, 0, SEEK_END); 1569c2c66affSColin Finck if (endPos != -1) 1570c2c66affSColin Finck { 1571c2c66affSColin Finck if (endPos != curPos) 1572c2c66affSColin Finck _lseeki64(fd, curPos, SEEK_SET); 1573c2c66affSColin Finck return endPos; 1574c2c66affSColin Finck } 1575c2c66affSColin Finck } 1576c2c66affSColin Finck return -1; 1577c2c66affSColin Finck } 1578c2c66affSColin Finck 1579c2c66affSColin Finck /********************************************************************* 1580c2c66affSColin Finck * _fileno (MSVCRT.@) 1581c2c66affSColin Finck */ 1582c2c66affSColin Finck int CDECL _fileno(FILE* file) 1583c2c66affSColin Finck { 1584c2c66affSColin Finck TRACE(":FILE* (%p) fd (%d)\n",file,file->_file); 1585c2c66affSColin Finck return file->_file; 1586c2c66affSColin Finck } 1587c2c66affSColin Finck 1588c2c66affSColin Finck /********************************************************************* 1589c2c66affSColin Finck * _get_osfhandle (MSVCRT.@) 1590c2c66affSColin Finck */ 1591c2c66affSColin Finck intptr_t CDECL _get_osfhandle(int fd) 1592c2c66affSColin Finck { 159353864fccSThomas Faber HANDLE hand = get_ioinfo_nolock(fd)->handle; 1594c2c66affSColin Finck TRACE(":fd (%d) handle (%p)\n",fd,hand); 1595c2c66affSColin Finck 159653864fccSThomas Faber if(hand == INVALID_HANDLE_VALUE) 159753864fccSThomas Faber *_errno() = EBADF; 1598c2c66affSColin Finck return (intptr_t)hand; 1599c2c66affSColin Finck } 1600c2c66affSColin Finck 1601c2c66affSColin Finck /********************************************************************* 1602c2c66affSColin Finck * _mktemp (MSVCRT.@) 1603c2c66affSColin Finck */ 1604c2c66affSColin Finck char * CDECL _mktemp(char *pattern) 1605c2c66affSColin Finck { 1606c2c66affSColin Finck int numX = 0; 1607c2c66affSColin Finck char *retVal = pattern; 1608c2c66affSColin Finck int id; 1609c2c66affSColin Finck char letter = 'a'; 1610c2c66affSColin Finck 1611c2c66affSColin Finck if(!pattern) 1612c2c66affSColin Finck return NULL; 1613c2c66affSColin Finck 1614c2c66affSColin Finck while(*pattern) 1615c2c66affSColin Finck numX = (*pattern++ == 'X')? numX + 1 : 0; 1616c2c66affSColin Finck if (numX < 6) 1617c2c66affSColin Finck return NULL; 1618c2c66affSColin Finck pattern--; 1619c2c66affSColin Finck id = GetCurrentProcessId(); 1620c2c66affSColin Finck numX = 6; 1621c2c66affSColin Finck while(numX--) 1622c2c66affSColin Finck { 1623c2c66affSColin Finck int tempNum = id / 10; 1624c2c66affSColin Finck *pattern-- = id - (tempNum * 10) + '0'; 1625c2c66affSColin Finck id = tempNum; 1626c2c66affSColin Finck } 1627c2c66affSColin Finck pattern++; 1628c2c66affSColin Finck do 1629c2c66affSColin Finck { 1630c2c66affSColin Finck *pattern = letter++; 1631c2c66affSColin Finck if (GetFileAttributesA(retVal) == INVALID_FILE_ATTRIBUTES) 1632c2c66affSColin Finck return retVal; 1633c2c66affSColin Finck } while(letter <= 'z'); 1634c2c66affSColin Finck return NULL; 1635c2c66affSColin Finck } 1636c2c66affSColin Finck 1637c2c66affSColin Finck /********************************************************************* 1638c2c66affSColin Finck * _wmktemp (MSVCRT.@) 1639c2c66affSColin Finck */ 1640c2c66affSColin Finck wchar_t * CDECL _wmktemp(wchar_t *pattern) 1641c2c66affSColin Finck { 1642c2c66affSColin Finck int numX = 0; 1643c2c66affSColin Finck wchar_t *retVal = pattern; 1644c2c66affSColin Finck int id; 1645c2c66affSColin Finck wchar_t letter = 'a'; 1646c2c66affSColin Finck 1647c2c66affSColin Finck while(*pattern) 1648c2c66affSColin Finck numX = (*pattern++ == 'X')? numX + 1 : 0; 1649c2c66affSColin Finck if (numX < 5) 1650c2c66affSColin Finck return NULL; 1651c2c66affSColin Finck pattern--; 1652c2c66affSColin Finck id = GetCurrentProcessId(); 1653c2c66affSColin Finck numX = 6; 1654c2c66affSColin Finck while(numX--) 1655c2c66affSColin Finck { 1656c2c66affSColin Finck int tempNum = id / 10; 1657c2c66affSColin Finck *pattern-- = id - (tempNum * 10) + '0'; 1658c2c66affSColin Finck id = tempNum; 1659c2c66affSColin Finck } 1660c2c66affSColin Finck pattern++; 1661c2c66affSColin Finck do 1662c2c66affSColin Finck { 1663c2c66affSColin Finck if (GetFileAttributesW(retVal) == INVALID_FILE_ATTRIBUTES && 1664c2c66affSColin Finck GetLastError() == ERROR_FILE_NOT_FOUND) 1665c2c66affSColin Finck return retVal; 1666c2c66affSColin Finck *pattern = letter++; 1667c2c66affSColin Finck } while(letter != '|'); 1668c2c66affSColin Finck return NULL; 1669c2c66affSColin Finck } 1670c2c66affSColin Finck 1671c2c66affSColin Finck /*static*/ unsigned split_oflags(unsigned oflags) 1672c2c66affSColin Finck { 1673c2c66affSColin Finck int wxflags = 0; 1674c2c66affSColin Finck unsigned unsupp; /* until we support everything */ 1675c2c66affSColin Finck 1676c2c66affSColin Finck if (oflags & _O_APPEND) wxflags |= WX_APPEND; 1677c2c66affSColin Finck if (oflags & _O_BINARY) {/* Nothing to do */} 1678c2c66affSColin Finck else if (oflags & _O_TEXT) wxflags |= WX_TEXT; 1679c2c66affSColin Finck else if (oflags & _O_WTEXT) wxflags |= WX_TEXT; 1680c2c66affSColin Finck else if (oflags & _O_U16TEXT) wxflags |= WX_TEXT; 1681c2c66affSColin Finck else if (oflags & _O_U8TEXT) wxflags |= WX_TEXT; 1682c2c66affSColin Finck else if (*__p__fmode() & _O_BINARY) {/* Nothing to do */} 1683c2c66affSColin Finck else wxflags |= WX_TEXT; /* default to TEXT*/ 1684c2c66affSColin Finck if (oflags & _O_NOINHERIT) wxflags |= WX_DONTINHERIT; 1685c2c66affSColin Finck 1686c2c66affSColin Finck if ((unsupp = oflags & ~( 1687c2c66affSColin Finck _O_BINARY|_O_TEXT|_O_APPEND| 1688c2c66affSColin Finck _O_TRUNC|_O_EXCL|_O_CREAT| 1689c2c66affSColin Finck _O_RDWR|_O_WRONLY|_O_TEMPORARY| 1690c2c66affSColin Finck _O_NOINHERIT| 1691c2c66affSColin Finck _O_SEQUENTIAL|_O_RANDOM|_O_SHORT_LIVED| 1692c2c66affSColin Finck _O_WTEXT|_O_U16TEXT|_O_U8TEXT 1693c2c66affSColin Finck ))) 1694c2c66affSColin Finck ERR(":unsupported oflags 0x%04x\n",unsupp); 1695c2c66affSColin Finck 1696c2c66affSColin Finck return wxflags; 1697c2c66affSColin Finck } 1698c2c66affSColin Finck 1699c2c66affSColin Finck /********************************************************************* 1700c2c66affSColin Finck * _pipe (MSVCRT.@) 1701c2c66affSColin Finck */ 1702c2c66affSColin Finck int CDECL _pipe(int *pfds, unsigned int psize, int textmode) 1703c2c66affSColin Finck { 1704c2c66affSColin Finck int ret = -1; 1705c2c66affSColin Finck SECURITY_ATTRIBUTES sa; 1706c2c66affSColin Finck HANDLE readHandle, writeHandle; 1707c2c66affSColin Finck 1708c2c66affSColin Finck if (!pfds) 1709c2c66affSColin Finck { 1710c2c66affSColin Finck *_errno() = EINVAL; 1711c2c66affSColin Finck return -1; 1712c2c66affSColin Finck } 1713c2c66affSColin Finck 1714c2c66affSColin Finck sa.nLength = sizeof(SECURITY_ATTRIBUTES); 1715c2c66affSColin Finck sa.bInheritHandle = !(textmode & _O_NOINHERIT); 1716c2c66affSColin Finck sa.lpSecurityDescriptor = NULL; 1717c2c66affSColin Finck if (CreatePipe(&readHandle, &writeHandle, &sa, psize)) 1718c2c66affSColin Finck { 1719c2c66affSColin Finck unsigned int wxflags = split_oflags(textmode); 1720c2c66affSColin Finck int fd; 1721c2c66affSColin Finck 1722c2c66affSColin Finck fd = msvcrt_alloc_fd(readHandle, wxflags); 1723c2c66affSColin Finck if (fd != -1) 1724c2c66affSColin Finck { 1725c2c66affSColin Finck pfds[0] = fd; 1726c2c66affSColin Finck fd = msvcrt_alloc_fd(writeHandle, wxflags); 1727c2c66affSColin Finck if (fd != -1) 1728c2c66affSColin Finck { 1729c2c66affSColin Finck pfds[1] = fd; 1730c2c66affSColin Finck ret = 0; 1731c2c66affSColin Finck } 1732c2c66affSColin Finck else 1733c2c66affSColin Finck { 1734c2c66affSColin Finck _close(pfds[0]); 1735c2c66affSColin Finck CloseHandle(writeHandle); 1736c2c66affSColin Finck *_errno() = EMFILE; 1737c2c66affSColin Finck } 1738c2c66affSColin Finck } 1739c2c66affSColin Finck else 1740c2c66affSColin Finck { 1741c2c66affSColin Finck CloseHandle(readHandle); 1742c2c66affSColin Finck CloseHandle(writeHandle); 1743c2c66affSColin Finck *_errno() = EMFILE; 1744c2c66affSColin Finck } 1745c2c66affSColin Finck } 1746c2c66affSColin Finck else 1747c2c66affSColin Finck _dosmaperr(GetLastError()); 1748c2c66affSColin Finck 1749c2c66affSColin Finck return ret; 1750c2c66affSColin Finck } 1751c2c66affSColin Finck 1752c2c66affSColin Finck static int check_bom(HANDLE h, int oflags, BOOL seek) 1753c2c66affSColin Finck { 1754c2c66affSColin Finck char bom[sizeof(utf8_bom)]; 1755c2c66affSColin Finck DWORD r; 1756c2c66affSColin Finck 1757c2c66affSColin Finck oflags &= ~(_O_WTEXT|_O_U16TEXT|_O_U8TEXT); 1758c2c66affSColin Finck 1759c2c66affSColin Finck if (!ReadFile(h, bom, sizeof(utf8_bom), &r, NULL)) 1760c2c66affSColin Finck return oflags; 1761c2c66affSColin Finck 1762c2c66affSColin Finck if (r==sizeof(utf8_bom) && !memcmp(bom, utf8_bom, sizeof(utf8_bom))) { 1763c2c66affSColin Finck oflags |= _O_U8TEXT; 1764c2c66affSColin Finck }else if (r>=sizeof(utf16_bom) && !memcmp(bom, utf16_bom, sizeof(utf16_bom))) { 1765c2c66affSColin Finck if (seek && r>2) 1766c2c66affSColin Finck SetFilePointer(h, 2, NULL, FILE_BEGIN); 1767c2c66affSColin Finck oflags |= _O_U16TEXT; 1768c2c66affSColin Finck }else if (seek) { 1769c2c66affSColin Finck SetFilePointer(h, 0, NULL, FILE_BEGIN); 1770c2c66affSColin Finck } 1771c2c66affSColin Finck 1772c2c66affSColin Finck return oflags; 1773c2c66affSColin Finck } 1774c2c66affSColin Finck 1775c2c66affSColin Finck /********************************************************************* 1776c2c66affSColin Finck * _wsopen_s (MSVCRT.@) 1777c2c66affSColin Finck */ 1778c2c66affSColin Finck int CDECL _wsopen_s( int *fd, const wchar_t* path, int oflags, int shflags, int pmode ) 1779c2c66affSColin Finck { 1780c2c66affSColin Finck DWORD access = 0, creation = 0, attrib; 1781c2c66affSColin Finck SECURITY_ATTRIBUTES sa; 1782c2c66affSColin Finck DWORD sharing, type; 1783c2c66affSColin Finck int wxflag; 1784c2c66affSColin Finck HANDLE hand; 1785c2c66affSColin Finck 1786c2c66affSColin Finck TRACE("fd*: %p :file (%s) oflags: 0x%04x shflags: 0x%04x pmode: 0x%04x\n", 1787c2c66affSColin Finck fd, debugstr_w(path), oflags, shflags, pmode); 1788c2c66affSColin Finck 1789c2c66affSColin Finck if (!MSVCRT_CHECK_PMT( fd != NULL )) return EINVAL; 1790c2c66affSColin Finck 1791c2c66affSColin Finck *fd = -1; 1792c2c66affSColin Finck wxflag = split_oflags(oflags); 1793c2c66affSColin Finck switch (oflags & (_O_RDONLY | _O_WRONLY | _O_RDWR)) 1794c2c66affSColin Finck { 1795c2c66affSColin Finck case _O_RDONLY: access |= GENERIC_READ; break; 1796c2c66affSColin Finck case _O_WRONLY: access |= GENERIC_WRITE; break; 1797c2c66affSColin Finck case _O_RDWR: access |= GENERIC_WRITE | GENERIC_READ; break; 1798c2c66affSColin Finck } 1799c2c66affSColin Finck 1800c2c66affSColin Finck if (oflags & _O_CREAT) 1801c2c66affSColin Finck { 1802c2c66affSColin Finck if(pmode & ~(_S_IREAD | _S_IWRITE)) 1803c2c66affSColin Finck FIXME(": pmode 0x%04x ignored\n", pmode); 1804c2c66affSColin Finck else 1805c2c66affSColin Finck WARN(": pmode 0x%04x ignored\n", pmode); 1806c2c66affSColin Finck 1807c2c66affSColin Finck if (oflags & _O_EXCL) 1808c2c66affSColin Finck creation = CREATE_NEW; 1809c2c66affSColin Finck else if (oflags & _O_TRUNC) 1810c2c66affSColin Finck creation = CREATE_ALWAYS; 1811c2c66affSColin Finck else 1812c2c66affSColin Finck creation = OPEN_ALWAYS; 1813c2c66affSColin Finck } 1814c2c66affSColin Finck else /* no _O_CREAT */ 1815c2c66affSColin Finck { 1816c2c66affSColin Finck if (oflags & _O_TRUNC) 1817c2c66affSColin Finck creation = TRUNCATE_EXISTING; 1818c2c66affSColin Finck else 1819c2c66affSColin Finck creation = OPEN_EXISTING; 1820c2c66affSColin Finck } 1821c2c66affSColin Finck 1822c2c66affSColin Finck switch( shflags ) 1823c2c66affSColin Finck { 1824c2c66affSColin Finck case _SH_DENYRW: 1825c2c66affSColin Finck sharing = 0L; 1826c2c66affSColin Finck break; 1827c2c66affSColin Finck case _SH_DENYWR: 1828c2c66affSColin Finck sharing = FILE_SHARE_READ; 1829c2c66affSColin Finck break; 1830c2c66affSColin Finck case _SH_DENYRD: 1831c2c66affSColin Finck sharing = FILE_SHARE_WRITE; 1832c2c66affSColin Finck break; 1833c2c66affSColin Finck case _SH_DENYNO: 1834c2c66affSColin Finck sharing = FILE_SHARE_READ | FILE_SHARE_WRITE; 1835c2c66affSColin Finck break; 1836c2c66affSColin Finck default: 1837c2c66affSColin Finck ERR( "Unhandled shflags 0x%x\n", shflags ); 1838c2c66affSColin Finck return EINVAL; 1839c2c66affSColin Finck } 1840c2c66affSColin Finck attrib = FILE_ATTRIBUTE_NORMAL; 1841c2c66affSColin Finck 1842c2c66affSColin Finck if (oflags & _O_TEMPORARY) 1843c2c66affSColin Finck { 1844c2c66affSColin Finck attrib |= FILE_FLAG_DELETE_ON_CLOSE; 1845c2c66affSColin Finck access |= DELETE; 1846c2c66affSColin Finck sharing |= FILE_SHARE_DELETE; 1847c2c66affSColin Finck } 1848c2c66affSColin Finck 1849c2c66affSColin Finck sa.nLength = sizeof( SECURITY_ATTRIBUTES ); 1850c2c66affSColin Finck sa.lpSecurityDescriptor = NULL; 1851c2c66affSColin Finck sa.bInheritHandle = !(oflags & _O_NOINHERIT); 1852c2c66affSColin Finck 1853c2c66affSColin Finck if ((oflags&(_O_WTEXT|_O_U16TEXT|_O_U8TEXT)) 1854c2c66affSColin Finck && (creation==OPEN_ALWAYS || creation==OPEN_EXISTING) 1855c2c66affSColin Finck && !(access&GENERIC_READ)) 1856c2c66affSColin Finck { 1857c2c66affSColin Finck hand = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, 1858c2c66affSColin Finck &sa, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); 1859c2c66affSColin Finck if (hand != INVALID_HANDLE_VALUE) 1860c2c66affSColin Finck { 1861c2c66affSColin Finck oflags = check_bom(hand, oflags, FALSE); 1862c2c66affSColin Finck CloseHandle(hand); 1863c2c66affSColin Finck } 1864c2c66affSColin Finck else 1865c2c66affSColin Finck oflags &= ~(_O_WTEXT|_O_U16TEXT|_O_U8TEXT); 1866c2c66affSColin Finck } 1867c2c66affSColin Finck 1868c2c66affSColin Finck hand = CreateFileW(path, access, sharing, &sa, creation, attrib, 0); 1869c2c66affSColin Finck if (hand == INVALID_HANDLE_VALUE) { 1870c2c66affSColin Finck WARN(":failed-last error (%d)\n",GetLastError()); 1871c2c66affSColin Finck _dosmaperr(GetLastError()); 1872c2c66affSColin Finck return *_errno(); 1873c2c66affSColin Finck } 1874c2c66affSColin Finck 1875c2c66affSColin Finck if (oflags & (_O_WTEXT|_O_U16TEXT|_O_U8TEXT)) 1876c2c66affSColin Finck { 1877c2c66affSColin Finck if ((access & GENERIC_WRITE) && (creation==CREATE_NEW 1878c2c66affSColin Finck || creation==CREATE_ALWAYS || creation==TRUNCATE_EXISTING 1879c2c66affSColin Finck || (creation==OPEN_ALWAYS && GetLastError()==ERROR_ALREADY_EXISTS))) 1880c2c66affSColin Finck { 1881c2c66affSColin Finck if (oflags & _O_U8TEXT) 1882c2c66affSColin Finck { 1883c2c66affSColin Finck DWORD written = 0, tmp; 1884c2c66affSColin Finck 1885c2c66affSColin Finck while(written!=sizeof(utf8_bom) && WriteFile(hand, (char*)utf8_bom+written, 1886c2c66affSColin Finck sizeof(utf8_bom)-written, &tmp, NULL)) 1887c2c66affSColin Finck written += tmp; 1888c2c66affSColin Finck if (written != sizeof(utf8_bom)) { 1889c2c66affSColin Finck WARN("error writing BOM\n"); 1890c2c66affSColin Finck CloseHandle(hand); 1891c2c66affSColin Finck _dosmaperr(GetLastError()); 1892c2c66affSColin Finck return *_errno(); 1893c2c66affSColin Finck } 1894c2c66affSColin Finck } 1895c2c66affSColin Finck else 1896c2c66affSColin Finck { 1897c2c66affSColin Finck DWORD written = 0, tmp; 1898c2c66affSColin Finck 1899c2c66affSColin Finck while(written!=sizeof(utf16_bom) && WriteFile(hand, (char*)utf16_bom+written, 1900c2c66affSColin Finck sizeof(utf16_bom)-written, &tmp, NULL)) 1901c2c66affSColin Finck written += tmp; 1902c2c66affSColin Finck if (written != sizeof(utf16_bom)) 1903c2c66affSColin Finck { 1904c2c66affSColin Finck WARN("error writing BOM\n"); 1905c2c66affSColin Finck CloseHandle(hand); 1906c2c66affSColin Finck _dosmaperr(GetLastError()); 1907c2c66affSColin Finck return *_errno(); 1908c2c66affSColin Finck } 1909c2c66affSColin Finck } 1910c2c66affSColin Finck } 1911c2c66affSColin Finck else if (access & GENERIC_READ) 1912c2c66affSColin Finck oflags = check_bom(hand, oflags, TRUE); 1913c2c66affSColin Finck } 1914c2c66affSColin Finck 1915c2c66affSColin Finck type = GetFileType(hand); 1916c2c66affSColin Finck if (type == FILE_TYPE_CHAR) 1917c2c66affSColin Finck wxflag |= WX_TTY; 1918c2c66affSColin Finck else if (type == FILE_TYPE_PIPE) 1919c2c66affSColin Finck wxflag |= WX_PIPE; 1920c2c66affSColin Finck 1921c2c66affSColin Finck *fd = msvcrt_alloc_fd(hand, wxflag); 1922c2c66affSColin Finck if (*fd == -1) 1923c2c66affSColin Finck return *_errno(); 1924c2c66affSColin Finck 1925c2c66affSColin Finck if (oflags & _O_WTEXT) 192625064fdfSThomas Faber get_ioinfo_nolock(*fd)->exflag |= EF_UTF16|EF_UNK_UNICODE; 1927c2c66affSColin Finck else if (oflags & _O_U16TEXT) 192825064fdfSThomas Faber get_ioinfo_nolock(*fd)->exflag |= EF_UTF16; 1929c2c66affSColin Finck else if (oflags & _O_U8TEXT) 193025064fdfSThomas Faber get_ioinfo_nolock(*fd)->exflag |= EF_UTF8; 1931c2c66affSColin Finck 1932c2c66affSColin Finck TRACE(":fd (%d) handle (%p)\n", *fd, hand); 1933c2c66affSColin Finck return 0; 1934c2c66affSColin Finck } 1935c2c66affSColin Finck 1936c2c66affSColin Finck /********************************************************************* 1937c2c66affSColin Finck * _wsopen (MSVCRT.@) 1938c2c66affSColin Finck */ 1939c2c66affSColin Finck int CDECL _wsopen( const wchar_t *path, int oflags, int shflags, ... ) 1940c2c66affSColin Finck { 1941c2c66affSColin Finck int pmode; 1942c2c66affSColin Finck int fd; 1943c2c66affSColin Finck 1944c2c66affSColin Finck if (oflags & _O_CREAT) 1945c2c66affSColin Finck { 1946c2c66affSColin Finck __ms_va_list ap; 1947c2c66affSColin Finck 1948c2c66affSColin Finck __ms_va_start(ap, shflags); 1949c2c66affSColin Finck pmode = va_arg(ap, int); 1950c2c66affSColin Finck __ms_va_end(ap); 1951c2c66affSColin Finck } 1952c2c66affSColin Finck else 1953c2c66affSColin Finck pmode = 0; 1954c2c66affSColin Finck 1955c2c66affSColin Finck _wsopen_s(&fd, path, oflags, shflags, pmode); 1956c2c66affSColin Finck return fd; 1957c2c66affSColin Finck } 1958c2c66affSColin Finck 1959c2c66affSColin Finck /********************************************************************* 1960c2c66affSColin Finck * _sopen_s (MSVCRT.@) 1961c2c66affSColin Finck */ 1962c2c66affSColin Finck int CDECL _sopen_s( int *fd, const char *path, int oflags, int shflags, int pmode ) 1963c2c66affSColin Finck { 1964c2c66affSColin Finck wchar_t *pathW; 1965c2c66affSColin Finck int ret; 1966c2c66affSColin Finck 1967c2c66affSColin Finck if(!MSVCRT_CHECK_PMT(path && (pathW = msvcrt_wstrdupa(path)))) 1968c2c66affSColin Finck return EINVAL; 1969c2c66affSColin Finck 1970c2c66affSColin Finck ret = _wsopen_s(fd, pathW, oflags, shflags, pmode); 1971c2c66affSColin Finck free(pathW); 1972c2c66affSColin Finck return ret; 1973c2c66affSColin Finck } 1974c2c66affSColin Finck 1975c2c66affSColin Finck /********************************************************************* 1976c2c66affSColin Finck * _sopen (MSVCRT.@) 1977c2c66affSColin Finck */ 1978c2c66affSColin Finck int CDECL _sopen( const char *path, int oflags, int shflags, ... ) 1979c2c66affSColin Finck { 1980c2c66affSColin Finck int pmode; 1981c2c66affSColin Finck int fd; 1982c2c66affSColin Finck 1983c2c66affSColin Finck if (oflags & _O_CREAT) 1984c2c66affSColin Finck { 1985c2c66affSColin Finck va_list ap; 1986c2c66affSColin Finck 1987c2c66affSColin Finck va_start(ap, shflags); 1988c2c66affSColin Finck pmode = va_arg(ap, int); 1989c2c66affSColin Finck va_end(ap); 1990c2c66affSColin Finck } 1991c2c66affSColin Finck else 1992c2c66affSColin Finck pmode = 0; 1993c2c66affSColin Finck 1994c2c66affSColin Finck _sopen_s(&fd, path, oflags, shflags, pmode); 1995c2c66affSColin Finck return fd; 1996c2c66affSColin Finck } 1997c2c66affSColin Finck 1998c2c66affSColin Finck /********************************************************************* 1999c2c66affSColin Finck * _open (MSVCRT.@) 2000c2c66affSColin Finck */ 2001c2c66affSColin Finck int CDECL _open( const char *path, int flags, ... ) 2002c2c66affSColin Finck { 2003c2c66affSColin Finck va_list ap; 2004c2c66affSColin Finck 2005c2c66affSColin Finck if (flags & _O_CREAT) 2006c2c66affSColin Finck { 2007c2c66affSColin Finck int pmode; 2008c2c66affSColin Finck va_start(ap, flags); 2009c2c66affSColin Finck pmode = va_arg(ap, int); 2010c2c66affSColin Finck va_end(ap); 2011c2c66affSColin Finck return _sopen( path, flags, _SH_DENYNO, pmode ); 2012c2c66affSColin Finck } 2013c2c66affSColin Finck else 2014c2c66affSColin Finck return _sopen( path, flags, _SH_DENYNO); 2015c2c66affSColin Finck } 2016c2c66affSColin Finck 2017c2c66affSColin Finck /********************************************************************* 2018c2c66affSColin Finck * _wopen (MSVCRT.@) 2019c2c66affSColin Finck */ 2020c2c66affSColin Finck int CDECL _wopen(const wchar_t *path,int flags,...) 2021c2c66affSColin Finck { 2022c2c66affSColin Finck va_list ap; 2023c2c66affSColin Finck 2024c2c66affSColin Finck if (flags & _O_CREAT) 2025c2c66affSColin Finck { 2026c2c66affSColin Finck int pmode; 2027c2c66affSColin Finck va_start(ap, flags); 2028c2c66affSColin Finck pmode = va_arg(ap, int); 2029c2c66affSColin Finck va_end(ap); 2030c2c66affSColin Finck return _wsopen( path, flags, _SH_DENYNO, pmode ); 2031c2c66affSColin Finck } 2032c2c66affSColin Finck else 2033c2c66affSColin Finck return _wsopen( path, flags, _SH_DENYNO); 2034c2c66affSColin Finck } 2035c2c66affSColin Finck 2036c2c66affSColin Finck /********************************************************************* 2037c2c66affSColin Finck * _creat (MSVCRT.@) 2038c2c66affSColin Finck */ 2039c2c66affSColin Finck int CDECL _creat(const char *path, int flags) 2040c2c66affSColin Finck { 2041c2c66affSColin Finck int usedFlags = (flags & _O_TEXT)| _O_CREAT| _O_WRONLY| _O_TRUNC; 2042c2c66affSColin Finck return _open(path, usedFlags); 2043c2c66affSColin Finck } 2044c2c66affSColin Finck 2045c2c66affSColin Finck /********************************************************************* 2046c2c66affSColin Finck * _wcreat (MSVCRT.@) 2047c2c66affSColin Finck */ 2048c2c66affSColin Finck int CDECL _wcreat(const wchar_t *path, int flags) 2049c2c66affSColin Finck { 2050c2c66affSColin Finck int usedFlags = (flags & _O_TEXT)| _O_CREAT| _O_WRONLY| _O_TRUNC; 2051c2c66affSColin Finck return _wopen(path, usedFlags); 2052c2c66affSColin Finck } 2053c2c66affSColin Finck 2054c2c66affSColin Finck /********************************************************************* 2055c2c66affSColin Finck * _open_osfhandle (MSVCRT.@) 2056c2c66affSColin Finck */ 2057c2c66affSColin Finck int CDECL _open_osfhandle(intptr_t handle, int oflags) 2058c2c66affSColin Finck { 2059c2c66affSColin Finck DWORD flags; 2060c2c66affSColin Finck int fd; 2061c2c66affSColin Finck 2062c2c66affSColin Finck /* _O_RDONLY (0) always matches, so set the read flag 2063c2c66affSColin Finck * MFC's CStdioFile clears O_RDONLY (0)! if it wants to write to the 2064c2c66affSColin Finck * file, so set the write flag. It also only sets _O_TEXT if it wants 2065c2c66affSColin Finck * text - it never sets _O_BINARY. 2066c2c66affSColin Finck */ 2067c2c66affSColin Finck /* don't let split_oflags() decide the mode if no mode is passed */ 2068c2c66affSColin Finck if (!(oflags & (_O_BINARY | _O_TEXT))) 2069c2c66affSColin Finck oflags |= _O_BINARY; 2070c2c66affSColin Finck 2071c2c66affSColin Finck flags = GetFileType((HANDLE)handle); 2072c2c66affSColin Finck if (flags==FILE_TYPE_UNKNOWN && GetLastError()!=NO_ERROR) 2073c2c66affSColin Finck { 2074c2c66affSColin Finck _dosmaperr(GetLastError()); 2075c2c66affSColin Finck return -1; 2076c2c66affSColin Finck } 2077c2c66affSColin Finck 2078c2c66affSColin Finck if (flags == FILE_TYPE_CHAR) 2079c2c66affSColin Finck flags = WX_TTY; 2080c2c66affSColin Finck else if (flags == FILE_TYPE_PIPE) 2081c2c66affSColin Finck flags = WX_PIPE; 2082c2c66affSColin Finck else 2083c2c66affSColin Finck flags = 0; 2084c2c66affSColin Finck flags |= split_oflags(oflags); 2085c2c66affSColin Finck 2086c2c66affSColin Finck fd = msvcrt_alloc_fd((HANDLE)handle, flags); 2087c2c66affSColin Finck TRACE(":handle (%ld) fd (%d) flags 0x%08x\n", handle, fd, flags); 2088c2c66affSColin Finck return fd; 2089c2c66affSColin Finck } 2090c2c66affSColin Finck 2091c2c66affSColin Finck /********************************************************************* 2092c2c66affSColin Finck * _rmtmp (MSVCRT.@) 2093c2c66affSColin Finck */ 2094c2c66affSColin Finck int CDECL _rmtmp(void) 2095c2c66affSColin Finck { 2096c2c66affSColin Finck int num_removed = 0, i; 2097c2c66affSColin Finck FILE *file; 2098c2c66affSColin Finck 2099c2c66affSColin Finck LOCK_FILES(); 2100c2c66affSColin Finck for (i = 3; i < MSVCRT_stream_idx; i++) { 2101c2c66affSColin Finck file = msvcrt_get_file(i); 2102c2c66affSColin Finck 2103c2c66affSColin Finck if (file->_tmpfname) 2104c2c66affSColin Finck { 2105c2c66affSColin Finck fclose(file); 2106c2c66affSColin Finck num_removed++; 2107c2c66affSColin Finck } 2108c2c66affSColin Finck } 2109c2c66affSColin Finck UNLOCK_FILES(); 2110c2c66affSColin Finck 2111c2c66affSColin Finck if (num_removed) 2112c2c66affSColin Finck TRACE(":removed (%d) temp files\n",num_removed); 2113c2c66affSColin Finck return num_removed; 2114c2c66affSColin Finck } 2115c2c66affSColin Finck 2116c2c66affSColin Finck static inline int get_utf8_char_len(char ch) 2117c2c66affSColin Finck { 2118c2c66affSColin Finck if((ch&0xf8) == 0xf0) 2119c2c66affSColin Finck return 4; 2120c2c66affSColin Finck else if((ch&0xf0) == 0xe0) 2121c2c66affSColin Finck return 3; 2122c2c66affSColin Finck else if((ch&0xe0) == 0xc0) 2123c2c66affSColin Finck return 2; 2124c2c66affSColin Finck return 1; 2125c2c66affSColin Finck } 2126c2c66affSColin Finck 2127c2c66affSColin Finck /********************************************************************* 2128c2c66affSColin Finck * (internal) read_utf8 2129c2c66affSColin Finck */ 2130bffd8201SThomas Faber static int read_utf8(ioinfo *fdinfo, wchar_t *buf, unsigned int count) 2131c2c66affSColin Finck { 2132c2c66affSColin Finck HANDLE hand = fdinfo->handle; 2133c2c66affSColin Finck char min_buf[4], *readbuf, lookahead; 2134c2c66affSColin Finck DWORD readbuf_size, pos=0, num_read=1, char_len, i, j; 2135c2c66affSColin Finck 2136c2c66affSColin Finck /* make the buffer big enough to hold at least one character */ 2137c2c66affSColin Finck /* read bytes have to fit to output and lookahead buffers */ 2138c2c66affSColin Finck count /= 2; 2139c2c66affSColin Finck readbuf_size = count < 4 ? 4 : count; 2140c2c66affSColin Finck if(readbuf_size<=4 || !(readbuf = malloc(readbuf_size))) { 2141c2c66affSColin Finck readbuf_size = 4; 2142c2c66affSColin Finck readbuf = min_buf; 2143c2c66affSColin Finck } 2144c2c66affSColin Finck 2145c2c66affSColin Finck if(fdinfo->lookahead[0] != '\n') { 2146c2c66affSColin Finck readbuf[pos++] = fdinfo->lookahead[0]; 2147c2c66affSColin Finck fdinfo->lookahead[0] = '\n'; 2148c2c66affSColin Finck 2149c2c66affSColin Finck if(fdinfo->lookahead[1] != '\n') { 2150c2c66affSColin Finck readbuf[pos++] = fdinfo->lookahead[1]; 2151c2c66affSColin Finck fdinfo->lookahead[1] = '\n'; 2152c2c66affSColin Finck 2153c2c66affSColin Finck if(fdinfo->lookahead[2] != '\n') { 2154c2c66affSColin Finck readbuf[pos++] = fdinfo->lookahead[2]; 2155c2c66affSColin Finck fdinfo->lookahead[2] = '\n'; 2156c2c66affSColin Finck } 2157c2c66affSColin Finck } 2158c2c66affSColin Finck } 2159c2c66affSColin Finck 2160c2c66affSColin Finck /* NOTE: this case is broken in native dll, reading 2161c2c66affSColin Finck * sometimes fails when small buffer is passed 2162c2c66affSColin Finck */ 2163c2c66affSColin Finck if(count < 4) { 2164c2c66affSColin Finck if(!pos && !ReadFile(hand, readbuf, 1, &num_read, NULL)) { 2165c2c66affSColin Finck if (GetLastError() == ERROR_BROKEN_PIPE) { 2166c2c66affSColin Finck fdinfo->wxflag |= WX_ATEOF; 2167c2c66affSColin Finck return 0; 2168c2c66affSColin Finck }else { 2169c2c66affSColin Finck _dosmaperr(GetLastError()); 2170c2c66affSColin Finck return -1; 2171c2c66affSColin Finck } 2172c2c66affSColin Finck }else if(!num_read) { 2173c2c66affSColin Finck fdinfo->wxflag |= WX_ATEOF; 2174c2c66affSColin Finck return 0; 2175c2c66affSColin Finck }else { 2176c2c66affSColin Finck pos++; 2177c2c66affSColin Finck } 2178c2c66affSColin Finck 2179c2c66affSColin Finck char_len = get_utf8_char_len(readbuf[0]); 2180c2c66affSColin Finck if(char_len>pos) { 2181c2c66affSColin Finck if(ReadFile(hand, readbuf+pos, char_len-pos, &num_read, NULL)) 2182c2c66affSColin Finck pos += num_read; 2183c2c66affSColin Finck } 2184c2c66affSColin Finck 2185c2c66affSColin Finck if(readbuf[0] == '\n') 2186c2c66affSColin Finck fdinfo->wxflag |= WX_READNL; 2187c2c66affSColin Finck else 2188c2c66affSColin Finck fdinfo->wxflag &= ~WX_READNL; 2189c2c66affSColin Finck 2190c2c66affSColin Finck if(readbuf[0] == 0x1a) { 2191c2c66affSColin Finck fdinfo->wxflag |= WX_ATEOF; 2192c2c66affSColin Finck return 0; 2193c2c66affSColin Finck } 2194c2c66affSColin Finck 2195c2c66affSColin Finck if(readbuf[0] == '\r') { 2196c2c66affSColin Finck if(!ReadFile(hand, &lookahead, 1, &num_read, NULL) || num_read!=1) 2197c2c66affSColin Finck buf[0] = '\r'; 2198c2c66affSColin Finck else if(lookahead == '\n') 2199c2c66affSColin Finck buf[0] = '\n'; 2200c2c66affSColin Finck else { 2201c2c66affSColin Finck buf[0] = '\r'; 2202c2c66affSColin Finck if(fdinfo->wxflag & (WX_PIPE | WX_TTY)) 2203c2c66affSColin Finck fdinfo->lookahead[0] = lookahead; 2204c2c66affSColin Finck else 2205c2c66affSColin Finck SetFilePointer(fdinfo->handle, -1, NULL, FILE_CURRENT); 2206c2c66affSColin Finck } 2207c2c66affSColin Finck return 2; 2208c2c66affSColin Finck } 2209c2c66affSColin Finck 2210c2c66affSColin Finck if(!(num_read = MultiByteToWideChar(CP_UTF8, 0, readbuf, pos, buf, count))) { 2211c2c66affSColin Finck _dosmaperr(GetLastError()); 2212c2c66affSColin Finck return -1; 2213c2c66affSColin Finck } 2214c2c66affSColin Finck 2215c2c66affSColin Finck return num_read*2; 2216c2c66affSColin Finck } 2217c2c66affSColin Finck 2218c2c66affSColin Finck if(!ReadFile(hand, readbuf+pos, readbuf_size-pos, &num_read, NULL)) { 2219c2c66affSColin Finck if(pos) { 2220c2c66affSColin Finck num_read = 0; 2221c2c66affSColin Finck }else if(GetLastError() == ERROR_BROKEN_PIPE) { 2222c2c66affSColin Finck fdinfo->wxflag |= WX_ATEOF; 2223c2c66affSColin Finck if (readbuf != min_buf) free(readbuf); 2224c2c66affSColin Finck return 0; 2225c2c66affSColin Finck }else { 2226c2c66affSColin Finck _dosmaperr(GetLastError()); 2227c2c66affSColin Finck if (readbuf != min_buf) free(readbuf); 2228c2c66affSColin Finck return -1; 2229c2c66affSColin Finck } 2230c2c66affSColin Finck }else if(!pos && !num_read) { 2231c2c66affSColin Finck fdinfo->wxflag |= WX_ATEOF; 2232c2c66affSColin Finck if (readbuf != min_buf) free(readbuf); 2233c2c66affSColin Finck return 0; 2234c2c66affSColin Finck } 2235c2c66affSColin Finck 2236c2c66affSColin Finck pos += num_read; 2237c2c66affSColin Finck if(readbuf[0] == '\n') 2238c2c66affSColin Finck fdinfo->wxflag |= WX_READNL; 2239c2c66affSColin Finck else 2240c2c66affSColin Finck fdinfo->wxflag &= ~WX_READNL; 2241c2c66affSColin Finck 2242c2c66affSColin Finck /* Find first byte of last character (may be incomplete) */ 2243c2c66affSColin Finck for(i=pos-1; i>0 && i>pos-4; i--) 2244c2c66affSColin Finck if((readbuf[i]&0xc0) != 0x80) 2245c2c66affSColin Finck break; 2246c2c66affSColin Finck char_len = get_utf8_char_len(readbuf[i]); 2247c2c66affSColin Finck if(char_len+i <= pos) 2248c2c66affSColin Finck i += char_len; 2249c2c66affSColin Finck 2250c2c66affSColin Finck if(fdinfo->wxflag & (WX_PIPE | WX_TTY)) { 2251c2c66affSColin Finck if(i < pos) 2252c2c66affSColin Finck fdinfo->lookahead[0] = readbuf[i]; 2253c2c66affSColin Finck if(i+1 < pos) 2254c2c66affSColin Finck fdinfo->lookahead[1] = readbuf[i+1]; 2255c2c66affSColin Finck if(i+2 < pos) 2256c2c66affSColin Finck fdinfo->lookahead[2] = readbuf[i+2]; 2257c2c66affSColin Finck }else if(i < pos) { 2258c2c66affSColin Finck SetFilePointer(fdinfo->handle, i-pos, NULL, FILE_CURRENT); 2259c2c66affSColin Finck } 2260c2c66affSColin Finck pos = i; 2261c2c66affSColin Finck 2262c2c66affSColin Finck for(i=0, j=0; i<pos; i++) { 2263c2c66affSColin Finck if(readbuf[i] == 0x1a) { 2264c2c66affSColin Finck fdinfo->wxflag |= WX_ATEOF; 2265c2c66affSColin Finck break; 2266c2c66affSColin Finck } 2267c2c66affSColin Finck 2268c2c66affSColin Finck /* strip '\r' if followed by '\n' */ 2269c2c66affSColin Finck if(readbuf[i] == '\r' && i+1==pos) { 2270c2c66affSColin Finck if(fdinfo->lookahead[0] != '\n' || !ReadFile(hand, &lookahead, 1, &num_read, NULL) || !num_read) { 2271c2c66affSColin Finck readbuf[j++] = '\r'; 2272c2c66affSColin Finck }else if(lookahead == '\n' && j==0) { 2273c2c66affSColin Finck readbuf[j++] = '\n'; 2274c2c66affSColin Finck }else { 2275c2c66affSColin Finck if(lookahead != '\n') 2276c2c66affSColin Finck readbuf[j++] = '\r'; 2277c2c66affSColin Finck 2278c2c66affSColin Finck if(fdinfo->wxflag & (WX_PIPE | WX_TTY)) 2279c2c66affSColin Finck fdinfo->lookahead[0] = lookahead; 2280c2c66affSColin Finck else 2281c2c66affSColin Finck SetFilePointer(fdinfo->handle, -1, NULL, FILE_CURRENT); 2282c2c66affSColin Finck } 2283c2c66affSColin Finck }else if(readbuf[i]!='\r' || readbuf[i+1]!='\n') { 2284c2c66affSColin Finck readbuf[j++] = readbuf[i]; 2285c2c66affSColin Finck } 2286c2c66affSColin Finck } 2287c2c66affSColin Finck pos = j; 2288c2c66affSColin Finck 2289c2c66affSColin Finck if(!(num_read = MultiByteToWideChar(CP_UTF8, 0, readbuf, pos, buf, count))) { 2290c2c66affSColin Finck _dosmaperr(GetLastError()); 2291c2c66affSColin Finck if (readbuf != min_buf) free(readbuf); 2292c2c66affSColin Finck return -1; 2293c2c66affSColin Finck } 2294c2c66affSColin Finck 2295c2c66affSColin Finck if (readbuf != min_buf) free(readbuf); 2296c2c66affSColin Finck return num_read*2; 2297c2c66affSColin Finck } 2298c2c66affSColin Finck 2299c2c66affSColin Finck /********************************************************************* 2300c2c66affSColin Finck * (internal) read_i 2301c2c66affSColin Finck * 2302c2c66affSColin Finck * When reading \r as last character in text mode, read() positions 2303c2c66affSColin Finck * the file pointer on the \r character while getc() goes on to 2304c2c66affSColin Finck * the following \n 2305c2c66affSColin Finck */ 2306bffd8201SThomas Faber static int read_i(int fd, ioinfo *fdinfo, void *buf, unsigned int count) 2307c2c66affSColin Finck { 2308c2c66affSColin Finck DWORD num_read, utf16; 2309c2c66affSColin Finck char *bufstart = buf; 2310c2c66affSColin Finck 2311c2c66affSColin Finck if (count == 0) 2312c2c66affSColin Finck return 0; 2313c2c66affSColin Finck 2314c2c66affSColin Finck if (fdinfo->wxflag & WX_ATEOF) { 2315c2c66affSColin Finck TRACE("already at EOF, returning 0\n"); 2316c2c66affSColin Finck return 0; 2317c2c66affSColin Finck } 2318c2c66affSColin Finck /* Don't trace small reads, it gets *very* annoying */ 2319c2c66affSColin Finck if (count > 4) 2320bffd8201SThomas Faber TRACE(":fd (%d) handle (%p) buf (%p) len (%d)\n", fd, fdinfo->handle, buf, count); 2321bffd8201SThomas Faber if (fdinfo->handle == INVALID_HANDLE_VALUE) 2322c2c66affSColin Finck { 2323c2c66affSColin Finck *_errno() = EBADF; 2324c2c66affSColin Finck return -1; 2325c2c66affSColin Finck } 2326c2c66affSColin Finck 2327c2c66affSColin Finck utf16 = (fdinfo->exflag & EF_UTF16) != 0; 2328c2c66affSColin Finck if (((fdinfo->exflag&EF_UTF8) || utf16) && count&1) 2329c2c66affSColin Finck { 2330c2c66affSColin Finck *_errno() = EINVAL; 2331c2c66affSColin Finck return -1; 2332c2c66affSColin Finck } 2333c2c66affSColin Finck 2334c2c66affSColin Finck if((fdinfo->wxflag&WX_TEXT) && (fdinfo->exflag&EF_UTF8)) 2335bffd8201SThomas Faber return read_utf8(fdinfo, buf, count); 2336c2c66affSColin Finck 2337bffd8201SThomas Faber if (fdinfo->lookahead[0]!='\n' || ReadFile(fdinfo->handle, bufstart, count, &num_read, NULL)) 2338c2c66affSColin Finck { 2339c2c66affSColin Finck if (fdinfo->lookahead[0] != '\n') 2340c2c66affSColin Finck { 2341c2c66affSColin Finck bufstart[0] = fdinfo->lookahead[0]; 2342c2c66affSColin Finck fdinfo->lookahead[0] = '\n'; 2343c2c66affSColin Finck 2344c2c66affSColin Finck if (utf16) 2345c2c66affSColin Finck { 2346c2c66affSColin Finck bufstart[1] = fdinfo->lookahead[1]; 2347c2c66affSColin Finck fdinfo->lookahead[1] = '\n'; 2348c2c66affSColin Finck } 2349c2c66affSColin Finck 2350bffd8201SThomas Faber if(count>1+utf16 && ReadFile(fdinfo->handle, bufstart+1+utf16, count-1-utf16, &num_read, NULL)) 2351c2c66affSColin Finck num_read += 1+utf16; 2352c2c66affSColin Finck else 2353c2c66affSColin Finck num_read = 1+utf16; 2354c2c66affSColin Finck } 2355c2c66affSColin Finck 2356c2c66affSColin Finck if(utf16 && (num_read&1)) 2357c2c66affSColin Finck { 2358c2c66affSColin Finck /* msvcr90 uses uninitialized value from the buffer in this case */ 2359c2c66affSColin Finck /* msvcrt ignores additional data */ 2360c2c66affSColin Finck ERR("got odd number of bytes in UTF16 mode\n"); 2361c2c66affSColin Finck num_read--; 2362c2c66affSColin Finck } 2363c2c66affSColin Finck 2364c2c66affSColin Finck if (count != 0 && num_read == 0) 2365c2c66affSColin Finck { 2366c2c66affSColin Finck fdinfo->wxflag |= WX_ATEOF; 2367c2c66affSColin Finck TRACE(":EOF %s\n",debugstr_an(buf,num_read)); 2368c2c66affSColin Finck } 2369c2c66affSColin Finck else if (fdinfo->wxflag & WX_TEXT) 2370c2c66affSColin Finck { 2371c2c66affSColin Finck DWORD i, j; 2372c2c66affSColin Finck 2373c2c66affSColin Finck if (bufstart[0]=='\n' && (!utf16 || bufstart[1]==0)) 2374c2c66affSColin Finck fdinfo->wxflag |= WX_READNL; 2375c2c66affSColin Finck else 2376c2c66affSColin Finck fdinfo->wxflag &= ~WX_READNL; 2377c2c66affSColin Finck 2378c2c66affSColin Finck for (i=0, j=0; i<num_read; i+=1+utf16) 2379c2c66affSColin Finck { 2380c2c66affSColin Finck /* in text mode, a ctrl-z signals EOF */ 2381c2c66affSColin Finck if (bufstart[i]==0x1a && (!utf16 || bufstart[i+1]==0)) 2382c2c66affSColin Finck { 2383c2c66affSColin Finck fdinfo->wxflag |= WX_ATEOF; 2384c2c66affSColin Finck TRACE(":^Z EOF %s\n",debugstr_an(buf,num_read)); 2385c2c66affSColin Finck break; 2386c2c66affSColin Finck } 2387c2c66affSColin Finck 2388c2c66affSColin Finck /* in text mode, strip \r if followed by \n */ 2389c2c66affSColin Finck if (bufstart[i]=='\r' && (!utf16 || bufstart[i+1]==0) && i+1+utf16==num_read) 2390c2c66affSColin Finck { 2391c2c66affSColin Finck char lookahead[2]; 2392c2c66affSColin Finck DWORD len; 2393c2c66affSColin Finck 2394c2c66affSColin Finck lookahead[1] = '\n'; 2395bffd8201SThomas Faber if (ReadFile(fdinfo->handle, lookahead, 1+utf16, &len, NULL) && len) 2396c2c66affSColin Finck { 2397c2c66affSColin Finck if(lookahead[0]=='\n' && (!utf16 || lookahead[1]==0) && j==0) 2398c2c66affSColin Finck { 2399c2c66affSColin Finck bufstart[j++] = '\n'; 2400c2c66affSColin Finck if(utf16) bufstart[j++] = 0; 2401c2c66affSColin Finck } 2402c2c66affSColin Finck else 2403c2c66affSColin Finck { 2404c2c66affSColin Finck if(lookahead[0]!='\n' || (utf16 && lookahead[1]!=0)) 2405c2c66affSColin Finck { 2406c2c66affSColin Finck bufstart[j++] = '\r'; 2407c2c66affSColin Finck if(utf16) bufstart[j++] = 0; 2408c2c66affSColin Finck } 2409c2c66affSColin Finck 2410c2c66affSColin Finck if (fdinfo->wxflag & (WX_PIPE | WX_TTY)) 2411c2c66affSColin Finck { 2412c2c66affSColin Finck if (lookahead[0]=='\n' && (!utf16 || !lookahead[1])) 2413c2c66affSColin Finck { 2414c2c66affSColin Finck bufstart[j++] = '\n'; 2415c2c66affSColin Finck if (utf16) bufstart[j++] = 0; 2416c2c66affSColin Finck } 2417c2c66affSColin Finck else 2418c2c66affSColin Finck { 2419c2c66affSColin Finck fdinfo->lookahead[0] = lookahead[0]; 2420c2c66affSColin Finck fdinfo->lookahead[1] = lookahead[1]; 2421c2c66affSColin Finck } 2422c2c66affSColin Finck } 2423c2c66affSColin Finck else 2424c2c66affSColin Finck SetFilePointer(fdinfo->handle, -1-utf16, NULL, FILE_CURRENT); 2425c2c66affSColin Finck } 2426c2c66affSColin Finck } 2427c2c66affSColin Finck else 2428c2c66affSColin Finck { 2429c2c66affSColin Finck bufstart[j++] = '\r'; 2430c2c66affSColin Finck if(utf16) bufstart[j++] = 0; 2431c2c66affSColin Finck } 2432c2c66affSColin Finck } 2433c2c66affSColin Finck else if((bufstart[i]!='\r' || (utf16 && bufstart[i+1]!=0)) 2434c2c66affSColin Finck || (bufstart[i+1+utf16]!='\n' || (utf16 && bufstart[i+3]!=0))) 2435c2c66affSColin Finck { 2436c2c66affSColin Finck bufstart[j++] = bufstart[i]; 2437c2c66affSColin Finck if(utf16) bufstart[j++] = bufstart[i+1]; 2438c2c66affSColin Finck } 2439c2c66affSColin Finck } 2440c2c66affSColin Finck num_read = j; 2441c2c66affSColin Finck } 2442c2c66affSColin Finck } 2443c2c66affSColin Finck else 2444c2c66affSColin Finck { 2445c2c66affSColin Finck if (GetLastError() == ERROR_BROKEN_PIPE) 2446c2c66affSColin Finck { 2447c2c66affSColin Finck TRACE(":end-of-pipe\n"); 2448c2c66affSColin Finck fdinfo->wxflag |= WX_ATEOF; 2449c2c66affSColin Finck return 0; 2450c2c66affSColin Finck } 2451c2c66affSColin Finck else 2452c2c66affSColin Finck { 2453c2c66affSColin Finck TRACE(":failed-last error (%d)\n",GetLastError()); 2454c2c66affSColin Finck return -1; 2455c2c66affSColin Finck } 2456c2c66affSColin Finck } 2457c2c66affSColin Finck 2458c2c66affSColin Finck if (count > 4) 2459c2c66affSColin Finck TRACE("(%u), %s\n",num_read,debugstr_an(buf, num_read)); 2460c2c66affSColin Finck return num_read; 2461c2c66affSColin Finck } 2462c2c66affSColin Finck 2463c2c66affSColin Finck /********************************************************************* 2464c2c66affSColin Finck * _read (MSVCRT.@) 2465c2c66affSColin Finck */ 2466c2c66affSColin Finck int CDECL _read(int fd, void *buf, unsigned int count) 2467c2c66affSColin Finck { 2468bffd8201SThomas Faber ioinfo *info = get_ioinfo(fd); 2469bffd8201SThomas Faber int num_read = read_i(fd, info, buf, count); 2470bffd8201SThomas Faber release_ioinfo(info); 2471c2c66affSColin Finck return num_read; 2472c2c66affSColin Finck } 2473c2c66affSColin Finck 2474c2c66affSColin Finck /********************************************************************* 2475c2c66affSColin Finck * _setmode (MSVCRT.@) 2476c2c66affSColin Finck */ 2477c2c66affSColin Finck int CDECL _setmode(int fd,int mode) 2478c2c66affSColin Finck { 2479bffd8201SThomas Faber ioinfo *info = get_ioinfo(fd); 2480bffd8201SThomas Faber int ret = info->wxflag & WX_TEXT ? _O_TEXT : _O_BINARY; 2481bffd8201SThomas Faber if(ret==_O_TEXT && (info->exflag & (EF_UTF8|EF_UTF16))) 2482c2c66affSColin Finck ret = _O_WTEXT; 2483c2c66affSColin Finck 2484c2c66affSColin Finck if(mode!=_O_TEXT && mode!=_O_BINARY && mode!=_O_WTEXT 2485c2c66affSColin Finck && mode!=_O_U16TEXT && mode!=_O_U8TEXT) { 2486c2c66affSColin Finck *_errno() = EINVAL; 2487bffd8201SThomas Faber release_ioinfo(info); 2488c2c66affSColin Finck return -1; 2489c2c66affSColin Finck } 2490c2c66affSColin Finck 24912765bddfSThomas Faber if(info == &__badioinfo) { 24922765bddfSThomas Faber *_errno() = EBADF; 24932765bddfSThomas Faber return EOF; 24942765bddfSThomas Faber } 24952765bddfSThomas Faber 2496c2c66affSColin Finck if(mode == _O_BINARY) { 2497bffd8201SThomas Faber info->wxflag &= ~WX_TEXT; 2498bffd8201SThomas Faber info->exflag &= ~(EF_UTF8|EF_UTF16); 2499bffd8201SThomas Faber release_ioinfo(info); 2500c2c66affSColin Finck return ret; 2501c2c66affSColin Finck } 2502c2c66affSColin Finck 2503bffd8201SThomas Faber info->wxflag |= WX_TEXT; 2504c2c66affSColin Finck if(mode == _O_TEXT) 2505bffd8201SThomas Faber info->exflag &= ~(EF_UTF8|EF_UTF16); 2506c2c66affSColin Finck else if(mode == _O_U8TEXT) 2507bffd8201SThomas Faber info->exflag = (info->exflag & ~EF_UTF16) | EF_UTF8; 2508c2c66affSColin Finck else 2509bffd8201SThomas Faber info->exflag = (info->exflag & ~EF_UTF8) | EF_UTF16; 2510c2c66affSColin Finck 2511bffd8201SThomas Faber release_ioinfo(info); 2512c2c66affSColin Finck return ret; 2513c2c66affSColin Finck 2514c2c66affSColin Finck } 2515c2c66affSColin Finck 2516c2c66affSColin Finck /********************************************************************* 2517c2c66affSColin Finck * _tell (MSVCRT.@) 2518c2c66affSColin Finck */ 2519c2c66affSColin Finck long CDECL _tell(int fd) 2520c2c66affSColin Finck { 2521c2c66affSColin Finck return _lseek(fd, 0, SEEK_CUR); 2522c2c66affSColin Finck } 2523c2c66affSColin Finck 2524c2c66affSColin Finck /********************************************************************* 2525c2c66affSColin Finck * _telli64 (MSVCRT.@) 2526c2c66affSColin Finck */ 2527c2c66affSColin Finck __int64 CDECL _telli64(int fd) 2528c2c66affSColin Finck { 2529c2c66affSColin Finck return _lseeki64(fd, 0, SEEK_CUR); 2530c2c66affSColin Finck } 2531c2c66affSColin Finck 2532c2c66affSColin Finck /********************************************************************* 2533c2c66affSColin Finck * _tempnam (MSVCRT.@) 2534c2c66affSColin Finck */ 2535c2c66affSColin Finck char * CDECL _tempnam(const char *dir, const char *prefix) 2536c2c66affSColin Finck { 2537c2c66affSColin Finck char tmpbuf[MAX_PATH]; 2538c2c66affSColin Finck const char *tmp_dir = getenv("TMP"); 2539c2c66affSColin Finck 2540c2c66affSColin Finck if (tmp_dir) dir = tmp_dir; 2541c2c66affSColin Finck 2542c2c66affSColin Finck TRACE("dir (%s) prefix (%s)\n",dir,prefix); 2543c2c66affSColin Finck if (GetTempFileNameA(dir,prefix,0,tmpbuf)) 2544c2c66affSColin Finck { 2545c2c66affSColin Finck TRACE("got name (%s)\n",tmpbuf); 2546c2c66affSColin Finck DeleteFileA(tmpbuf); 2547c2c66affSColin Finck return _strdup(tmpbuf); 2548c2c66affSColin Finck } 2549c2c66affSColin Finck TRACE("failed (%d)\n",GetLastError()); 2550c2c66affSColin Finck return NULL; 2551c2c66affSColin Finck } 2552c2c66affSColin Finck 2553c2c66affSColin Finck /********************************************************************* 2554c2c66affSColin Finck * _wtempnam (MSVCRT.@) 2555c2c66affSColin Finck */ 2556c2c66affSColin Finck wchar_t * CDECL _wtempnam(const wchar_t *dir, const wchar_t *prefix) 2557c2c66affSColin Finck { 2558c2c66affSColin Finck wchar_t tmpbuf[MAX_PATH]; 2559c2c66affSColin Finck 2560c2c66affSColin Finck TRACE("dir (%s) prefix (%s)\n",debugstr_w(dir),debugstr_w(prefix)); 2561c2c66affSColin Finck if (GetTempFileNameW(dir,prefix,0,tmpbuf)) 2562c2c66affSColin Finck { 2563c2c66affSColin Finck TRACE("got name (%s)\n",debugstr_w(tmpbuf)); 2564c2c66affSColin Finck DeleteFileW(tmpbuf); 2565c2c66affSColin Finck return _wcsdup(tmpbuf); 2566c2c66affSColin Finck } 2567c2c66affSColin Finck TRACE("failed (%d)\n",GetLastError()); 2568c2c66affSColin Finck return NULL; 2569c2c66affSColin Finck } 2570c2c66affSColin Finck 2571c2c66affSColin Finck /********************************************************************* 2572c2c66affSColin Finck * _umask (MSVCRT.@) 2573c2c66affSColin Finck */ 2574c2c66affSColin Finck int CDECL _umask(int umask) 2575c2c66affSColin Finck { 2576c2c66affSColin Finck int old_umask = MSVCRT_umask; 2577c2c66affSColin Finck TRACE("(%d)\n",umask); 2578c2c66affSColin Finck MSVCRT_umask = umask; 2579c2c66affSColin Finck return old_umask; 2580c2c66affSColin Finck } 2581c2c66affSColin Finck 2582c2c66affSColin Finck /********************************************************************* 2583c2c66affSColin Finck * _write (MSVCRT.@) 2584c2c66affSColin Finck */ 2585c2c66affSColin Finck int CDECL _write(int fd, const void* buf, unsigned int count) 2586c2c66affSColin Finck { 2587c2c66affSColin Finck DWORD num_written; 2588bffd8201SThomas Faber ioinfo *info = get_ioinfo(fd); 2589c2c66affSColin Finck HANDLE hand = info->handle; 2590c2c66affSColin Finck 2591c2c66affSColin Finck /* Don't trace small writes, it gets *very* annoying */ 2592c2c66affSColin Finck #if 0 2593c2c66affSColin Finck if (count > 32) 2594c2c66affSColin Finck TRACE(":fd (%d) handle (%d) buf (%p) len (%d)\n",fd,hand,buf,count); 2595c2c66affSColin Finck #endif 2596c2c66affSColin Finck if (hand == INVALID_HANDLE_VALUE) 2597c2c66affSColin Finck { 2598c2c66affSColin Finck *_errno() = EBADF; 2599bffd8201SThomas Faber release_ioinfo(info); 2600c2c66affSColin Finck return -1; 2601c2c66affSColin Finck } 2602c2c66affSColin Finck 2603c2c66affSColin Finck if (((info->exflag&EF_UTF8) || (info->exflag&EF_UTF16)) && count&1) 2604c2c66affSColin Finck { 2605c2c66affSColin Finck *_errno() = EINVAL; 2606bffd8201SThomas Faber release_ioinfo(info); 2607c2c66affSColin Finck return -1; 2608c2c66affSColin Finck } 2609c2c66affSColin Finck 2610c2c66affSColin Finck /* If appending, go to EOF */ 2611c2c66affSColin Finck if (info->wxflag & WX_APPEND) 2612c2c66affSColin Finck _lseek(fd, 0, FILE_END); 2613c2c66affSColin Finck 2614c2c66affSColin Finck if (!(info->wxflag & WX_TEXT)) 2615c2c66affSColin Finck { 2616c2c66affSColin Finck if (WriteFile(hand, buf, count, &num_written, NULL) 2617c2c66affSColin Finck && (num_written == count)) 2618bffd8201SThomas Faber { 2619bffd8201SThomas Faber release_ioinfo(info); 2620c2c66affSColin Finck return num_written; 2621bffd8201SThomas Faber } 2622c2c66affSColin Finck TRACE("WriteFile (fd %d, hand %p) failed-last error (%d)\n", fd, 2623c2c66affSColin Finck hand, GetLastError()); 2624c2c66affSColin Finck *_errno() = ENOSPC; 2625c2c66affSColin Finck } 2626c2c66affSColin Finck else 2627c2c66affSColin Finck { 2628c2c66affSColin Finck unsigned int i, j, nr_lf, size; 2629c2c66affSColin Finck char *p = NULL; 2630c2c66affSColin Finck const char *q; 2631c2c66affSColin Finck const char *s = buf, *buf_start = buf; 2632c2c66affSColin Finck 2633c2c66affSColin Finck if (!(info->exflag & (EF_UTF8|EF_UTF16))) 2634c2c66affSColin Finck { 2635c2c66affSColin Finck /* find number of \n */ 2636c2c66affSColin Finck for (nr_lf=0, i=0; i<count; i++) 2637c2c66affSColin Finck if (s[i] == '\n') 2638c2c66affSColin Finck nr_lf++; 2639c2c66affSColin Finck if (nr_lf) 2640c2c66affSColin Finck { 2641c2c66affSColin Finck size = count+nr_lf; 2642c2c66affSColin Finck if ((q = p = malloc(size))) 2643c2c66affSColin Finck { 2644c2c66affSColin Finck for (s = buf, i = 0, j = 0; i < count; i++) 2645c2c66affSColin Finck { 2646c2c66affSColin Finck if (s[i] == '\n') 2647c2c66affSColin Finck p[j++] = '\r'; 2648c2c66affSColin Finck p[j++] = s[i]; 2649c2c66affSColin Finck } 2650c2c66affSColin Finck } 2651c2c66affSColin Finck else 2652c2c66affSColin Finck { 2653c2c66affSColin Finck FIXME("Malloc failed\n"); 2654c2c66affSColin Finck nr_lf = 0; 2655c2c66affSColin Finck size = count; 2656c2c66affSColin Finck q = buf; 2657c2c66affSColin Finck } 2658c2c66affSColin Finck } 2659c2c66affSColin Finck else 2660c2c66affSColin Finck { 2661c2c66affSColin Finck size = count; 2662c2c66affSColin Finck q = buf; 2663c2c66affSColin Finck } 2664c2c66affSColin Finck } 2665c2c66affSColin Finck else if (info->exflag & EF_UTF16) 2666c2c66affSColin Finck { 2667c2c66affSColin Finck for (nr_lf=0, i=0; i<count; i+=2) 2668c2c66affSColin Finck if (s[i]=='\n' && s[i+1]==0) 2669c2c66affSColin Finck nr_lf += 2; 2670c2c66affSColin Finck if (nr_lf) 2671c2c66affSColin Finck { 2672c2c66affSColin Finck size = count+nr_lf; 2673c2c66affSColin Finck if ((q = p = malloc(size))) 2674c2c66affSColin Finck { 2675c2c66affSColin Finck for (s=buf, i=0, j=0; i<count; i++) 2676c2c66affSColin Finck { 2677c2c66affSColin Finck if (s[i]=='\n' && s[i+1]==0) 2678c2c66affSColin Finck { 2679c2c66affSColin Finck p[j++] = '\r'; 2680c2c66affSColin Finck p[j++] = 0; 2681c2c66affSColin Finck } 2682c2c66affSColin Finck p[j++] = s[i++]; 2683c2c66affSColin Finck p[j++] = s[i]; 2684c2c66affSColin Finck } 2685c2c66affSColin Finck } 2686c2c66affSColin Finck else 2687c2c66affSColin Finck { 2688c2c66affSColin Finck FIXME("Malloc failed\n"); 2689c2c66affSColin Finck nr_lf = 0; 2690c2c66affSColin Finck size = count; 2691c2c66affSColin Finck q = buf; 2692c2c66affSColin Finck } 2693c2c66affSColin Finck } 2694c2c66affSColin Finck else 2695c2c66affSColin Finck { 2696c2c66affSColin Finck size = count; 2697c2c66affSColin Finck q = buf; 2698c2c66affSColin Finck } 2699c2c66affSColin Finck } 2700c2c66affSColin Finck else 2701c2c66affSColin Finck { 2702c2c66affSColin Finck DWORD conv_len; 2703c2c66affSColin Finck 2704c2c66affSColin Finck for(nr_lf=0, i=0; i<count; i+=2) 2705c2c66affSColin Finck if (s[i]=='\n' && s[i+1]==0) 2706c2c66affSColin Finck nr_lf++; 2707c2c66affSColin Finck 2708c2c66affSColin Finck conv_len = WideCharToMultiByte(CP_UTF8, 0, (WCHAR*)buf, count/2, NULL, 0, NULL, NULL); 2709c2c66affSColin Finck if(!conv_len) { 2710c2c66affSColin Finck _dosmaperr(GetLastError()); 2711c2c66affSColin Finck free(p); 2712bffd8201SThomas Faber release_ioinfo(info); 2713c2c66affSColin Finck return -1; 2714c2c66affSColin Finck } 2715c2c66affSColin Finck 2716c2c66affSColin Finck size = conv_len+nr_lf; 2717c2c66affSColin Finck if((p = malloc(count+nr_lf*2+size))) 2718c2c66affSColin Finck { 2719c2c66affSColin Finck for (s=buf, i=0, j=0; i<count; i++) 2720c2c66affSColin Finck { 2721c2c66affSColin Finck if (s[i]=='\n' && s[i+1]==0) 2722c2c66affSColin Finck { 2723c2c66affSColin Finck p[j++] = '\r'; 2724c2c66affSColin Finck p[j++] = 0; 2725c2c66affSColin Finck } 2726c2c66affSColin Finck p[j++] = s[i++]; 2727c2c66affSColin Finck p[j++] = s[i]; 2728c2c66affSColin Finck } 2729c2c66affSColin Finck q = p+count+nr_lf*2; 2730c2c66affSColin Finck WideCharToMultiByte(CP_UTF8, 0, (WCHAR*)p, count/2+nr_lf, 2731c2c66affSColin Finck p+count+nr_lf*2, conv_len+nr_lf, NULL, NULL); 2732c2c66affSColin Finck } 2733c2c66affSColin Finck else 2734c2c66affSColin Finck { 2735c2c66affSColin Finck FIXME("Malloc failed\n"); 2736c2c66affSColin Finck nr_lf = 0; 2737c2c66affSColin Finck size = count; 2738c2c66affSColin Finck q = buf; 2739c2c66affSColin Finck } 2740c2c66affSColin Finck } 2741c2c66affSColin Finck 2742c2c66affSColin Finck if (!WriteFile(hand, q, size, &num_written, NULL)) 2743c2c66affSColin Finck num_written = -1; 2744bffd8201SThomas Faber release_ioinfo(info); 2745c2c66affSColin Finck if(p) 2746c2c66affSColin Finck free(p); 2747c2c66affSColin Finck if (num_written != size) 2748c2c66affSColin Finck { 2749c2c66affSColin Finck TRACE("WriteFile (fd %d, hand %p) failed-last error (%d), num_written %d\n", 2750c2c66affSColin Finck fd, hand, GetLastError(), num_written); 2751c2c66affSColin Finck *_errno() = ENOSPC; 2752c2c66affSColin Finck return s - buf_start; 2753c2c66affSColin Finck } 2754c2c66affSColin Finck return count; 2755c2c66affSColin Finck } 2756c2c66affSColin Finck 2757bffd8201SThomas Faber release_ioinfo(info); 2758c2c66affSColin Finck return -1; 2759c2c66affSColin Finck } 2760c2c66affSColin Finck 2761c2c66affSColin Finck /********************************************************************* 2762c2c66affSColin Finck * _putw (MSVCRT.@) 2763c2c66affSColin Finck */ 2764c2c66affSColin Finck int CDECL _putw(int val, FILE* file) 2765c2c66affSColin Finck { 2766c2c66affSColin Finck int len; 2767c2c66affSColin Finck 2768c2c66affSColin Finck _lock_file(file); 2769c2c66affSColin Finck len = _write(file->_file, &val, sizeof(val)); 2770c2c66affSColin Finck if (len == sizeof(val)) { 2771c2c66affSColin Finck _unlock_file(file); 2772c2c66affSColin Finck return val; 2773c2c66affSColin Finck } 2774c2c66affSColin Finck 2775c2c66affSColin Finck file->_flag |= _IOERR; 2776c2c66affSColin Finck _unlock_file(file); 2777c2c66affSColin Finck return EOF; 2778c2c66affSColin Finck } 2779c2c66affSColin Finck 2780c2c66affSColin Finck /********************************************************************* 2781c2c66affSColin Finck * fclose (MSVCRT.@) 2782c2c66affSColin Finck */ 2783c2c66affSColin Finck int CDECL fclose(FILE* file) 2784c2c66affSColin Finck { 2785c2c66affSColin Finck int r, flag; 2786c2c66affSColin Finck 2787c2c66affSColin Finck _lock_file(file); 2788c2c66affSColin Finck flag = file->_flag; 2789c2c66affSColin Finck free(file->_tmpfname); 2790c2c66affSColin Finck file->_tmpfname = NULL; 2791c2c66affSColin Finck /* flush stdio buffers */ 2792c2c66affSColin Finck if(file->_flag & _IOWRT) 2793c2c66affSColin Finck fflush(file); 2794c2c66affSColin Finck if(file->_flag & _IOMYBUF) 2795c2c66affSColin Finck free(file->_base); 2796c2c66affSColin Finck 2797c2c66affSColin Finck r=_close(file->_file); 2798c2c66affSColin Finck 2799c2c66affSColin Finck file->_flag = 0; 2800c2c66affSColin Finck _unlock_file(file); 2801c2c66affSColin Finck if(file<_iob || file>=_iob+_IOB_ENTRIES) 2802c2c66affSColin Finck DeleteCriticalSection(&((file_crit*)file)->crit); 2803c2c66affSColin Finck 2804c2c66affSColin Finck if(file == msvcrt_get_file(MSVCRT_stream_idx-1)) { 2805c2c66affSColin Finck while(MSVCRT_stream_idx>3 && !file->_flag) { 2806c2c66affSColin Finck MSVCRT_stream_idx--; 2807c2c66affSColin Finck file = msvcrt_get_file(MSVCRT_stream_idx-1); 2808c2c66affSColin Finck } 2809c2c66affSColin Finck } 2810c2c66affSColin Finck 2811c2c66affSColin Finck return ((r == -1) || (flag & _IOERR) ? EOF : 0); 2812c2c66affSColin Finck } 2813c2c66affSColin Finck 2814c2c66affSColin Finck /********************************************************************* 2815c2c66affSColin Finck * feof (MSVCRT.@) 2816c2c66affSColin Finck */ 2817c2c66affSColin Finck int CDECL feof(FILE* file) 2818c2c66affSColin Finck { 2819c2c66affSColin Finck return file->_flag & _IOEOF; 2820c2c66affSColin Finck } 2821c2c66affSColin Finck 2822c2c66affSColin Finck /********************************************************************* 2823c2c66affSColin Finck * ferror (MSVCRT.@) 2824c2c66affSColin Finck */ 2825c2c66affSColin Finck int CDECL ferror(FILE* file) 2826c2c66affSColin Finck { 2827c2c66affSColin Finck return file->_flag & _IOERR; 2828c2c66affSColin Finck } 2829c2c66affSColin Finck 2830c2c66affSColin Finck /********************************************************************* 2831c2c66affSColin Finck * _filbuf (MSVCRT.@) 2832c2c66affSColin Finck */ 2833c2c66affSColin Finck int CDECL _filbuf(FILE* file) 2834c2c66affSColin Finck { 2835c2c66affSColin Finck unsigned char c; 2836c2c66affSColin Finck _lock_file(file); 2837c2c66affSColin Finck 2838c2c66affSColin Finck if(file->_flag & _IOSTRG) { 2839c2c66affSColin Finck _unlock_file(file); 2840c2c66affSColin Finck return EOF; 2841c2c66affSColin Finck } 2842c2c66affSColin Finck 2843c2c66affSColin Finck /* Allocate buffer if needed */ 2844c2c66affSColin Finck if(!(file->_flag & (_IONBF | _IOMYBUF | _USERBUF))) 2845c2c66affSColin Finck msvcrt_alloc_buffer(file); 2846c2c66affSColin Finck 2847c2c66affSColin Finck if(!(file->_flag & _IOREAD)) { 2848c2c66affSColin Finck if(file->_flag & _IORW) 2849c2c66affSColin Finck file->_flag |= _IOREAD; 2850c2c66affSColin Finck else { 2851c2c66affSColin Finck _unlock_file(file); 2852c2c66affSColin Finck return EOF; 2853c2c66affSColin Finck } 2854c2c66affSColin Finck } 2855c2c66affSColin Finck 2856c2c66affSColin Finck if(!(file->_flag & (_IOMYBUF | _USERBUF))) { 2857c2c66affSColin Finck int r; 2858bffd8201SThomas Faber if ((r = _read(file->_file,&c,1)) != 1) { 2859c2c66affSColin Finck file->_flag |= (r == 0) ? _IOEOF : _IOERR; 2860c2c66affSColin Finck _unlock_file(file); 2861c2c66affSColin Finck return EOF; 2862c2c66affSColin Finck } 2863c2c66affSColin Finck 2864c2c66affSColin Finck _unlock_file(file); 2865c2c66affSColin Finck return c; 2866c2c66affSColin Finck } else { 2867bffd8201SThomas Faber file->_cnt = _read(file->_file, file->_base, file->_bufsiz); 2868c2c66affSColin Finck if(file->_cnt<=0) { 2869c2c66affSColin Finck file->_flag |= (file->_cnt == 0) ? _IOEOF : _IOERR; 2870c2c66affSColin Finck file->_cnt = 0; 2871c2c66affSColin Finck _unlock_file(file); 2872c2c66affSColin Finck return EOF; 2873c2c66affSColin Finck } 2874c2c66affSColin Finck 2875c2c66affSColin Finck file->_cnt--; 2876c2c66affSColin Finck file->_ptr = file->_base+1; 2877c2c66affSColin Finck c = *(unsigned char *)file->_base; 2878c2c66affSColin Finck _unlock_file(file); 2879c2c66affSColin Finck return c; 2880c2c66affSColin Finck } 2881c2c66affSColin Finck } 2882c2c66affSColin Finck 2883c2c66affSColin Finck /********************************************************************* 2884c2c66affSColin Finck * fgetc (MSVCRT.@) 2885c2c66affSColin Finck */ 2886c2c66affSColin Finck int CDECL fgetc(FILE* file) 2887c2c66affSColin Finck { 2888c2c66affSColin Finck unsigned char *i; 2889c2c66affSColin Finck unsigned int j; 2890c2c66affSColin Finck 2891c2c66affSColin Finck _lock_file(file); 2892c2c66affSColin Finck if (file->_cnt>0) { 2893c2c66affSColin Finck file->_cnt--; 2894c2c66affSColin Finck i = (unsigned char *)file->_ptr++; 2895c2c66affSColin Finck j = *i; 2896c2c66affSColin Finck } else 2897c2c66affSColin Finck j = _filbuf(file); 2898c2c66affSColin Finck 2899c2c66affSColin Finck _unlock_file(file); 2900c2c66affSColin Finck return j; 2901c2c66affSColin Finck } 2902c2c66affSColin Finck 2903c2c66affSColin Finck /********************************************************************* 2904c2c66affSColin Finck * _fgetchar (MSVCRT.@) 2905c2c66affSColin Finck */ 2906c2c66affSColin Finck int CDECL _fgetchar(void) 2907c2c66affSColin Finck { 2908c2c66affSColin Finck return fgetc(stdin); 2909c2c66affSColin Finck } 2910c2c66affSColin Finck 2911c2c66affSColin Finck /********************************************************************* 2912c2c66affSColin Finck * fgets (MSVCRT.@) 2913c2c66affSColin Finck */ 2914c2c66affSColin Finck char * CDECL fgets(char *s, int size, FILE* file) 2915c2c66affSColin Finck { 2916c2c66affSColin Finck int cc = EOF; 2917c2c66affSColin Finck char * buf_start = s; 2918c2c66affSColin Finck 2919c2c66affSColin Finck TRACE(":file(%p) fd (%d) str (%p) len (%d)\n", 2920c2c66affSColin Finck file,file->_file,s,size); 2921c2c66affSColin Finck 2922c2c66affSColin Finck _lock_file(file); 2923c2c66affSColin Finck 2924c2c66affSColin Finck while ((size >1) && (cc = fgetc(file)) != EOF && cc != '\n') 2925c2c66affSColin Finck { 2926c2c66affSColin Finck *s++ = (char)cc; 2927c2c66affSColin Finck size --; 2928c2c66affSColin Finck } 2929c2c66affSColin Finck if ((cc == EOF) && (s == buf_start)) /* If nothing read, return 0*/ 2930c2c66affSColin Finck { 2931c2c66affSColin Finck TRACE(":nothing read\n"); 2932c2c66affSColin Finck _unlock_file(file); 2933c2c66affSColin Finck return NULL; 2934c2c66affSColin Finck } 2935c2c66affSColin Finck if ((cc != EOF) && (size > 1)) 2936c2c66affSColin Finck *s++ = cc; 2937c2c66affSColin Finck *s = '\0'; 2938c2c66affSColin Finck TRACE(":got %s\n", debugstr_a(buf_start)); 2939c2c66affSColin Finck _unlock_file(file); 2940c2c66affSColin Finck return buf_start; 2941c2c66affSColin Finck } 2942c2c66affSColin Finck 2943c2c66affSColin Finck /********************************************************************* 2944c2c66affSColin Finck * fgetwc (MSVCRT.@) 2945c2c66affSColin Finck */ 2946c2c66affSColin Finck wint_t CDECL fgetwc(FILE* file) 2947c2c66affSColin Finck { 2948c2c66affSColin Finck wint_t ret; 2949c2c66affSColin Finck int ch; 2950c2c66affSColin Finck 2951c2c66affSColin Finck _lock_file(file); 2952c2c66affSColin Finck 295325064fdfSThomas Faber if((get_ioinfo_nolock(file->_file)->exflag & (EF_UTF8 | EF_UTF16)) 295425064fdfSThomas Faber || !(get_ioinfo_nolock(file->_file)->wxflag & WX_TEXT)) { 2955c2c66affSColin Finck char *p; 2956c2c66affSColin Finck 2957c2c66affSColin Finck for(p=(char*)&ret; (wint_t*)p<&ret+1; p++) { 2958c2c66affSColin Finck ch = fgetc(file); 2959c2c66affSColin Finck if(ch == EOF) { 2960c2c66affSColin Finck ret = WEOF; 2961c2c66affSColin Finck break; 2962c2c66affSColin Finck } 2963c2c66affSColin Finck *p = (char)ch; 2964c2c66affSColin Finck } 2965c2c66affSColin Finck }else { 2966c2c66affSColin Finck char mbs[MB_LEN_MAX]; 2967c2c66affSColin Finck int len = 0; 2968c2c66affSColin Finck 2969c2c66affSColin Finck ch = fgetc(file); 2970c2c66affSColin Finck if(ch != EOF) { 2971c2c66affSColin Finck mbs[0] = (char)ch; 2972c2c66affSColin Finck if(isleadbyte((unsigned char)mbs[0])) { 2973c2c66affSColin Finck ch = fgetc(file); 2974c2c66affSColin Finck if(ch != EOF) { 2975c2c66affSColin Finck mbs[1] = (char)ch; 2976c2c66affSColin Finck len = 2; 2977c2c66affSColin Finck } 2978c2c66affSColin Finck }else { 2979c2c66affSColin Finck len = 1; 2980c2c66affSColin Finck } 2981c2c66affSColin Finck } 2982c2c66affSColin Finck 2983c2c66affSColin Finck if(!len || mbtowc(&ret, mbs, len)==-1) 2984c2c66affSColin Finck ret = WEOF; 2985c2c66affSColin Finck } 2986c2c66affSColin Finck 2987c2c66affSColin Finck _unlock_file(file); 2988c2c66affSColin Finck return ret; 2989c2c66affSColin Finck } 2990c2c66affSColin Finck 2991c2c66affSColin Finck /********************************************************************* 2992c2c66affSColin Finck * _getw (MSVCRT.@) 2993c2c66affSColin Finck */ 2994c2c66affSColin Finck int CDECL _getw(FILE* file) 2995c2c66affSColin Finck { 2996c2c66affSColin Finck char *ch; 2997c2c66affSColin Finck int i, k; 2998c2c66affSColin Finck unsigned int j; 2999c2c66affSColin Finck ch = (char *)&i; 3000c2c66affSColin Finck 3001c2c66affSColin Finck _lock_file(file); 3002c2c66affSColin Finck for (j=0; j<sizeof(int); j++) { 3003c2c66affSColin Finck k = fgetc(file); 3004c2c66affSColin Finck if (k == EOF) { 3005c2c66affSColin Finck file->_flag |= _IOEOF; 3006c2c66affSColin Finck _unlock_file(file); 3007c2c66affSColin Finck return EOF; 3008c2c66affSColin Finck } 3009c2c66affSColin Finck ch[j] = k; 3010c2c66affSColin Finck } 3011c2c66affSColin Finck 3012c2c66affSColin Finck _unlock_file(file); 3013c2c66affSColin Finck return i; 3014c2c66affSColin Finck } 3015c2c66affSColin Finck 3016c2c66affSColin Finck /********************************************************************* 3017c2c66affSColin Finck * getwc (MSVCRT.@) 3018c2c66affSColin Finck */ 3019c2c66affSColin Finck wint_t CDECL getwc(FILE* file) 3020c2c66affSColin Finck { 3021c2c66affSColin Finck return fgetwc(file); 3022c2c66affSColin Finck } 3023c2c66affSColin Finck 3024c2c66affSColin Finck /********************************************************************* 3025c2c66affSColin Finck * _fgetwchar (MSVCRT.@) 3026c2c66affSColin Finck */ 3027c2c66affSColin Finck wint_t CDECL _fgetwchar(void) 3028c2c66affSColin Finck { 3029c2c66affSColin Finck return fgetwc(stdin); 3030c2c66affSColin Finck } 3031c2c66affSColin Finck 3032c2c66affSColin Finck /********************************************************************* 3033c2c66affSColin Finck * getwchar (MSVCRT.@) 3034c2c66affSColin Finck */ 3035c2c66affSColin Finck wint_t CDECL getwchar(void) 3036c2c66affSColin Finck { 3037c2c66affSColin Finck return _fgetwchar(); 3038c2c66affSColin Finck } 3039c2c66affSColin Finck 3040c2c66affSColin Finck /********************************************************************* 3041c2c66affSColin Finck * fgetws (MSVCRT.@) 3042c2c66affSColin Finck */ 3043c2c66affSColin Finck wchar_t * CDECL fgetws(wchar_t *s, int size, FILE* file) 3044c2c66affSColin Finck { 3045c2c66affSColin Finck int cc = WEOF; 3046c2c66affSColin Finck wchar_t * buf_start = s; 3047c2c66affSColin Finck 3048c2c66affSColin Finck TRACE(":file(%p) fd (%d) str (%p) len (%d)\n", 3049c2c66affSColin Finck file,file->_file,s,size); 3050c2c66affSColin Finck 3051c2c66affSColin Finck _lock_file(file); 3052c2c66affSColin Finck 3053c2c66affSColin Finck while ((size >1) && (cc = fgetwc(file)) != WEOF && cc != '\n') 3054c2c66affSColin Finck { 3055c2c66affSColin Finck *s++ = (char)cc; 3056c2c66affSColin Finck size --; 3057c2c66affSColin Finck } 3058c2c66affSColin Finck if ((cc == WEOF) && (s == buf_start)) /* If nothing read, return 0*/ 3059c2c66affSColin Finck { 3060c2c66affSColin Finck TRACE(":nothing read\n"); 3061c2c66affSColin Finck _unlock_file(file); 3062c2c66affSColin Finck return NULL; 3063c2c66affSColin Finck } 3064c2c66affSColin Finck if ((cc != WEOF) && (size > 1)) 3065c2c66affSColin Finck *s++ = cc; 3066c2c66affSColin Finck *s = 0; 3067c2c66affSColin Finck TRACE(":got %s\n", debugstr_w(buf_start)); 3068c2c66affSColin Finck _unlock_file(file); 3069c2c66affSColin Finck return buf_start; 3070c2c66affSColin Finck } 3071c2c66affSColin Finck 3072c2c66affSColin Finck /********************************************************************* 3073c2c66affSColin Finck * fwrite (MSVCRT.@) 3074c2c66affSColin Finck */ 3075c2c66affSColin Finck size_t CDECL fwrite(const void *ptr, size_t size, size_t nmemb, FILE* file) 3076c2c66affSColin Finck { 3077c2c66affSColin Finck size_t wrcnt=size * nmemb; 3078c2c66affSColin Finck int written = 0; 3079c2c66affSColin Finck if (size == 0) 3080c2c66affSColin Finck return 0; 3081c2c66affSColin Finck 3082c2c66affSColin Finck _lock_file(file); 3083c2c66affSColin Finck 3084c2c66affSColin Finck while(wrcnt) { 3085c2c66affSColin Finck #ifndef __REACTOS__ 3086c2c66affSColin Finck if(file->_cnt < 0) { 3087c2c66affSColin Finck WARN("negative file->_cnt value in %p\n", file); 3088c2c66affSColin Finck file->_flag |= MSVCRT__IOERR; 3089c2c66affSColin Finck break; 3090c2c66affSColin Finck } else 3091c2c66affSColin Finck #endif 3092c2c66affSColin Finck if(file->_cnt) { 3093c2c66affSColin Finck int pcnt=(file->_cnt>wrcnt)? wrcnt: file->_cnt; 3094c2c66affSColin Finck memcpy(file->_ptr, ptr, pcnt); 3095c2c66affSColin Finck file->_cnt -= pcnt; 3096c2c66affSColin Finck file->_ptr += pcnt; 3097c2c66affSColin Finck written += pcnt; 3098c2c66affSColin Finck wrcnt -= pcnt; 3099c2c66affSColin Finck ptr = (const char*)ptr + pcnt; 3100c2c66affSColin Finck } else if((file->_flag & _IONBF) 3101c2c66affSColin Finck || ((file->_flag & (_IOMYBUF | _USERBUF)) && wrcnt >= file->_bufsiz) 3102c2c66affSColin Finck || (!(file->_flag & (_IOMYBUF | _USERBUF)) && wrcnt >= MSVCRT_INTERNAL_BUFSIZ)) { 3103c2c66affSColin Finck size_t pcnt; 3104c2c66affSColin Finck int bufsiz; 3105c2c66affSColin Finck 3106c2c66affSColin Finck if(file->_flag & _IONBF) 3107c2c66affSColin Finck bufsiz = 1; 3108c2c66affSColin Finck else if(!(file->_flag & (_IOMYBUF | _USERBUF))) 3109c2c66affSColin Finck bufsiz = MSVCRT_INTERNAL_BUFSIZ; 3110c2c66affSColin Finck else 3111c2c66affSColin Finck bufsiz = file->_bufsiz; 3112c2c66affSColin Finck 3113c2c66affSColin Finck pcnt = (wrcnt / bufsiz) * bufsiz; 3114c2c66affSColin Finck 3115c2c66affSColin Finck if(msvcrt_flush_buffer(file) == EOF) 3116c2c66affSColin Finck break; 3117c2c66affSColin Finck 3118c2c66affSColin Finck if(_write(file->_file, ptr, pcnt) <= 0) { 3119c2c66affSColin Finck file->_flag |= _IOERR; 3120c2c66affSColin Finck break; 3121c2c66affSColin Finck } 3122c2c66affSColin Finck written += pcnt; 3123c2c66affSColin Finck wrcnt -= pcnt; 3124c2c66affSColin Finck ptr = (const char*)ptr + pcnt; 3125c2c66affSColin Finck } else { 3126c2c66affSColin Finck if(_flsbuf(*(const char*)ptr, file) == EOF) 3127c2c66affSColin Finck break; 3128c2c66affSColin Finck written++; 3129c2c66affSColin Finck wrcnt--; 3130c2c66affSColin Finck ptr = (const char*)ptr + 1; 3131c2c66affSColin Finck } 3132c2c66affSColin Finck } 3133c2c66affSColin Finck 3134c2c66affSColin Finck _unlock_file(file); 3135c2c66affSColin Finck return written / size; 3136c2c66affSColin Finck } 3137c2c66affSColin Finck 3138c2c66affSColin Finck /********************************************************************* 3139c2c66affSColin Finck * fputwc (MSVCRT.@) 3140c2c66affSColin Finck * FORKED for ReactOS, don't sync with Wine! 3141c2c66affSColin Finck * References: 3142c2c66affSColin Finck * - http://jira.reactos.org/browse/CORE-6495 3143c2c66affSColin Finck * - http://bugs.winehq.org/show_bug.cgi?id=8598 3144c2c66affSColin Finck */ 3145c2c66affSColin Finck wint_t CDECL fputwc(wchar_t c, FILE* stream) 3146c2c66affSColin Finck { 3147c2c66affSColin Finck /* If this is a real file stream (and not some temporary one for 3148c2c66affSColin Finck sprintf-like functions), check whether it is opened in text mode. 3149c2c66affSColin Finck In this case, we have to perform an implicit conversion to ANSI. */ 315025064fdfSThomas Faber if (!(stream->_flag & _IOSTRG) && get_ioinfo_nolock(stream->_file)->wxflag & WX_TEXT) 3151c2c66affSColin Finck { 3152c2c66affSColin Finck /* Convert to multibyte in text mode */ 3153c2c66affSColin Finck char mbc[MB_LEN_MAX]; 3154c2c66affSColin Finck int mb_return; 3155c2c66affSColin Finck 3156c2c66affSColin Finck mb_return = wctomb(mbc, c); 3157c2c66affSColin Finck 3158c2c66affSColin Finck if(mb_return == -1) 3159c2c66affSColin Finck return WEOF; 3160c2c66affSColin Finck 3161c2c66affSColin Finck /* Output all characters */ 3162c2c66affSColin Finck if (fwrite(mbc, mb_return, 1, stream) != 1) 3163c2c66affSColin Finck return WEOF; 3164c2c66affSColin Finck } 3165c2c66affSColin Finck else 3166c2c66affSColin Finck { 3167c2c66affSColin Finck if (fwrite(&c, sizeof(c), 1, stream) != 1) 3168c2c66affSColin Finck return WEOF; 3169c2c66affSColin Finck } 3170c2c66affSColin Finck 3171c2c66affSColin Finck return c; 3172c2c66affSColin Finck } 3173c2c66affSColin Finck 3174c2c66affSColin Finck /********************************************************************* 3175c2c66affSColin Finck * _fputwchar (MSVCRT.@) 3176c2c66affSColin Finck */ 3177c2c66affSColin Finck wint_t CDECL _fputwchar(wint_t wc) 3178c2c66affSColin Finck { 3179c2c66affSColin Finck return fputwc(wc, stdout); 3180c2c66affSColin Finck } 3181c2c66affSColin Finck 3182c2c66affSColin Finck /********************************************************************* 3183c2c66affSColin Finck * _wfsopen (MSVCRT.@) 3184c2c66affSColin Finck */ 3185c2c66affSColin Finck FILE * CDECL _wfsopen(const wchar_t *path, const wchar_t *mode, int share) 3186c2c66affSColin Finck { 3187c2c66affSColin Finck FILE* file; 3188c2c66affSColin Finck int open_flags, stream_flags, fd; 3189c2c66affSColin Finck 3190c2c66affSColin Finck TRACE("(%s,%s)\n", debugstr_w(path), debugstr_w(mode)); 3191c2c66affSColin Finck 3192c2c66affSColin Finck /* map mode string to open() flags. "man fopen" for possibilities. */ 3193c2c66affSColin Finck if (msvcrt_get_flags(mode, &open_flags, &stream_flags) == -1) 3194c2c66affSColin Finck return NULL; 3195c2c66affSColin Finck 3196c2c66affSColin Finck LOCK_FILES(); 3197c2c66affSColin Finck fd = _wsopen(path, open_flags, share, _S_IREAD | _S_IWRITE); 3198c2c66affSColin Finck if (fd < 0) 3199c2c66affSColin Finck file = NULL; 3200c2c66affSColin Finck else if ((file = msvcrt_alloc_fp()) && msvcrt_init_fp(file, fd, stream_flags) 3201c2c66affSColin Finck != -1) 3202c2c66affSColin Finck TRACE(":fd (%d) mode (%s) FILE* (%p)\n", fd, debugstr_w(mode), file); 3203c2c66affSColin Finck else if (file) 3204c2c66affSColin Finck { 3205c2c66affSColin Finck file->_flag = 0; 3206c2c66affSColin Finck file = NULL; 3207c2c66affSColin Finck } 3208c2c66affSColin Finck 3209c2c66affSColin Finck TRACE(":got (%p)\n",file); 3210c2c66affSColin Finck if (fd >= 0 && !file) 3211c2c66affSColin Finck _close(fd); 3212c2c66affSColin Finck UNLOCK_FILES(); 3213c2c66affSColin Finck return file; 3214c2c66affSColin Finck } 3215c2c66affSColin Finck 3216c2c66affSColin Finck /********************************************************************* 3217c2c66affSColin Finck * _fsopen (MSVCRT.@) 3218c2c66affSColin Finck */ 3219c2c66affSColin Finck FILE * CDECL _fsopen(const char *path, const char *mode, int share) 3220c2c66affSColin Finck { 3221c2c66affSColin Finck FILE *ret; 3222c2c66affSColin Finck wchar_t *pathW = NULL, *modeW = NULL; 3223c2c66affSColin Finck 3224c2c66affSColin Finck if (path && !(pathW = msvcrt_wstrdupa(path))) { 3225c2c66affSColin Finck _invalid_parameter(NULL, NULL, NULL, 0, 0); 3226c2c66affSColin Finck *_errno() = EINVAL; 3227c2c66affSColin Finck return NULL; 3228c2c66affSColin Finck } 3229c2c66affSColin Finck if (mode && !(modeW = msvcrt_wstrdupa(mode))) 3230c2c66affSColin Finck { 3231c2c66affSColin Finck free(pathW); 3232c2c66affSColin Finck _invalid_parameter(NULL, NULL, NULL, 0, 0); 3233c2c66affSColin Finck *_errno() = EINVAL; 3234c2c66affSColin Finck return NULL; 3235c2c66affSColin Finck } 3236c2c66affSColin Finck 3237c2c66affSColin Finck ret = _wfsopen(pathW, modeW, share); 3238c2c66affSColin Finck 3239c2c66affSColin Finck free(pathW); 3240c2c66affSColin Finck free(modeW); 3241c2c66affSColin Finck return ret; 3242c2c66affSColin Finck } 3243c2c66affSColin Finck 3244c2c66affSColin Finck /********************************************************************* 3245c2c66affSColin Finck * fopen (MSVCRT.@) 3246c2c66affSColin Finck */ 3247c2c66affSColin Finck FILE * CDECL fopen(const char *path, const char *mode) 3248c2c66affSColin Finck { 3249c2c66affSColin Finck return _fsopen( path, mode, _SH_DENYNO ); 3250c2c66affSColin Finck } 3251c2c66affSColin Finck 3252c2c66affSColin Finck /********************************************************************* 3253c2c66affSColin Finck * fopen_s (MSVCRT.@) 3254c2c66affSColin Finck */ 3255c2c66affSColin Finck int CDECL fopen_s(FILE** pFile, 3256c2c66affSColin Finck const char *filename, const char *mode) 3257c2c66affSColin Finck { 3258c2c66affSColin Finck if (!MSVCRT_CHECK_PMT(pFile != NULL)) return EINVAL; 3259c2c66affSColin Finck if (!MSVCRT_CHECK_PMT(filename != NULL)) return EINVAL; 3260c2c66affSColin Finck if (!MSVCRT_CHECK_PMT(mode != NULL)) return EINVAL; 3261c2c66affSColin Finck 3262c2c66affSColin Finck *pFile = fopen(filename, mode); 3263c2c66affSColin Finck 3264c2c66affSColin Finck if(!*pFile) 3265c2c66affSColin Finck return *_errno(); 3266c2c66affSColin Finck return 0; 3267c2c66affSColin Finck } 3268c2c66affSColin Finck 3269c2c66affSColin Finck /********************************************************************* 3270c2c66affSColin Finck * _wfopen (MSVCRT.@) 3271c2c66affSColin Finck */ 3272c2c66affSColin Finck FILE * CDECL _wfopen(const wchar_t *path, const wchar_t *mode) 3273c2c66affSColin Finck { 3274c2c66affSColin Finck return _wfsopen( path, mode, _SH_DENYNO ); 3275c2c66affSColin Finck } 3276c2c66affSColin Finck 3277c2c66affSColin Finck /********************************************************************* 3278c2c66affSColin Finck * _wfopen_s (MSVCRT.@) 3279c2c66affSColin Finck */ 3280c2c66affSColin Finck int CDECL _wfopen_s(FILE** pFile, const wchar_t *filename, 3281c2c66affSColin Finck const wchar_t *mode) 3282c2c66affSColin Finck { 3283c2c66affSColin Finck if (!MSVCRT_CHECK_PMT(pFile != NULL) || !MSVCRT_CHECK_PMT(filename != NULL) || 3284c2c66affSColin Finck !MSVCRT_CHECK_PMT(mode != NULL)) { 3285c2c66affSColin Finck *_errno() = EINVAL; 3286c2c66affSColin Finck return EINVAL; 3287c2c66affSColin Finck } 3288c2c66affSColin Finck 3289c2c66affSColin Finck *pFile = _wfopen(filename, mode); 3290c2c66affSColin Finck 3291c2c66affSColin Finck if(!*pFile) 3292c2c66affSColin Finck return *_errno(); 3293c2c66affSColin Finck return 0; 3294c2c66affSColin Finck } 3295c2c66affSColin Finck 3296c2c66affSColin Finck /* fputc calls _flsbuf which calls fputc */ 3297c2c66affSColin Finck int CDECL _flsbuf(int c, FILE* file); 3298c2c66affSColin Finck 3299c2c66affSColin Finck /********************************************************************* 3300c2c66affSColin Finck * fputc (MSVCRT.@) 3301c2c66affSColin Finck */ 3302c2c66affSColin Finck int CDECL fputc(int c, FILE* file) 3303c2c66affSColin Finck { 3304c2c66affSColin Finck int res; 3305c2c66affSColin Finck 3306c2c66affSColin Finck _lock_file(file); 3307c2c66affSColin Finck if(file->_cnt>0) { 3308c2c66affSColin Finck *file->_ptr++=c; 3309c2c66affSColin Finck file->_cnt--; 3310c2c66affSColin Finck if (c == '\n') 3311c2c66affSColin Finck { 3312c2c66affSColin Finck res = msvcrt_flush_buffer(file); 3313c2c66affSColin Finck _unlock_file(file); 3314c2c66affSColin Finck return res ? res : c; 3315c2c66affSColin Finck } 3316c2c66affSColin Finck else { 3317c2c66affSColin Finck _unlock_file(file); 3318c2c66affSColin Finck return c & 0xff; 3319c2c66affSColin Finck } 3320c2c66affSColin Finck } else { 3321c2c66affSColin Finck res = _flsbuf(c, file); 3322c2c66affSColin Finck _unlock_file(file); 3323c2c66affSColin Finck return res; 3324c2c66affSColin Finck } 3325c2c66affSColin Finck } 3326c2c66affSColin Finck 3327c2c66affSColin Finck /********************************************************************* 3328c2c66affSColin Finck * _fputchar (MSVCRT.@) 3329c2c66affSColin Finck */ 3330c2c66affSColin Finck int CDECL _fputchar(int c) 3331c2c66affSColin Finck { 3332c2c66affSColin Finck return fputc(c, stdout); 3333c2c66affSColin Finck } 3334c2c66affSColin Finck 3335c2c66affSColin Finck /********************************************************************* 3336c2c66affSColin Finck * fread (MSVCRT.@) 3337c2c66affSColin Finck */ 3338c2c66affSColin Finck size_t CDECL fread(void *ptr, size_t size, size_t nmemb, FILE* file) 3339c2c66affSColin Finck { 3340c2c66affSColin Finck size_t rcnt=size * nmemb; 3341c2c66affSColin Finck size_t read=0; 3342c2c66affSColin Finck size_t pread=0; 3343c2c66affSColin Finck 3344c2c66affSColin Finck if(!rcnt) 3345c2c66affSColin Finck return 0; 3346c2c66affSColin Finck 3347c2c66affSColin Finck _lock_file(file); 3348c2c66affSColin Finck 3349c2c66affSColin Finck /* first buffered data */ 3350c2c66affSColin Finck if(file->_cnt>0) { 3351c2c66affSColin Finck int pcnt= (rcnt>file->_cnt)? file->_cnt:rcnt; 3352c2c66affSColin Finck memcpy(ptr, file->_ptr, pcnt); 3353c2c66affSColin Finck file->_cnt -= pcnt; 3354c2c66affSColin Finck file->_ptr += pcnt; 3355c2c66affSColin Finck read += pcnt ; 3356c2c66affSColin Finck rcnt -= pcnt ; 3357c2c66affSColin Finck ptr = (char*)ptr + pcnt; 3358c2c66affSColin Finck } else if(!(file->_flag & _IOREAD )) { 3359c2c66affSColin Finck if(file->_flag & _IORW) { 3360c2c66affSColin Finck file->_flag |= _IOREAD; 3361c2c66affSColin Finck } else { 3362c2c66affSColin Finck _unlock_file(file); 3363c2c66affSColin Finck return 0; 3364c2c66affSColin Finck } 3365c2c66affSColin Finck } 3366c2c66affSColin Finck 3367c2c66affSColin Finck if(rcnt>0 && !(file->_flag & (_IONBF | _IOMYBUF | _USERBUF))) 3368c2c66affSColin Finck msvcrt_alloc_buffer(file); 3369c2c66affSColin Finck 3370c2c66affSColin Finck while(rcnt>0) 3371c2c66affSColin Finck { 3372c2c66affSColin Finck int i; 3373c2c66affSColin Finck if (!file->_cnt && rcnt<BUFSIZ && (file->_flag & (_IOMYBUF | _USERBUF))) { 3374c2c66affSColin Finck file->_cnt = _read(file->_file, file->_base, file->_bufsiz); 3375c2c66affSColin Finck file->_ptr = file->_base; 3376c2c66affSColin Finck i = (file->_cnt<rcnt) ? file->_cnt : rcnt; 3377c2c66affSColin Finck /* If the buffer fill reaches eof but fread wouldn't, clear eof. */ 3378c2c66affSColin Finck if (i > 0 && i < file->_cnt) { 337925064fdfSThomas Faber get_ioinfo_nolock(file->_file)->wxflag &= ~WX_ATEOF; 3380c2c66affSColin Finck file->_flag &= ~_IOEOF; 3381c2c66affSColin Finck } 3382c2c66affSColin Finck if (i > 0) { 3383c2c66affSColin Finck memcpy(ptr, file->_ptr, i); 3384c2c66affSColin Finck file->_cnt -= i; 3385c2c66affSColin Finck file->_ptr += i; 3386c2c66affSColin Finck } 3387c2c66affSColin Finck } else if (rcnt > INT_MAX) { 3388c2c66affSColin Finck i = _read(file->_file, ptr, INT_MAX); 3389c2c66affSColin Finck } else if (rcnt < BUFSIZ) { 3390c2c66affSColin Finck i = _read(file->_file, ptr, rcnt); 3391c2c66affSColin Finck } else { 3392c2c66affSColin Finck i = _read(file->_file, ptr, rcnt - BUFSIZ/2); 3393c2c66affSColin Finck } 3394c2c66affSColin Finck pread += i; 3395c2c66affSColin Finck rcnt -= i; 3396c2c66affSColin Finck ptr = (char *)ptr+i; 3397c2c66affSColin Finck /* expose feof condition in the flags 3398c2c66affSColin Finck * MFC tests file->_flag for feof, and doesn't call feof()) 3399c2c66affSColin Finck */ 340025064fdfSThomas Faber if (get_ioinfo_nolock(file->_file)->wxflag & WX_ATEOF) 3401c2c66affSColin Finck file->_flag |= _IOEOF; 3402c2c66affSColin Finck else if (i == -1) 3403c2c66affSColin Finck { 3404c2c66affSColin Finck file->_flag |= _IOERR; 3405c2c66affSColin Finck pread = 0; 3406c2c66affSColin Finck rcnt = 0; 3407c2c66affSColin Finck } 3408c2c66affSColin Finck if (i < 1) break; 3409c2c66affSColin Finck } 3410c2c66affSColin Finck read+=pread; 3411c2c66affSColin Finck _unlock_file(file); 3412c2c66affSColin Finck return read / size; 3413c2c66affSColin Finck } 3414c2c66affSColin Finck 3415c2c66affSColin Finck /********************************************************************* 3416c2c66affSColin Finck * _wfreopen (MSVCRT.@) 3417c2c66affSColin Finck * 3418c2c66affSColin Finck */ 3419c2c66affSColin Finck FILE* CDECL _wfreopen(const wchar_t *path, const wchar_t *mode, FILE* file) 3420c2c66affSColin Finck { 3421c2c66affSColin Finck int open_flags, stream_flags, fd; 3422c2c66affSColin Finck 3423c2c66affSColin Finck TRACE(":path (%p) mode (%s) file (%p) fd (%d)\n", debugstr_w(path), debugstr_w(mode), file, file ? file->_file : -1); 3424c2c66affSColin Finck 3425c2c66affSColin Finck LOCK_FILES(); 34266aa8e3ccSThomas Faber if (!file || ((fd = file->_file) < 0)) 3427c2c66affSColin Finck file = NULL; 3428c2c66affSColin Finck else 3429c2c66affSColin Finck { 3430c2c66affSColin Finck fclose(file); 3431c2c66affSColin Finck /* map mode string to open() flags. "man fopen" for possibilities. */ 3432c2c66affSColin Finck if (msvcrt_get_flags(mode, &open_flags, &stream_flags) == -1) 3433c2c66affSColin Finck file = NULL; 3434c2c66affSColin Finck else 3435c2c66affSColin Finck { 3436c2c66affSColin Finck fd = _wopen(path, open_flags, _S_IREAD | _S_IWRITE); 3437c2c66affSColin Finck if (fd < 0) 3438c2c66affSColin Finck file = NULL; 3439c2c66affSColin Finck else if (msvcrt_init_fp(file, fd, stream_flags) == -1) 3440c2c66affSColin Finck { 3441c2c66affSColin Finck file->_flag = 0; 3442c2c66affSColin Finck WARN(":failed-last error (%d)\n",GetLastError()); 3443c2c66affSColin Finck _dosmaperr(GetLastError()); 3444c2c66affSColin Finck file = NULL; 3445c2c66affSColin Finck } 3446c2c66affSColin Finck } 3447c2c66affSColin Finck } 3448c2c66affSColin Finck UNLOCK_FILES(); 3449c2c66affSColin Finck return file; 3450c2c66affSColin Finck } 3451c2c66affSColin Finck 3452c2c66affSColin Finck /********************************************************************* 3453c2c66affSColin Finck * freopen (MSVCRT.@) 3454c2c66affSColin Finck * 3455c2c66affSColin Finck */ 3456c2c66affSColin Finck FILE* CDECL freopen(const char *path, const char *mode, FILE* file) 3457c2c66affSColin Finck { 3458c2c66affSColin Finck FILE *ret; 3459c2c66affSColin Finck wchar_t *pathW = NULL, *modeW = NULL; 3460c2c66affSColin Finck 3461c2c66affSColin Finck if (path && !(pathW = msvcrt_wstrdupa(path))) return NULL; 3462c2c66affSColin Finck if (mode && !(modeW = msvcrt_wstrdupa(mode))) 3463c2c66affSColin Finck { 3464c2c66affSColin Finck free(pathW); 3465c2c66affSColin Finck return NULL; 3466c2c66affSColin Finck } 3467c2c66affSColin Finck 3468c2c66affSColin Finck ret = _wfreopen(pathW, modeW, file); 3469c2c66affSColin Finck 3470c2c66affSColin Finck free(pathW); 3471c2c66affSColin Finck free(modeW); 3472c2c66affSColin Finck return ret; 3473c2c66affSColin Finck } 3474c2c66affSColin Finck 3475c2c66affSColin Finck /********************************************************************* 3476c2c66affSColin Finck * fsetpos (MSVCRT.@) 3477c2c66affSColin Finck */ 3478c2c66affSColin Finck int CDECL fsetpos(FILE* file, const fpos_t *pos) 3479c2c66affSColin Finck { 3480c2c66affSColin Finck int ret; 3481c2c66affSColin Finck 3482c2c66affSColin Finck _lock_file(file); 3483c2c66affSColin Finck /* Note that all this has been lifted 'as is' from fseek */ 3484c2c66affSColin Finck if(file->_flag & _IOWRT) 3485c2c66affSColin Finck msvcrt_flush_buffer(file); 3486c2c66affSColin Finck 3487c2c66affSColin Finck /* Discard buffered input */ 3488c2c66affSColin Finck file->_cnt = 0; 3489c2c66affSColin Finck file->_ptr = file->_base; 3490c2c66affSColin Finck 3491c2c66affSColin Finck /* Reset direction of i/o */ 3492c2c66affSColin Finck if(file->_flag & _IORW) { 3493c2c66affSColin Finck file->_flag &= ~(_IOREAD|_IOWRT); 3494c2c66affSColin Finck } 3495c2c66affSColin Finck 3496c2c66affSColin Finck ret = (_lseeki64(file->_file,*pos,SEEK_SET) == -1) ? -1 : 0; 3497c2c66affSColin Finck _unlock_file(file); 3498c2c66affSColin Finck return ret; 3499c2c66affSColin Finck } 3500c2c66affSColin Finck 3501c2c66affSColin Finck /********************************************************************* 3502c2c66affSColin Finck * _ftelli64 (MSVCRT.@) 3503c2c66affSColin Finck */ 3504c2c66affSColin Finck __int64 CDECL _ftelli64(FILE* file) 3505c2c66affSColin Finck { 3506c2c66affSColin Finck __int64 pos; 3507c2c66affSColin Finck 3508c2c66affSColin Finck _lock_file(file); 3509c2c66affSColin Finck pos = _telli64(file->_file); 3510c2c66affSColin Finck if(pos == -1) { 3511c2c66affSColin Finck _unlock_file(file); 3512c2c66affSColin Finck return -1; 3513c2c66affSColin Finck } 3514c2c66affSColin Finck if(file->_flag & (_IOMYBUF | _USERBUF)) { 3515c2c66affSColin Finck if(file->_flag & _IOWRT) { 3516c2c66affSColin Finck pos += file->_ptr - file->_base; 3517c2c66affSColin Finck 351825064fdfSThomas Faber if(get_ioinfo_nolock(file->_file)->wxflag & WX_TEXT) { 3519c2c66affSColin Finck char *p; 3520c2c66affSColin Finck 3521c2c66affSColin Finck for(p=file->_base; p<file->_ptr; p++) 3522c2c66affSColin Finck if(*p == '\n') 3523c2c66affSColin Finck pos++; 3524c2c66affSColin Finck } 3525c2c66affSColin Finck } else if(!file->_cnt) { /* nothing to do */ 3526c2c66affSColin Finck } else if(_lseeki64(file->_file, 0, SEEK_END)==pos) { 3527c2c66affSColin Finck int i; 3528c2c66affSColin Finck 3529c2c66affSColin Finck pos -= file->_cnt; 353025064fdfSThomas Faber if(get_ioinfo_nolock(file->_file)->wxflag & WX_TEXT) { 3531c2c66affSColin Finck for(i=0; i<file->_cnt; i++) 3532c2c66affSColin Finck if(file->_ptr[i] == '\n') 3533c2c66affSColin Finck pos--; 3534c2c66affSColin Finck } 3535c2c66affSColin Finck } else { 3536c2c66affSColin Finck char *p; 3537c2c66affSColin Finck 3538c2c66affSColin Finck if(_lseeki64(file->_file, pos, SEEK_SET) != pos) { 3539c2c66affSColin Finck _unlock_file(file); 3540c2c66affSColin Finck return -1; 3541c2c66affSColin Finck } 3542c2c66affSColin Finck 3543c2c66affSColin Finck pos -= file->_bufsiz; 3544c2c66affSColin Finck pos += file->_ptr - file->_base; 3545c2c66affSColin Finck 354625064fdfSThomas Faber if(get_ioinfo_nolock(file->_file)->wxflag & WX_TEXT) { 354725064fdfSThomas Faber if(get_ioinfo_nolock(file->_file)->wxflag & WX_READNL) 3548c2c66affSColin Finck pos--; 3549c2c66affSColin Finck 3550c2c66affSColin Finck for(p=file->_base; p<file->_ptr; p++) 3551c2c66affSColin Finck if(*p == '\n') 3552c2c66affSColin Finck pos++; 3553c2c66affSColin Finck } 3554c2c66affSColin Finck } 3555c2c66affSColin Finck } 3556c2c66affSColin Finck 3557c2c66affSColin Finck _unlock_file(file); 3558c2c66affSColin Finck return pos; 3559c2c66affSColin Finck } 3560c2c66affSColin Finck 3561c2c66affSColin Finck /********************************************************************* 3562c2c66affSColin Finck * ftell (MSVCRT.@) 3563c2c66affSColin Finck */ 3564c2c66affSColin Finck LONG CDECL ftell(FILE* file) 3565c2c66affSColin Finck { 3566c2c66affSColin Finck return (LONG)_ftelli64(file); 3567c2c66affSColin Finck } 3568c2c66affSColin Finck 3569c2c66affSColin Finck /********************************************************************* 3570c2c66affSColin Finck * fgetpos (MSVCRT.@) 3571c2c66affSColin Finck */ 3572c2c66affSColin Finck int CDECL fgetpos(FILE* file, fpos_t *pos) 3573c2c66affSColin Finck { 3574c2c66affSColin Finck *pos = _ftelli64(file); 3575c2c66affSColin Finck if(*pos == -1) 3576c2c66affSColin Finck return -1; 3577c2c66affSColin Finck return 0; 3578c2c66affSColin Finck } 3579c2c66affSColin Finck 3580c2c66affSColin Finck /********************************************************************* 3581c2c66affSColin Finck * fputs (MSVCRT.@) 3582c2c66affSColin Finck */ 3583c2c66affSColin Finck int CDECL fputs(const char *s, FILE* file) 3584c2c66affSColin Finck { 3585c2c66affSColin Finck size_t len = strlen(s); 3586c2c66affSColin Finck int ret; 3587c2c66affSColin Finck 3588c2c66affSColin Finck _lock_file(file); 3589c2c66affSColin Finck ret = fwrite(s, sizeof(*s), len, file) == len ? 0 : EOF; 3590c2c66affSColin Finck _unlock_file(file); 3591c2c66affSColin Finck return ret; 3592c2c66affSColin Finck } 3593c2c66affSColin Finck 3594c2c66affSColin Finck /********************************************************************* 3595c2c66affSColin Finck * fputws (MSVCRT.@) 3596c2c66affSColin Finck */ 3597c2c66affSColin Finck int CDECL fputws(const wchar_t *s, FILE* file) 3598c2c66affSColin Finck { 3599c2c66affSColin Finck size_t i, len = strlenW(s); 3600c2c66affSColin Finck BOOL tmp_buf; 3601c2c66affSColin Finck int ret; 3602c2c66affSColin Finck 3603c2c66affSColin Finck _lock_file(file); 360425064fdfSThomas Faber if (!(get_ioinfo_nolock(file->_file)->wxflag & WX_TEXT)) { 3605c2c66affSColin Finck ret = fwrite(s,sizeof(*s),len,file) == len ? 0 : EOF; 3606c2c66affSColin Finck _unlock_file(file); 3607c2c66affSColin Finck return ret; 3608c2c66affSColin Finck } 3609c2c66affSColin Finck 3610c2c66affSColin Finck tmp_buf = add_std_buffer(file); 3611c2c66affSColin Finck for (i=0; i<len; i++) { 3612c2c66affSColin Finck if(fputwc(s[i], file) == WEOF) { 3613c2c66affSColin Finck if(tmp_buf) remove_std_buffer(file); 3614c2c66affSColin Finck _unlock_file(file); 3615c2c66affSColin Finck return WEOF; 3616c2c66affSColin Finck } 3617c2c66affSColin Finck } 3618c2c66affSColin Finck 3619c2c66affSColin Finck if(tmp_buf) remove_std_buffer(file); 3620c2c66affSColin Finck _unlock_file(file); 3621c2c66affSColin Finck return 0; 3622c2c66affSColin Finck } 3623c2c66affSColin Finck 3624c2c66affSColin Finck /********************************************************************* 3625c2c66affSColin Finck * getchar (MSVCRT.@) 3626c2c66affSColin Finck */ 3627c2c66affSColin Finck int CDECL getchar(void) 3628c2c66affSColin Finck { 3629c2c66affSColin Finck return fgetc(stdin); 3630c2c66affSColin Finck } 3631c2c66affSColin Finck 3632c2c66affSColin Finck /********************************************************************* 3633c2c66affSColin Finck * getc (MSVCRT.@) 3634c2c66affSColin Finck */ 3635c2c66affSColin Finck int CDECL getc(FILE* file) 3636c2c66affSColin Finck { 3637c2c66affSColin Finck return fgetc(file); 3638c2c66affSColin Finck } 3639c2c66affSColin Finck 3640c2c66affSColin Finck /********************************************************************* 3641c2c66affSColin Finck * gets (MSVCRT.@) 3642c2c66affSColin Finck */ 3643c2c66affSColin Finck char * CDECL gets(char *buf) 3644c2c66affSColin Finck { 3645c2c66affSColin Finck int cc; 3646c2c66affSColin Finck char * buf_start = buf; 3647c2c66affSColin Finck 3648c2c66affSColin Finck _lock_file(stdin); 3649c2c66affSColin Finck for(cc = fgetc(stdin); cc != EOF && cc != '\n'; 3650c2c66affSColin Finck cc = fgetc(stdin)) 3651c2c66affSColin Finck if(cc != '\r') *buf++ = (char)cc; 3652c2c66affSColin Finck 3653c2c66affSColin Finck *buf = '\0'; 3654c2c66affSColin Finck 3655c2c66affSColin Finck TRACE("got '%s'\n", buf_start); 3656c2c66affSColin Finck _unlock_file(stdin); 3657c2c66affSColin Finck return buf_start; 3658c2c66affSColin Finck } 3659c2c66affSColin Finck 3660c2c66affSColin Finck /********************************************************************* 3661c2c66affSColin Finck * _getws (MSVCRT.@) 3662c2c66affSColin Finck */ 3663c2c66affSColin Finck wchar_t* CDECL _getws(wchar_t* buf) 3664c2c66affSColin Finck { 3665c2c66affSColin Finck wint_t cc; 3666c2c66affSColin Finck wchar_t* ws = buf; 3667c2c66affSColin Finck 3668c2c66affSColin Finck _lock_file(stdin); 3669c2c66affSColin Finck for (cc = fgetwc(stdin); cc != WEOF && cc != '\n'; 3670c2c66affSColin Finck cc = fgetwc(stdin)) 3671c2c66affSColin Finck { 3672c2c66affSColin Finck if (cc != '\r') 3673c2c66affSColin Finck *buf++ = (wchar_t)cc; 3674c2c66affSColin Finck } 3675c2c66affSColin Finck *buf = '\0'; 3676c2c66affSColin Finck 3677c2c66affSColin Finck TRACE("got %s\n", debugstr_w(ws)); 3678c2c66affSColin Finck _unlock_file(stdin); 3679c2c66affSColin Finck return ws; 3680c2c66affSColin Finck } 3681c2c66affSColin Finck 3682c2c66affSColin Finck /********************************************************************* 3683c2c66affSColin Finck * putc (MSVCRT.@) 3684c2c66affSColin Finck */ 3685c2c66affSColin Finck int CDECL putc(int c, FILE* file) 3686c2c66affSColin Finck { 3687c2c66affSColin Finck return fputc(c, file); 3688c2c66affSColin Finck } 3689c2c66affSColin Finck 3690c2c66affSColin Finck /********************************************************************* 3691c2c66affSColin Finck * putchar (MSVCRT.@) 3692c2c66affSColin Finck */ 3693c2c66affSColin Finck int CDECL putchar(int c) 3694c2c66affSColin Finck { 3695c2c66affSColin Finck return fputc(c, stdout); 3696c2c66affSColin Finck } 3697c2c66affSColin Finck 3698c2c66affSColin Finck /********************************************************************* 3699c2c66affSColin Finck * _putwch (MSVCRT.@) 3700c2c66affSColin Finck */ 3701c2c66affSColin Finck wint_t CDECL _putwch(wchar_t c) 3702c2c66affSColin Finck { 3703c2c66affSColin Finck return fputwc(c, stdout); 3704c2c66affSColin Finck } 3705c2c66affSColin Finck 3706c2c66affSColin Finck /********************************************************************* 3707c2c66affSColin Finck * puts (MSVCRT.@) 3708c2c66affSColin Finck */ 3709c2c66affSColin Finck int CDECL puts(const char *s) 3710c2c66affSColin Finck { 3711c2c66affSColin Finck size_t len = strlen(s); 3712c2c66affSColin Finck int ret; 3713c2c66affSColin Finck 3714c2c66affSColin Finck _lock_file(stdout); 3715c2c66affSColin Finck if(fwrite(s, sizeof(*s), len, stdout) != len) { 3716c2c66affSColin Finck _unlock_file(stdout); 3717c2c66affSColin Finck return EOF; 3718c2c66affSColin Finck } 3719c2c66affSColin Finck 3720c2c66affSColin Finck ret = fwrite("\n",1,1,stdout) == 1 ? 0 : EOF; 3721c2c66affSColin Finck _unlock_file(stdout); 3722c2c66affSColin Finck return ret; 3723c2c66affSColin Finck } 3724c2c66affSColin Finck 3725c2c66affSColin Finck /********************************************************************* 3726c2c66affSColin Finck * _putws (MSVCRT.@) 3727c2c66affSColin Finck */ 3728c2c66affSColin Finck int CDECL _putws(const wchar_t *s) 3729c2c66affSColin Finck { 3730c2c66affSColin Finck static const wchar_t nl = '\n'; 3731c2c66affSColin Finck size_t len = strlenW(s); 3732c2c66affSColin Finck int ret; 3733c2c66affSColin Finck 3734c2c66affSColin Finck _lock_file(stdout); 3735c2c66affSColin Finck if(fwrite(s, sizeof(*s), len, stdout) != len) { 3736c2c66affSColin Finck _unlock_file(stdout); 3737c2c66affSColin Finck return EOF; 3738c2c66affSColin Finck } 3739c2c66affSColin Finck 3740c2c66affSColin Finck ret = fwrite(&nl,sizeof(nl),1,stdout) == 1 ? 0 : EOF; 3741c2c66affSColin Finck _unlock_file(stdout); 3742c2c66affSColin Finck return ret; 3743c2c66affSColin Finck } 3744c2c66affSColin Finck 3745c2c66affSColin Finck /********************************************************************* 3746c2c66affSColin Finck * remove (MSVCRT.@) 3747c2c66affSColin Finck */ 3748c2c66affSColin Finck int CDECL remove(const char *path) 3749c2c66affSColin Finck { 3750c2c66affSColin Finck TRACE("(%s)\n",path); 3751c2c66affSColin Finck if (DeleteFileA(path)) 3752c2c66affSColin Finck return 0; 3753c2c66affSColin Finck TRACE(":failed (%d)\n",GetLastError()); 3754c2c66affSColin Finck _dosmaperr(GetLastError()); 3755c2c66affSColin Finck return -1; 3756c2c66affSColin Finck } 3757c2c66affSColin Finck 3758c2c66affSColin Finck /********************************************************************* 3759c2c66affSColin Finck * _wremove (MSVCRT.@) 3760c2c66affSColin Finck */ 3761c2c66affSColin Finck int CDECL _wremove(const wchar_t *path) 3762c2c66affSColin Finck { 3763c2c66affSColin Finck TRACE("(%s)\n",debugstr_w(path)); 3764c2c66affSColin Finck if (DeleteFileW(path)) 3765c2c66affSColin Finck return 0; 3766c2c66affSColin Finck TRACE(":failed (%d)\n",GetLastError()); 3767c2c66affSColin Finck _dosmaperr(GetLastError()); 3768c2c66affSColin Finck return -1; 3769c2c66affSColin Finck } 3770c2c66affSColin Finck 3771c2c66affSColin Finck /********************************************************************* 3772c2c66affSColin Finck * rename (MSVCRT.@) 3773c2c66affSColin Finck */ 3774c2c66affSColin Finck int CDECL rename(const char *oldpath,const char *newpath) 3775c2c66affSColin Finck { 3776c2c66affSColin Finck TRACE(":from %s to %s\n",oldpath,newpath); 3777c2c66affSColin Finck if (MoveFileExA(oldpath, newpath, MOVEFILE_COPY_ALLOWED)) 3778c2c66affSColin Finck return 0; 3779c2c66affSColin Finck TRACE(":failed (%d)\n",GetLastError()); 3780c2c66affSColin Finck _dosmaperr(GetLastError()); 3781c2c66affSColin Finck return -1; 3782c2c66affSColin Finck } 3783c2c66affSColin Finck 3784c2c66affSColin Finck /********************************************************************* 3785c2c66affSColin Finck * _wrename (MSVCRT.@) 3786c2c66affSColin Finck */ 3787c2c66affSColin Finck int CDECL _wrename(const wchar_t *oldpath,const wchar_t *newpath) 3788c2c66affSColin Finck { 3789c2c66affSColin Finck TRACE(":from %s to %s\n",debugstr_w(oldpath),debugstr_w(newpath)); 3790c2c66affSColin Finck if (MoveFileExW(oldpath, newpath, MOVEFILE_COPY_ALLOWED)) 3791c2c66affSColin Finck return 0; 3792c2c66affSColin Finck TRACE(":failed (%d)\n",GetLastError()); 3793c2c66affSColin Finck _dosmaperr(GetLastError()); 3794c2c66affSColin Finck return -1; 3795c2c66affSColin Finck } 3796c2c66affSColin Finck 3797c2c66affSColin Finck /********************************************************************* 3798c2c66affSColin Finck * setvbuf (MSVCRT.@) 3799c2c66affSColin Finck */ 3800c2c66affSColin Finck int CDECL setvbuf(FILE* file, char *buf, int mode, size_t size) 3801c2c66affSColin Finck { 3802c2c66affSColin Finck if(!MSVCRT_CHECK_PMT(file != NULL)) return -1; 3803c2c66affSColin Finck if(!MSVCRT_CHECK_PMT(mode==_IONBF || mode==_IOFBF || mode==_IOLBF)) return -1; 3804c2c66affSColin Finck if(!MSVCRT_CHECK_PMT(mode==_IONBF || (size>=2 && size<=INT_MAX))) return -1; 3805c2c66affSColin Finck 3806c2c66affSColin Finck _lock_file(file); 3807c2c66affSColin Finck 3808c2c66affSColin Finck fflush(file); 3809c2c66affSColin Finck if(file->_flag & _IOMYBUF) 3810c2c66affSColin Finck free(file->_base); 3811c2c66affSColin Finck file->_flag &= ~(_IONBF | _IOMYBUF | _USERBUF); 3812c2c66affSColin Finck file->_cnt = 0; 3813c2c66affSColin Finck 3814c2c66affSColin Finck if(mode == _IONBF) { 3815c2c66affSColin Finck file->_flag |= _IONBF; 3816c2c66affSColin Finck file->_base = file->_ptr = (char*)&file->_charbuf; 3817c2c66affSColin Finck file->_bufsiz = 2; 3818c2c66affSColin Finck }else if(buf) { 3819c2c66affSColin Finck file->_base = file->_ptr = buf; 3820c2c66affSColin Finck file->_flag |= _USERBUF; 3821c2c66affSColin Finck file->_bufsiz = size; 3822c2c66affSColin Finck }else { 3823c2c66affSColin Finck file->_base = file->_ptr = malloc(size); 3824c2c66affSColin Finck if(!file->_base) { 3825c2c66affSColin Finck file->_bufsiz = 0; 3826c2c66affSColin Finck _unlock_file(file); 3827c2c66affSColin Finck return -1; 3828c2c66affSColin Finck } 3829c2c66affSColin Finck 3830c2c66affSColin Finck file->_flag |= _IOMYBUF; 3831c2c66affSColin Finck file->_bufsiz = size; 3832c2c66affSColin Finck } 3833c2c66affSColin Finck _unlock_file(file); 3834c2c66affSColin Finck return 0; 3835c2c66affSColin Finck } 3836c2c66affSColin Finck 3837c2c66affSColin Finck /********************************************************************* 3838c2c66affSColin Finck * setbuf (MSVCRT.@) 3839c2c66affSColin Finck */ 3840c2c66affSColin Finck void CDECL setbuf(FILE* file, char *buf) 3841c2c66affSColin Finck { 3842c2c66affSColin Finck setvbuf(file, buf, buf ? _IOFBF : _IONBF, BUFSIZ); 3843c2c66affSColin Finck } 3844c2c66affSColin Finck 3845c2c66affSColin Finck /********************************************************************* 3846c2c66affSColin Finck * tmpnam (MSVCRT.@) 3847c2c66affSColin Finck */ 3848c2c66affSColin Finck char * CDECL tmpnam(char *s) 3849c2c66affSColin Finck { 3850c2c66affSColin Finck char tmpstr[16]; 3851c2c66affSColin Finck char *p; 3852c2c66affSColin Finck int count, size; 3853c2c66affSColin Finck 3854c2c66affSColin Finck if (!s) { 3855c2c66affSColin Finck thread_data_t *data = msvcrt_get_thread_data(); 3856c2c66affSColin Finck 3857c2c66affSColin Finck if(!data->tmpnam_buffer) 3858c2c66affSColin Finck data->tmpnam_buffer = malloc(MAX_PATH); 3859c2c66affSColin Finck 3860c2c66affSColin Finck s = data->tmpnam_buffer; 3861c2c66affSColin Finck } 3862c2c66affSColin Finck 3863c2c66affSColin Finck msvcrt_int_to_base32(GetCurrentProcessId(), tmpstr); 3864c2c66affSColin Finck p = s + sprintf(s, "\\s%s.", tmpstr); 3865c2c66affSColin Finck for (count = 0; count < TMP_MAX; count++) 3866c2c66affSColin Finck { 3867c2c66affSColin Finck size = msvcrt_int_to_base32(tmpnam_unique++, tmpstr); 3868c2c66affSColin Finck memcpy(p, tmpstr, size); 3869c2c66affSColin Finck p[size] = '\0'; 3870c2c66affSColin Finck if (GetFileAttributesA(s) == INVALID_FILE_ATTRIBUTES && 3871c2c66affSColin Finck GetLastError() == ERROR_FILE_NOT_FOUND) 3872c2c66affSColin Finck break; 3873c2c66affSColin Finck } 3874c2c66affSColin Finck return s; 3875c2c66affSColin Finck } 3876c2c66affSColin Finck 3877c2c66affSColin Finck /********************************************************************* 3878c2c66affSColin Finck * _wtmpnam (MSVCRT.@) 3879c2c66affSColin Finck */ 3880c2c66affSColin Finck wchar_t * CDECL _wtmpnam(wchar_t *s) 3881c2c66affSColin Finck { 3882c2c66affSColin Finck static const wchar_t format[] = {'\\','s','%','s','.',0}; 3883c2c66affSColin Finck wchar_t tmpstr[16]; 3884c2c66affSColin Finck wchar_t *p; 3885c2c66affSColin Finck int count, size; 3886c2c66affSColin Finck if (!s) { 3887c2c66affSColin Finck thread_data_t *data = msvcrt_get_thread_data(); 3888c2c66affSColin Finck 3889c2c66affSColin Finck if(!data->wtmpnam_buffer) 3890c2c66affSColin Finck data->wtmpnam_buffer = malloc(sizeof(wchar_t[MAX_PATH])); 3891c2c66affSColin Finck 3892c2c66affSColin Finck s = data->wtmpnam_buffer; 3893c2c66affSColin Finck } 3894c2c66affSColin Finck 3895c2c66affSColin Finck msvcrt_int_to_base32_w(GetCurrentProcessId(), tmpstr); 3896c2c66affSColin Finck p = s + _snwprintf(s, MAX_PATH, format, tmpstr); 3897c2c66affSColin Finck for (count = 0; count < TMP_MAX; count++) 3898c2c66affSColin Finck { 3899c2c66affSColin Finck size = msvcrt_int_to_base32_w(tmpnam_unique++, tmpstr); 3900c2c66affSColin Finck memcpy(p, tmpstr, size*sizeof(wchar_t)); 3901c2c66affSColin Finck p[size] = '\0'; 3902c2c66affSColin Finck if (GetFileAttributesW(s) == INVALID_FILE_ATTRIBUTES && 3903c2c66affSColin Finck GetLastError() == ERROR_FILE_NOT_FOUND) 3904c2c66affSColin Finck break; 3905c2c66affSColin Finck } 3906c2c66affSColin Finck return s; 3907c2c66affSColin Finck } 3908c2c66affSColin Finck 3909c2c66affSColin Finck /********************************************************************* 3910c2c66affSColin Finck * tmpfile (MSVCRT.@) 3911c2c66affSColin Finck */ 3912c2c66affSColin Finck FILE* CDECL tmpfile(void) 3913c2c66affSColin Finck { 3914c2c66affSColin Finck char *filename = tmpnam(NULL); 3915c2c66affSColin Finck int fd; 3916c2c66affSColin Finck FILE* file = NULL; 3917c2c66affSColin Finck 3918c2c66affSColin Finck LOCK_FILES(); 3919c2c66affSColin Finck fd = _open(filename, _O_CREAT | _O_BINARY | _O_RDWR | _O_TEMPORARY, 3920c2c66affSColin Finck _S_IREAD | _S_IWRITE); 3921c2c66affSColin Finck if (fd != -1 && (file = msvcrt_alloc_fp())) 3922c2c66affSColin Finck { 3923c2c66affSColin Finck if (msvcrt_init_fp(file, fd, _IORW) == -1) 3924c2c66affSColin Finck { 3925c2c66affSColin Finck file->_flag = 0; 3926c2c66affSColin Finck file = NULL; 3927c2c66affSColin Finck } 3928c2c66affSColin Finck else file->_tmpfname = _strdup(filename); 3929c2c66affSColin Finck } 3930c2c66affSColin Finck 3931c2c66affSColin Finck if(fd != -1 && !file) 3932c2c66affSColin Finck _close(fd); 3933c2c66affSColin Finck UNLOCK_FILES(); 3934c2c66affSColin Finck return file; 3935c2c66affSColin Finck } 3936c2c66affSColin Finck 3937c2c66affSColin Finck /********************************************************************* 3938c2c66affSColin Finck * ungetc (MSVCRT.@) 3939c2c66affSColin Finck */ 3940c2c66affSColin Finck int CDECL ungetc(int c, FILE * file) 3941c2c66affSColin Finck { 3942c2c66affSColin Finck if(!MSVCRT_CHECK_PMT(file != NULL)) return EOF; 3943c2c66affSColin Finck 3944c2c66affSColin Finck if (c == EOF || !(file->_flag&_IOREAD || 3945c2c66affSColin Finck (file->_flag&_IORW && !(file->_flag&_IOWRT)))) 3946c2c66affSColin Finck return EOF; 3947c2c66affSColin Finck 3948c2c66affSColin Finck _lock_file(file); 3949c2c66affSColin Finck if((!(file->_flag & (_IONBF | _IOMYBUF | _USERBUF)) 3950c2c66affSColin Finck && msvcrt_alloc_buffer(file)) 3951c2c66affSColin Finck || (!file->_cnt && file->_ptr==file->_base)) 3952c2c66affSColin Finck file->_ptr++; 3953c2c66affSColin Finck 3954c2c66affSColin Finck if(file->_ptr>file->_base) { 3955c2c66affSColin Finck file->_ptr--; 3956c2c66affSColin Finck if(file->_flag & _IOSTRG) { 3957c2c66affSColin Finck if(*file->_ptr != c) { 3958c2c66affSColin Finck file->_ptr++; 3959c2c66affSColin Finck _unlock_file(file); 3960c2c66affSColin Finck return EOF; 3961c2c66affSColin Finck } 3962c2c66affSColin Finck }else { 3963c2c66affSColin Finck *file->_ptr = c; 3964c2c66affSColin Finck } 3965c2c66affSColin Finck file->_cnt++; 3966c2c66affSColin Finck clearerr(file); 3967c2c66affSColin Finck file->_flag |= _IOREAD; 3968c2c66affSColin Finck _unlock_file(file); 3969c2c66affSColin Finck return c; 3970c2c66affSColin Finck } 3971c2c66affSColin Finck 3972c2c66affSColin Finck _unlock_file(file); 3973c2c66affSColin Finck return EOF; 3974c2c66affSColin Finck } 3975c2c66affSColin Finck 3976c2c66affSColin Finck /********************************************************************* 3977c2c66affSColin Finck * ungetwc (MSVCRT.@) 3978c2c66affSColin Finck */ 3979c2c66affSColin Finck wint_t CDECL ungetwc(wint_t wc, FILE * file) 3980c2c66affSColin Finck { 3981c2c66affSColin Finck wchar_t mwc = wc; 3982c2c66affSColin Finck 3983c2c66affSColin Finck if (wc == WEOF) 3984c2c66affSColin Finck return WEOF; 3985c2c66affSColin Finck 3986c2c66affSColin Finck _lock_file(file); 3987c2c66affSColin Finck 398825064fdfSThomas Faber if((get_ioinfo_nolock(file->_file)->exflag & (EF_UTF8 | EF_UTF16)) 398925064fdfSThomas Faber || !(get_ioinfo_nolock(file->_file)->wxflag & WX_TEXT)) { 3990c2c66affSColin Finck unsigned char * pp = (unsigned char *)&mwc; 3991c2c66affSColin Finck int i; 3992c2c66affSColin Finck 3993c2c66affSColin Finck for(i=sizeof(wchar_t)-1;i>=0;i--) { 3994c2c66affSColin Finck if(pp[i] != ungetc(pp[i],file)) { 3995c2c66affSColin Finck _unlock_file(file); 3996c2c66affSColin Finck return WEOF; 3997c2c66affSColin Finck } 3998c2c66affSColin Finck } 3999c2c66affSColin Finck }else { 4000c2c66affSColin Finck char mbs[MB_LEN_MAX]; 4001c2c66affSColin Finck int len; 4002c2c66affSColin Finck 4003c2c66affSColin Finck len = wctomb(mbs, mwc); 4004c2c66affSColin Finck if(len == -1) { 4005c2c66affSColin Finck _unlock_file(file); 4006c2c66affSColin Finck return WEOF; 4007c2c66affSColin Finck } 4008c2c66affSColin Finck 4009c2c66affSColin Finck for(len--; len>=0; len--) { 4010c2c66affSColin Finck if(mbs[len] != ungetc(mbs[len], file)) { 4011c2c66affSColin Finck _unlock_file(file); 4012c2c66affSColin Finck return WEOF; 4013c2c66affSColin Finck } 4014c2c66affSColin Finck } 4015c2c66affSColin Finck } 4016c2c66affSColin Finck 4017c2c66affSColin Finck _unlock_file(file); 4018c2c66affSColin Finck return mwc; 4019c2c66affSColin Finck } 4020c2c66affSColin Finck 4021c2c66affSColin Finck 4022c2c66affSColin Finck 4023c2c66affSColin Finck /********************************************************************* 4024c2c66affSColin Finck * _getmaxstdio (MSVCRT.@) 4025c2c66affSColin Finck */ 4026c2c66affSColin Finck int CDECL _getmaxstdio(void) 4027c2c66affSColin Finck { 4028c2c66affSColin Finck return MSVCRT_max_streams; 4029c2c66affSColin Finck } 4030c2c66affSColin Finck 4031c2c66affSColin Finck /********************************************************************* 4032c2c66affSColin Finck * _setmaxstdio (MSVCRT.@) 4033c2c66affSColin Finck */ 4034c2c66affSColin Finck int CDECL _setmaxstdio(int newmax) 4035c2c66affSColin Finck { 4036c2c66affSColin Finck TRACE("%d\n", newmax); 4037c2c66affSColin Finck 4038c2c66affSColin Finck if(newmax<_IOB_ENTRIES || newmax>MSVCRT_MAX_FILES || newmax<MSVCRT_stream_idx) 4039c2c66affSColin Finck return -1; 4040c2c66affSColin Finck 4041c2c66affSColin Finck MSVCRT_max_streams = newmax; 4042c2c66affSColin Finck return MSVCRT_max_streams; 4043c2c66affSColin Finck } 4044