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