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

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

Added more wide character versions of RT functions to minivcrt.lib.

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