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