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