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

Last change on this file since 21395 was 21395, checked in by dmik, 15 years ago

Attempted to resurrect building of msvcrt.dll.

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