Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenfile.c
Go to the documentation of this file.
00001 /* 00002 * PROJECT: ReactOS CRT library 00003 * LICENSE: LGPL - See COPYING in the top level directory 00004 * FILE: lib/sdk/crt/stdio/file.c 00005 * PURPOSE: File CRT functions 00006 * PROGRAMMERS: Wine team 00007 * Ported to ReactOS by Aleksey Bragin (aleksey@reactos.org) 00008 */ 00009 00010 /* 00011 * msvcrt.dll file functions 00012 * 00013 * Copyright 1996,1998 Marcus Meissner 00014 * Copyright 1996 Jukka Iivonen 00015 * Copyright 1997,2000 Uwe Bonnes 00016 * Copyright 2000 Jon Griffiths 00017 * Copyright 2004 Eric Pouech 00018 * Copyright 2004 Juan Lang 00019 * 00020 * This library is free software; you can redistribute it and/or 00021 * modify it under the terms of the GNU Lesser General Public 00022 * License as published by the Free Software Foundation; either 00023 * version 2.1 of the License, or (at your option) any later version. 00024 * 00025 * This library is distributed in the hope that it will be useful, 00026 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00027 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00028 * Lesser General Public License for more details. 00029 * 00030 * You should have received a copy of the GNU Lesser General Public 00031 * License along with this library; if not, write to the Free Software 00032 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00033 * 00034 * TODO 00035 * Use the file flag hints O_SEQUENTIAL, O_RANDOM, O_SHORT_LIVED 00036 */ 00037 00038 #include <precomp.h> 00039 #include "wine/unicode.h" 00040 00041 #include <sys/utime.h> 00042 #include <direct.h> 00043 00044 int *__p__fmode(void); 00045 int *__p___mb_cur_max(void); 00046 00047 #ifdef feof 00048 #undef feof 00049 #endif 00050 #ifdef _fileno 00051 #undef _fileno 00052 #endif 00053 #ifdef ferror 00054 #undef ferror 00055 #endif 00056 #ifdef clearerr 00057 #undef clearerr 00058 #endif 00059 00060 #undef getc 00061 #undef getwc 00062 #undef getchar 00063 #undef getwchar 00064 #undef putc 00065 #undef putwc 00066 #undef putchar 00067 #undef putwchar 00068 00069 #undef vprintf 00070 #undef vwprintf 00071 00072 /* _access() bit flags FIXME: incomplete */ 00073 /* defined in crt/io.h */ 00074 00075 /* values for wxflag in file descriptor */ 00076 #define WX_OPEN 0x01 00077 #define WX_ATEOF 0x02 00078 #define WX_READEOF 0x04 /* like ATEOF, but for underlying file rather than buffer */ 00079 #define WX_READCR 0x08 /* underlying file is at \r */ 00080 #define WX_DONTINHERIT 0x10 00081 #define WX_APPEND 0x20 00082 #define WX_TEXT 0x80 00083 00084 /* FIXME: this should be allocated dynamically */ 00085 #define MAX_FILES 2048 00086 #define FD_BLOCK_SIZE 64 00087 00088 typedef struct { 00089 HANDLE handle; 00090 unsigned char wxflag; 00091 char unk1; 00092 BOOL crit_init; 00093 CRITICAL_SECTION crit; 00094 } ioinfo; 00095 00096 /********************************************************************* 00097 * __pioinfo (MSVCRT.@) 00098 * array of pointers to ioinfo arrays [64] 00099 */ 00100 ioinfo * __pioinfo[MAX_FILES/FD_BLOCK_SIZE] = { 0 }; 00101 00102 /********************************************************************* 00103 * __badioinfo (MSVCRT.@) 00104 */ 00105 ioinfo __badioinfo = { INVALID_HANDLE_VALUE, WX_TEXT }; 00106 00107 static int fdstart = 3; /* first unallocated fd */ 00108 static int fdend = 3; /* highest allocated fd */ 00109 00110 typedef struct { 00111 FILE file; 00112 CRITICAL_SECTION crit; 00113 } file_crit; 00114 00115 FILE _iob[_IOB_ENTRIES] = { { 0 } }; 00116 static file_crit* fstream[MAX_FILES/FD_BLOCK_SIZE] = { NULL }; 00117 static int max_streams = 512, stream_idx; 00118 00119 /* INTERNAL: process umask */ 00120 static int MSVCRT_umask = 0; 00121 00122 /* INTERNAL: static data for tmpnam and _wtmpname functions */ 00123 static int tmpnam_unique; 00124 00125 /* This critical section protects the tables __pioinfo and fstreams, 00126 * and their related indexes, fdstart, fdend, 00127 * and stream_idx, from race conditions. 00128 * It doesn't protect against race conditions manipulating the underlying files 00129 * or flags; doing so would probably be better accomplished with per-file 00130 * protection, rather than locking the whole table for every change. 00131 */ 00132 static CRITICAL_SECTION file_cs; 00133 #define LOCK_FILES() do { EnterCriticalSection(&file_cs); } while (0) 00134 #define UNLOCK_FILES() do { LeaveCriticalSection(&file_cs); } while (0) 00135 00136 static inline ioinfo* get_ioinfo(int fd) 00137 { 00138 ioinfo *ret = NULL; 00139 if(fd < MAX_FILES) 00140 ret = __pioinfo[fd/FD_BLOCK_SIZE]; 00141 if(!ret) 00142 return &__badioinfo; 00143 00144 return ret + (fd%FD_BLOCK_SIZE); 00145 } 00146 00147 static inline FILE* get_file(int i) 00148 { 00149 file_crit *ret; 00150 00151 if(i >= max_streams) 00152 return NULL; 00153 00154 if(i < _IOB_ENTRIES) 00155 return &_iob[i]; 00156 00157 ret = fstream[i/FD_BLOCK_SIZE]; 00158 if(!ret) { 00159 fstream[i/FD_BLOCK_SIZE] = calloc(FD_BLOCK_SIZE, sizeof(file_crit)); 00160 if(!fstream[i/FD_BLOCK_SIZE]) { 00161 ERR("out of memory\n"); 00162 *_errno() = ENOMEM; 00163 return NULL; 00164 } 00165 00166 ret = fstream[i/FD_BLOCK_SIZE] + (i%FD_BLOCK_SIZE); 00167 } else 00168 ret += i%FD_BLOCK_SIZE; 00169 00170 return &ret->file; 00171 } 00172 00173 static inline BOOL is_valid_fd(int fd) 00174 { 00175 return fd >= 0 && fd < fdend && (get_ioinfo(fd)->wxflag & WX_OPEN); 00176 } 00177 00178 /* INTERNAL: Get the HANDLE for a fd 00179 * This doesn't lock the table, because a failure will result in 00180 * INVALID_HANDLE_VALUE being returned, which should be handled correctly. If 00181 * it returns a valid handle which is about to be closed, a subsequent call 00182 * will fail, most likely in a sane way. 00183 */ 00184 /*static*/ HANDLE fdtoh(int fd) 00185 { 00186 if (!is_valid_fd(fd)) 00187 { 00188 WARN(":fd (%d) - no handle!\n",fd); 00189 *__doserrno() = 0; 00190 *_errno() = EBADF; 00191 return INVALID_HANDLE_VALUE; 00192 } 00193 //if (get_ioinfo(fd)->handle == INVALID_HANDLE_VALUE) 00194 //FIXME("returning INVALID_HANDLE_VALUE for %d\n", fd); 00195 return get_ioinfo(fd)->handle; 00196 } 00197 00198 /* INTERNAL: free a file entry fd */ 00199 static void free_fd(int fd) 00200 { 00201 HANDLE old_handle; 00202 ioinfo *fdinfo; 00203 00204 LOCK_FILES(); 00205 fdinfo = get_ioinfo(fd); 00206 old_handle = fdinfo->handle; 00207 if(fdinfo != &__badioinfo) 00208 { 00209 fdinfo->handle = INVALID_HANDLE_VALUE; 00210 fdinfo->wxflag = 0; 00211 } 00212 TRACE(":fd (%d) freed\n",fd); 00213 if (fd < 3) /* don't use 0,1,2 for user files */ 00214 { 00215 switch (fd) 00216 { 00217 case 0: 00218 if (GetStdHandle(STD_INPUT_HANDLE) == old_handle) SetStdHandle(STD_INPUT_HANDLE, 0); 00219 break; 00220 case 1: 00221 if (GetStdHandle(STD_OUTPUT_HANDLE) == old_handle) SetStdHandle(STD_OUTPUT_HANDLE, 0); 00222 break; 00223 case 2: 00224 if (GetStdHandle(STD_ERROR_HANDLE) == old_handle) SetStdHandle(STD_ERROR_HANDLE, 0); 00225 break; 00226 } 00227 } 00228 else 00229 { 00230 if (fd == fdend - 1) 00231 fdend--; 00232 if (fd < fdstart) 00233 fdstart = fd; 00234 } 00235 UNLOCK_FILES(); 00236 } 00237 00238 /* INTERNAL: Allocate an fd slot from a Win32 HANDLE, starting from fd */ 00239 /* caller must hold the files lock */ 00240 static int alloc_fd_from(HANDLE hand, int flag, int fd) 00241 { 00242 ioinfo *fdinfo; 00243 00244 if (fd >= MAX_FILES) 00245 { 00246 WARN(":files exhausted!\n"); 00247 *_errno() = ENFILE; 00248 return -1; 00249 } 00250 00251 fdinfo = get_ioinfo(fd); 00252 if(fdinfo == &__badioinfo) { 00253 int i; 00254 00255 __pioinfo[fd/FD_BLOCK_SIZE] = calloc(FD_BLOCK_SIZE, sizeof(ioinfo)); 00256 if(!__pioinfo[fd/FD_BLOCK_SIZE]) { 00257 WARN(":out of memory!\n"); 00258 *_errno() = ENOMEM; 00259 return -1; 00260 } 00261 00262 for(i=0; i<FD_BLOCK_SIZE; i++) 00263 __pioinfo[fd/FD_BLOCK_SIZE][i].handle = INVALID_HANDLE_VALUE; 00264 00265 fdinfo = get_ioinfo(fd); 00266 } 00267 00268 fdinfo->handle = hand; 00269 fdinfo->wxflag = WX_OPEN | (flag & (WX_DONTINHERIT | WX_APPEND | WX_TEXT)); 00270 00271 /* locate next free slot */ 00272 if (fd == fdstart && fd == fdend) 00273 fdstart = fdend + 1; 00274 else 00275 while (fdstart < fdend && 00276 get_ioinfo(fdstart)->handle != INVALID_HANDLE_VALUE) 00277 fdstart++; 00278 /* update last fd in use */ 00279 if (fd >= fdend) 00280 fdend = fd + 1; 00281 TRACE("fdstart is %d, fdend is %d\n", fdstart, fdend); 00282 00283 switch (fd) 00284 { 00285 case 0: SetStdHandle(STD_INPUT_HANDLE, hand); break; 00286 case 1: SetStdHandle(STD_OUTPUT_HANDLE, hand); break; 00287 case 2: SetStdHandle(STD_ERROR_HANDLE, hand); break; 00288 } 00289 00290 return fd; 00291 } 00292 00293 /* INTERNAL: Allocate an fd slot from a Win32 HANDLE */ 00294 /*static*/ int alloc_fd(HANDLE hand, int flag) 00295 { 00296 int ret; 00297 00298 LOCK_FILES(); 00299 TRACE(":handle (%p) allocating fd (%d)\n",hand,fdstart); 00300 ret = alloc_fd_from(hand, flag, fdstart); 00301 UNLOCK_FILES(); 00302 return ret; 00303 } 00304 00305 /* INTERNAL: Allocate a FILE* for an fd slot */ 00306 /* caller must hold the files lock */ 00307 static FILE* alloc_fp(void) 00308 { 00309 unsigned int i; 00310 FILE *file; 00311 00312 for (i = 3; i < max_streams; i++) 00313 { 00314 file = get_file(i); 00315 if (!file) 00316 return NULL; 00317 00318 if (file->_flag == 0) 00319 { 00320 if (i == stream_idx) stream_idx++; 00321 return file; 00322 } 00323 } 00324 00325 return NULL; 00326 } 00327 00328 /* INTERNAL: initialize a FILE* from an open fd */ 00329 static int init_fp(FILE* file, int fd, unsigned stream_flags) 00330 { 00331 TRACE(":fd (%d) allocating FILE*\n",fd); 00332 if (!is_valid_fd(fd)) 00333 { 00334 WARN(":invalid fd %d\n",fd); 00335 *__doserrno() = 0; 00336 *_errno() = EBADF; 00337 return -1; 00338 } 00339 memset(file, 0, sizeof(*file)); 00340 file->_file = fd; 00341 file->_flag = stream_flags; 00342 00343 if(file<_iob || file>=_iob+_IOB_ENTRIES) 00344 InitializeCriticalSection(&((file_crit*)file)->crit); 00345 00346 TRACE(":got FILE* (%p)\n",file); 00347 return 0; 00348 } 00349 00350 /* INTERNAL: Create an inheritance data block (for spawned process) 00351 * The inheritance block is made of: 00352 * 00 int nb of file descriptor (NBFD) 00353 * 04 char file flags (wxflag): repeated for each fd 00354 * 4+NBFD HANDLE file handle: repeated for each fd 00355 */ 00356 unsigned create_io_inherit_block(WORD *size, BYTE **block) 00357 { 00358 int fd; 00359 char* wxflag_ptr; 00360 HANDLE* handle_ptr; 00361 ioinfo* fdinfo; 00362 00363 *size = sizeof(unsigned) + (sizeof(char) + sizeof(HANDLE)) * fdend; 00364 *block = calloc(*size, 1); 00365 if (!*block) 00366 { 00367 *size = 0; 00368 return FALSE; 00369 } 00370 wxflag_ptr = (char*)*block + sizeof(unsigned); 00371 handle_ptr = (HANDLE*)(wxflag_ptr + fdend * sizeof(char)); 00372 00373 *(unsigned*)*block = fdend; 00374 for (fd = 0; fd < fdend; fd++) 00375 { 00376 /* to be inherited, we need it to be open, and that DONTINHERIT isn't set */ 00377 fdinfo = get_ioinfo(fd); 00378 if ((fdinfo->wxflag & (WX_OPEN | WX_DONTINHERIT)) == WX_OPEN) 00379 { 00380 *wxflag_ptr = fdinfo->wxflag; 00381 *handle_ptr = fdinfo->handle; 00382 } 00383 else 00384 { 00385 *wxflag_ptr = 0; 00386 *handle_ptr = INVALID_HANDLE_VALUE; 00387 } 00388 wxflag_ptr++; handle_ptr++; 00389 } 00390 return TRUE; 00391 } 00392 00393 /* INTERNAL: Set up all file descriptors, 00394 * as well as default streams (stdin, stderr and stdout) 00395 */ 00396 void msvcrt_init_io(void) 00397 { 00398 STARTUPINFOA si; 00399 int i; 00400 ioinfo *fdinfo; 00401 00402 InitializeCriticalSection(&file_cs); 00403 file_cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": file_cs"); 00404 GetStartupInfoA(&si); 00405 if (si.cbReserved2 >= sizeof(unsigned int) && si.lpReserved2 != NULL) 00406 { 00407 BYTE* wxflag_ptr; 00408 HANDLE* handle_ptr; 00409 unsigned int count; 00410 00411 count = *(unsigned*)si.lpReserved2; 00412 wxflag_ptr = si.lpReserved2 + sizeof(unsigned); 00413 handle_ptr = (HANDLE*)(wxflag_ptr + count); 00414 00415 count = min(count, (si.cbReserved2 - sizeof(unsigned)) / (sizeof(HANDLE) + 1)); 00416 count = min(count, MAX_FILES); 00417 for (i = 0; i < count; i++) 00418 { 00419 if ((*wxflag_ptr & WX_OPEN) && *handle_ptr != INVALID_HANDLE_VALUE) 00420 alloc_fd_from(*handle_ptr, *wxflag_ptr, i); 00421 00422 wxflag_ptr++; handle_ptr++; 00423 } 00424 fdend = max( 3, count ); 00425 for (fdstart = 3; fdstart < fdend; fdstart++) 00426 if (get_ioinfo(fdstart)->handle == INVALID_HANDLE_VALUE) break; 00427 } 00428 00429 if(!__pioinfo[0]) 00430 alloc_fd_from(INVALID_HANDLE_VALUE, 0, 3); 00431 00432 fdinfo = get_ioinfo(0); 00433 if (!(fdinfo->wxflag & WX_OPEN) || fdinfo->handle == INVALID_HANDLE_VALUE) 00434 { 00435 HANDLE std = GetStdHandle(STD_INPUT_HANDLE); 00436 #ifndef __REACTOS__ 00437 if (std != INVALID_HANDLE_VALUE && DuplicateHandle(GetCurrentProcess(), std, 00438 GetCurrentProcess(), &fdinfo->handle, 00439 0, TRUE, DUPLICATE_SAME_ACCESS)) 00440 #else 00441 fdinfo->handle = std; 00442 #endif 00443 fdinfo->wxflag = WX_OPEN | WX_TEXT; 00444 } 00445 00446 fdinfo = get_ioinfo(1); 00447 if (!(fdinfo->wxflag & WX_OPEN) || fdinfo->handle == INVALID_HANDLE_VALUE) 00448 { 00449 HANDLE std = GetStdHandle(STD_OUTPUT_HANDLE); 00450 #ifndef __REACTOS__ 00451 if (std != INVALID_HANDLE_VALUE && DuplicateHandle(GetCurrentProcess(), std, 00452 GetCurrentProcess(), &fdinfo->handle, 00453 0, TRUE, DUPLICATE_SAME_ACCESS)) 00454 #else 00455 fdinfo->handle = std; 00456 #endif 00457 fdinfo->wxflag = WX_OPEN | WX_TEXT; 00458 } 00459 00460 fdinfo = get_ioinfo(2); 00461 if (!(fdinfo->wxflag & WX_OPEN) || fdinfo->handle == INVALID_HANDLE_VALUE) 00462 { 00463 HANDLE std = GetStdHandle(STD_ERROR_HANDLE); 00464 #ifndef __REACTOS__ 00465 if (std != INVALID_HANDLE_VALUE && DuplicateHandle(GetCurrentProcess(), std, 00466 GetCurrentProcess(), &fdinfo->handle, 00467 0, TRUE, DUPLICATE_SAME_ACCESS)) 00468 #else 00469 fdinfo->handle = std; 00470 #endif 00471 fdinfo->wxflag = WX_OPEN | WX_TEXT; 00472 } 00473 00474 TRACE(":handles (%p)(%p)(%p)\n", get_ioinfo(0)->handle, 00475 get_ioinfo(1)->handle, get_ioinfo(2)->handle); 00476 00477 memset(_iob,0,3*sizeof(FILE)); 00478 for (i = 0; i < 3; i++) 00479 { 00480 /* FILE structs for stdin/out/err are static and never deleted */ 00481 _iob[i]._file = i; 00482 _iob[i]._tmpfname = NULL; 00483 _iob[i]._flag = (i == 0) ? _IOREAD : _IOWRT; 00484 } 00485 stream_idx = 3; 00486 } 00487 00488 /* INTERNAL: Flush stdio file buffer */ 00489 static int flush_buffer(FILE* file) 00490 { 00491 if(file->_bufsiz) { 00492 int cnt=file->_ptr-file->_base; 00493 if(cnt>0 && _write(file->_file, file->_base, cnt) != cnt) { 00494 file->_flag |= _IOERR; 00495 return EOF; 00496 } 00497 file->_ptr=file->_base; 00498 file->_cnt=file->_bufsiz; 00499 } 00500 return 0; 00501 } 00502 00503 /* INTERNAL: Allocate stdio file buffer */ 00504 /*static*/ void alloc_buffer(FILE* file) 00505 { 00506 file->_base = calloc(BUFSIZ,1); 00507 if(file->_base) { 00508 file->_bufsiz = BUFSIZ; 00509 file->_flag |= _IOMYBUF; 00510 } else { 00511 file->_base = (char*)(&file->_charbuf); 00512 /* put here 2 ??? */ 00513 file->_bufsiz = sizeof(file->_charbuf); 00514 } 00515 file->_ptr = file->_base; 00516 file->_cnt = 0; 00517 } 00518 00519 /* INTERNAL: Convert integer to base32 string (0-9a-v), 0 becomes "" */ 00520 static int int_to_base32(int num, char *str) 00521 { 00522 char *p; 00523 int n = num; 00524 int digits = 0; 00525 00526 while (n != 0) 00527 { 00528 n >>= 5; 00529 digits++; 00530 } 00531 p = str + digits; 00532 *p = 0; 00533 while (--p >= str) 00534 { 00535 *p = (num & 31) + '0'; 00536 if (*p > '9') 00537 *p += ('a' - '0' - 10); 00538 num >>= 5; 00539 } 00540 00541 return digits; 00542 } 00543 00544 /* INTERNAL: wide character version of int_to_base32 */ 00545 static int int_to_base32_w(int num, wchar_t *str) 00546 { 00547 wchar_t *p; 00548 int n = num; 00549 int digits = 0; 00550 00551 while (n != 0) 00552 { 00553 n >>= 5; 00554 digits++; 00555 } 00556 p = str + digits; 00557 *p = 0; 00558 while (--p >= str) 00559 { 00560 *p = (num & 31) + '0'; 00561 if (*p > '9') 00562 *p += ('a' - '0' - 10); 00563 num >>= 5; 00564 } 00565 00566 return digits; 00567 } 00568 00569 /* INTERNAL: Create a wide string from an ascii string */ 00570 wchar_t *msvcrt_wstrdupa(const char *str) 00571 { 00572 const unsigned int len = strlen(str) + 1 ; 00573 wchar_t *wstr = malloc(len* sizeof (wchar_t)); 00574 if (!wstr) 00575 return NULL; 00576 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED,str,len,wstr,len); 00577 return wstr; 00578 } 00579 00580 /********************************************************************* 00581 * __iob_func(MSVCRT.@) 00582 */ 00583 FILE * CDECL __iob_func(void) 00584 { 00585 return &_iob[0]; 00586 } 00587 00588 /********************************************************************* 00589 * _access (MSVCRT.@) 00590 */ 00591 int CDECL _access(const char *filename, int mode) 00592 { 00593 DWORD attr = GetFileAttributesA(filename); 00594 00595 TRACE("(%s,%d) %d\n",filename,mode,attr); 00596 00597 if (!filename || attr == INVALID_FILE_ATTRIBUTES) 00598 { 00599 _dosmaperr(GetLastError()); 00600 return -1; 00601 } 00602 if ((attr & FILE_ATTRIBUTE_READONLY) && (mode & W_OK)) 00603 { 00604 _set_errno(ERROR_ACCESS_DENIED); 00605 return -1; 00606 } 00607 return 0; 00608 } 00609 00610 /********************************************************************* 00611 * _access_s (MSVCRT.@) 00612 */ 00613 int CDECL _access_s(const char *filename, int mode) 00614 { 00615 if (!MSVCRT_CHECK_PMT(filename != NULL) || 00616 !MSVCRT_CHECK_PMT((mode & ~(R_OK | W_OK)) == 0)) 00617 { 00618 _set_errno(EINVAL); 00619 return -1; 00620 } 00621 00622 return _access(filename, mode); 00623 } 00624 00625 /********************************************************************* 00626 * _waccess (MSVCRT.@) 00627 */ 00628 int CDECL _waccess(const wchar_t *filename, int mode) 00629 { 00630 DWORD attr = GetFileAttributesW(filename); 00631 00632 TRACE("(%s,%d) %d\n",debugstr_w(filename),mode,attr); 00633 00634 if (!filename || attr == INVALID_FILE_ATTRIBUTES) 00635 { 00636 _dosmaperr(GetLastError()); 00637 return -1; 00638 } 00639 if ((attr & FILE_ATTRIBUTE_READONLY) && (mode & W_OK)) 00640 { 00641 _set_errno(ERROR_ACCESS_DENIED); 00642 return -1; 00643 } 00644 return 0; 00645 } 00646 00647 /********************************************************************* 00648 * _waccess_s (MSVCRT.@) 00649 */ 00650 int CDECL _waccess_s(const wchar_t *filename, int mode) 00651 { 00652 if (!MSVCRT_CHECK_PMT(filename != NULL) || 00653 !MSVCRT_CHECK_PMT((mode & ~(R_OK | W_OK)) == 0)) 00654 { 00655 *_errno() = EINVAL; 00656 return -1; 00657 } 00658 00659 return _waccess(filename, mode); 00660 } 00661 00662 /********************************************************************* 00663 * _chmod (MSVCRT.@) 00664 */ 00665 int CDECL _chmod(const char *path, int flags) 00666 { 00667 DWORD oldFlags = GetFileAttributesA(path); 00668 00669 if (oldFlags != INVALID_FILE_ATTRIBUTES) 00670 { 00671 DWORD newFlags = (flags & _S_IWRITE)? oldFlags & ~FILE_ATTRIBUTE_READONLY: 00672 oldFlags | FILE_ATTRIBUTE_READONLY; 00673 00674 if (newFlags == oldFlags || SetFileAttributesA(path, newFlags)) 00675 return 0; 00676 } 00677 _dosmaperr(GetLastError()); 00678 return -1; 00679 } 00680 00681 /********************************************************************* 00682 * _wchmod (MSVCRT.@) 00683 */ 00684 int CDECL _wchmod(const wchar_t *path, int flags) 00685 { 00686 DWORD oldFlags = GetFileAttributesW(path); 00687 00688 if (oldFlags != INVALID_FILE_ATTRIBUTES) 00689 { 00690 DWORD newFlags = (flags & _S_IWRITE)? oldFlags & ~FILE_ATTRIBUTE_READONLY: 00691 oldFlags | FILE_ATTRIBUTE_READONLY; 00692 00693 if (newFlags == oldFlags || SetFileAttributesW(path, newFlags)) 00694 return 0; 00695 } 00696 _dosmaperr(GetLastError()); 00697 return -1; 00698 } 00699 00700 /********************************************************************* 00701 * _unlink (MSVCRT.@) 00702 */ 00703 int CDECL _unlink(const char *path) 00704 { 00705 TRACE("%s\n",debugstr_a(path)); 00706 if(DeleteFileA(path)) 00707 return 0; 00708 TRACE("failed (%d)\n",GetLastError()); 00709 _dosmaperr(GetLastError()); 00710 return -1; 00711 } 00712 00713 /********************************************************************* 00714 * _wunlink (MSVCRT.@) 00715 */ 00716 int CDECL _wunlink(const wchar_t *path) 00717 { 00718 TRACE("(%s)\n",debugstr_w(path)); 00719 if(DeleteFileW(path)) 00720 return 0; 00721 TRACE("failed (%d)\n",GetLastError()); 00722 _dosmaperr(GetLastError()); 00723 return -1; 00724 } 00725 00726 /* _flushall calls fflush which calls _flushall */ 00727 int CDECL fflush(FILE* file); 00728 00729 /********************************************************************* 00730 * _flushall (MSVCRT.@) 00731 */ 00732 int CDECL _flushall(void) 00733 { 00734 int i, num_flushed = 0; 00735 FILE *file; 00736 00737 LOCK_FILES(); 00738 for (i = 3; i < stream_idx; i++) { 00739 file = get_file(i); 00740 00741 if (file->_flag) 00742 { 00743 if(file->_flag & _IOWRT) { 00744 fflush(file); 00745 num_flushed++; 00746 } 00747 } 00748 } 00749 UNLOCK_FILES(); 00750 00751 TRACE(":flushed (%d) handles\n",num_flushed); 00752 return num_flushed; 00753 } 00754 00755 /********************************************************************* 00756 * fflush (MSVCRT.@) 00757 */ 00758 int CDECL fflush(FILE* file) 00759 { 00760 if(!file) { 00761 _flushall(); 00762 } else if(file->_flag & _IOWRT) { 00763 int res; 00764 00765 _lock_file(file); 00766 res = flush_buffer(file); 00767 _unlock_file(file); 00768 00769 return res; 00770 } 00771 return 0; 00772 } 00773 00774 /********************************************************************* 00775 * _close (MSVCRT.@) 00776 */ 00777 int CDECL _close(int fd) 00778 { 00779 HANDLE hand; 00780 int ret; 00781 00782 LOCK_FILES(); 00783 hand = fdtoh(fd); 00784 TRACE(":fd (%d) handle (%p)\n",fd,hand); 00785 if (hand == INVALID_HANDLE_VALUE) 00786 ret = -1; 00787 else if (!CloseHandle(hand)) 00788 { 00789 WARN(":failed-last error (%d)\n",GetLastError()); 00790 _dosmaperr(GetLastError()); 00791 ret = -1; 00792 } 00793 else 00794 { 00795 free_fd(fd); 00796 ret = 0; 00797 } 00798 UNLOCK_FILES(); 00799 TRACE(":ok\n"); 00800 return ret; 00801 } 00802 00803 /********************************************************************* 00804 * _commit (MSVCRT.@) 00805 */ 00806 int CDECL _commit(int fd) 00807 { 00808 HANDLE hand = fdtoh(fd); 00809 00810 TRACE(":fd (%d) handle (%p)\n",fd,hand); 00811 if (hand == INVALID_HANDLE_VALUE) 00812 return -1; 00813 00814 if (!FlushFileBuffers(hand)) 00815 { 00816 if (GetLastError() == ERROR_INVALID_HANDLE) 00817 { 00818 /* FlushFileBuffers fails for console handles 00819 * so we ignore this error. 00820 */ 00821 return 0; 00822 } 00823 TRACE(":failed-last error (%d)\n",GetLastError()); 00824 _dosmaperr(GetLastError()); 00825 return -1; 00826 } 00827 TRACE(":ok\n"); 00828 return 0; 00829 } 00830 00831 /********************************************************************* 00832 * _dup2 (MSVCRT.@) 00833 * NOTES 00834 * MSDN isn't clear on this point, but the remarks for _pipe 00835 * indicate file descriptors duplicated with _dup and _dup2 are always 00836 * inheritable. 00837 */ 00838 int CDECL _dup2(int od, int nd) 00839 { 00840 int ret; 00841 00842 TRACE("(od=%d, nd=%d)\n", od, nd); 00843 LOCK_FILES(); 00844 if (nd < MAX_FILES && nd >= 0 && is_valid_fd(od)) 00845 { 00846 HANDLE handle; 00847 00848 if (DuplicateHandle(GetCurrentProcess(), get_ioinfo(od)->handle, 00849 GetCurrentProcess(), &handle, 0, TRUE, DUPLICATE_SAME_ACCESS)) 00850 { 00851 int wxflag = get_ioinfo(od)->wxflag & ~_O_NOINHERIT; 00852 00853 if (is_valid_fd(nd)) 00854 _close(nd); 00855 ret = alloc_fd_from(handle, wxflag, nd); 00856 if (ret == -1) 00857 { 00858 CloseHandle(handle); 00859 *_errno() = EMFILE; 00860 } 00861 else 00862 { 00863 /* _dup2 returns 0, not nd, on success */ 00864 ret = 0; 00865 } 00866 } 00867 else 00868 { 00869 ret = -1; 00870 _dosmaperr(GetLastError()); 00871 } 00872 } 00873 else 00874 { 00875 *_errno() = EBADF; 00876 ret = -1; 00877 } 00878 UNLOCK_FILES(); 00879 return ret; 00880 } 00881 00882 /********************************************************************* 00883 * _dup (MSVCRT.@) 00884 */ 00885 int CDECL _dup(int od) 00886 { 00887 int fd, ret; 00888 00889 LOCK_FILES(); 00890 fd = fdstart; 00891 if (_dup2(od, fd) == 0) 00892 ret = fd; 00893 else 00894 ret = -1; 00895 UNLOCK_FILES(); 00896 return ret; 00897 } 00898 00899 /********************************************************************* 00900 * _eof (MSVCRT.@) 00901 */ 00902 int CDECL _eof(int fd) 00903 { 00904 DWORD curpos,endpos; 00905 LONG hcurpos,hendpos; 00906 HANDLE hand = fdtoh(fd); 00907 00908 TRACE(":fd (%d) handle (%p)\n",fd,hand); 00909 00910 if (hand == INVALID_HANDLE_VALUE) 00911 return -1; 00912 00913 if (get_ioinfo(fd)->wxflag & WX_ATEOF) return TRUE; 00914 00915 /* Otherwise we do it the hard way */ 00916 hcurpos = hendpos = 0; 00917 curpos = SetFilePointer(hand, 0, &hcurpos, FILE_CURRENT); 00918 endpos = SetFilePointer(hand, 0, &hendpos, FILE_END); 00919 00920 if (curpos == endpos && hcurpos == hendpos) 00921 { 00922 /* FIXME: shouldn't WX_ATEOF be set here? */ 00923 return TRUE; 00924 } 00925 00926 SetFilePointer(hand, curpos, &hcurpos, FILE_BEGIN); 00927 return FALSE; 00928 } 00929 00930 /********************************************************************* 00931 * _fcloseall (MSVCRT.@) 00932 */ 00933 int CDECL _fcloseall(void) 00934 { 00935 int num_closed = 0, i; 00936 FILE *file; 00937 00938 LOCK_FILES(); 00939 for (i = 3; i < stream_idx; i++) { 00940 file = get_file(i); 00941 00942 if (file->_flag && !fclose(file)) 00943 num_closed++; 00944 } 00945 UNLOCK_FILES(); 00946 00947 TRACE(":closed (%d) handles\n",num_closed); 00948 return num_closed; 00949 } 00950 00951 /* free everything on process exit */ 00952 void msvcrt_free_io(void) 00953 { 00954 int i; 00955 00956 _fcloseall(); 00957 /* The Win32 _fcloseall() function explicitly doesn't close stdin, 00958 * stdout, and stderr (unlike GNU), so we need to fclose() them here 00959 * or they won't get flushed. 00960 */ 00961 fclose(&_iob[0]); 00962 fclose(&_iob[1]); 00963 fclose(&_iob[2]); 00964 00965 for(i=0; i<sizeof(__pioinfo)/sizeof(__pioinfo[0]); i++) 00966 free(__pioinfo[i]); 00967 00968 for(i=0; i<sizeof(fstream)/sizeof(fstream[0]); i++) 00969 free(fstream[i]); 00970 00971 file_cs.DebugInfo->Spare[0] = 0; 00972 DeleteCriticalSection(&file_cs); 00973 } 00974 00975 /********************************************************************* 00976 * _lseeki64 (MSVCRT.@) 00977 */ 00978 __int64 CDECL _lseeki64(int fd, __int64 offset, int whence) 00979 { 00980 HANDLE hand = fdtoh(fd); 00981 LARGE_INTEGER ofs; 00982 00983 TRACE(":fd (%d) handle (%p)\n",fd,hand); 00984 if (hand == INVALID_HANDLE_VALUE) 00985 return -1; 00986 00987 if (whence < 0 || whence > 2) 00988 { 00989 *_errno() = EINVAL; 00990 return -1; 00991 } 00992 00993 TRACE(":fd (%d) to %s pos %s\n", 00994 fd,wine_dbgstr_longlong(offset), 00995 (whence==SEEK_SET)?"SEEK_SET": 00996 (whence==SEEK_CUR)?"SEEK_CUR": 00997 (whence==SEEK_END)?"SEEK_END":"UNKNOWN"); 00998 00999 /* The MoleBox protection scheme expects msvcrt to use SetFilePointer only, 01000 * so a LARGE_INTEGER offset cannot be passed directly via SetFilePointerEx. */ 01001 ofs.QuadPart = offset; 01002 if ((ofs.u.LowPart = SetFilePointer(hand, ofs.u.LowPart, &ofs.u.HighPart, whence)) != INVALID_SET_FILE_POINTER || 01003 GetLastError() == ERROR_SUCCESS) 01004 { 01005 get_ioinfo(fd)->wxflag &= ~(WX_ATEOF|WX_READEOF); 01006 /* FIXME: What if we seek _to_ EOF - is EOF set? */ 01007 01008 return ofs.QuadPart; 01009 } 01010 TRACE(":error-last error (%d)\n",GetLastError()); 01011 _dosmaperr(GetLastError()); 01012 return -1; 01013 } 01014 01015 /********************************************************************* 01016 * _lseek (MSVCRT.@) 01017 */ 01018 LONG CDECL _lseek(int fd, LONG offset, int whence) 01019 { 01020 return _lseeki64(fd, offset, whence); 01021 } 01022 01023 /********************************************************************* 01024 * _lock_file (MSVCRT.@) 01025 */ 01026 void CDECL _lock_file(FILE *file) 01027 { 01028 if(file>=_iob && file<_iob+_IOB_ENTRIES) 01029 _lock(_STREAM_LOCKS+(file-_iob)); 01030 /* ReactOS: string streams dont need to be locked */ 01031 else if(!(file->_flag & _IOSTRG)) 01032 EnterCriticalSection(&((file_crit*)file)->crit); 01033 } 01034 01035 /********************************************************************* 01036 * _unlock_file (MSVCRT.@) 01037 */ 01038 void CDECL _unlock_file(FILE *file) 01039 { 01040 if(file>=_iob && file<_iob+_IOB_ENTRIES) 01041 _unlock(_STREAM_LOCKS+(file-_iob)); 01042 /* ReactOS: string streams dont need to be locked */ 01043 else if(!(file->_flag & _IOSTRG)) 01044 LeaveCriticalSection(&((file_crit*)file)->crit); 01045 01046 } 01047 01048 /********************************************************************* 01049 * _locking (MSVCRT.@) 01050 * 01051 * This is untested; the underlying LockFile doesn't work yet. 01052 */ 01053 int CDECL _locking(int fd, int mode, LONG nbytes) 01054 { 01055 BOOL ret; 01056 DWORD cur_locn; 01057 HANDLE hand = fdtoh(fd); 01058 01059 TRACE(":fd (%d) handle (%p)\n",fd,hand); 01060 if (hand == INVALID_HANDLE_VALUE) 01061 return -1; 01062 01063 if (mode < 0 || mode > 4) 01064 { 01065 *_errno() = EINVAL; 01066 return -1; 01067 } 01068 01069 TRACE(":fd (%d) by 0x%08x mode %s\n", 01070 fd,nbytes,(mode==_LK_UNLCK)?"_LK_UNLCK": 01071 (mode==_LK_LOCK)?"_LK_LOCK": 01072 (mode==_LK_NBLCK)?"_LK_NBLCK": 01073 (mode==_LK_RLCK)?"_LK_RLCK": 01074 (mode==_LK_NBRLCK)?"_LK_NBRLCK": 01075 "UNKNOWN"); 01076 01077 if ((cur_locn = SetFilePointer(hand, 0L, NULL, SEEK_CUR)) == INVALID_SET_FILE_POINTER) 01078 { 01079 FIXME ("Seek failed\n"); 01080 *_errno() = EINVAL; /* FIXME */ 01081 return -1; 01082 } 01083 if (mode == _LK_LOCK || mode == _LK_RLCK) 01084 { 01085 int nretry = 10; 01086 ret = 1; /* just to satisfy gcc */ 01087 while (nretry--) 01088 { 01089 ret = LockFile(hand, cur_locn, 0L, nbytes, 0L); 01090 if (ret) break; 01091 Sleep(1); 01092 } 01093 } 01094 else if (mode == _LK_UNLCK) 01095 ret = UnlockFile(hand, cur_locn, 0L, nbytes, 0L); 01096 else 01097 ret = LockFile(hand, cur_locn, 0L, nbytes, 0L); 01098 /* FIXME - what about error settings? */ 01099 return ret ? 0 : -1; 01100 } 01101 01102 /********************************************************************* 01103 * _fseeki64 (MSVCRT.@) 01104 */ 01105 int CDECL _fseeki64(FILE* file, __int64 offset, int whence) 01106 { 01107 int ret; 01108 01109 _lock_file(file); 01110 /* Flush output if needed */ 01111 if(file->_flag & _IOWRT) 01112 flush_buffer(file); 01113 01114 if(whence == SEEK_CUR && file->_flag & _IOREAD ) { 01115 offset -= file->_cnt; 01116 if (get_ioinfo(file->_file)->wxflag & WX_TEXT) { 01117 /* Black magic correction for CR removal */ 01118 int i; 01119 for (i=0; i<file->_cnt; i++) { 01120 if (file->_ptr[i] == '\n') 01121 offset--; 01122 } 01123 /* Black magic when reading CR at buffer boundary*/ 01124 if(get_ioinfo(file->_file)->wxflag & WX_READCR) 01125 offset--; 01126 } 01127 } 01128 /* Discard buffered input */ 01129 file->_cnt = 0; 01130 file->_ptr = file->_base; 01131 /* Reset direction of i/o */ 01132 if(file->_flag & _IORW) { 01133 file->_flag &= ~(_IOREAD|_IOWRT); 01134 } 01135 /* Clear end of file flag */ 01136 file->_flag &= ~_IOEOF; 01137 ret = (_lseeki64(file->_file,offset,whence) == -1)?-1:0; 01138 01139 _unlock_file(file); 01140 return ret; 01141 } 01142 01143 /********************************************************************* 01144 * fseek (MSVCRT.@) 01145 */ 01146 int CDECL fseek(FILE* file, long offset, int whence) 01147 { 01148 return _fseeki64( file, offset, whence ); 01149 } 01150 01151 /********************************************************************* 01152 * _chsize (MSVCRT.@) 01153 */ 01154 int CDECL _chsize(int fd, long size) 01155 { 01156 LONG cur, pos; 01157 HANDLE handle; 01158 BOOL ret = FALSE; 01159 01160 TRACE("(fd=%d, size=%d)\n", fd, size); 01161 01162 LOCK_FILES(); 01163 01164 handle = fdtoh(fd); 01165 if (handle != INVALID_HANDLE_VALUE) 01166 { 01167 /* save the current file pointer */ 01168 cur = _lseek(fd, 0, SEEK_CUR); 01169 if (cur >= 0) 01170 { 01171 pos = _lseek(fd, size, SEEK_SET); 01172 if (pos >= 0) 01173 { 01174 ret = SetEndOfFile(handle); 01175 if (!ret) _dosmaperr(GetLastError()); 01176 } 01177 01178 /* restore the file pointer */ 01179 _lseek(fd, cur, SEEK_SET); 01180 } 01181 } 01182 01183 UNLOCK_FILES(); 01184 return ret ? 0 : -1; 01185 } 01186 01187 /********************************************************************* 01188 * clearerr (MSVCRT.@) 01189 */ 01190 void CDECL clearerr(FILE* file) 01191 { 01192 TRACE(":file (%p) fd (%d)\n",file,file->_file); 01193 01194 _lock_file(file); 01195 file->_flag &= ~(_IOERR | _IOEOF); 01196 _unlock_file(file); 01197 } 01198 01199 /********************************************************************* 01200 * rewind (MSVCRT.@) 01201 */ 01202 void CDECL rewind(FILE* file) 01203 { 01204 TRACE(":file (%p) fd (%d)\n",file,file->_file); 01205 01206 _lock_file(file); 01207 fseek(file, 0L, SEEK_SET); 01208 clearerr(file); 01209 _unlock_file(file); 01210 } 01211 01212 static int get_flags(const wchar_t* mode, int *open_flags, int* stream_flags) 01213 { 01214 int plus = strchrW(mode, '+') != NULL; 01215 01216 switch(*mode++) 01217 { 01218 case 'R': case 'r': 01219 *open_flags = plus ? _O_RDWR : _O_RDONLY; 01220 *stream_flags = plus ? _IORW : _IOREAD; 01221 break; 01222 case 'W': case 'w': 01223 *open_flags = _O_CREAT | _O_TRUNC | (plus ? _O_RDWR : _O_WRONLY); 01224 *stream_flags = plus ? _IORW : _IOWRT; 01225 break; 01226 case 'A': case 'a': 01227 *open_flags = _O_CREAT | _O_APPEND | (plus ? _O_RDWR : _O_WRONLY); 01228 *stream_flags = plus ? _IORW : _IOWRT; 01229 break; 01230 default: 01231 _invalid_parameter(NULL, NULL, NULL, 0, 0); 01232 *_errno() = EINVAL; 01233 return -1; 01234 } 01235 01236 while (*mode) 01237 switch (*mode++) 01238 { 01239 case 'B': case 'b': 01240 *open_flags |= _O_BINARY; 01241 *open_flags &= ~_O_TEXT; 01242 break; 01243 case 'T': case 't': 01244 *open_flags |= _O_TEXT; 01245 *open_flags &= ~_O_BINARY; 01246 break; 01247 case '+': 01248 case ' ': 01249 break; 01250 default: 01251 FIXME(":unknown flag %c not supported\n",mode[-1]); 01252 } 01253 return 0; 01254 } 01255 01256 /********************************************************************* 01257 * _fdopen (MSVCRT.@) 01258 */ 01259 FILE* CDECL _fdopen(int fd, const char *mode) 01260 { 01261 FILE *ret; 01262 wchar_t *modeW = NULL; 01263 01264 if (mode && !(modeW = msvcrt_wstrdupa(mode))) return NULL; 01265 01266 ret = _wfdopen(fd, modeW); 01267 01268 free(modeW); 01269 return ret; 01270 } 01271 01272 /********************************************************************* 01273 * _wfdopen (MSVCRT.@) 01274 */ 01275 FILE* CDECL _wfdopen(int fd, const wchar_t *mode) 01276 { 01277 int open_flags, stream_flags; 01278 FILE* file; 01279 01280 if (get_flags(mode, &open_flags, &stream_flags) == -1) return NULL; 01281 01282 LOCK_FILES(); 01283 if (!(file = alloc_fp())) 01284 file = NULL; 01285 else if (init_fp(file, fd, stream_flags) == -1) 01286 { 01287 file->_flag = 0; 01288 file = NULL; 01289 } 01290 else TRACE(":fd (%d) mode (%s) FILE* (%p)\n", fd, debugstr_w(mode), file); 01291 UNLOCK_FILES(); 01292 01293 return file; 01294 } 01295 01296 /********************************************************************* 01297 * _filelength (MSVCRT.@) 01298 */ 01299 LONG CDECL _filelength(int fd) 01300 { 01301 LONG curPos = _lseek(fd, 0, SEEK_CUR); 01302 if (curPos != -1) 01303 { 01304 LONG endPos = _lseek(fd, 0, SEEK_END); 01305 if (endPos != -1) 01306 { 01307 if (endPos != curPos) 01308 _lseek(fd, curPos, SEEK_SET); 01309 return endPos; 01310 } 01311 } 01312 return -1; 01313 } 01314 01315 /********************************************************************* 01316 * _filelengthi64 (MSVCRT.@) 01317 */ 01318 __int64 CDECL _filelengthi64(int fd) 01319 { 01320 __int64 curPos = _lseeki64(fd, 0, SEEK_CUR); 01321 if (curPos != -1) 01322 { 01323 __int64 endPos = _lseeki64(fd, 0, SEEK_END); 01324 if (endPos != -1) 01325 { 01326 if (endPos != curPos) 01327 _lseeki64(fd, curPos, SEEK_SET); 01328 return endPos; 01329 } 01330 } 01331 return -1; 01332 } 01333 01334 /********************************************************************* 01335 * _fileno (MSVCRT.@) 01336 */ 01337 int CDECL _fileno(FILE* file) 01338 { 01339 TRACE(":FILE* (%p) fd (%d)\n",file,file->_file); 01340 return file->_file; 01341 } 01342 01343 /********************************************************************* 01344 * _get_osfhandle (MSVCRT.@) 01345 */ 01346 intptr_t CDECL _get_osfhandle(int fd) 01347 { 01348 HANDLE hand = fdtoh(fd); 01349 TRACE(":fd (%d) handle (%p)\n",fd,hand); 01350 01351 return (intptr_t)hand; 01352 } 01353 01354 /********************************************************************* 01355 * _isatty (MSVCRT.@) 01356 */ 01357 int CDECL _isatty(int fd) 01358 { 01359 HANDLE hand = fdtoh(fd); 01360 01361 TRACE(":fd (%d) handle (%p)\n",fd,hand); 01362 if (hand == INVALID_HANDLE_VALUE) 01363 return 0; 01364 01365 return GetFileType(hand) == FILE_TYPE_CHAR? 1 : 0; 01366 } 01367 01368 /********************************************************************* 01369 * _mktemp (MSVCRT.@) 01370 */ 01371 char * CDECL _mktemp(char *pattern) 01372 { 01373 int numX = 0; 01374 char *retVal = pattern; 01375 int id; 01376 char letter = 'a'; 01377 01378 while(*pattern) 01379 numX = (*pattern++ == 'X')? numX + 1 : 0; 01380 if (numX < 5) 01381 return NULL; 01382 pattern--; 01383 id = GetCurrentProcessId(); 01384 numX = 6; 01385 while(numX--) 01386 { 01387 int tempNum = id / 10; 01388 *pattern-- = id - (tempNum * 10) + '0'; 01389 id = tempNum; 01390 } 01391 pattern++; 01392 do 01393 { 01394 *pattern = letter++; 01395 if (GetFileAttributesA(retVal) == INVALID_FILE_ATTRIBUTES && 01396 GetLastError() == ERROR_FILE_NOT_FOUND) 01397 return retVal; 01398 } while(letter <= 'z'); 01399 return NULL; 01400 } 01401 01402 /********************************************************************* 01403 * _wmktemp (MSVCRT.@) 01404 */ 01405 wchar_t * CDECL _wmktemp(wchar_t *pattern) 01406 { 01407 int numX = 0; 01408 wchar_t *retVal = pattern; 01409 int id; 01410 wchar_t letter = 'a'; 01411 01412 while(*pattern) 01413 numX = (*pattern++ == 'X')? numX + 1 : 0; 01414 if (numX < 5) 01415 return NULL; 01416 pattern--; 01417 id = GetCurrentProcessId(); 01418 numX = 6; 01419 while(numX--) 01420 { 01421 int tempNum = id / 10; 01422 *pattern-- = id - (tempNum * 10) + '0'; 01423 id = tempNum; 01424 } 01425 pattern++; 01426 do 01427 { 01428 if (GetFileAttributesW(retVal) == INVALID_FILE_ATTRIBUTES && 01429 GetLastError() == ERROR_FILE_NOT_FOUND) 01430 return retVal; 01431 *pattern = letter++; 01432 } while(letter != '|'); 01433 return NULL; 01434 } 01435 01436 /*static*/ unsigned split_oflags(unsigned oflags) 01437 { 01438 int wxflags = 0; 01439 unsigned unsupp; /* until we support everything */ 01440 01441 if (oflags & _O_APPEND) wxflags |= WX_APPEND; 01442 if (oflags & _O_BINARY) {/* Nothing to do */} 01443 else if (oflags & _O_TEXT) wxflags |= WX_TEXT; 01444 else if (*__p__fmode() & _O_BINARY) {/* Nothing to do */} 01445 else wxflags |= WX_TEXT; /* default to TEXT*/ 01446 if (oflags & _O_NOINHERIT) wxflags |= WX_DONTINHERIT; 01447 01448 if ((unsupp = oflags & ~( 01449 _O_BINARY|_O_TEXT|_O_APPEND| 01450 _O_TRUNC|_O_EXCL|_O_CREAT| 01451 _O_RDWR|_O_WRONLY|_O_TEMPORARY| 01452 _O_NOINHERIT| 01453 _O_SEQUENTIAL|_O_RANDOM|_O_SHORT_LIVED 01454 ))) 01455 ERR(":unsupported oflags 0x%04x\n",unsupp); 01456 01457 return wxflags; 01458 } 01459 01460 /********************************************************************* 01461 * _pipe (MSVCRT.@) 01462 */ 01463 int CDECL _pipe(int *pfds, unsigned int psize, int textmode) 01464 { 01465 int ret = -1; 01466 SECURITY_ATTRIBUTES sa; 01467 HANDLE readHandle, writeHandle; 01468 01469 if (!pfds) 01470 { 01471 *_errno() = EINVAL; 01472 return -1; 01473 } 01474 01475 sa.nLength = sizeof(SECURITY_ATTRIBUTES); 01476 sa.bInheritHandle = !(textmode & _O_NOINHERIT); 01477 sa.lpSecurityDescriptor = NULL; 01478 if (CreatePipe(&readHandle, &writeHandle, &sa, psize)) 01479 { 01480 unsigned int wxflags = split_oflags(textmode); 01481 int fd; 01482 01483 LOCK_FILES(); 01484 fd = alloc_fd(readHandle, wxflags); 01485 if (fd != -1) 01486 { 01487 pfds[0] = fd; 01488 fd = alloc_fd(writeHandle, wxflags); 01489 if (fd != -1) 01490 { 01491 pfds[1] = fd; 01492 ret = 0; 01493 } 01494 else 01495 { 01496 _close(pfds[0]); 01497 CloseHandle(writeHandle); 01498 *_errno() = EMFILE; 01499 } 01500 } 01501 else 01502 { 01503 CloseHandle(readHandle); 01504 CloseHandle(writeHandle); 01505 *_errno() = EMFILE; 01506 } 01507 UNLOCK_FILES(); 01508 } 01509 else 01510 _dosmaperr(GetLastError()); 01511 01512 return ret; 01513 } 01514 01515 /********************************************************************* 01516 * _sopen_s (MSVCRT.@) 01517 */ 01518 int CDECL _sopen_s( int *fd, const char *path, int oflags, int shflags, int pmode ) 01519 { 01520 DWORD access = 0, creation = 0, attrib; 01521 DWORD sharing; 01522 int wxflag; 01523 HANDLE hand; 01524 SECURITY_ATTRIBUTES sa; 01525 01526 TRACE("fd*: %p file: (%s) oflags: 0x%04x shflags: 0x%04x pmode: 0x%04x\n", 01527 fd, path, oflags, shflags, pmode); 01528 01529 if (!fd) 01530 { 01531 MSVCRT_INVALID_PMT("null out fd pointer"); 01532 *_errno() = EINVAL; 01533 return EINVAL; 01534 } 01535 01536 *fd = -1; 01537 wxflag = split_oflags(oflags); 01538 switch (oflags & (_O_RDONLY | _O_WRONLY | _O_RDWR)) 01539 { 01540 case _O_RDONLY: access |= GENERIC_READ; break; 01541 case _O_WRONLY: access |= GENERIC_WRITE; break; 01542 case _O_RDWR: access |= GENERIC_WRITE | GENERIC_READ; break; 01543 } 01544 01545 if (oflags & _O_CREAT) 01546 { 01547 if(pmode & ~(_S_IREAD | _S_IWRITE)) 01548 FIXME(": pmode 0x%04x ignored\n", pmode); 01549 else 01550 WARN(": pmode 0x%04x ignored\n", pmode); 01551 01552 if (oflags & _O_EXCL) 01553 creation = CREATE_NEW; 01554 else if (oflags & _O_TRUNC) 01555 creation = CREATE_ALWAYS; 01556 else 01557 creation = OPEN_ALWAYS; 01558 } 01559 else /* no _O_CREAT */ 01560 { 01561 if (oflags & _O_TRUNC) 01562 creation = TRUNCATE_EXISTING; 01563 else 01564 creation = OPEN_EXISTING; 01565 } 01566 01567 switch( shflags ) 01568 { 01569 case _SH_DENYRW: 01570 sharing = 0L; 01571 break; 01572 case _SH_DENYWR: 01573 sharing = FILE_SHARE_READ; 01574 break; 01575 case _SH_DENYRD: 01576 sharing = FILE_SHARE_WRITE; 01577 break; 01578 case _SH_DENYNO: 01579 sharing = FILE_SHARE_READ | FILE_SHARE_WRITE; 01580 break; 01581 default: 01582 ERR( "Unhandled shflags 0x%x\n", shflags ); 01583 return EINVAL; 01584 } 01585 attrib = FILE_ATTRIBUTE_NORMAL; 01586 01587 if (oflags & _O_TEMPORARY) 01588 { 01589 attrib |= FILE_FLAG_DELETE_ON_CLOSE; 01590 access |= DELETE; 01591 sharing |= FILE_SHARE_DELETE; 01592 } 01593 01594 sa.nLength = sizeof( SECURITY_ATTRIBUTES ); 01595 sa.lpSecurityDescriptor = NULL; 01596 sa.bInheritHandle = (oflags & _O_NOINHERIT) ? FALSE : TRUE; 01597 01598 hand = CreateFileA(path, access, sharing, &sa, creation, attrib, 0); 01599 if (hand == INVALID_HANDLE_VALUE) { 01600 WARN(":failed-last error (%d)\n", GetLastError()); 01601 _dosmaperr(GetLastError()); 01602 return *_errno(); 01603 } 01604 01605 *fd = alloc_fd(hand, wxflag); 01606 01607 TRACE(":fd (%d) handle (%p)\n", *fd, hand); 01608 return 0; 01609 } 01610 01611 /********************************************************************* 01612 * _sopen (MSVCRT.@) 01613 */ 01614 int CDECL _sopen( const char *path, int oflags, int shflags, ... ) 01615 { 01616 int pmode; 01617 int fd; 01618 01619 if (oflags & _O_CREAT) 01620 { 01621 va_list ap; 01622 01623 va_start(ap, shflags); 01624 pmode = va_arg(ap, int); 01625 va_end(ap); 01626 } 01627 else 01628 pmode = 0; 01629 01630 _sopen_s(&fd, path, oflags, shflags, pmode); 01631 return fd; 01632 } 01633 01634 /********************************************************************* 01635 * _wsopen_s (MSVCRT.@) 01636 */ 01637 int CDECL _wsopen_s( int *fd, const wchar_t* path, int oflags, int shflags, int pmode ) 01638 { 01639 DWORD access = 0, creation = 0, attrib; 01640 SECURITY_ATTRIBUTES sa; 01641 DWORD sharing; 01642 int wxflag; 01643 HANDLE hand; 01644 01645 TRACE("fd*: %p :file (%s) oflags: 0x%04x shflags: 0x%04x pmode: 0x%04x\n", 01646 fd, debugstr_w(path), oflags, shflags, pmode); 01647 01648 if (!fd) 01649 { 01650 MSVCRT_INVALID_PMT("null out fd pointer"); 01651 *_errno() = EINVAL; 01652 return EINVAL; 01653 } 01654 01655 *fd = -1; 01656 wxflag = split_oflags(oflags); 01657 switch (oflags & (_O_RDONLY | _O_WRONLY | _O_RDWR)) 01658 { 01659 case _O_RDONLY: access |= GENERIC_READ; break; 01660 case _O_WRONLY: access |= GENERIC_WRITE; break; 01661 case _O_RDWR: access |= GENERIC_WRITE | GENERIC_READ; break; 01662 } 01663 01664 if (oflags & _O_CREAT) 01665 { 01666 if(pmode & ~(_S_IREAD | _S_IWRITE)) 01667 FIXME(": pmode 0x%04x ignored\n", pmode); 01668 else 01669 WARN(": pmode 0x%04x ignored\n", pmode); 01670 01671 if (oflags & _O_EXCL) 01672 creation = CREATE_NEW; 01673 else if (oflags & _O_TRUNC) 01674 creation = CREATE_ALWAYS; 01675 else 01676 creation = OPEN_ALWAYS; 01677 } 01678 else /* no _O_CREAT */ 01679 { 01680 if (oflags & _O_TRUNC) 01681 creation = TRUNCATE_EXISTING; 01682 else 01683 creation = OPEN_EXISTING; 01684 } 01685 01686 switch( shflags ) 01687 { 01688 case _SH_DENYRW: 01689 sharing = 0L; 01690 break; 01691 case _SH_DENYWR: 01692 sharing = FILE_SHARE_READ; 01693 break; 01694 case _SH_DENYRD: 01695 sharing = FILE_SHARE_WRITE; 01696 break; 01697 case _SH_DENYNO: 01698 sharing = FILE_SHARE_READ | FILE_SHARE_WRITE; 01699 break; 01700 default: 01701 ERR( "Unhandled shflags 0x%x\n", shflags ); 01702 return EINVAL; 01703 } 01704 attrib = FILE_ATTRIBUTE_NORMAL; 01705 01706 if (oflags & _O_TEMPORARY) 01707 { 01708 attrib |= FILE_FLAG_DELETE_ON_CLOSE; 01709 access |= DELETE; 01710 sharing |= FILE_SHARE_DELETE; 01711 } 01712 01713 sa.nLength = sizeof( SECURITY_ATTRIBUTES ); 01714 sa.lpSecurityDescriptor = NULL; 01715 sa.bInheritHandle = (oflags & _O_NOINHERIT) ? FALSE : TRUE; 01716 01717 hand = CreateFileW(path, access, sharing, &sa, creation, attrib, 0); 01718 01719 if (hand == INVALID_HANDLE_VALUE) { 01720 WARN(":failed-last error (%d)\n",GetLastError()); 01721 _dosmaperr(GetLastError()); 01722 return *_errno(); 01723 } 01724 01725 *fd = alloc_fd(hand, wxflag); 01726 01727 TRACE(":fd (%d) handle (%p)\n", *fd, hand); 01728 return 0; 01729 } 01730 01731 /********************************************************************* 01732 * _wsopen (MSVCRT.@) 01733 */ 01734 int CDECL _wsopen( const wchar_t *path, int oflags, int shflags, ... ) 01735 { 01736 int pmode; 01737 int fd; 01738 01739 if (oflags & _O_CREAT) 01740 { 01741 va_list ap; 01742 01743 va_start(ap, shflags); 01744 pmode = va_arg(ap, int); 01745 va_end(ap); 01746 } 01747 else 01748 pmode = 0; 01749 01750 _wsopen_s(&fd, path, oflags, shflags, pmode); 01751 return fd; 01752 } 01753 01754 /********************************************************************* 01755 * _open (MSVCRT.@) 01756 */ 01757 int CDECL _open( const char *path, int flags, ... ) 01758 { 01759 va_list ap; 01760 01761 if (flags & _O_CREAT) 01762 { 01763 int pmode; 01764 va_start(ap, flags); 01765 pmode = va_arg(ap, int); 01766 va_end(ap); 01767 return _sopen( path, flags, _SH_DENYNO, pmode ); 01768 } 01769 else 01770 return _sopen( path, flags, _SH_DENYNO); 01771 } 01772 01773 /********************************************************************* 01774 * _wopen (MSVCRT.@) 01775 */ 01776 int CDECL _wopen(const wchar_t *path,int flags,...) 01777 { 01778 va_list ap; 01779 01780 if (flags & _O_CREAT) 01781 { 01782 int pmode; 01783 va_start(ap, flags); 01784 pmode = va_arg(ap, int); 01785 va_end(ap); 01786 return _wsopen( path, flags, _SH_DENYNO, pmode ); 01787 } 01788 else 01789 return _wsopen( path, flags, _SH_DENYNO); 01790 } 01791 01792 /********************************************************************* 01793 * _creat (MSVCRT.@) 01794 */ 01795 int CDECL _creat(const char *path, int flags) 01796 { 01797 int usedFlags = (flags & _O_TEXT)| _O_CREAT| _O_WRONLY| _O_TRUNC; 01798 return _open(path, usedFlags); 01799 } 01800 01801 /********************************************************************* 01802 * _wcreat (MSVCRT.@) 01803 */ 01804 int CDECL _wcreat(const wchar_t *path, int flags) 01805 { 01806 int usedFlags = (flags & _O_TEXT)| _O_CREAT| _O_WRONLY| _O_TRUNC; 01807 return _wopen(path, usedFlags); 01808 } 01809 01810 /********************************************************************* 01811 * _open_osfhandle (MSVCRT.@) 01812 */ 01813 int CDECL _open_osfhandle(intptr_t handle, int oflags) 01814 { 01815 int fd; 01816 01817 /* _O_RDONLY (0) always matches, so set the read flag 01818 * MFC's CStdioFile clears O_RDONLY (0)! if it wants to write to the 01819 * file, so set the write flag. It also only sets _O_TEXT if it wants 01820 * text - it never sets _O_BINARY. 01821 */ 01822 /* don't let split_oflags() decide the mode if no mode is passed */ 01823 if (!(oflags & (_O_BINARY | _O_TEXT))) 01824 oflags |= _O_BINARY; 01825 01826 fd = alloc_fd((HANDLE)handle, split_oflags(oflags)); 01827 TRACE(":handle (%ld) fd (%d) flags 0x%08x\n", handle, fd, oflags); 01828 return fd; 01829 } 01830 01831 /********************************************************************* 01832 * _rmtmp (MSVCRT.@) 01833 */ 01834 int CDECL _rmtmp(void) 01835 { 01836 int num_removed = 0, i; 01837 FILE *file; 01838 01839 LOCK_FILES(); 01840 for (i = 3; i < stream_idx; i++) { 01841 file = get_file(i); 01842 01843 if (file->_tmpfname) 01844 { 01845 fclose(file); 01846 num_removed++; 01847 } 01848 } 01849 UNLOCK_FILES(); 01850 01851 if (num_removed) 01852 TRACE(":removed (%d) temp files\n",num_removed); 01853 return num_removed; 01854 } 01855 01856 /********************************************************************* 01857 * (internal) read_i 01858 * 01859 * When reading \r as last character in text mode, read() positions 01860 * the file pointer on the \r character while getc() goes on to 01861 * the following \n 01862 */ 01863 static int read_i(int fd, void *buf, unsigned int count) 01864 { 01865 DWORD num_read; 01866 char *bufstart = buf; 01867 HANDLE hand = fdtoh(fd); 01868 ioinfo *fdinfo = get_ioinfo(fd); 01869 01870 if (count == 0) 01871 return 0; 01872 01873 if (fdinfo->wxflag & WX_READEOF) { 01874 fdinfo->wxflag |= WX_ATEOF; 01875 TRACE("already at EOF, returning 0\n"); 01876 return 0; 01877 } 01878 /* Don't trace small reads, it gets *very* annoying */ 01879 if (count > 4) 01880 TRACE(":fd (%d) handle (%p) buf (%p) len (%d)\n",fd,hand,buf,count); 01881 if (hand == INVALID_HANDLE_VALUE) 01882 return -1; 01883 01884 /* Reading single bytes in O_TEXT mode makes things slow 01885 * So read big chunks 01886 */ 01887 if (ReadFile(hand, bufstart, count, &num_read, NULL)) 01888 { 01889 if (count != 0 && num_read == 0) 01890 { 01891 fdinfo->wxflag |= (WX_ATEOF|WX_READEOF); 01892 TRACE(":EOF %s\n",debugstr_an(buf,num_read)); 01893 } 01894 else if (fdinfo->wxflag & WX_TEXT) 01895 { 01896 DWORD i, j; 01897 if (bufstart[num_read-1] == '\r') 01898 { 01899 if(count == 1) 01900 { 01901 fdinfo->wxflag &= ~WX_READCR; 01902 ReadFile(hand, bufstart, 1, &num_read, NULL); 01903 } 01904 else 01905 { 01906 fdinfo->wxflag |= WX_READCR; 01907 num_read--; 01908 } 01909 } 01910 else 01911 fdinfo->wxflag &= ~WX_READCR; 01912 for (i=0, j=0; i<num_read; i++) 01913 { 01914 /* in text mode, a ctrl-z signals EOF */ 01915 if (bufstart[i] == 0x1a) 01916 { 01917 fdinfo->wxflag |= (WX_ATEOF|WX_READEOF); 01918 TRACE(":^Z EOF %s\n",debugstr_an(buf,num_read)); 01919 break; 01920 } 01921 /* in text mode, strip \r if followed by \n. 01922 * BUG: should save state across calls somehow, so CR LF that 01923 * straddles buffer boundary gets recognized properly? 01924 */ 01925 if ((bufstart[i] != '\r') 01926 || ((i+1) < num_read && bufstart[i+1] != '\n')) 01927 bufstart[j++] = bufstart[i]; 01928 } 01929 num_read = j; 01930 } 01931 } 01932 else 01933 { 01934 if (GetLastError() == ERROR_BROKEN_PIPE) 01935 { 01936 TRACE(":end-of-pipe\n"); 01937 fdinfo->wxflag |= (WX_ATEOF|WX_READEOF); 01938 return 0; 01939 } 01940 else 01941 { 01942 TRACE(":failed-last error (%d)\n",GetLastError()); 01943 return -1; 01944 } 01945 } 01946 01947 if (count > 4) 01948 TRACE("(%u), %s\n",num_read,debugstr_an(buf, num_read)); 01949 return num_read; 01950 } 01951 01952 /********************************************************************* 01953 * _read (MSVCRT.@) 01954 */ 01955 int CDECL _read(int fd, void *buf, unsigned int count) 01956 { 01957 int num_read; 01958 num_read = read_i(fd, buf, count); 01959 return num_read; 01960 } 01961 01962 /********************************************************************* 01963 * _setmode (MSVCRT.@) 01964 */ 01965 int CDECL _setmode(int fd,int mode) 01966 { 01967 int ret = get_ioinfo(fd)->wxflag & WX_TEXT ? _O_TEXT : _O_BINARY; 01968 if (mode & (~(_O_TEXT|_O_BINARY))) 01969 FIXME("fd (%d) mode (0x%08x) unknown\n",fd,mode); 01970 if ((mode & _O_TEXT) == _O_TEXT) 01971 get_ioinfo(fd)->wxflag |= WX_TEXT; 01972 else 01973 get_ioinfo(fd)->wxflag &= ~WX_TEXT; 01974 return ret; 01975 } 01976 01977 /********************************************************************* 01978 * _tell (MSVCRT.@) 01979 */ 01980 long CDECL _tell(int fd) 01981 { 01982 return _lseek(fd, 0, SEEK_CUR); 01983 } 01984 01985 /********************************************************************* 01986 * _telli64 (MSVCRT.@) 01987 */ 01988 __int64 CDECL _telli64(int fd) 01989 { 01990 return _lseeki64(fd, 0, SEEK_CUR); 01991 } 01992 01993 /********************************************************************* 01994 * _tempnam (MSVCRT.@) 01995 */ 01996 char * CDECL _tempnam(const char *dir, const char *prefix) 01997 { 01998 char tmpbuf[MAX_PATH]; 01999 const char *tmp_dir = getenv("TMP"); 02000 02001 if (tmp_dir) dir = tmp_dir; 02002 02003 TRACE("dir (%s) prefix (%s)\n",dir,prefix); 02004 if (GetTempFileNameA(dir,prefix,0,tmpbuf)) 02005 { 02006 TRACE("got name (%s)\n",tmpbuf); 02007 DeleteFileA(tmpbuf); 02008 return _strdup(tmpbuf); 02009 } 02010 TRACE("failed (%d)\n",GetLastError()); 02011 return NULL; 02012 } 02013 02014 /********************************************************************* 02015 * _wtempnam (MSVCRT.@) 02016 */ 02017 wchar_t * CDECL _wtempnam(const wchar_t *dir, const wchar_t *prefix) 02018 { 02019 wchar_t tmpbuf[MAX_PATH]; 02020 02021 TRACE("dir (%s) prefix (%s)\n",debugstr_w(dir),debugstr_w(prefix)); 02022 if (GetTempFileNameW(dir,prefix,0,tmpbuf)) 02023 { 02024 TRACE("got name (%s)\n",debugstr_w(tmpbuf)); 02025 DeleteFileW(tmpbuf); 02026 return _wcsdup(tmpbuf); 02027 } 02028 TRACE("failed (%d)\n",GetLastError()); 02029 return NULL; 02030 } 02031 02032 /********************************************************************* 02033 * _umask (MSVCRT.@) 02034 */ 02035 int CDECL _umask(int umask) 02036 { 02037 int old_umask = umask; 02038 TRACE("(%d)\n",umask); 02039 MSVCRT_umask = umask; 02040 return old_umask; 02041 } 02042 02043 /********************************************************************* 02044 * _write (MSVCRT.@) 02045 */ 02046 int CDECL _write(int fd, const void* buf, unsigned int count) 02047 { 02048 DWORD num_written; 02049 HANDLE hand = fdtoh(fd); 02050 02051 /* Don't trace small writes, it gets *very* annoying */ 02052 #if 0 02053 if (count > 32) 02054 TRACE(":fd (%d) handle (%d) buf (%p) len (%d)\n",fd,hand,buf,count); 02055 #endif 02056 if (hand == INVALID_HANDLE_VALUE) 02057 { 02058 *_errno() = EBADF; 02059 return -1; 02060 } 02061 02062 /* If appending, go to EOF */ 02063 if (get_ioinfo(fd)->wxflag & WX_APPEND) 02064 _lseek(fd, 0, FILE_END); 02065 02066 if (!(get_ioinfo(fd)->wxflag & WX_TEXT)) 02067 { 02068 if (WriteFile(hand, buf, count, &num_written, NULL) 02069 && (num_written == count)) 02070 return num_written; 02071 TRACE("WriteFile (fd %d, hand %p) failed-last error (%d)\n", fd, 02072 hand, GetLastError()); 02073 *_errno() = ENOSPC; 02074 } 02075 else 02076 { 02077 unsigned int i, j, nr_lf; 02078 char *p = NULL; 02079 const char *q; 02080 const char *s = buf, *buf_start = buf; 02081 /* find number of \n ( without preceding \r ) */ 02082 for ( nr_lf=0,i = 0; i <count; i++) 02083 { 02084 if (s[i]== '\n') 02085 { 02086 nr_lf++; 02087 /*if ((i >1) && (s[i-1] == '\r')) nr_lf--; */ 02088 } 02089 } 02090 if (nr_lf) 02091 { 02092 if ((q = p = malloc(count + nr_lf))) 02093 { 02094 for (s = buf, i = 0, j = 0; i < count; i++) 02095 { 02096 if (s[i]== '\n') 02097 { 02098 p[j++] = '\r'; 02099 /*if ((i >1) && (s[i-1] == '\r'))j--;*/ 02100 } 02101 p[j++] = s[i]; 02102 } 02103 } 02104 else 02105 { 02106 FIXME("Malloc failed\n"); 02107 nr_lf =0; 02108 q = buf; 02109 } 02110 } 02111 else 02112 q = buf; 02113 02114 if ((WriteFile(hand, q, count+nr_lf, &num_written, NULL) == 0 ) || (num_written != count+nr_lf)) 02115 { 02116 TRACE("WriteFile (fd %d, hand %p) failed-last error (%d), num_written %d\n", 02117 fd, hand, GetLastError(), num_written); 02118 *_errno() = ENOSPC; 02119 if(nr_lf) 02120 free(p); 02121 return s - buf_start; 02122 } 02123 else 02124 { 02125 if(nr_lf) 02126 free(p); 02127 return count; 02128 } 02129 } 02130 return -1; 02131 } 02132 02133 /********************************************************************* 02134 * _putw (MSVCRT.@) 02135 */ 02136 int CDECL _putw(int val, FILE* file) 02137 { 02138 int len; 02139 02140 _lock_file(file); 02141 len = _write(file->_file, &val, sizeof(val)); 02142 if (len == sizeof(val)) { 02143 _unlock_file(file); 02144 return val; 02145 } 02146 02147 file->_flag |= _IOERR; 02148 _unlock_file(file); 02149 return EOF; 02150 } 02151 02152 /********************************************************************* 02153 * fclose (MSVCRT.@) 02154 */ 02155 int CDECL fclose(FILE* file) 02156 { 02157 int r, flag; 02158 02159 _lock_file(file); 02160 flag = file->_flag; 02161 free(file->_tmpfname); 02162 file->_tmpfname = NULL; 02163 /* flush stdio buffers */ 02164 if(file->_flag & _IOWRT) 02165 fflush(file); 02166 if(file->_flag & _IOMYBUF) 02167 free(file->_base); 02168 02169 r=_close(file->_file); 02170 02171 file->_flag = 0; 02172 _unlock_file(file); 02173 if(file<_iob || file>=_iob+_IOB_ENTRIES) 02174 DeleteCriticalSection(&((file_crit*)file)->crit); 02175 02176 if(file == get_file(stream_idx-1)) { 02177 while(stream_idx>3 && !file->_flag) { 02178 stream_idx--; 02179 file = get_file(stream_idx-1); 02180 } 02181 } 02182 02183 return ((r == -1) || (flag & _IOERR) ? EOF : 0); 02184 } 02185 02186 /********************************************************************* 02187 * feof (MSVCRT.@) 02188 */ 02189 int CDECL feof(FILE* file) 02190 { 02191 int ret; 02192 02193 _lock_file(file); 02194 ret = file->_flag & _IOEOF; 02195 _unlock_file(file); 02196 02197 return ret; 02198 } 02199 02200 /********************************************************************* 02201 * ferror (MSVCRT.@) 02202 */ 02203 int CDECL ferror(FILE* file) 02204 { 02205 int ret; 02206 02207 _lock_file(file); 02208 ret = file->_flag & _IOERR; 02209 _unlock_file(file); 02210 02211 return ret; 02212 } 02213 02214 /********************************************************************* 02215 * _filbuf (MSVCRT.@) 02216 */ 02217 int CDECL _filbuf(FILE* file) 02218 { 02219 unsigned char c; 02220 _lock_file(file); 02221 02222 /* Allocate buffer if needed */ 02223 if(file->_bufsiz == 0 && !(file->_flag & _IONBF)) 02224 alloc_buffer(file); 02225 02226 if(!(file->_flag & _IOREAD)) { 02227 if(file->_flag & _IORW) 02228 file->_flag |= _IOREAD; 02229 else { 02230 _unlock_file(file); 02231 return EOF; 02232 } 02233 } 02234 02235 if(file->_flag & _IONBF) { 02236 int r; 02237 if ((r = read_i(file->_file,&c,1)) != 1) { 02238 file->_flag |= (r == 0) ? _IOEOF : _IOERR; 02239 _unlock_file(file); 02240 return EOF; 02241 } 02242 02243 _unlock_file(file); 02244 return c; 02245 } else { 02246 file->_cnt = read_i(file->_file, file->_base, file->_bufsiz); 02247 if(file->_cnt<=0) { 02248 file->_flag |= (file->_cnt == 0) ? _IOEOF : _IOERR; 02249 file->_cnt = 0; 02250 _unlock_file(file); 02251 return EOF; 02252 } 02253 02254 file->_cnt--; 02255 file->_ptr = file->_base+1; 02256 c = *(unsigned char *)file->_base; 02257 _unlock_file(file); 02258 return c; 02259 } 02260 } 02261 02262 /********************************************************************* 02263 * fgetc (MSVCRT.@) 02264 */ 02265 int CDECL fgetc(FILE* file) 02266 { 02267 unsigned char *i; 02268 unsigned int j; 02269 02270 _lock_file(file); 02271 if (file->_cnt>0) { 02272 file->_cnt--; 02273 i = (unsigned char *)file->_ptr++; 02274 j = *i; 02275 } else 02276 j = _filbuf(file); 02277 02278 _unlock_file(file); 02279 return j; 02280 } 02281 02282 /********************************************************************* 02283 * _fgetchar (MSVCRT.@) 02284 */ 02285 int CDECL _fgetchar(void) 02286 { 02287 return fgetc(stdin); 02288 } 02289 02290 /********************************************************************* 02291 * fgets (MSVCRT.@) 02292 */ 02293 char * CDECL fgets(char *s, int size, FILE* file) 02294 { 02295 int cc = EOF; 02296 char * buf_start = s; 02297 02298 TRACE(":file(%p) fd (%d) str (%p) len (%d)\n", 02299 file,file->_file,s,size); 02300 02301 _lock_file(file); 02302 02303 while ((size >1) && (cc = fgetc(file)) != EOF && cc != '\n') 02304 { 02305 *s++ = (char)cc; 02306 size --; 02307 } 02308 if ((cc == EOF) && (s == buf_start)) /* If nothing read, return 0*/ 02309 { 02310 TRACE(":nothing read\n"); 02311 _unlock_file(file); 02312 return NULL; 02313 } 02314 if ((cc != EOF) && (size > 1)) 02315 *s++ = cc; 02316 *s = '\0'; 02317 TRACE(":got %s\n", debugstr_a(buf_start)); 02318 _unlock_file(file); 02319 return buf_start; 02320 } 02321 02322 /********************************************************************* 02323 * fgetwc (MSVCRT.@) 02324 * 02325 * In _O_TEXT mode, multibyte characters are read from the file, dropping 02326 * the CR from CR/LF combinations 02327 */ 02328 wint_t CDECL fgetwc(FILE* file) 02329 { 02330 int c; 02331 02332 _lock_file(file); 02333 if (!(get_ioinfo(file->_file)->wxflag & WX_TEXT)) 02334 { 02335 wchar_t wc; 02336 unsigned int i; 02337 int j; 02338 char *chp, *wcp; 02339 wcp = (char *)&wc; 02340 for(i=0; i<sizeof(wc); i++) 02341 { 02342 if (file->_cnt>0) 02343 { 02344 file->_cnt--; 02345 chp = file->_ptr++; 02346 wcp[i] = *chp; 02347 } 02348 else 02349 { 02350 j = _filbuf(file); 02351 if(file->_cnt<=0) 02352 { 02353 file->_flag |= (file->_cnt == 0) ? _IOEOF : _IOERR; 02354 file->_cnt = 0; 02355 02356 _unlock_file(file); 02357 return WEOF; 02358 } 02359 wcp[i] = j; 02360 } 02361 } 02362 02363 _unlock_file(file); 02364 return wc; 02365 } 02366 02367 c = fgetc(file); 02368 if ((__mb_cur_max > 1) && isleadbyte(c)) 02369 { 02370 FIXME("Treat Multibyte characters\n"); 02371 } 02372 02373 _unlock_file(file); 02374 if (c == EOF) 02375 return WEOF; 02376 else 02377 return (wint_t)c; 02378 } 02379 02380 /********************************************************************* 02381 * _getw (MSVCRT.@) 02382 */ 02383 int CDECL _getw(FILE* file) 02384 { 02385 char *ch; 02386 int i, k; 02387 unsigned int j; 02388 ch = (char *)&i; 02389 02390 _lock_file(file); 02391 for (j=0; j<sizeof(int); j++) { 02392 k = fgetc(file); 02393 if (k == EOF) { 02394 file->_flag |= _IOEOF; 02395 _unlock_file(file); 02396 return EOF; 02397 } 02398 ch[j] = k; 02399 } 02400 02401 _unlock_file(file); 02402 return i; 02403 } 02404 02405 /********************************************************************* 02406 * getwc (MSVCRT.@) 02407 */ 02408 wint_t CDECL getwc(FILE* file) 02409 { 02410 return fgetwc(file); 02411 } 02412 02413 /********************************************************************* 02414 * _fgetwchar (MSVCRT.@) 02415 */ 02416 wint_t CDECL _fgetwchar(void) 02417 { 02418 return fgetwc(stdin); 02419 } 02420 02421 /********************************************************************* 02422 * getwchar (MSVCRT.@) 02423 */ 02424 wint_t CDECL getwchar(void) 02425 { 02426 return _fgetwchar(); 02427 } 02428 02429 /********************************************************************* 02430 * fgetws (MSVCRT.@) 02431 */ 02432 wchar_t * CDECL fgetws(wchar_t *s, int size, FILE* file) 02433 { 02434 int cc = WEOF; 02435 wchar_t * buf_start = s; 02436 02437 TRACE(":file(%p) fd (%d) str (%p) len (%d)\n", 02438 file,file->_file,s,size); 02439 02440 _lock_file(file); 02441 02442 while ((size >1) && (cc = fgetwc(file)) != WEOF && cc != '\n') 02443 { 02444 *s++ = (char)cc; 02445 size --; 02446 } 02447 if ((cc == WEOF) && (s == buf_start)) /* If nothing read, return 0*/ 02448 { 02449 TRACE(":nothing read\n"); 02450 _unlock_file(file); 02451 return NULL; 02452 } 02453 if ((cc != WEOF) && (size > 1)) 02454 *s++ = cc; 02455 *s = 0; 02456 TRACE(":got %s\n", debugstr_w(buf_start)); 02457 _unlock_file(file); 02458 return buf_start; 02459 } 02460 02461 /********************************************************************* 02462 * fwrite (MSVCRT.@) 02463 */ 02464 size_t CDECL fwrite(const void *ptr, size_t size, size_t nmemb, FILE* file) 02465 { 02466 size_t wrcnt=size * nmemb; 02467 int written = 0; 02468 if (size == 0) 02469 return 0; 02470 02471 _lock_file(file); 02472 if(file->_cnt) { 02473 int pcnt=(file->_cnt>wrcnt)? wrcnt: file->_cnt; 02474 memcpy(file->_ptr, ptr, pcnt); 02475 file->_cnt -= pcnt; 02476 file->_ptr += pcnt; 02477 written = pcnt; 02478 wrcnt -= pcnt; 02479 ptr = (const char*)ptr + pcnt; 02480 } else if(!(file->_flag & _IOWRT)) { 02481 if(file->_flag & _IORW) { 02482 file->_flag |= _IOWRT; 02483 } else { 02484 _unlock_file(file); 02485 return 0; 02486 } 02487 } 02488 if(wrcnt) { 02489 /* Flush buffer */ 02490 int res=flush_buffer(file); 02491 if(!res) { 02492 int pwritten = _write(file->_file, ptr, wrcnt); 02493 if (pwritten <= 0) 02494 { 02495 file->_flag |= _IOERR; 02496 pwritten=0; 02497 } 02498 written += pwritten; 02499 } 02500 } 02501 02502 _unlock_file(file); 02503 return written / size; 02504 } 02505 02506 /********************************************************************* 02507 * fputwc (MSVCRT.@) 02508 */ 02509 wint_t CDECL fputwc(wint_t wc, FILE* file) 02510 { 02511 wchar_t mwc=wc; 02512 if (fwrite( &mwc, sizeof(mwc), 1, file) != 1) 02513 return WEOF; 02514 return wc; 02515 } 02516 02517 /********************************************************************* 02518 * _fputwchar (MSVCRT.@) 02519 */ 02520 wint_t CDECL _fputwchar(wint_t wc) 02521 { 02522 return fputwc(wc, stdout); 02523 } 02524 02525 /********************************************************************* 02526 * _wfsopen (MSVCRT.@) 02527 */ 02528 FILE * CDECL _wfsopen(const wchar_t *path, const wchar_t *mode, int share) 02529 { 02530 FILE* file; 02531 int open_flags, stream_flags, fd; 02532 02533 TRACE("(%s,%s)\n", debugstr_w(path), debugstr_w(mode)); 02534 02535 /* map mode string to open() flags. "man fopen" for possibilities. */ 02536 if (get_flags(mode, &open_flags, &stream_flags) == -1) 02537 return NULL; 02538 02539 LOCK_FILES(); 02540 fd = _wsopen(path, open_flags, share, _S_IREAD | _S_IWRITE); 02541 if (fd < 0) 02542 file = NULL; 02543 else if ((file = alloc_fp()) && init_fp(file, fd, stream_flags) 02544 != -1) 02545 TRACE(":fd (%d) mode (%s) FILE* (%p)\n", fd, debugstr_w(mode), file); 02546 else if (file) 02547 { 02548 file->_flag = 0; 02549 file = NULL; 02550 } 02551 02552 TRACE(":got (%p)\n",file); 02553 if (fd >= 0 && !file) 02554 _close(fd); 02555 UNLOCK_FILES(); 02556 return file; 02557 } 02558 02559 /********************************************************************* 02560 * _fsopen (MSVCRT.@) 02561 */ 02562 FILE * CDECL _fsopen(const char *path, const char *mode, int share) 02563 { 02564 FILE *ret; 02565 wchar_t *pathW = NULL, *modeW = NULL; 02566 02567 if (path && !(pathW = msvcrt_wstrdupa(path))) { 02568 _invalid_parameter(NULL, NULL, NULL, 0, 0); 02569 *_errno() = EINVAL; 02570 return NULL; 02571 } 02572 if (mode && !(modeW = msvcrt_wstrdupa(mode))) 02573 { 02574 free(pathW); 02575 _invalid_parameter(NULL, NULL, NULL, 0, 0); 02576 *_errno() = EINVAL; 02577 return NULL; 02578 } 02579 02580 ret = _wfsopen(pathW, modeW, share); 02581 02582 free(pathW); 02583 free(modeW); 02584 return ret; 02585 } 02586 02587 /********************************************************************* 02588 * fopen (MSVCRT.@) 02589 */ 02590 FILE * CDECL fopen(const char *path, const char *mode) 02591 { 02592 return _fsopen( path, mode, _SH_DENYNO ); 02593 } 02594 02595 /********************************************************************* 02596 * fopen_s (MSVCRT.@) 02597 */ 02598 int CDECL fopen_s(FILE** pFile, 02599 const char *filename, const char *mode) 02600 { 02601 if (!MSVCRT_CHECK_PMT(pFile != NULL) || !MSVCRT_CHECK_PMT(filename != NULL) || 02602 !MSVCRT_CHECK_PMT(mode != NULL)) { 02603 *_errno() = EINVAL; 02604 return EINVAL; 02605 } 02606 02607 *pFile = fopen(filename, mode); 02608 02609 if(!*pFile) 02610 return *_errno(); 02611 return 0; 02612 } 02613 02614 /********************************************************************* 02615 * _wfopen (MSVCRT.@) 02616 */ 02617 FILE * CDECL _wfopen(const wchar_t *path, const wchar_t *mode) 02618 { 02619 return _wfsopen( path, mode, _SH_DENYNO ); 02620 } 02621 02622 /********************************************************************* 02623 * _wfopen_s (MSVCRT.@) 02624 */ 02625 int CDECL _wfopen_s(FILE** pFile, const wchar_t *filename, 02626 const wchar_t *mode) 02627 { 02628 if (!MSVCRT_CHECK_PMT(pFile != NULL) || !MSVCRT_CHECK_PMT(filename != NULL) || 02629 !MSVCRT_CHECK_PMT(mode != NULL)) { 02630 *_errno() = EINVAL; 02631 return EINVAL; 02632 } 02633 02634 *pFile = _wfopen(filename, mode); 02635 02636 if(!*pFile) 02637 return *_errno(); 02638 return 0; 02639 } 02640 02641 /* fputc calls _flsbuf which calls fputc */ 02642 int CDECL _flsbuf(int c, FILE* file); 02643 02644 /********************************************************************* 02645 * fputc (MSVCRT.@) 02646 */ 02647 int CDECL fputc(int c, FILE* file) 02648 { 02649 int res; 02650 02651 _lock_file(file); 02652 if(file->_cnt>0) { 02653 *file->_ptr++=c; 02654 file->_cnt--; 02655 if (c == '\n') 02656 { 02657 res = flush_buffer(file); 02658 _unlock_file(file); 02659 return res ? res : c; 02660 } 02661 else { 02662 _unlock_file(file); 02663 return c & 0xff; 02664 } 02665 } else { 02666 res = _flsbuf(c, file); 02667 _unlock_file(file); 02668 return res; 02669 } 02670 } 02671 02672 /********************************************************************* 02673 * _fputchar (MSVCRT.@) 02674 */ 02675 int CDECL _fputchar(int c) 02676 { 02677 return fputc(c, stdout); 02678 } 02679 02680 /********************************************************************* 02681 * fread (MSVCRT.@) 02682 */ 02683 size_t CDECL fread(void *ptr, size_t size, size_t nmemb, FILE* file) 02684 { 02685 size_t rcnt=size * nmemb; 02686 size_t read=0; 02687 int pread=0; 02688 02689 if(!rcnt) 02690 return 0; 02691 02692 _lock_file(file); 02693 02694 /* first buffered data */ 02695 if(file->_cnt>0) { 02696 int pcnt= (rcnt>file->_cnt)? file->_cnt:rcnt; 02697 memcpy(ptr, file->_ptr, pcnt); 02698 file->_cnt -= pcnt; 02699 file->_ptr += pcnt; 02700 read += pcnt ; 02701 rcnt -= pcnt ; 02702 ptr = (char*)ptr + pcnt; 02703 } else if(!(file->_flag & _IOREAD )) { 02704 if(file->_flag & _IORW) { 02705 file->_flag |= _IOREAD; 02706 } else { 02707 _unlock_file(file); 02708 return 0; 02709 } 02710 } 02711 while(rcnt>0) 02712 { 02713 int i; 02714 /* Fill the buffer on small reads. 02715 * TODO: Use a better buffering strategy. 02716 */ 02717 if (!file->_cnt && size*nmemb <= BUFSIZ/2 && !(file->_flag & _IONBF)) { 02718 if (file->_bufsiz == 0) { 02719 alloc_buffer(file); 02720 } 02721 file->_cnt = _read(file->_file, file->_base, file->_bufsiz); 02722 file->_ptr = file->_base; 02723 i = (file->_cnt<rcnt) ? file->_cnt : rcnt; 02724 /* If the buffer fill reaches eof but fread wouldn't, clear eof. */ 02725 if (i > 0 && i < file->_cnt) { 02726 get_ioinfo(file->_file)->wxflag &= ~WX_ATEOF; 02727 file->_flag &= ~_IOEOF; 02728 } 02729 if (i > 0) { 02730 memcpy(ptr, file->_ptr, i); 02731 file->_cnt -= i; 02732 file->_ptr += i; 02733 } 02734 } else { 02735 i = _read(file->_file,ptr, rcnt); 02736 } 02737 pread += i; 02738 rcnt -= i; 02739 ptr = (char *)ptr+i; 02740 /* expose feof condition in the flags 02741 * MFC tests file->_flag for feof, and doesn't call feof()) 02742 */ 02743 if (get_ioinfo(file->_file)->wxflag & WX_ATEOF) 02744 file->_flag |= _IOEOF; 02745 else if (i == -1) 02746 { 02747 file->_flag |= _IOERR; 02748 pread = 0; 02749 rcnt = 0; 02750 } 02751 if (i < 1) break; 02752 } 02753 read+=pread; 02754 _unlock_file(file); 02755 return read / size; 02756 } 02757 02758 /********************************************************************* 02759 * _wfreopen (MSVCRT.@) 02760 * 02761 */ 02762 FILE* CDECL _wfreopen(const wchar_t *path, const wchar_t *mode, FILE* file) 02763 { 02764 int open_flags, stream_flags, fd; 02765 02766 TRACE(":path (%p) mode (%s) file (%p) fd (%d)\n", debugstr_w(path), debugstr_w(mode), file, file->_file); 02767 02768 LOCK_FILES(); 02769 if (!file || ((fd = file->_file) < 0) || fd > fdend) 02770 file = NULL; 02771 else 02772 { 02773 fclose(file); 02774 /* map mode string to open() flags. "man fopen" for possibilities. */ 02775 if (get_flags(mode, &open_flags, &stream_flags) == -1) 02776 file = NULL; 02777 else 02778 { 02779 fd = _wopen(path, open_flags, _S_IREAD | _S_IWRITE); 02780 if (fd < 0) 02781 file = NULL; 02782 else if (init_fp(file, fd, stream_flags) == -1) 02783 { 02784 file->_flag = 0; 02785 WARN(":failed-last error (%d)\n",GetLastError()); 02786 _dosmaperr(GetLastError()); 02787 file = NULL; 02788 } 02789 } 02790 } 02791 UNLOCK_FILES(); 02792 return file; 02793 } 02794 02795 /********************************************************************* 02796 * freopen (MSVCRT.@) 02797 * 02798 */ 02799 FILE* CDECL freopen(const char *path, const char *mode, FILE* file) 02800 { 02801 FILE *ret; 02802 wchar_t *pathW = NULL, *modeW = NULL; 02803 02804 if (path && !(pathW = msvcrt_wstrdupa(path))) return NULL; 02805 if (mode && !(modeW = msvcrt_wstrdupa(mode))) 02806 { 02807 free(pathW); 02808 return NULL; 02809 } 02810 02811 ret = _wfreopen(pathW, modeW, file); 02812 02813 free(pathW); 02814 free(modeW); 02815 return ret; 02816 } 02817 02818 /********************************************************************* 02819 * fsetpos (MSVCRT.@) 02820 */ 02821 int CDECL fsetpos(FILE* file, const fpos_t *pos) 02822 { 02823 int ret; 02824 02825 _lock_file(file); 02826 /* Note that all this has been lifted 'as is' from fseek */ 02827 if(file->_flag & _IOWRT) 02828 flush_buffer(file); 02829 02830 /* Discard buffered input */ 02831 file->_cnt = 0; 02832 file->_ptr = file->_base; 02833 02834 /* Reset direction of i/o */ 02835 if(file->_flag & _IORW) { 02836 file->_flag &= ~(_IOREAD|_IOWRT); 02837 } 02838 02839 ret = (_lseeki64(file->_file,*pos,SEEK_SET) == -1) ? -1 : 0; 02840 _unlock_file(file); 02841 return ret; 02842 } 02843 02844 /********************************************************************* 02845 * _ftelli64 (MSVCRT.@) 02846 */ 02847 __int64 CDECL _ftelli64(FILE* file) 02848 { 02849 /* TODO: just call fgetpos and return lower half of result */ 02850 int off=0; 02851 __int64 pos; 02852 02853 _lock_file(file); 02854 pos = _telli64(file->_file); 02855 if(pos == -1) { 02856 _unlock_file(file); 02857 return -1; 02858 } 02859 if(file->_bufsiz) { 02860 if( file->_flag & _IOWRT ) { 02861 off = file->_ptr - file->_base; 02862 } else { 02863 off = -file->_cnt; 02864 if (get_ioinfo(file->_file)->wxflag & WX_TEXT) { 02865 /* Black magic correction for CR removal */ 02866 int i; 02867 for (i=0; i<file->_cnt; i++) { 02868 if (file->_ptr[i] == '\n') 02869 off--; 02870 } 02871 /* Black magic when reading CR at buffer boundary*/ 02872 if(get_ioinfo(file->_file)->wxflag & WX_READCR) 02873 off--; 02874 } 02875 } 02876 } 02877 02878 _unlock_file(file); 02879 return off + pos; 02880 } 02881 02882 /********************************************************************* 02883 * ftell (MSVCRT.@) 02884 */ 02885 LONG CDECL ftell(FILE* file) 02886 { 02887 return _ftelli64(file); 02888 } 02889 02890 /********************************************************************* 02891 * fgetpos (MSVCRT.@) 02892 */ 02893 int CDECL fgetpos(FILE* file, fpos_t *pos) 02894 { 02895 int off=0; 02896 02897 _lock_file(file); 02898 *pos = _lseeki64(file->_file,0,SEEK_CUR); 02899 if(*pos == -1) { 02900 _unlock_file(file); 02901 return -1; 02902 } 02903 if(file->_bufsiz) { 02904 if( file->_flag & _IOWRT ) { 02905 off = file->_ptr - file->_base; 02906 } else { 02907 off = -file->_cnt; 02908 if (get_ioinfo(file->_file)->wxflag & WX_TEXT) { 02909 /* Black magic correction for CR removal */ 02910 int i; 02911 for (i=0; i<file->_cnt; i++) { 02912 if (file->_ptr[i] == '\n') 02913 off--; 02914 } 02915 /* Black magic when reading CR at buffer boundary*/ 02916 if(get_ioinfo(file->_file)->wxflag & WX_READCR) 02917 off--; 02918 } 02919 } 02920 } 02921 *pos += off; 02922 _unlock_file(file); 02923 return 0; 02924 } 02925 02926 /********************************************************************* 02927 * fputs (MSVCRT.@) 02928 */ 02929 int CDECL fputs(const char *s, FILE* file) 02930 { 02931 size_t i, len = strlen(s); 02932 int ret; 02933 02934 _lock_file(file); 02935 if (!(get_ioinfo(file->_file)->wxflag & WX_TEXT)) { 02936 ret = fwrite(s,sizeof(*s),len,file) == len ? 0 : EOF; 02937 _unlock_file(file); 02938 return ret; 02939 } 02940 for (i=0; i<len; i++) 02941 if (fputc(s[i], file) == EOF) { 02942 _unlock_file(file); 02943 return EOF; 02944 } 02945 02946 _unlock_file(file); 02947 return 0; 02948 } 02949 02950 /********************************************************************* 02951 * fputws (MSVCRT.@) 02952 */ 02953 int CDECL fputws(const wchar_t *s, FILE* file) 02954 { 02955 size_t i, len = strlenW(s); 02956 int ret; 02957 02958 _lock_file(file); 02959 if (!(get_ioinfo(file->_file)->wxflag & WX_TEXT)) { 02960 ret = fwrite(s,sizeof(*s),len,file) == len ? 0 : EOF; 02961 _unlock_file(file); 02962 return ret; 02963 } 02964 for (i=0; i<len; i++) { 02965 if (((s[i] == '\n') && (fputc('\r', file) == EOF)) 02966 || fputwc(s[i], file) == WEOF) { 02967 _unlock_file(file); 02968 return WEOF; 02969 } 02970 } 02971 02972 _unlock_file(file); 02973 return 0; 02974 } 02975 02976 /********************************************************************* 02977 * getchar (MSVCRT.@) 02978 */ 02979 int CDECL getchar(void) 02980 { 02981 return fgetc(stdin); 02982 } 02983 02984 /********************************************************************* 02985 * getc (MSVCRT.@) 02986 */ 02987 int CDECL getc(FILE* file) 02988 { 02989 return fgetc(file); 02990 } 02991 02992 /********************************************************************* 02993 * gets (MSVCRT.@) 02994 */ 02995 char * CDECL gets(char *buf) 02996 { 02997 int cc; 02998 char * buf_start = buf; 02999 03000 _lock_file(stdin); 03001 for(cc = fgetc(stdin); cc != EOF && cc != '\n'; 03002 cc = fgetc(stdin)) 03003 if(cc != '\r') *buf++ = (char)cc; 03004 03005 *buf = '\0'; 03006 03007 TRACE("got '%s'\n", buf_start); 03008 _unlock_file(stdin); 03009 return buf_start; 03010 } 03011 03012 /********************************************************************* 03013 * _getws (MSVCRT.@) 03014 */ 03015 wchar_t* CDECL _getws(wchar_t* buf) 03016 { 03017 wint_t cc; 03018 wchar_t* ws = buf; 03019 03020 _lock_file(stdin); 03021 for (cc = fgetwc(stdin); cc != WEOF && cc != '\n'; 03022 cc = fgetwc(stdin)) 03023 { 03024 if (cc != '\r') 03025 *buf++ = (wchar_t)cc; 03026 } 03027 *buf = '\0'; 03028 03029 TRACE("got %s\n", debugstr_w(ws)); 03030 _unlock_file(stdin); 03031 return ws; 03032 } 03033 03034 /********************************************************************* 03035 * putc (MSVCRT.@) 03036 */ 03037 int CDECL putc(int c, FILE* file) 03038 { 03039 return fputc(c, file); 03040 } 03041 03042 /********************************************************************* 03043 * putchar (MSVCRT.@) 03044 */ 03045 int CDECL putchar(int c) 03046 { 03047 return fputc(c, stdout); 03048 } 03049 03050 /********************************************************************* 03051 * _putwch (MSVCRT.@) 03052 */ 03053 wint_t CDECL _putwch(wchar_t c) 03054 { 03055 return fputwc(c, stdout); 03056 } 03057 03058 /********************************************************************* 03059 * puts (MSVCRT.@) 03060 */ 03061 int CDECL puts(const char *s) 03062 { 03063 size_t len = strlen(s); 03064 int ret; 03065 03066 _lock_file(stdout); 03067 if(fwrite(s, sizeof(*s), len, stdout) != len) { 03068 _unlock_file(stdout); 03069 return EOF; 03070 } 03071 03072 ret = fwrite("\n",1,1,stdout) == 1 ? 0 : EOF; 03073 _unlock_file(stdout); 03074 return ret; 03075 } 03076 03077 /********************************************************************* 03078 * _putws (MSVCRT.@) 03079 */ 03080 int CDECL _putws(const wchar_t *s) 03081 { 03082 static const wchar_t nl = '\n'; 03083 size_t len = strlenW(s); 03084 int ret; 03085 03086 _lock_file(stdout); 03087 if(fwrite(s, sizeof(*s), len, stdout) != len) { 03088 _unlock_file(stdout); 03089 return EOF; 03090 } 03091 03092 ret = fwrite(&nl,sizeof(nl),1,stdout) == 1 ? 0 : EOF; 03093 _unlock_file(stdout); 03094 return ret; 03095 } 03096 03097 /********************************************************************* 03098 * remove (MSVCRT.@) 03099 */ 03100 int CDECL remove(const char *path) 03101 { 03102 TRACE("(%s)\n",path); 03103 if (DeleteFileA(path)) 03104 return 0; 03105 TRACE(":failed (%d)\n",GetLastError()); 03106 _dosmaperr(GetLastError()); 03107 return -1; 03108 } 03109 03110 /********************************************************************* 03111 * _wremove (MSVCRT.@) 03112 */ 03113 int CDECL _wremove(const wchar_t *path) 03114 { 03115 TRACE("(%s)\n",debugstr_w(path)); 03116 if (DeleteFileW(path)) 03117 return 0; 03118 TRACE(":failed (%d)\n",GetLastError()); 03119 _dosmaperr(GetLastError()); 03120 return -1; 03121 } 03122 03123 /********************************************************************* 03124 * rename (MSVCRT.@) 03125 */ 03126 int CDECL rename(const char *oldpath,const char *newpath) 03127 { 03128 TRACE(":from %s to %s\n",oldpath,newpath); 03129 if (MoveFileExA(oldpath, newpath, MOVEFILE_COPY_ALLOWED)) 03130 return 0; 03131 TRACE(":failed (%d)\n",GetLastError()); 03132 _dosmaperr(GetLastError()); 03133 return -1; 03134 } 03135 03136 /********************************************************************* 03137 * _wrename (MSVCRT.@) 03138 */ 03139 int CDECL _wrename(const wchar_t *oldpath,const wchar_t *newpath) 03140 { 03141 TRACE(":from %s to %s\n",debugstr_w(oldpath),debugstr_w(newpath)); 03142 if (MoveFileExW(oldpath, newpath, MOVEFILE_COPY_ALLOWED)) 03143 return 0; 03144 TRACE(":failed (%d)\n",GetLastError()); 03145 _dosmaperr(GetLastError()); 03146 return -1; 03147 } 03148 03149 /********************************************************************* 03150 * setvbuf (MSVCRT.@) 03151 */ 03152 int CDECL setvbuf(FILE* file, char *buf, int mode, size_t size) 03153 { 03154 _lock_file(file); 03155 if(file->_bufsiz) { 03156 free(file->_base); 03157 file->_bufsiz = 0; 03158 file->_cnt = 0; 03159 } 03160 if(mode == _IOFBF) { 03161 file->_flag &= ~_IONBF; 03162 file->_base = file->_ptr = buf; 03163 if(buf) { 03164 file->_bufsiz = size; 03165 } 03166 } else { 03167 file->_flag |= _IONBF; 03168 } 03169 _unlock_file(file); 03170 return 0; 03171 } 03172 03173 /********************************************************************* 03174 * setbuf (MSVCRT.@) 03175 */ 03176 void CDECL setbuf(FILE* file, char *buf) 03177 { 03178 setvbuf(file, buf, buf ? _IOFBF : _IONBF, BUFSIZ); 03179 } 03180 03181 /********************************************************************* 03182 * tmpnam (MSVCRT.@) 03183 */ 03184 char * CDECL tmpnam(char *s) 03185 { 03186 char tmpstr[16]; 03187 char *p; 03188 int count, size; 03189 03190 if (!s) { 03191 thread_data_t *data = msvcrt_get_thread_data(); 03192 03193 if(!data->tmpnam_buffer) 03194 data->tmpnam_buffer = malloc(MAX_PATH); 03195 03196 s = data->tmpnam_buffer; 03197 } 03198 03199 int_to_base32(GetCurrentProcessId(), tmpstr); 03200 p = s + sprintf(s, "\\s%s.", tmpstr); 03201 for (count = 0; count < TMP_MAX; count++) 03202 { 03203 size = int_to_base32(tmpnam_unique++, tmpstr); 03204 memcpy(p, tmpstr, size); 03205 if (GetFileAttributesA(s) == INVALID_FILE_ATTRIBUTES && 03206 GetLastError() == ERROR_FILE_NOT_FOUND) 03207 break; 03208 } 03209 return s; 03210 } 03211 03212 /********************************************************************* 03213 * _wtmpnam (MSVCRT.@) 03214 */ 03215 wchar_t * CDECL _wtmpnam(wchar_t *s) 03216 { 03217 static const wchar_t format[] = {'\\','s','%','s','.',0}; 03218 wchar_t tmpstr[16]; 03219 wchar_t *p; 03220 int count, size; 03221 if (!s) { 03222 thread_data_t *data = msvcrt_get_thread_data(); 03223 03224 if(!data->wtmpnam_buffer) 03225 data->wtmpnam_buffer = malloc(sizeof(wchar_t[MAX_PATH])); 03226 03227 s = data->wtmpnam_buffer; 03228 } 03229 03230 int_to_base32_w(GetCurrentProcessId(), tmpstr); 03231 p = s + _snwprintf(s, MAX_PATH, format, tmpstr); 03232 for (count = 0; count < TMP_MAX; count++) 03233 { 03234 size = int_to_base32_w(tmpnam_unique++, tmpstr); 03235 memcpy(p, tmpstr, size*sizeof(wchar_t)); 03236 if (GetFileAttributesW(s) == INVALID_FILE_ATTRIBUTES && 03237 GetLastError() == ERROR_FILE_NOT_FOUND) 03238 break; 03239 } 03240 return s; 03241 } 03242 03243 /********************************************************************* 03244 * tmpfile (MSVCRT.@) 03245 */ 03246 FILE* CDECL tmpfile(void) 03247 { 03248 char *filename = tmpnam(NULL); 03249 int fd; 03250 FILE* file = NULL; 03251 03252 LOCK_FILES(); 03253 fd = _open(filename, _O_CREAT | _O_BINARY | _O_RDWR | _O_TEMPORARY); 03254 if (fd != -1 && (file = alloc_fp())) 03255 { 03256 if (init_fp(file, fd, _O_RDWR) == -1) 03257 { 03258 file->_flag = 0; 03259 file = NULL; 03260 } 03261 else file->_tmpfname = _strdup(filename); 03262 } 03263 UNLOCK_FILES(); 03264 return file; 03265 } 03266 03267 /********************************************************************* 03268 * ungetc (MSVCRT.@) 03269 */ 03270 int CDECL ungetc(int c, FILE * file) 03271 { 03272 if (c == EOF) 03273 return EOF; 03274 03275 _lock_file(file); 03276 if(file->_bufsiz == 0) { 03277 alloc_buffer(file); 03278 file->_ptr++; 03279 } 03280 if(file->_ptr>file->_base) { 03281 file->_ptr--; 03282 *file->_ptr=c; 03283 file->_cnt++; 03284 clearerr(file); 03285 _unlock_file(file); 03286 return c; 03287 } 03288 03289 _unlock_file(file); 03290 return EOF; 03291 } 03292 03293 /********************************************************************* 03294 * ungetwc (MSVCRT.@) 03295 */ 03296 wint_t CDECL ungetwc(wint_t wc, FILE * file) 03297 { 03298 wchar_t mwc = wc; 03299 char * pp = (char *)&mwc; 03300 int i; 03301 03302 _lock_file(file); 03303 for(i=sizeof(wchar_t)-1;i>=0;i--) { 03304 if(pp[i] != ungetc(pp[i],file)) { 03305 _unlock_file(file); 03306 return WEOF; 03307 } 03308 } 03309 03310 _unlock_file(file); 03311 return mwc; 03312 } 03313 03314 03315 03316 /********************************************************************* 03317 * _getmaxstdio (MSVCRT.@) 03318 */ 03319 int CDECL _getmaxstdio(void) 03320 { 03321 return max_streams; 03322 } 03323 03324 /********************************************************************* 03325 * _setmaxstdio (MSVCRT.@) 03326 */ 03327 int CDECL _setmaxstdio(int newmax) 03328 { 03329 TRACE("%d\n", newmax); 03330 03331 if(newmax<_IOB_ENTRIES || newmax>MAX_FILES || newmax<stream_idx) 03332 return -1; 03333 03334 max_streams = newmax; 03335 return max_streams; 03336 } Generated on Sun May 27 2012 04:17:52 for ReactOS by
1.7.6.1
|