source: trunk/src/msvcrt/file.c@ 9633

Last change on this file since 9633 was 9633, checked in by sandervl, 23 years ago

PF: Msvcrt Wine port with GCC

File size: 58.7 KB
Line 
1/*
2 * msvcrt.dll file functions
3 *
4 * Copyright 1996,1998 Marcus Meissner
5 * Copyright 1996 Jukka Iivonen
6 * Copyright 1997,2000 Uwe Bonnes
7 * Copyright 2000 Jon Griffiths
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */
23#ifdef __WIN32OS2__
24#include <emxheader.h>
25#include <winbase.h>
26#else
27#include "config.h"
28#include "wine/port.h"
29#endif
30
31#include <time.h>
32#include <stdio.h>
33#ifdef HAVE_UNISTD_H
34# include <unistd.h>
35#endif
36
37#include "winternl.h"
38#include "msvcrt.h"
39#include "msvcrt/errno.h"
40
41#include "wine/unicode.h"
42#include "msvcrt/direct.h"
43#include "msvcrt/fcntl.h"
44#include "msvcrt/io.h"
45#include "msvcrt/sys/locking.h"
46#include "msvcrt/stdio.h"
47#include "msvcrt/stdlib.h"
48#include "msvcrt/string.h"
49#include "msvcrt/sys/stat.h"
50#include "msvcrt/sys/utime.h"
51#include "msvcrt/time.h"
52#include "msvcrt/share.h"
53#include "msvcrt/wctype.h"
54
55#include "wine/debug.h"
56
57WINE_DEFAULT_DEBUG_CHANNEL(msvcrt);
58
59/* for stat mode, permissions apply to all,owner and group */
60#define MSVCRT_S_IREAD (_S_IREAD | (_S_IREAD >> 3) | (_S_IREAD >> 6))
61#define MSVCRT_S_IWRITE (_S_IWRITE | (_S_IWRITE >> 3) | (_S_IWRITE >> 6))
62#define MSVCRT_S_IEXEC (_S_IEXEC | (_S_IEXEC >> 3) | (_S_IEXEC >> 6))
63
64/* _access() bit flags FIXME: incomplete */
65#define MSVCRT_W_OK 0x02
66
67
68/* FIXME: Make this dynamic */
69#define MSVCRT_MAX_FILES 257
70
71HANDLE MSVCRT_handles[MSVCRT_MAX_FILES];
72MSVCRT_FILE* MSVCRT_files[MSVCRT_MAX_FILES];
73int MSVCRT_flags[MSVCRT_MAX_FILES];
74char *MSVCRT_tempfiles[MSVCRT_MAX_FILES];
75MSVCRT_FILE MSVCRT__iob[3];
76#define MSVCRT_stdin (MSVCRT__iob+STDIN_FILENO)
77#define MSVCRT_stdout (MSVCRT__iob+STDOUT_FILENO)
78#define MSVCRT_stderr (MSVCRT__iob+STDERR_FILENO)
79
80static int MSVCRT_fdstart = 3; /* first unallocated fd */
81static int MSVCRT_fdend = 3; /* highest allocated fd */
82
83/* INTERNAL: process umask */
84static int MSVCRT_umask = 0;
85
86/* INTERNAL: Static buffer for temp file name */
87static char MSVCRT_tmpname[MAX_PATH];
88
89static const unsigned int EXE = 'e' << 16 | 'x' << 8 | 'e';
90static const unsigned int BAT = 'b' << 16 | 'a' << 8 | 't';
91static const unsigned int CMD = 'c' << 16 | 'm' << 8 | 'd';
92static const unsigned int COM = 'c' << 16 | 'o' << 8 | 'm';
93
94#define TOUL(x) (ULONGLONG)(x)
95static const ULONGLONG WCEXE = TOUL('e') << 32 | TOUL('x') << 16 | TOUL('e');
96static const ULONGLONG WCBAT = TOUL('b') << 32 | TOUL('a') << 16 | TOUL('t');
97static const ULONGLONG WCCMD = TOUL('c') << 32 | TOUL('m') << 16 | TOUL('d');
98static const ULONGLONG WCCOM = TOUL('c') << 32 | TOUL('o') << 16 | TOUL('m');
99
100extern CRITICAL_SECTION MSVCRT_file_cs;
101#define LOCK_FILES EnterCriticalSection(&MSVCRT_file_cs)
102#define UNLOCK_FILES LeaveCriticalSection(&MSVCRT_file_cs)
103
104static void msvcrt_cp_from_stati64(const struct _stati64 *bufi64, struct _stat *buf)
105{
106 buf->st_dev = bufi64->st_dev;
107 buf->st_ino = bufi64->st_ino;
108 buf->st_mode = bufi64->st_mode;
109 buf->st_nlink = bufi64->st_nlink;
110 buf->st_uid = bufi64->st_uid;
111 buf->st_gid = bufi64->st_gid;
112 buf->st_rdev = bufi64->st_rdev;
113 buf->st_size = bufi64->st_size;
114 buf->st_atime = bufi64->st_atime;
115 buf->st_mtime = bufi64->st_mtime;
116 buf->st_ctime = bufi64->st_ctime;
117}
118
119/* INTERNAL: Get the HANDLE for a fd */
120static HANDLE msvcrt_fdtoh(int fd)
121{
122 if (fd < 0 || fd >= MSVCRT_fdend ||
123 MSVCRT_handles[fd] == INVALID_HANDLE_VALUE)
124 {
125 WARN(":fd (%d) - no handle!\n",fd);
126 *__doserrno() = 0;
127 *MSVCRT__errno() = MSVCRT_EBADF;
128 return INVALID_HANDLE_VALUE;
129 }
130 return MSVCRT_handles[fd];
131}
132
133/* INTERNAL: free a file entry fd */
134static void msvcrt_free_fd(int fd)
135{
136 MSVCRT_handles[fd] = INVALID_HANDLE_VALUE;
137 MSVCRT_files[fd] = 0;
138 MSVCRT_flags[fd] = 0;
139 TRACE(":fd (%d) freed\n",fd);
140 if (fd < 3)
141 return; /* dont use 0,1,2 for user files */
142 if (fd == MSVCRT_fdend - 1)
143 MSVCRT_fdend--;
144 if (fd < MSVCRT_fdstart)
145 MSVCRT_fdstart = fd;
146}
147
148/* INTERNAL: Allocate an fd slot from a Win32 HANDLE */
149static int msvcrt_alloc_fd(HANDLE hand, int flag)
150{
151 int fd = MSVCRT_fdstart;
152
153 TRACE(":handle (%p) allocating fd (%d)\n",hand,fd);
154 if (fd >= MSVCRT_MAX_FILES)
155 {
156 WARN(":files exhausted!\n");
157 return -1;
158 }
159 MSVCRT_handles[fd] = hand;
160 MSVCRT_flags[fd] = flag;
161
162 /* locate next free slot */
163 if (fd == MSVCRT_fdend)
164 MSVCRT_fdstart = ++MSVCRT_fdend;
165 else
166 while(MSVCRT_fdstart < MSVCRT_fdend &&
167 MSVCRT_handles[MSVCRT_fdstart] != INVALID_HANDLE_VALUE)
168 MSVCRT_fdstart++;
169
170 return fd;
171}
172
173/* INTERNAL: Allocate a FILE* for an fd slot
174 * This is done lazily to avoid memory wastage for low level open/write
175 * usage when a FILE* is not requested (but may be later).
176 */
177static MSVCRT_FILE* msvcrt_alloc_fp(int fd)
178{
179 TRACE(":fd (%d) allocating FILE*\n",fd);
180 if (fd < 0 || fd >= MSVCRT_fdend ||
181 MSVCRT_handles[fd] == INVALID_HANDLE_VALUE)
182 {
183 WARN(":invalid fd %d\n",fd);
184 *__doserrno() = 0;
185 *MSVCRT__errno() = MSVCRT_EBADF;
186 return NULL;
187 }
188 if (!MSVCRT_files[fd])
189 {
190 if ((MSVCRT_files[fd] = MSVCRT_calloc(sizeof(MSVCRT_FILE),1)))
191 {
192 MSVCRT_files[fd]->_file = fd;
193 MSVCRT_files[fd]->_flag = MSVCRT_flags[fd];
194 MSVCRT_files[fd]->_flag &= ~MSVCRT__IOAPPEND; /* mask out, see above */
195 }
196 }
197 TRACE(":got FILE* (%p)\n",MSVCRT_files[fd]);
198 return MSVCRT_files[fd];
199}
200
201
202/* INTERNAL: Set up stdin, stderr and stdout */
203void msvcrt_init_io(void)
204{
205 int i;
206 memset(MSVCRT__iob,0,3*sizeof(MSVCRT_FILE));
207 MSVCRT_handles[0] = GetStdHandle(STD_INPUT_HANDLE);
208 MSVCRT_flags[0] = MSVCRT__iob[0]._flag = MSVCRT__IOREAD;
209 MSVCRT_handles[1] = GetStdHandle(STD_OUTPUT_HANDLE);
210 MSVCRT_flags[1] = MSVCRT__iob[1]._flag = MSVCRT__IOWRT;
211 MSVCRT_handles[2] = GetStdHandle(STD_ERROR_HANDLE);
212 MSVCRT_flags[2] = MSVCRT__iob[2]._flag = MSVCRT__IOWRT;
213
214 TRACE(":handles (%p)(%p)(%p)\n",MSVCRT_handles[0],
215 MSVCRT_handles[1],MSVCRT_handles[2]);
216
217 for (i = 0; i < 3; i++)
218 {
219 /* FILE structs for stdin/out/err are static and never deleted */
220 MSVCRT_files[i] = &MSVCRT__iob[i];
221 MSVCRT__iob[i]._file = i;
222 MSVCRT_tempfiles[i] = NULL;
223 }
224}
225
226/* free everything on process exit */
227void msvcrt_free_io(void)
228{
229 _fcloseall();
230 _close(0);
231 _close(1);
232 _close(2);
233}
234
235/* INTERNAL: Flush stdio file buffer */
236static int msvcrt_flush_buffer(MSVCRT_FILE* file)
237{
238 if(file->_bufsiz) {
239 int cnt=file->_ptr-file->_base;
240 if(cnt>0 && _write(file->_file, file->_base, cnt) != cnt) {
241 return MSVCRT_EOF;
242 }
243 file->_ptr=file->_base;
244 file->_cnt=file->_bufsiz;
245 }
246 return 0;
247}
248
249/* INTERNAL: Allocate stdio file buffer */
250static void msvcrt_alloc_buffer(MSVCRT_FILE* file)
251{
252 file->_base = MSVCRT_calloc(MSVCRT_BUFSIZ,1);
253 if(file->_base) {
254 file->_bufsiz = MSVCRT_BUFSIZ;
255 file->_flag |= MSVCRT__IOMYBUF;
256 } else {
257 file->_base = (unsigned char *)(&file->_charbuf);
258 /* put here 2 ??? */
259 file->_bufsiz = sizeof(file->_charbuf);
260 }
261 file->_ptr = file->_base;
262 file->_cnt = 0;
263}
264
265/*********************************************************************
266 * __p__iob(MSVCRT.@)
267 */
268MSVCRT_FILE *__p__iob(void)
269{
270 return &MSVCRT__iob[0];
271}
272
273/*********************************************************************
274 * _access (MSVCRT.@)
275 */
276int _access(const char *filename, int mode)
277{
278 DWORD attr = GetFileAttributesA(filename);
279
280 TRACE("(%s,%d) %ld\n",filename,mode,attr);
281
282 if (!filename || attr == 0xffffffff)
283 {
284 MSVCRT__set_errno(GetLastError());
285 return -1;
286 }
287 if ((attr & FILE_ATTRIBUTE_READONLY) && (mode & MSVCRT_W_OK))
288 {
289 MSVCRT__set_errno(ERROR_ACCESS_DENIED);
290 return -1;
291 }
292 return 0;
293}
294
295/*********************************************************************
296 * _waccess (MSVCRT.@)
297 */
298int _waccess(const MSVCRT_wchar_t *filename, int mode)
299{
300 DWORD attr = GetFileAttributesW(filename);
301
302 TRACE("(%s,%d) %ld\n",debugstr_w(filename),mode,attr);
303
304 if (!filename || attr == 0xffffffff)
305 {
306 MSVCRT__set_errno(GetLastError());
307 return -1;
308 }
309 if ((attr & FILE_ATTRIBUTE_READONLY) && (mode & MSVCRT_W_OK))
310 {
311 MSVCRT__set_errno(ERROR_ACCESS_DENIED);
312 return -1;
313 }
314 return 0;
315}
316
317/*********************************************************************
318 * _chmod (MSVCRT.@)
319 */
320int _chmod(const char *path, int flags)
321{
322 DWORD oldFlags = GetFileAttributesA(path);
323
324 if (oldFlags != 0x0FFFFFFFF)
325 {
326 DWORD newFlags = (flags & _S_IWRITE)? oldFlags & ~FILE_ATTRIBUTE_READONLY:
327 oldFlags | FILE_ATTRIBUTE_READONLY;
328
329 if (newFlags == oldFlags || SetFileAttributesA(path, newFlags))
330 return 0;
331 }
332 MSVCRT__set_errno(GetLastError());
333 return -1;
334}
335
336/*********************************************************************
337 * _wchmod (MSVCRT.@)
338 */
339int _wchmod(const MSVCRT_wchar_t *path, int flags)
340{
341 DWORD oldFlags = GetFileAttributesW(path);
342
343 if (oldFlags != 0x0FFFFFFFF)
344 {
345 DWORD newFlags = (flags & _S_IWRITE)? oldFlags & ~FILE_ATTRIBUTE_READONLY:
346 oldFlags | FILE_ATTRIBUTE_READONLY;
347
348 if (newFlags == oldFlags || SetFileAttributesW(path, newFlags))
349 return 0;
350 }
351 MSVCRT__set_errno(GetLastError());
352 return -1;
353}
354
355/*********************************************************************
356 * _unlink (MSVCRT.@)
357 */
358int _unlink(const char *path)
359{
360 TRACE("(%s)\n",path);
361 if(DeleteFileA(path))
362 return 0;
363 TRACE("failed (%ld)\n",GetLastError());
364 MSVCRT__set_errno(GetLastError());
365 return -1;
366}
367
368/*********************************************************************
369 * _wunlink (MSVCRT.@)
370 */
371int _wunlink(const MSVCRT_wchar_t *path)
372{
373 TRACE("(%s)\n",debugstr_w(path));
374 if(DeleteFileW(path))
375 return 0;
376 TRACE("failed (%ld)\n",GetLastError());
377 MSVCRT__set_errno(GetLastError());
378 return -1;
379}
380
381/*********************************************************************
382 * _close (MSVCRT.@)
383 */
384int _close(int fd)
385{
386 HANDLE hand = msvcrt_fdtoh(fd);
387
388 TRACE(":fd (%d) handle (%p)\n",fd,hand);
389 if (hand == INVALID_HANDLE_VALUE)
390 return -1;
391 /* flush stdio buffers */
392 if(MSVCRT_files[fd]) {
393 if(MSVCRT_files[fd]->_flag & MSVCRT__IOWRT)
394 MSVCRT_fflush(MSVCRT_files[fd]);
395
396 if(MSVCRT_files[fd]->_flag & MSVCRT__IOMYBUF)
397 MSVCRT_free(MSVCRT_files[fd]->_base);
398 }
399
400 /* Dont free std FILE*'s, they are not dynamic */
401 if (fd > 2 && MSVCRT_files[fd])
402 MSVCRT_free(MSVCRT_files[fd]);
403
404 msvcrt_free_fd(fd);
405
406 if (!CloseHandle(hand))
407 {
408 WARN(":failed-last error (%ld)\n",GetLastError());
409 MSVCRT__set_errno(GetLastError());
410 return -1;
411 }
412 if (MSVCRT_tempfiles[fd])
413 {
414 TRACE("deleting temporary file '%s'\n",MSVCRT_tempfiles[fd]);
415 _unlink(MSVCRT_tempfiles[fd]);
416 MSVCRT_free(MSVCRT_tempfiles[fd]);
417 MSVCRT_tempfiles[fd] = NULL;
418 }
419
420 TRACE(":ok\n");
421 return 0;
422}
423
424/*********************************************************************
425 * _commit (MSVCRT.@)
426 */
427int _commit(int fd)
428{
429 HANDLE hand = msvcrt_fdtoh(fd);
430
431 TRACE(":fd (%d) handle (%p)\n",fd,hand);
432 if (hand == INVALID_HANDLE_VALUE)
433 return -1;
434
435 if (!FlushFileBuffers(hand))
436 {
437 if (GetLastError() == ERROR_INVALID_HANDLE)
438 {
439 /* FlushFileBuffers fails for console handles
440 * so we ignore this error.
441 */
442 return 0;
443 }
444 TRACE(":failed-last error (%ld)\n",GetLastError());
445 MSVCRT__set_errno(GetLastError());
446 return -1;
447 }
448 TRACE(":ok\n");
449 return 0;
450}
451
452/*********************************************************************
453 * _eof (MSVCRT.@)
454 */
455int _eof(int fd)
456{
457 DWORD curpos,endpos;
458 HANDLE hand = msvcrt_fdtoh(fd);
459
460 TRACE(":fd (%d) handle (%p)\n",fd,hand);
461
462 if (hand == INVALID_HANDLE_VALUE)
463 return -1;
464
465 /* If we have a FILE* for this file, the EOF flag
466 * will be set by the read()/write() functions.
467 */
468 if (MSVCRT_files[fd])
469 return MSVCRT_flags[fd] & MSVCRT__IOEOF;
470
471 /* Otherwise we do it the hard way */
472 curpos = SetFilePointer(hand, 0, NULL, SEEK_CUR);
473 endpos = SetFilePointer(hand, 0, NULL, FILE_END);
474
475 if (curpos == endpos)
476 return TRUE;
477
478 SetFilePointer(hand, curpos, 0, FILE_BEGIN);
479 return FALSE;
480}
481
482/*********************************************************************
483 * _fcloseall (MSVCRT.@)
484 */
485int _fcloseall(void)
486{
487 int num_closed = 0, i;
488
489 for (i = 3; i < MSVCRT_fdend; i++)
490 if (MSVCRT_handles[i] != INVALID_HANDLE_VALUE)
491 {
492 _close(i);
493 num_closed++;
494 }
495
496 TRACE(":closed (%d) handles\n",num_closed);
497 return num_closed;
498}
499
500/*********************************************************************
501 * _lseek (MSVCRT.@)
502 */
503__int64 _lseeki64(int fd, __int64 offset, int whence)
504{
505 DWORD ret, hoffset = (DWORD) (offset >> 32);
506 HANDLE hand = msvcrt_fdtoh(fd);
507
508 TRACE(":fd (%d) handle (%p)\n",fd,hand);
509 if (hand == INVALID_HANDLE_VALUE)
510 return -1;
511
512 if (whence < 0 || whence > 2)
513 {
514 *MSVCRT__errno() = MSVCRT_EINVAL;
515 return -1;
516 }
517
518 TRACE(":fd (%d) to 0x%08lx%08lx pos %s\n",
519 fd,hoffset,(long)offset,
520 (whence==SEEK_SET)?"SEEK_SET":
521 (whence==SEEK_CUR)?"SEEK_CUR":
522 (whence==SEEK_END)?"SEEK_END":"UNKNOWN");
523
524 if (((ret = SetFilePointer(hand, (long)offset, &hoffset,
525 whence)) != INVALID_SET_FILE_POINTER) || !GetLastError())
526 {
527 if (MSVCRT_files[fd])
528 MSVCRT_files[fd]->_flag &= ~MSVCRT__IOEOF;
529 /* FIXME: What if we seek _to_ EOF - is EOF set? */
530
531 return ((__int64)hoffset << 32) | ret;
532 }
533 TRACE(":error-last error (%ld)\n",GetLastError());
534 if (MSVCRT_files[fd])
535 switch(GetLastError())
536 {
537 case ERROR_NEGATIVE_SEEK:
538 case ERROR_SEEK_ON_DEVICE:
539 MSVCRT__set_errno(GetLastError());
540 MSVCRT_files[fd]->_flag |= MSVCRT__IOERR;
541 break;
542 default:
543 break;
544 }
545 return -1;
546}
547
548/*********************************************************************
549 * _lseek (MSVCRT.@)
550 */
551LONG _lseek(int fd, LONG offset, int whence)
552{
553 return _lseeki64(fd, offset, whence);
554}
555
556/*********************************************************************
557 * _locking (MSVCRT.@)
558 *
559 * This is untested; the underlying LockFile doesn't work yet.
560 */
561int _locking(int fd, int mode, LONG nbytes)
562{
563 BOOL ret;
564 DWORD cur_locn;
565 HANDLE hand = msvcrt_fdtoh(fd);
566
567 TRACE(":fd (%d) handle (%p)\n",fd,hand);
568 if (hand == INVALID_HANDLE_VALUE)
569 return -1;
570
571 if (mode < 0 || mode > 4)
572 {
573 *MSVCRT__errno() = MSVCRT_EINVAL;
574 return -1;
575 }
576
577 TRACE(":fd (%d) by 0x%08lx mode %s\n",
578 fd,nbytes,(mode==_LK_UNLCK)?"_LK_UNLCK":
579 (mode==_LK_LOCK)?"_LK_LOCK":
580 (mode==_LK_NBLCK)?"_LK_NBLCK":
581 (mode==_LK_RLCK)?"_LK_RLCK":
582 (mode==_LK_NBRLCK)?"_LK_NBRLCK":
583 "UNKNOWN");
584
585 if ((cur_locn = SetFilePointer(hand, 0L, NULL, SEEK_CUR)) == 0xffffffff)
586 {
587 FIXME ("Seek failed\n");
588 *MSVCRT__errno() = MSVCRT_EINVAL; /* FIXME */
589 return -1;
590 }
591 if (mode == _LK_LOCK || mode == _LK_RLCK)
592 {
593 int nretry = 10;
594 ret = 1; /* just to satisfy gcc */
595 while (nretry--)
596 {
597 ret = LockFile(hand, cur_locn, 0L, nbytes, 0L);
598 if (ret) break;
599 sleep (1);
600 }
601 }
602 else if (mode == _LK_UNLCK)
603 ret = UnlockFile(hand, cur_locn, 0L, nbytes, 0L);
604 else
605 ret = LockFile(hand, cur_locn, 0L, nbytes, 0L);
606 /* FIXME - what about error settings? */
607 return ret ? 0 : -1;
608}
609
610/*********************************************************************
611 * rewind (MSVCRT.@)
612 */
613void MSVCRT_rewind(MSVCRT_FILE* file)
614{
615 TRACE(":file (%p) fd (%d)\n",file,file->_file);
616 MSVCRT_fseek(file, 0L, SEEK_SET);
617 MSVCRT_clearerr(file);
618}
619
620/*********************************************************************
621 * _fdopen (MSVCRT.@)
622 */
623MSVCRT_FILE* _fdopen(int fd, const char *mode)
624{
625 MSVCRT_FILE* file = msvcrt_alloc_fp(fd);
626
627 TRACE(":fd (%d) mode (%s) FILE* (%p)\n",fd,mode,file);
628
629 return file;
630}
631
632/*********************************************************************
633 * _wfdopen (MSVCRT.@)
634 */
635MSVCRT_FILE* _wfdopen(int fd, const MSVCRT_wchar_t *mode)
636{
637 MSVCRT_FILE* file = msvcrt_alloc_fp(fd);
638
639 TRACE(":fd (%d) mode (%s) FILE* (%p)\n",fd,debugstr_w(mode),file);
640 if (file)
641 MSVCRT_rewind(file);
642
643 return file;
644}
645
646/*********************************************************************
647 * _filelength (MSVCRT.@)
648 */
649LONG _filelength(int fd)
650{
651 LONG curPos = _lseek(fd, 0, SEEK_CUR);
652 if (curPos != -1)
653 {
654 LONG endPos = _lseek(fd, 0, SEEK_END);
655 if (endPos != -1)
656 {
657 if (endPos != curPos)
658 _lseek(fd, curPos, SEEK_SET);
659 return endPos;
660 }
661 }
662 return -1;
663}
664
665/*********************************************************************
666 * _fileno (MSVCRT.@)
667 */
668int _fileno(MSVCRT_FILE* file)
669{
670 TRACE(":FILE* (%p) fd (%d)\n",file,file->_file);
671 return file->_file;
672}
673
674/*********************************************************************
675 * _flushall (MSVCRT.@)
676 */
677int _flushall(void)
678{
679 int num_flushed = 0, i = 3;
680
681 while(i < MSVCRT_fdend)
682 if (MSVCRT_handles[i] != INVALID_HANDLE_VALUE)
683 {
684#if 0
685 /* FIXME: flush, do not commit */
686 if (_commit(i) == -1)
687 if (MSVCRT_files[i])
688 MSVCRT_files[i]->_flag |= MSVCRT__IOERR;
689#endif
690 if(MSVCRT_files[i] && MSVCRT_files[i]->_flag & MSVCRT__IOWRT) {
691 MSVCRT_fflush(MSVCRT_files[i]);
692 num_flushed++;
693 }
694 }
695
696 TRACE(":flushed (%d) handles\n",num_flushed);
697 return num_flushed;
698}
699
700/*********************************************************************
701 * _fstati64 (MSVCRT.@)
702 */
703int _fstati64(int fd, struct _stati64* buf)
704{
705 DWORD dw;
706 BY_HANDLE_FILE_INFORMATION hfi;
707 HANDLE hand = msvcrt_fdtoh(fd);
708
709 TRACE(":fd (%d) stat (%p)\n",fd,buf);
710 if (hand == INVALID_HANDLE_VALUE)
711 return -1;
712
713 if (!buf)
714 {
715 WARN(":failed-NULL buf\n");
716 MSVCRT__set_errno(ERROR_INVALID_PARAMETER);
717 return -1;
718 }
719
720 memset(&hfi, 0, sizeof(hfi));
721 memset(buf, 0, sizeof(struct _stati64));
722 if (!GetFileInformationByHandle(hand, &hfi))
723 {
724 WARN(":failed-last error (%ld)\n",GetLastError());
725 MSVCRT__set_errno(ERROR_INVALID_PARAMETER);
726 return -1;
727 }
728 FIXME(":dwFileAttributes = %ld, mode set to 0\n",hfi.dwFileAttributes);
729 buf->st_nlink = hfi.nNumberOfLinks;
730 buf->st_size = ((__int64)hfi.nFileSizeHigh << 32) + hfi.nFileSizeLow;
731 RtlTimeToSecondsSince1970((LARGE_INTEGER *)&hfi.ftLastAccessTime, &dw);
732 buf->st_atime = dw;
733 RtlTimeToSecondsSince1970((LARGE_INTEGER *)&hfi.ftLastWriteTime, &dw);
734 buf->st_mtime = buf->st_ctime = dw;
735 return 0;
736}
737
738/*********************************************************************
739 * _fstat (MSVCRT.@)
740 */
741int MSVCRT__fstat(int fd, struct _stat* buf)
742{ int ret;
743 struct _stati64 bufi64;
744
745 ret = _fstati64(fd, &bufi64);
746 if (!ret)
747 msvcrt_cp_from_stati64(&bufi64, buf);
748 return ret;
749}
750
751/*********************************************************************
752 * _futime (MSVCRT.@)
753 */
754int _futime(int fd, struct _utimbuf *t)
755{
756 HANDLE hand = msvcrt_fdtoh(fd);
757 FILETIME at, wt;
758
759 if (!t)
760 {
761 MSVCRT_time_t currTime;
762 MSVCRT_time(&currTime);
763 RtlSecondsSince1970ToTime(currTime, (LARGE_INTEGER *)&at);
764 memcpy(&wt, &at, sizeof(wt));
765 }
766 else
767 {
768 RtlSecondsSince1970ToTime(t->actime, (LARGE_INTEGER *)&at);
769 if (t->actime == t->modtime)
770 memcpy(&wt, &at, sizeof(wt));
771 else
772 RtlSecondsSince1970ToTime(t->modtime, (LARGE_INTEGER *)&wt);
773 }
774
775 if (!SetFileTime(hand, NULL, &at, &wt))
776 {
777 MSVCRT__set_errno(GetLastError());
778 return -1 ;
779 }
780 return 0;
781}
782
783/*********************************************************************
784 * _get_osfhandle (MSVCRT.@)
785 */
786long _get_osfhandle(int fd)
787{
788 HANDLE hand = msvcrt_fdtoh(fd);
789 HANDLE newhand = hand;
790 TRACE(":fd (%d) handle (%p)\n",fd,hand);
791
792 if (hand != INVALID_HANDLE_VALUE)
793 {
794 /* FIXME: I'm not convinced that I should be copying the
795 * handle here - it may be leaked if the app doesn't
796 * close it (and the API docs dont say that it should)
797 * Not duplicating it means that it can't be inherited
798 * and so lcc's wedit doesn't cope when it passes it to
799 * child processes. I've an idea that it should either
800 * be copied by CreateProcess, or marked as inheritable
801 * when initialised, or maybe both? JG 21-9-00.
802 */
803 DuplicateHandle(GetCurrentProcess(),hand,GetCurrentProcess(),
804 &newhand,0,TRUE,DUPLICATE_SAME_ACCESS);
805 }
806 return (long)newhand;
807}
808
809/*********************************************************************
810 * _isatty (MSVCRT.@)
811 */
812int _isatty(int fd)
813{
814 HANDLE hand = msvcrt_fdtoh(fd);
815
816 TRACE(":fd (%d) handle (%p)\n",fd,hand);
817 if (hand == INVALID_HANDLE_VALUE)
818 return 0;
819
820 return GetFileType(hand) == FILE_TYPE_CHAR? 1 : 0;
821}
822
823/*********************************************************************
824 * _mktemp (MSVCRT.@)
825 */
826char *_mktemp(char *pattern)
827{
828 int numX = 0;
829 char *retVal = pattern;
830 int id;
831 char letter = 'a';
832
833 while(*pattern)
834 numX = (*pattern++ == 'X')? numX + 1 : 0;
835 if (numX < 5)
836 return NULL;
837 pattern--;
838 id = GetCurrentProcessId();
839 numX = 6;
840 while(numX--)
841 {
842 int tempNum = id / 10;
843 *pattern-- = id - (tempNum * 10) + '0';
844 id = tempNum;
845 }
846 pattern++;
847 do
848 {
849 if (GetFileAttributesA(retVal) == 0xFFFFFFFF &&
850 GetLastError() == ERROR_FILE_NOT_FOUND)
851 return retVal;
852 *pattern = letter++;
853 } while(letter != '|');
854 return NULL;
855}
856
857/*********************************************************************
858 * _wmktemp (MSVCRT.@)
859 */
860MSVCRT_wchar_t *_wmktemp(MSVCRT_wchar_t *pattern)
861{
862 int numX = 0;
863 MSVCRT_wchar_t *retVal = pattern;
864 int id;
865 MSVCRT_wchar_t letter = 'a';
866
867 while(*pattern)
868 numX = (*pattern++ == 'X')? numX + 1 : 0;
869 if (numX < 5)
870 return NULL;
871 pattern--;
872 id = GetCurrentProcessId();
873 numX = 6;
874 while(numX--)
875 {
876 int tempNum = id / 10;
877 *pattern-- = id - (tempNum * 10) + '0';
878 id = tempNum;
879 }
880 pattern++;
881 do
882 {
883 if (GetFileAttributesW(retVal) == 0xFFFFFFFF &&
884 GetLastError() == ERROR_FILE_NOT_FOUND)
885 return retVal;
886 *pattern = letter++;
887 } while(letter != '|');
888 return NULL;
889}
890
891/*********************************************************************
892 * _sopen (MSVCRT.@)
893 */
894int MSVCRT__sopen( const char *path, int oflags, int shflags, ... )
895{
896 va_list ap;
897 int pmode;
898 DWORD access = 0, creation = 0;
899 DWORD sharing;
900 int ioflag = 0, fd;
901 HANDLE hand;
902 SECURITY_ATTRIBUTES sa;
903
904
905 TRACE(":file (%s) oflags: 0x%04x shflags: 0x%04x\n",
906 path, oflags, shflags);
907
908 switch(oflags & (_O_RDONLY | _O_WRONLY | _O_RDWR))
909 {
910 case _O_RDONLY:
911 access |= GENERIC_READ;
912 ioflag |= MSVCRT__IOREAD;
913 break;
914 case _O_WRONLY:
915 access |= GENERIC_WRITE;
916 ioflag |= MSVCRT__IOWRT;
917 break;
918 case _O_RDWR:
919 access |= GENERIC_WRITE | GENERIC_READ;
920 ioflag |= MSVCRT__IORW;
921 break;
922 }
923
924 if (oflags & _O_CREAT)
925 {
926 va_start(ap, shflags);
927 pmode = va_arg(ap, int);
928 va_end(ap);
929
930 FIXME(": pmode 0x%04x ignored\n", pmode);
931
932 if (oflags & _O_EXCL)
933 creation = CREATE_NEW;
934 else if (oflags & _O_TRUNC)
935 creation = CREATE_ALWAYS;
936 else
937 creation = OPEN_ALWAYS;
938 }
939 else /* no _O_CREAT */
940 {
941 if (oflags & _O_TRUNC)
942 creation = TRUNCATE_EXISTING;
943 else
944 creation = OPEN_EXISTING;
945 }
946 if (oflags & _O_APPEND)
947 ioflag |= MSVCRT__IOAPPEND;
948
949
950 oflags |= _O_BINARY; /* FIXME: Default to text */
951
952 if (oflags & _O_TEXT)
953 {
954 /* Dont warn when writing */
955 if (ioflag & GENERIC_READ)
956 FIXME(":TEXT node not implemented\n");
957 oflags &= ~_O_TEXT;
958 }
959
960 switch( shflags )
961 {
962 case _SH_DENYRW:
963 sharing = 0L;
964 break;
965 case _SH_DENYWR:
966 sharing = FILE_SHARE_READ;
967 break;
968 case _SH_DENYRD:
969 sharing = FILE_SHARE_WRITE;
970 break;
971 case _SH_DENYNO:
972 sharing = FILE_SHARE_READ | FILE_SHARE_WRITE;
973 break;
974 default:
975 ERR( "Unhandled shflags 0x%x\n", shflags );
976 return -1;
977 }
978
979 if (oflags & ~(_O_BINARY|_O_TEXT|_O_APPEND|_O_TRUNC|_O_EXCL
980 |_O_CREAT|_O_RDWR|_O_TEMPORARY|_O_NOINHERIT))
981 TRACE(":unsupported oflags 0x%04x\n",oflags);
982
983 sa.nLength = sizeof( SECURITY_ATTRIBUTES );
984 sa.lpSecurityDescriptor = NULL;
985 sa.bInheritHandle = (oflags & _O_NOINHERIT) ? FALSE : TRUE;
986
987 hand = CreateFileA(path, access, sharing,
988 &sa, creation, FILE_ATTRIBUTE_NORMAL, 0);
989
990 if (hand == INVALID_HANDLE_VALUE) {
991 WARN(":failed-last error (%ld)\n",GetLastError());
992 MSVCRT__set_errno(GetLastError());
993 return -1;
994 }
995
996 fd = msvcrt_alloc_fd(hand, ioflag);
997
998 TRACE(":fd (%d) handle (%p)\n",fd, hand);
999
1000 if (fd > 0)
1001 {
1002 if (oflags & _O_TEMPORARY)
1003 MSVCRT_tempfiles[fd] = _strdup(path);
1004 if (ioflag & MSVCRT__IOAPPEND)
1005 _lseek(fd, 0, FILE_END);
1006 }
1007
1008 return fd;
1009}
1010
1011/*********************************************************************
1012 * _wsopen (MSVCRT.@)
1013 */
1014int MSVCRT__wsopen( const MSVCRT_wchar_t* path, int oflags, int shflags, ... )
1015{
1016 const unsigned int len = strlenW(path);
1017 char *patha = MSVCRT_calloc(len + 1,1);
1018 va_list ap;
1019 int pmode;
1020
1021 va_start(ap, shflags);
1022 pmode = va_arg(ap, int);
1023 va_end(ap);
1024
1025 if (patha && WideCharToMultiByte(CP_ACP,0,path,len,patha,len,NULL,NULL))
1026 {
1027 int retval = MSVCRT__sopen(patha,oflags,shflags,pmode);
1028 MSVCRT_free(patha);
1029 return retval;
1030 }
1031
1032 MSVCRT__set_errno(GetLastError());
1033 return -1;
1034}
1035
1036/*********************************************************************
1037 * _open (MSVCRT.@)
1038 */
1039int _open( const char *path, int flags, ... )
1040{
1041 va_list ap;
1042 int pmode;
1043
1044 va_start(ap, flags);
1045 pmode = va_arg(ap, int);
1046 va_end(ap);
1047
1048 return MSVCRT__sopen( path, flags, _SH_DENYNO, pmode );
1049}
1050
1051/*********************************************************************
1052 * _wopen (MSVCRT.@)
1053 */
1054int _wopen(const MSVCRT_wchar_t *path,int flags,...)
1055{
1056 const unsigned int len = strlenW(path);
1057 char *patha = MSVCRT_calloc(len + 1,1);
1058 va_list ap;
1059 int pmode;
1060
1061 va_start(ap, flags);
1062 pmode = va_arg(ap, int);
1063 va_end(ap);
1064
1065 if (patha && WideCharToMultiByte(CP_ACP,0,path,len,patha,len,NULL,NULL))
1066 {
1067 int retval = _open(patha,flags,pmode);
1068 MSVCRT_free(patha);
1069 return retval;
1070 }
1071
1072 MSVCRT__set_errno(GetLastError());
1073 return -1;
1074}
1075
1076/*********************************************************************
1077 * _creat (MSVCRT.@)
1078 */
1079int _creat(const char *path, int flags)
1080{
1081 int usedFlags = (flags & _O_TEXT)| _O_CREAT| _O_WRONLY| _O_TRUNC;
1082 return _open(path, usedFlags);
1083}
1084
1085/*********************************************************************
1086 * _wcreat (MSVCRT.@)
1087 */
1088int _wcreat(const MSVCRT_wchar_t *path, int flags)
1089{
1090 int usedFlags = (flags & _O_TEXT)| _O_CREAT| _O_WRONLY| _O_TRUNC;
1091 return _wopen(path, usedFlags);
1092}
1093
1094/*********************************************************************
1095 * _open_osfhandle (MSVCRT.@)
1096 */
1097int _open_osfhandle(long hand, int flags)
1098{
1099 /* _O_RDONLY (0) always matches, so set the read flag*/
1100 /* FIXME: handle more flags */
1101 int fd= msvcrt_alloc_fd((HANDLE)hand,flags|MSVCRT__IOREAD);
1102 TRACE(":handle (%ld) fd (%d) flags 0x%08x\n",hand,fd, flags |MSVCRT__IOREAD);
1103 return fd;
1104}
1105
1106/*********************************************************************
1107 * _rmtmp (MSVCRT.@)
1108 */
1109int _rmtmp(void)
1110{
1111 int num_removed = 0, i;
1112
1113 for (i = 3; i < MSVCRT_fdend; i++)
1114 if (MSVCRT_tempfiles[i])
1115 {
1116 _close(i);
1117 num_removed++;
1118 }
1119
1120 if (num_removed)
1121 TRACE(":removed (%d) temp files\n",num_removed);
1122 return num_removed;
1123}
1124
1125/*********************************************************************
1126 * _read (MSVCRT.@)
1127 */
1128int _read(int fd, void *buf, unsigned int count)
1129{
1130 DWORD num_read;
1131 HANDLE hand = msvcrt_fdtoh(fd);
1132
1133 /* Dont trace small reads, it gets *very* annoying */
1134 if (count > 4)
1135 TRACE(":fd (%d) handle (%p) buf (%p) len (%d)\n",fd,hand,buf,count);
1136 if (hand == INVALID_HANDLE_VALUE)
1137 return -1;
1138
1139 if (ReadFile(hand, buf, count, &num_read, NULL))
1140 {
1141 if (num_read != count && MSVCRT_files[fd])
1142 {
1143 TRACE(":EOF\n");
1144 MSVCRT_flags[fd] |= MSVCRT__IOEOF;
1145/*
1146 MSVCRT_files[fd]->_flag |= MSVCRT__IOEOF;
1147*/
1148 }
1149 return num_read;
1150 }
1151 TRACE(":failed-last error (%ld)\n",GetLastError());
1152 if (MSVCRT_files[fd])
1153 MSVCRT_files[fd]->_flag |= MSVCRT__IOERR;
1154 return -1;
1155}
1156
1157/*********************************************************************
1158 * _getw (MSVCRT.@)
1159 */
1160int _getw(MSVCRT_FILE* file)
1161{
1162 int i;
1163 if (_read(file->_file, &i, sizeof(int)) != 1)
1164 return MSVCRT_EOF;
1165 return i;
1166}
1167
1168/*********************************************************************
1169 * _setmode (MSVCRT.@)
1170 */
1171int _setmode(int fd,int mode)
1172{
1173 if (mode & _O_TEXT)
1174 FIXME("fd (%d) mode (%d) TEXT not implemented\n",fd,mode);
1175 return 0;
1176}
1177
1178/*********************************************************************
1179 * _stati64 (MSVCRT.@)
1180 */
1181int _stati64(const char* path, struct _stati64 * buf)
1182{
1183 DWORD dw;
1184 WIN32_FILE_ATTRIBUTE_DATA hfi;
1185 unsigned short mode = MSVCRT_S_IREAD;
1186 int plen;
1187
1188 TRACE(":file (%s) buf(%p)\n",path,buf);
1189
1190 if (!GetFileAttributesExA(path, GetFileExInfoStandard, &hfi))
1191 {
1192 TRACE("failed (%ld)\n",GetLastError());
1193 MSVCRT__set_errno(ERROR_FILE_NOT_FOUND);
1194 return -1;
1195 }
1196
1197 memset(buf,0,sizeof(struct _stati64));
1198
1199 /* FIXME: rdev isnt drive num,despite what the docs say-what is it?
1200 Bon 011120: This FIXME seems incorrect
1201 Also a letter as first char isn't enough to be classify
1202 as drive letter
1203 */
1204 if (isalpha(*path)&& (*(path+1)==':'))
1205 buf->st_dev = buf->st_rdev = toupper(*path) - 'A'; /* drive num */
1206 else
1207 buf->st_dev = buf->st_rdev = _getdrive() - 1;
1208
1209 plen = strlen(path);
1210
1211 /* Dir, or regular file? */
1212 if ((hfi.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ||
1213 (path[plen-1] == '\\'))
1214 mode |= (_S_IFDIR | MSVCRT_S_IEXEC);
1215 else
1216 {
1217 mode |= _S_IFREG;
1218 /* executable? */
1219 if (plen > 6 && path[plen-4] == '.') /* shortest exe: "\x.exe" */
1220 {
1221 unsigned int ext = tolower(path[plen-1]) | (tolower(path[plen-2]) << 8) |
1222 (tolower(path[plen-3]) << 16);
1223 if (ext == EXE || ext == BAT || ext == CMD || ext == COM)
1224 mode |= MSVCRT_S_IEXEC;
1225 }
1226 }
1227
1228 if (!(hfi.dwFileAttributes & FILE_ATTRIBUTE_READONLY))
1229 mode |= MSVCRT_S_IWRITE;
1230
1231 buf->st_mode = mode;
1232 buf->st_nlink = 1;
1233 buf->st_size = ((__int64)hfi.nFileSizeHigh << 32) + hfi.nFileSizeLow;
1234 RtlTimeToSecondsSince1970((LARGE_INTEGER *)&hfi.ftLastAccessTime, &dw);
1235 buf->st_atime = dw;
1236 RtlTimeToSecondsSince1970((LARGE_INTEGER *)&hfi.ftLastWriteTime, &dw);
1237 buf->st_mtime = buf->st_ctime = dw;
1238 TRACE("%d %d 0x%08lx%08lx %ld %ld %ld\n", buf->st_mode,buf->st_nlink,
1239 (long)(buf->st_size >> 32),(long)buf->st_size,
1240 buf->st_atime,buf->st_mtime, buf->st_ctime);
1241 return 0;
1242}
1243
1244/*********************************************************************
1245 * _stat (MSVCRT.@)
1246 */
1247int MSVCRT__stat(const char* path, struct _stat * buf)
1248{ int ret;
1249 struct _stati64 bufi64;
1250
1251 ret = _stati64( path, &bufi64);
1252 if (!ret)
1253 msvcrt_cp_from_stati64(&bufi64, buf);
1254 return ret;
1255}
1256
1257/*********************************************************************
1258 * _wstat (MSVCRT.@)
1259 */
1260int _wstat(const MSVCRT_wchar_t* path, struct _stat * buf)
1261{
1262 DWORD dw;
1263 WIN32_FILE_ATTRIBUTE_DATA hfi;
1264 unsigned short mode = MSVCRT_S_IREAD;
1265 int plen;
1266
1267 TRACE(":file (%s) buf(%p)\n",debugstr_w(path),buf);
1268
1269 if (!GetFileAttributesExW(path, GetFileExInfoStandard, &hfi))
1270 {
1271 TRACE("failed (%ld)\n",GetLastError());
1272 MSVCRT__set_errno(ERROR_FILE_NOT_FOUND);
1273 return -1;
1274 }
1275
1276 memset(buf,0,sizeof(struct _stat));
1277
1278 /* FIXME: rdev isn't drive num, despite what the docs says-what is it? */
1279 if (MSVCRT_iswalpha(*path))
1280 buf->st_dev = buf->st_rdev = toupperW(*path - 'A'); /* drive num */
1281 else
1282 buf->st_dev = buf->st_rdev = _getdrive() - 1;
1283
1284 plen = strlenW(path);
1285
1286 /* Dir, or regular file? */
1287 if ((hfi.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ||
1288 (path[plen-1] == '\\'))
1289 mode |= (_S_IFDIR | MSVCRT_S_IEXEC);
1290 else
1291 {
1292 mode |= _S_IFREG;
1293 /* executable? */
1294 if (plen > 6 && path[plen-4] == '.') /* shortest exe: "\x.exe" */
1295 {
1296 ULONGLONG ext = tolowerW(path[plen-1]) | (tolowerW(path[plen-2]) << 16) |
1297 ((ULONGLONG)tolowerW(path[plen-3]) << 32);
1298 if (ext == WCEXE || ext == WCBAT || ext == WCCMD || ext == WCCOM)
1299 mode |= MSVCRT_S_IEXEC;
1300 }
1301 }
1302
1303 if (!(hfi.dwFileAttributes & FILE_ATTRIBUTE_READONLY))
1304 mode |= MSVCRT_S_IWRITE;
1305
1306 buf->st_mode = mode;
1307 buf->st_nlink = 1;
1308 buf->st_size = hfi.nFileSizeLow;
1309 RtlTimeToSecondsSince1970((LARGE_INTEGER *)&hfi.ftLastAccessTime, &dw);
1310 buf->st_atime = dw;
1311 RtlTimeToSecondsSince1970((LARGE_INTEGER *)&hfi.ftLastWriteTime, &dw);
1312 buf->st_mtime = buf->st_ctime = dw;
1313 TRACE("\n%d %d %d %ld %ld %ld\n", buf->st_mode,buf->st_nlink,buf->st_size,
1314 buf->st_atime,buf->st_mtime, buf->st_ctime);
1315 return 0;
1316}
1317
1318/*********************************************************************
1319 * _tell (MSVCRT.@)
1320 */
1321LONG _tell(int fd)
1322{
1323 return _lseek(fd, 0, SEEK_CUR);
1324}
1325
1326/*********************************************************************
1327 * _tempnam (MSVCRT.@)
1328 */
1329char *_tempnam(const char *dir, const char *prefix)
1330{
1331 char tmpbuf[MAX_PATH];
1332
1333 TRACE("dir (%s) prefix (%s)\n",dir,prefix);
1334 if (GetTempFileNameA(dir,prefix,0,tmpbuf))
1335 {
1336 TRACE("got name (%s)\n",tmpbuf);
1337 return _strdup(tmpbuf);
1338 }
1339 TRACE("failed (%ld)\n",GetLastError());
1340 return NULL;
1341}
1342
1343/*********************************************************************
1344 * _wtempnam (MSVCRT.@)
1345 */
1346MSVCRT_wchar_t *_wtempnam(const MSVCRT_wchar_t *dir, const MSVCRT_wchar_t *prefix)
1347{
1348 MSVCRT_wchar_t tmpbuf[MAX_PATH];
1349
1350 TRACE("dir (%s) prefix (%s)\n",debugstr_w(dir),debugstr_w(prefix));
1351 if (GetTempFileNameW(dir,prefix,0,tmpbuf))
1352 {
1353 TRACE("got name (%s)\n",debugstr_w(tmpbuf));
1354 return _wcsdup(tmpbuf);
1355 }
1356 TRACE("failed (%ld)\n",GetLastError());
1357 return NULL;
1358}
1359
1360/*********************************************************************
1361 * _umask (MSVCRT.@)
1362 */
1363int _umask(int umask)
1364{
1365 int old_umask = MSVCRT_umask;
1366 TRACE("(%d)\n",umask);
1367 MSVCRT_umask = umask;
1368 return old_umask;
1369}
1370
1371/*********************************************************************
1372 * _utime (MSVCRT.@)
1373 */
1374int _utime(const char* path, struct _utimbuf *t)
1375{
1376 int fd = _open(path, _O_WRONLY | _O_BINARY);
1377
1378 if (fd > 0)
1379 {
1380 int retVal = _futime(fd, t);
1381 _close(fd);
1382 return retVal;
1383 }
1384 return -1;
1385}
1386
1387/*********************************************************************
1388 * _wutime (MSVCRT.@)
1389 */
1390int _wutime(const MSVCRT_wchar_t* path, struct _utimbuf *t)
1391{
1392 int fd = _wopen(path, _O_WRONLY | _O_BINARY);
1393
1394 if (fd > 0)
1395 {
1396 int retVal = _futime(fd, t);
1397 _close(fd);
1398 return retVal;
1399 }
1400 return -1;
1401}
1402
1403/*********************************************************************
1404 * _write (MSVCRT.@)
1405 */
1406int _write(int fd, const void* buf, unsigned int count)
1407{
1408 DWORD num_written;
1409 HANDLE hand = msvcrt_fdtoh(fd);
1410
1411 /* Dont trace small writes, it gets *very* annoying */
1412#if 0
1413 if (count > 32)
1414 TRACE(":fd (%d) handle (%d) buf (%p) len (%d)\n",fd,hand,buf,count);
1415#endif
1416 if (hand == INVALID_HANDLE_VALUE)
1417 return -1;
1418
1419 /* If appending, go to EOF */
1420 if (MSVCRT_flags[fd] & MSVCRT__IOAPPEND)
1421 _lseek(fd, 0, FILE_END);
1422
1423 if (WriteFile(hand, buf, count, &num_written, NULL)
1424 && (num_written == count))
1425 return num_written;
1426
1427 TRACE(":failed-last error (%ld)\n",GetLastError());
1428 if (MSVCRT_files[fd])
1429 MSVCRT_files[fd]->_flag |= MSVCRT__IOERR;
1430
1431 return -1;
1432}
1433
1434/*********************************************************************
1435 * _putw (MSVCRT.@)
1436 */
1437int _putw(int val, MSVCRT_FILE* file)
1438{
1439 return _write(file->_file, &val, sizeof(val)) == 1? val : MSVCRT_EOF;
1440}
1441
1442/*********************************************************************
1443 * clearerr (MSVCRT.@)
1444 */
1445void MSVCRT_clearerr(MSVCRT_FILE* file)
1446{
1447 TRACE(":file (%p) fd (%d)\n",file,file->_file);
1448 file->_flag &= ~(MSVCRT__IOERR | MSVCRT__IOEOF);
1449}
1450
1451/*********************************************************************
1452 * fclose (MSVCRT.@)
1453 */
1454int MSVCRT_fclose(MSVCRT_FILE* file)
1455{
1456 int r;
1457 r=_close(file->_file);
1458 return ((r==MSVCRT_EOF) || (file->_flag & MSVCRT__IOERR) ? MSVCRT_EOF : 0);
1459}
1460
1461/*********************************************************************
1462 * feof (MSVCRT.@)
1463 */
1464int MSVCRT_feof(MSVCRT_FILE* file)
1465{
1466 return file->_flag & MSVCRT__IOEOF;
1467}
1468
1469/*********************************************************************
1470 * ferror (MSVCRT.@)
1471 */
1472int MSVCRT_ferror(MSVCRT_FILE* file)
1473{
1474 return file->_flag & MSVCRT__IOERR;
1475}
1476
1477/*********************************************************************
1478 * fflush (MSVCRT.@)
1479 */
1480int MSVCRT_fflush(MSVCRT_FILE* file)
1481{
1482 if(!file) {
1483 _flushall();
1484 return 0;
1485 } else {
1486 int res=msvcrt_flush_buffer(file);
1487 return res;
1488 }
1489}
1490
1491/*********************************************************************
1492 * fgetc (MSVCRT.@)
1493 */
1494int MSVCRT_fgetc(MSVCRT_FILE* file)
1495{
1496 if (file->_cnt>0) {
1497 file->_cnt--;
1498 return *(unsigned char *)file->_ptr++;
1499 } else {
1500 return _filbuf(file);
1501 }
1502}
1503
1504/*********************************************************************
1505 * _fgetchar (MSVCRT.@)
1506 */
1507int _fgetchar(void)
1508{
1509 return MSVCRT_fgetc(MSVCRT_stdin);
1510}
1511
1512/*********************************************************************
1513 * _filbuf (MSVCRT.@)
1514 */
1515int _filbuf(MSVCRT_FILE* file)
1516{
1517
1518 /* Allocate buffer if needed */
1519 if(file->_bufsiz == 0 && !(file->_flag & MSVCRT__IONBF) ) {
1520 msvcrt_alloc_buffer(file);
1521 }
1522 if(!(file->_flag & MSVCRT__IOREAD)) {
1523 if(file->_flag & MSVCRT__IORW) {
1524 file->_flag |= MSVCRT__IOREAD;
1525 } else {
1526 return MSVCRT_EOF;
1527 }
1528 }
1529 if(file->_flag & MSVCRT__IONBF) {
1530 unsigned char c;
1531 if (_read(file->_file,&c,1) != 1) {
1532 file->_flag |= MSVCRT__IOEOF;
1533 return MSVCRT_EOF;
1534 }
1535 return c;
1536 } else {
1537 file->_cnt = _read(file->_file, file->_base, file->_bufsiz);
1538 if(file->_cnt<0) file->_cnt = 0;
1539 if(!file->_cnt) {
1540 file->_flag |= MSVCRT__IOEOF;
1541 return MSVCRT_EOF;
1542 }
1543 file->_cnt--;
1544 file->_ptr = file->_base+1;
1545 return *(unsigned char *)file->_base;
1546 }
1547}
1548
1549/*********************************************************************
1550 * fgetpos (MSVCRT.@)
1551 */
1552int MSVCRT_fgetpos(MSVCRT_FILE* file, MSVCRT_fpos_t *pos)
1553{
1554 *pos = MSVCRT_ftell(file);
1555 return (*pos == -1? -1 : 0);
1556}
1557
1558/*********************************************************************
1559 * fgets (MSVCRT.@)
1560 */
1561char *MSVCRT_fgets(char *s, int size, MSVCRT_FILE* file)
1562{
1563 int cc;
1564 char * buf_start = s;
1565
1566 TRACE(":file(%p) fd (%d) str (%p) len (%d)\n",
1567 file,file->_file,s,size);
1568
1569 for(cc = MSVCRT_fgetc(file); cc != MSVCRT_EOF && cc != '\n';
1570 cc = MSVCRT_fgetc(file))
1571 if (cc != '\r')
1572 {
1573 if (--size <= 0) break;
1574 *s++ = (char)cc;
1575 }
1576 if ((cc == MSVCRT_EOF) && (s == buf_start)) /* If nothing read, return 0*/
1577 {
1578 TRACE(":nothing read\n");
1579 return 0;
1580 }
1581 if (cc == '\n')
1582 if (--size > 0)
1583 *s++ = '\n';
1584 *s = '\0';
1585 TRACE(":got '%s'\n", buf_start);
1586 return buf_start;
1587}
1588
1589/*********************************************************************
1590 * fgetwc (MSVCRT.@)
1591 */
1592MSVCRT_wint_t MSVCRT_fgetwc(MSVCRT_FILE* file)
1593{
1594 MSVCRT_wchar_t wc;
1595 if (_read(file->_file, &wc, sizeof(wc)) != sizeof(wc))
1596 return MSVCRT_WEOF;
1597 return wc;
1598}
1599
1600/*********************************************************************
1601 * getwc (MSVCRT.@)
1602 */
1603MSVCRT_wint_t MSVCRT_getwc(MSVCRT_FILE* file)
1604{
1605 return MSVCRT_fgetwc(file);
1606}
1607
1608/*********************************************************************
1609 * _fgetwchar (MSVCRT.@)
1610 */
1611MSVCRT_wint_t _fgetwchar(void)
1612{
1613 return MSVCRT_fgetwc(MSVCRT_stdin);
1614}
1615
1616/*********************************************************************
1617 * getwchar (MSVCRT.@)
1618 */
1619MSVCRT_wint_t MSVCRT_getwchar(void)
1620{
1621 return _fgetwchar();
1622}
1623
1624/*********************************************************************
1625 * fgetws (MSVCRT.@)
1626 */
1627MSVCRT_wchar_t *MSVCRT_fgetws(MSVCRT_wchar_t *s, int size, MSVCRT_FILE* file)
1628{
1629 int cc;
1630 MSVCRT_wchar_t * buf_start = s;
1631
1632 TRACE(":file(%p) fd (%d) str (%p) len (%d)\n",
1633 file,file->_file,s,size);
1634
1635 for(cc = MSVCRT_fgetwc(file); cc != MSVCRT_WEOF && cc != L'\n';
1636 cc = MSVCRT_fgetwc(file))
1637 if (cc != L'\r')
1638 {
1639 if (--size <= 0) break;
1640 *s++ = cc;
1641 }
1642 if ((cc == MSVCRT_EOF) && (s == buf_start)) /* If nothing read, return 0*/
1643 {
1644 TRACE(":nothing read\n");
1645 return 0;
1646 }
1647 if (cc == L'\n')
1648 if (--size > 0)
1649 *s++ = '\n';
1650 *s = '\0';
1651/* TRACE(":got '%s'\n", buf_start); */
1652 return buf_start;
1653}
1654
1655
1656/*********************************************************************
1657 * fputwc (MSVCRT.@)
1658 */
1659MSVCRT_wint_t MSVCRT_fputwc(MSVCRT_wint_t wc, MSVCRT_FILE* file)
1660{
1661 MSVCRT_wchar_t mwc=wc;
1662 if (MSVCRT_fwrite( &mwc, sizeof(mwc), 1, file) != 1)
1663 return MSVCRT_WEOF;
1664 return wc;
1665}
1666
1667/*********************************************************************
1668 * _fputwchar (MSVCRT.@)
1669 */
1670MSVCRT_wint_t _fputwchar(MSVCRT_wint_t wc)
1671{
1672 return MSVCRT_fputwc(wc, MSVCRT_stdout);
1673}
1674
1675/*********************************************************************
1676 * fopen (MSVCRT.@)
1677 */
1678MSVCRT_FILE* MSVCRT_fopen(const char *path, const char *mode)
1679{
1680 MSVCRT_FILE* file;
1681 int flags = 0, plus = 0, fd;
1682 const char* search = mode;
1683
1684 TRACE("(%s,%s)\n",path,mode);
1685
1686 while (*search)
1687 if (*search++ == '+')
1688 plus = 1;
1689
1690 /* map mode string to open() flags. "man fopen" for possibilities. */
1691 switch(*mode++)
1692 {
1693 case 'R': case 'r':
1694 flags = (plus ? _O_RDWR : _O_RDONLY);
1695 break;
1696 case 'W': case 'w':
1697 flags = _O_CREAT | _O_TRUNC | (plus ? _O_RDWR : _O_WRONLY);
1698 break;
1699 case 'A': case 'a':
1700 flags = _O_CREAT | _O_APPEND | (plus ? _O_RDWR : _O_WRONLY);
1701 break;
1702 default:
1703 return NULL;
1704 }
1705
1706 while (*mode)
1707 switch (*mode++)
1708 {
1709 case 'B': case 'b':
1710 flags |= _O_BINARY;
1711 flags &= ~_O_TEXT;
1712 break;
1713 case 'T': case 't':
1714 flags |= _O_TEXT;
1715 flags &= ~_O_BINARY;
1716 break;
1717 case '+':
1718 break;
1719 default:
1720 FIXME(":unknown flag %c not supported\n",mode[-1]);
1721 }
1722
1723 fd = _open(path, flags);
1724
1725 if (fd < 0)
1726 return NULL;
1727
1728 file = msvcrt_alloc_fp(fd);
1729 TRACE(":got (%p)\n",file);
1730 if (!file)
1731 _close(fd);
1732
1733 return file;
1734}
1735
1736/*********************************************************************
1737 * _wfopen (MSVCRT.@)
1738 */
1739MSVCRT_FILE *_wfopen(const MSVCRT_wchar_t *path, const MSVCRT_wchar_t *mode)
1740{
1741 const unsigned int plen = strlenW(path), mlen = strlenW(mode);
1742 char *patha = MSVCRT_calloc(plen + 1, 1);
1743 char *modea = MSVCRT_calloc(mlen + 1, 1);
1744
1745 TRACE("(%s,%s)\n",debugstr_w(path),debugstr_w(mode));
1746
1747 if (patha && modea &&
1748 WideCharToMultiByte(CP_ACP,0,path,plen,patha,plen,NULL,NULL) &&
1749 WideCharToMultiByte(CP_ACP,0,mode,mlen,modea,mlen,NULL,NULL))
1750 {
1751 MSVCRT_FILE *retval = MSVCRT_fopen(patha,modea);
1752 MSVCRT_free(patha);
1753 MSVCRT_free(modea);
1754 return retval;
1755 }
1756
1757 MSVCRT__set_errno(GetLastError());
1758 return NULL;
1759}
1760
1761/*********************************************************************
1762 * _fsopen (MSVCRT.@)
1763 */
1764MSVCRT_FILE* _fsopen(const char *path, const char *mode, int share)
1765{
1766 FIXME(":(%s,%s,%d),ignoring share mode!\n",path,mode,share);
1767 return MSVCRT_fopen(path,mode);
1768}
1769
1770/*********************************************************************
1771 * _wfsopen (MSVCRT.@)
1772 */
1773MSVCRT_FILE* _wfsopen(const MSVCRT_wchar_t *path, const MSVCRT_wchar_t *mode, int share)
1774{
1775 FIXME(":(%s,%s,%d),ignoring share mode!\n",
1776 debugstr_w(path),debugstr_w(mode),share);
1777 return _wfopen(path,mode);
1778}
1779
1780/*********************************************************************
1781 * fputc (MSVCRT.@)
1782 */
1783int MSVCRT_fputc(int c, MSVCRT_FILE* file)
1784{
1785 if(file->_cnt>0) {
1786 *file->_ptr++=c;
1787 file->_cnt--;
1788 return c;
1789 } else {
1790 return _flsbuf(c, file);
1791 }
1792}
1793
1794/*********************************************************************
1795 * _flsbuf (MSVCRT.@)
1796 */
1797int _flsbuf(int c, MSVCRT_FILE* file)
1798{
1799 /* Flush output buffer */
1800 if(file->_bufsiz == 0 && !(file->_flag & MSVCRT__IONBF)) {
1801 msvcrt_alloc_buffer(file);
1802 }
1803 if(!(file->_flag & MSVCRT__IOWRT)) {
1804 if(file->_flag & MSVCRT__IORW) {
1805 file->_flag |= MSVCRT__IOWRT;
1806 } else {
1807 return MSVCRT_EOF;
1808 }
1809 }
1810 if(file->_bufsiz) {
1811 int res=msvcrt_flush_buffer(file);
1812 return res?res : MSVCRT_fputc(c, file);
1813 } else {
1814 unsigned char cc=c;
1815 return _write(file->_file, &cc, 1) == 1? c : MSVCRT_EOF;
1816 }
1817}
1818
1819/*********************************************************************
1820 * _fputchar (MSVCRT.@)
1821 */
1822int _fputchar(int c)
1823{
1824 return MSVCRT_fputc(c, MSVCRT_stdout);
1825}
1826
1827/*********************************************************************
1828 * fread (MSVCRT.@)
1829 */
1830MSVCRT_size_t MSVCRT_fread(void *ptr, MSVCRT_size_t size, MSVCRT_size_t nmemb, MSVCRT_FILE* file)
1831{ MSVCRT_size_t rcnt=size * nmemb;
1832 MSVCRT_size_t read=0;
1833 int pread=0;
1834 /* first buffered data */
1835 if(file->_cnt>0) {
1836 int pcnt= (rcnt>file->_cnt)? file->_cnt:rcnt;
1837 memcpy(ptr, file->_ptr, pcnt);
1838 file->_cnt -= pcnt;
1839 file->_ptr += pcnt;
1840 read += pcnt ;
1841 rcnt -= pcnt ;
1842 ptr = (char*)ptr + pcnt;
1843 } else if(!(file->_flag & MSVCRT__IOREAD )) {
1844 if(file->_flag & MSVCRT__IORW) {
1845 file->_flag |= MSVCRT__IOREAD;
1846 } else
1847 return 0;
1848 }
1849 if(rcnt) pread = _read(file->_file,ptr, rcnt);
1850 if (MSVCRT_flags[file->_file] & MSVCRT__IOEOF)
1851 /* expose feof condition in the flags
1852 MFC tests file->_flag for feof, and doesn't not call feof())
1853 */
1854 file->_flag |= MSVCRT__IOEOF;
1855 if (pread <= 0)
1856 pread = 0;
1857 read+=pread;
1858 return read / size;
1859}
1860
1861/*********************************************************************
1862 * freopen (MSVCRT.@)
1863 *
1864 */
1865MSVCRT_FILE* MSVCRT_freopen(const char *path, const char *mode,MSVCRT_FILE* file)
1866{
1867 MSVCRT_FILE* newfile;
1868 int fd;
1869
1870 TRACE(":path (%p) mode (%s) file (%p) fd (%d)\n",path,mode,file,file->_file);
1871 if (!file || ((fd = file->_file) < 0) || fd > MSVCRT_fdend)
1872 return NULL;
1873
1874 if (fd > 2)
1875 {
1876#if 0
1877 FIXME(":reopen on user file not implemented!\n");
1878 MSVCRT__set_errno(ERROR_CALL_NOT_IMPLEMENTED);
1879 return NULL;
1880#endif
1881 if(MSVCRT_fclose(file))
1882 return NULL;
1883 return MSVCRT_fopen(path, mode);
1884 }
1885
1886 /* first, create the new file */
1887 if ((newfile = MSVCRT_fopen(path,mode)) == NULL)
1888 return NULL;
1889
1890 if (fd < 3 && SetStdHandle(fd == 0 ? STD_INPUT_HANDLE :
1891 (fd == 1? STD_OUTPUT_HANDLE : STD_ERROR_HANDLE),
1892 MSVCRT_handles[newfile->_file]))
1893 {
1894 /* Redirecting std handle to file , copy over.. */
1895 MSVCRT_handles[fd] = MSVCRT_handles[newfile->_file];
1896 MSVCRT_flags[fd] = MSVCRT_flags[newfile->_file];
1897 memcpy(&MSVCRT__iob[fd], newfile, sizeof (MSVCRT_FILE));
1898 MSVCRT__iob[fd]._file = fd;
1899 /* And free up the resources allocated by fopen, but
1900 * not the HANDLE we copied. */
1901 MSVCRT_free(MSVCRT_files[fd]);
1902 msvcrt_free_fd(newfile->_file);
1903 return &MSVCRT__iob[fd];
1904 }
1905
1906 WARN(":failed-last error (%ld)\n",GetLastError());
1907 MSVCRT_fclose(newfile);
1908 MSVCRT__set_errno(GetLastError());
1909 return NULL;
1910}
1911
1912/*********************************************************************
1913 * fsetpos (MSVCRT.@)
1914 */
1915int MSVCRT_fsetpos(MSVCRT_FILE* file, MSVCRT_fpos_t *pos)
1916{
1917 return _lseek(file->_file,*pos,SEEK_SET);
1918}
1919
1920/*********************************************************************
1921 * fseek (MSVCRT.@)
1922 */
1923int MSVCRT_fseek(MSVCRT_FILE* file, long offset, int whence)
1924{
1925 /* Flush output if needed */
1926 if(file->_flag & MSVCRT__IOWRT)
1927 msvcrt_flush_buffer(file);
1928
1929 if(whence == SEEK_CUR && file->_flag & MSVCRT__IOREAD ) {
1930 offset -= file->_cnt;
1931 }
1932 /* Discard buffered input */
1933 file->_cnt = 0;
1934 file->_ptr = file->_base;
1935 /* Reset direction of i/o */
1936 if(file->_flag & MSVCRT__IORW) {
1937 file->_flag &= ~(MSVCRT__IOREAD|MSVCRT__IOWRT);
1938 }
1939 return (_lseek(file->_file,offset,whence) == -1)?-1:0;
1940}
1941
1942/*********************************************************************
1943 * ftell (MSVCRT.@)
1944 */
1945LONG MSVCRT_ftell(MSVCRT_FILE* file)
1946{
1947 int off=0;
1948 long pos;
1949 if(file->_bufsiz) {
1950 if( file->_flag & MSVCRT__IOWRT ) {
1951 off = file->_ptr - file->_base;
1952 } else {
1953 off = -file->_cnt;
1954 }
1955 }
1956 pos = _tell(file->_file);
1957 if(pos == -1) return pos;
1958 return off + pos;
1959}
1960
1961/*********************************************************************
1962 * fwrite (MSVCRT.@)
1963 */
1964MSVCRT_size_t MSVCRT_fwrite(const void *ptr, MSVCRT_size_t size, MSVCRT_size_t nmemb, MSVCRT_FILE* file)
1965{
1966 MSVCRT_size_t wrcnt=size * nmemb;
1967 int written = 0;
1968 if (size == 0)
1969 return 0;
1970 if(file->_cnt) {
1971 int pcnt=(file->_cnt>wrcnt)? wrcnt: file->_cnt;
1972 memcpy(file->_ptr, ptr, pcnt);
1973 file->_cnt -= pcnt;
1974 file->_ptr += pcnt;
1975 written = pcnt;
1976 wrcnt -= pcnt;
1977 ptr = (char*)ptr + pcnt;
1978 } else if(!(file->_flag & MSVCRT__IOWRT)) {
1979 if(file->_flag & MSVCRT__IORW) {
1980 file->_flag |= MSVCRT__IOWRT;
1981 } else
1982 return 0;
1983 }
1984 if(wrcnt) {
1985 /* Flush buffer */
1986 int res=msvcrt_flush_buffer(file);
1987 if(!res) {
1988 int pwritten = _write(file->_file, ptr, wrcnt);
1989 if (pwritten <= 0) pwritten=0;
1990 written += pwritten;
1991 }
1992 }
1993 return written / size;
1994}
1995
1996/*********************************************************************
1997 * fputs (MSVCRT.@)
1998 */
1999int MSVCRT_fputs(const char *s, MSVCRT_FILE* file)
2000{
2001 size_t len = strlen(s);
2002 return MSVCRT_fwrite(s,sizeof(*s),len,file) == len ? 0 : MSVCRT_EOF;
2003}
2004
2005/*********************************************************************
2006 * fputws (MSVCRT.@)
2007 */
2008int MSVCRT_fputws(const MSVCRT_wchar_t *s, MSVCRT_FILE* file)
2009{
2010 size_t len = strlenW(s);
2011 return MSVCRT_fwrite(s,sizeof(*s),len,file) == len ? 0 : MSVCRT_EOF;
2012}
2013
2014/*********************************************************************
2015 * getchar (MSVCRT.@)
2016 */
2017int MSVCRT_getchar(void)
2018{
2019 return MSVCRT_fgetc(MSVCRT_stdin);
2020}
2021
2022/*********************************************************************
2023 * getc (MSVCRT.@)
2024 */
2025int MSVCRT_getc(MSVCRT_FILE* file)
2026{
2027 return MSVCRT_fgetc(file);
2028}
2029
2030/*********************************************************************
2031 * gets (MSVCRT.@)
2032 */
2033char *MSVCRT_gets(char *buf)
2034{
2035 int cc;
2036 char * buf_start = buf;
2037
2038 for(cc = MSVCRT_fgetc(MSVCRT_stdin); cc != MSVCRT_EOF && cc != '\n';
2039 cc = MSVCRT_fgetc(MSVCRT_stdin))
2040 if(cc != '\r') *buf++ = (char)cc;
2041
2042 *buf = '\0';
2043
2044 TRACE("got '%s'\n", buf_start);
2045 return buf_start;
2046}
2047
2048/*********************************************************************
2049 * _getws (MSVCRT.@)
2050 */
2051MSVCRT_wchar_t* MSVCRT__getws(MSVCRT_wchar_t* buf)
2052{
2053 MSVCRT_wint_t cc;
2054 MSVCRT_wchar_t* ws = buf;
2055
2056 for (cc = MSVCRT_fgetwc(MSVCRT_stdin); cc != MSVCRT_WEOF && cc != '\n';
2057 cc = MSVCRT_fgetwc(MSVCRT_stdin))
2058 {
2059 if (cc != '\r')
2060 *buf++ = (MSVCRT_wchar_t)cc;
2061 }
2062 *buf = '\0';
2063
2064 TRACE("got '%s'\n", debugstr_w(ws));
2065 return ws;
2066}
2067
2068/*********************************************************************
2069 * putc (MSVCRT.@)
2070 */
2071int MSVCRT_putc(int c, MSVCRT_FILE* file)
2072{
2073 return MSVCRT_fputc(c, file);
2074}
2075
2076/*********************************************************************
2077 * putchar (MSVCRT.@)
2078 */
2079int MSVCRT_putchar(int c)
2080{
2081 return MSVCRT_fputc(c, MSVCRT_stdout);
2082}
2083
2084/*********************************************************************
2085 * puts (MSVCRT.@)
2086 */
2087int MSVCRT_puts(const char *s)
2088{
2089 size_t len = strlen(s);
2090 if (MSVCRT_fwrite(s,sizeof(*s),len,MSVCRT_stdout) != len) return MSVCRT_EOF;
2091 return MSVCRT_fwrite("\n",1,1,MSVCRT_stdout) == 1 ? 0 : MSVCRT_EOF;
2092}
2093
2094/*********************************************************************
2095 * _putws (MSVCRT.@)
2096 */
2097int _putws(const MSVCRT_wchar_t *s)
2098{
2099 static const MSVCRT_wchar_t nl = '\n';
2100 size_t len = strlenW(s);
2101 if (MSVCRT_fwrite(s,sizeof(*s),len,MSVCRT_stdout) != len) return MSVCRT_EOF;
2102 return MSVCRT_fwrite(&nl,sizeof(nl),1,MSVCRT_stdout) == 1 ? 0 : MSVCRT_EOF;
2103}
2104
2105/*********************************************************************
2106 * remove (MSVCRT.@)
2107 */
2108int MSVCRT_remove(const char *path)
2109{
2110 TRACE("(%s)\n",path);
2111 if (DeleteFileA(path))
2112 return 0;
2113 TRACE(":failed (%ld)\n",GetLastError());
2114 MSVCRT__set_errno(GetLastError());
2115 return -1;
2116}
2117
2118/*********************************************************************
2119 * _wremove (MSVCRT.@)
2120 */
2121int _wremove(const MSVCRT_wchar_t *path)
2122{
2123 TRACE("(%s)\n",debugstr_w(path));
2124 if (DeleteFileW(path))
2125 return 0;
2126 TRACE(":failed (%ld)\n",GetLastError());
2127 MSVCRT__set_errno(GetLastError());
2128 return -1;
2129}
2130
2131/*********************************************************************
2132 * scanf (MSVCRT.@)
2133 */
2134int MSVCRT_scanf(const char *format, ...)
2135{
2136 va_list valist;
2137 int res;
2138
2139 va_start(valist, format);
2140 res = MSVCRT_fscanf(MSVCRT_stdin, format, valist);
2141 va_end(valist);
2142 return res;
2143}
2144
2145/*********************************************************************
2146 * wscanf (MSVCRT.@)
2147 */
2148int MSVCRT_wscanf(const MSVCRT_wchar_t *format, ...)
2149{
2150 va_list valist;
2151 int res;
2152
2153 va_start(valist, format);
2154 res = MSVCRT_fwscanf(MSVCRT_stdin, format, valist);
2155 va_end(valist);
2156 return res;
2157}
2158
2159/*********************************************************************
2160 * rename (MSVCRT.@)
2161 */
2162int MSVCRT_rename(const char *oldpath,const char *newpath)
2163{
2164 TRACE(":from %s to %s\n",oldpath,newpath);
2165 if (MoveFileExA(oldpath, newpath, MOVEFILE_COPY_ALLOWED))
2166 return 0;
2167 TRACE(":failed (%ld)\n",GetLastError());
2168 MSVCRT__set_errno(GetLastError());
2169 return -1;
2170}
2171
2172/*********************************************************************
2173 * _wrename (MSVCRT.@)
2174 */
2175int _wrename(const MSVCRT_wchar_t *oldpath,const MSVCRT_wchar_t *newpath)
2176{
2177 TRACE(":from %s to %s\n",debugstr_w(oldpath),debugstr_w(newpath));
2178 if (MoveFileExW(oldpath, newpath, MOVEFILE_COPY_ALLOWED))
2179 return 0;
2180 TRACE(":failed (%ld)\n",GetLastError());
2181 MSVCRT__set_errno(GetLastError());
2182 return -1;
2183}
2184
2185/*********************************************************************
2186 * setvbuf (MSVCRT.@)
2187 */
2188int MSVCRT_setvbuf(MSVCRT_FILE* file, char *buf, int mode, MSVCRT_size_t size)
2189{
2190 /* TODO: Check if file busy */
2191 if(file->_bufsiz) {
2192 MSVCRT_free(file->_base);
2193 file->_bufsiz = 0;
2194 file->_cnt = 0;
2195 }
2196 if(mode == MSVCRT__IOFBF) {
2197 file->_flag &= ~MSVCRT__IONBF;
2198 file->_base = file->_ptr = buf;
2199 if(buf) {
2200 file->_bufsiz = size;
2201 }
2202 } else {
2203 file->_flag |= MSVCRT__IONBF;
2204 }
2205 return 0;
2206}
2207
2208/*********************************************************************
2209 * setbuf (MSVCRT.@)
2210 */
2211void MSVCRT_setbuf(MSVCRT_FILE* file, char *buf)
2212{
2213 MSVCRT_setvbuf(file, buf, buf ? MSVCRT__IOFBF : MSVCRT__IONBF, MSVCRT_BUFSIZ);
2214}
2215
2216/*********************************************************************
2217 * tmpnam (MSVCRT.@)
2218 */
2219char *MSVCRT_tmpnam(char *s)
2220{
2221 char tmpbuf[MAX_PATH];
2222 char* prefix = "TMP";
2223 if (!GetTempPathA(MAX_PATH,tmpbuf) ||
2224 !GetTempFileNameA(tmpbuf,prefix,0,MSVCRT_tmpname))
2225 {
2226 TRACE(":failed-last error (%ld)\n",GetLastError());
2227 return NULL;
2228 }
2229 TRACE(":got tmpnam %s\n",MSVCRT_tmpname);
2230 s = MSVCRT_tmpname;
2231 return s;
2232}
2233
2234/*********************************************************************
2235 * tmpfile (MSVCRT.@)
2236 */
2237MSVCRT_FILE* MSVCRT_tmpfile(void)
2238{
2239 char *filename = MSVCRT_tmpnam(NULL);
2240 int fd;
2241 fd = _open(filename, _O_CREAT | _O_BINARY | _O_RDWR | _O_TEMPORARY);
2242 if (fd != -1)
2243 return msvcrt_alloc_fp(fd);
2244 return NULL;
2245}
2246
2247/*********************************************************************
2248 * vfprintf (MSVCRT.@)
2249 */
2250int MSVCRT_vfprintf(MSVCRT_FILE* file, const char *format, va_list valist)
2251{
2252 char buf[2048], *mem = buf;
2253 int written, resize = sizeof(buf), retval;
2254 /* There are two conventions for vsnprintf failing:
2255 * Return -1 if we truncated, or
2256 * Return the number of bytes that would have been written
2257 * The code below handles both cases
2258 */
2259 while ((written = vsnprintf(mem, resize, format, valist)) == -1 ||
2260 written > resize)
2261 {
2262 resize = (written == -1 ? resize * 2 : written + 1);
2263 if (mem != buf)
2264 MSVCRT_free (mem);
2265 if (!(mem = (char *)MSVCRT_malloc(resize)))
2266 return MSVCRT_EOF;
2267 }
2268 retval = MSVCRT_fwrite(mem, sizeof(*mem), written, file);
2269 if (mem != buf)
2270 MSVCRT_free (mem);
2271 return retval;
2272}
2273
2274/*********************************************************************
2275 * vfwprintf (MSVCRT.@)
2276 * FIXME:
2277 * Is final char included in written (then resize is too big) or not
2278 * (then we must test for equality too)?
2279 */
2280int MSVCRT_vfwprintf(MSVCRT_FILE* file, const MSVCRT_wchar_t *format, va_list valist)
2281{
2282 MSVCRT_wchar_t buf[2048], *mem = buf;
2283 int written, resize = sizeof(buf) / sizeof(MSVCRT_wchar_t), retval;
2284 /* See vfprintf comments */
2285 while ((written = _vsnwprintf(mem, resize, format, valist)) == -1 ||
2286 written > resize)
2287 {
2288 resize = (written == -1 ? resize * 2 : written + sizeof(MSVCRT_wchar_t));
2289 if (mem != buf)
2290 MSVCRT_free (mem);
2291 if (!(mem = (MSVCRT_wchar_t *)MSVCRT_malloc(resize*sizeof(*mem))))
2292 return MSVCRT_EOF;
2293 }
2294 retval = MSVCRT_fwrite(mem, sizeof(*mem), written, file);
2295 if (mem != buf)
2296 MSVCRT_free (mem);
2297 return retval;
2298}
2299
2300/*********************************************************************
2301 * vprintf (MSVCRT.@)
2302 */
2303int MSVCRT_vprintf(const char *format, va_list valist)
2304{
2305 return MSVCRT_vfprintf(MSVCRT_stdout,format,valist);
2306}
2307
2308/*********************************************************************
2309 * vwprintf (MSVCRT.@)
2310 */
2311int MSVCRT_vwprintf(const MSVCRT_wchar_t *format, va_list valist)
2312{
2313 return MSVCRT_vfwprintf(MSVCRT_stdout,format,valist);
2314}
2315
2316/*********************************************************************
2317 * fprintf (MSVCRT.@)
2318 */
2319int MSVCRT_fprintf(MSVCRT_FILE* file, const char *format, ...)
2320{
2321 va_list valist;
2322 int res;
2323 va_start(valist, format);
2324 res = MSVCRT_vfprintf(file, format, valist);
2325 va_end(valist);
2326 return res;
2327}
2328
2329/*********************************************************************
2330 * fwprintf (MSVCRT.@)
2331 */
2332int MSVCRT_fwprintf(MSVCRT_FILE* file, const MSVCRT_wchar_t *format, ...)
2333{
2334 va_list valist;
2335 int res;
2336 va_start(valist, format);
2337 res = MSVCRT_vfwprintf(file, format, valist);
2338 va_end(valist);
2339 return res;
2340}
2341
2342/*********************************************************************
2343 * printf (MSVCRT.@)
2344 */
2345int MSVCRT_printf(const char *format, ...)
2346{
2347 va_list valist;
2348 int res;
2349 va_start(valist, format);
2350 res = MSVCRT_vfprintf(MSVCRT_stdout, format, valist);
2351 va_end(valist);
2352 return res;
2353}
2354
2355/*********************************************************************
2356 * ungetc (MSVCRT.@)
2357 */
2358int MSVCRT_ungetc(int c, MSVCRT_FILE * file)
2359{
2360 if(file->_bufsiz == 0 && !(file->_flag & MSVCRT__IONBF)) {
2361 msvcrt_alloc_buffer(file);
2362 file->_ptr++;
2363 }
2364 if(file->_ptr>file->_base) {
2365 file->_ptr--;
2366 *file->_ptr=c;
2367 file->_cnt++;
2368 return c;
2369 }
2370 return MSVCRT_EOF;
2371}
2372
2373/*********************************************************************
2374 * ungetwc (MSVCRT.@)
2375 */
2376MSVCRT_wint_t MSVCRT_ungetwc(MSVCRT_wint_t wc, MSVCRT_FILE * file)
2377{
2378 MSVCRT_wchar_t mwc = wc;
2379 char * pp = (char *)&mwc;
2380 int i;
2381 for(i=sizeof(MSVCRT_wchar_t)-1;i>=0;i--) {
2382 if(pp[i] != MSVCRT_ungetc(pp[i],file))
2383 return MSVCRT_WEOF;
2384 }
2385 return mwc;
2386}
2387
2388/*********************************************************************
2389 * wprintf (MSVCRT.@)
2390 */
2391int MSVCRT_wprintf(const MSVCRT_wchar_t *format, ...)
2392{
2393 va_list valist;
2394 int res;
2395 va_start(valist, format);
2396 res = MSVCRT_vwprintf(format, valist);
2397 va_end(valist);
2398 return res;
2399}
Note: See TracBrowser for help on using the repository browser.