msvcrt: memmove_s shouldn't zero its output buffer on error.
[wine] / dlls / msvcrt / tests / file.c
1 /*
2  * Unit test suite for file functions
3  *
4  * Copyright 2002 Bill Currie
5  * Copyright 2005 Paul Rupe
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21
22 #include "wine/test.h"
23 #include <stdarg.h>
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <fcntl.h>
27 #include <share.h>
28 #include <sys/stat.h>
29 #include <io.h>
30 #include <direct.h>
31 #include <windef.h>
32 #include <winbase.h>
33 #include <winnls.h>
34 #include <process.h>
35 #include <errno.h>
36
37 static HANDLE proc_handles[2];
38
39 static int (__cdecl *p_fopen_s)(FILE**, const char*, const char*);
40 static int (__cdecl *p__wfopen_s)(FILE**, const wchar_t*, const wchar_t*);
41
42 static void init(void)
43 {
44     HMODULE hmod = GetModuleHandleA("msvcrt.dll");
45
46     p_fopen_s = (void*)GetProcAddress(hmod, "fopen_s");
47     p__wfopen_s = (void*)GetProcAddress(hmod, "_wfopen_s");
48 }
49
50 static void test_filbuf( void )
51 {
52     FILE *fp;
53     int c;
54     fpos_t pos;
55
56     fp = fopen("filbuf.tst", "wb");
57     fwrite("\n\n\n\n", 1, 4, fp);
58     fclose(fp);
59
60     fp = fopen("filbuf.tst", "rt");
61     c = _filbuf(fp);
62     ok(c == '\n', "read wrong byte\n");
63     /* See bug 16970 for why we care about _filbuf.
64      * ftell returns screwy values on files with lots
65      * of bare LFs in ascii mode because it assumes
66      * that ascii files contain only CRLFs, removes
67      * the CR's early in _filbuf, and adjusts the return
68      * value of ftell to compensate.
69      * native _filbuf will read the whole file, then consume and return
70      * the first one.  That leaves fp->_fd at offset 4, and fp->_ptr
71      * pointing to a buffer of three bare LFs, so
72      * ftell will return 4 - 3 - 3 = -2.
73      */
74     ok(ftell(fp) == -2, "ascii crlf removal does not match native\n");
75     ok(fgetpos(fp, &pos) == 0, "fgetpos fail\n");
76     ok(pos == -2, "ftell does not match fgetpos\n");
77     fclose(fp);
78     unlink("filbuf.tst");
79 }
80
81 static void test_fdopen( void )
82 {
83     static const char buffer[] = {0,1,2,3,4,5,6,7,8,9};
84     char ibuf[10];
85     int fd;
86     FILE *file;
87
88     fd = open ("fdopen.tst", O_WRONLY | O_CREAT | O_BINARY, _S_IREAD |_S_IWRITE);
89     write (fd, buffer, sizeof (buffer));
90     close (fd);
91
92     fd = open ("fdopen.tst", O_RDONLY | O_BINARY);
93     lseek (fd, 5, SEEK_SET);
94     file = fdopen (fd, "rb");
95     ok (fread (ibuf, 1, sizeof (buffer), file) == 5, "read wrong byte count\n");
96     ok (memcmp (ibuf, buffer + 5, 5) == 0, "read wrong bytes\n");
97     fclose (file);
98     unlink ("fdopen.tst");
99 }
100
101 static void test_fileops( void )
102 {
103     static const char outbuffer[] = "0,1,2,3,4,5,6,7,8,9";
104     char buffer[256];
105     WCHAR wbuffer[256];
106     int fd;
107     FILE *file;
108     fpos_t pos;
109     int i, c, bufmode;
110     static const int bufmodes[] = {_IOFBF,_IONBF};
111
112     fd = open ("fdopen.tst", O_WRONLY | O_CREAT | O_BINARY, _S_IREAD |_S_IWRITE);
113     write (fd, outbuffer, sizeof (outbuffer));
114     close (fd);
115
116     for (bufmode=0; bufmode < sizeof(bufmodes)/sizeof(bufmodes[0]); bufmode++)
117     {
118         fd = open ("fdopen.tst", O_RDONLY | O_BINARY);
119         file = fdopen (fd, "rb");
120         setvbuf(file,NULL,bufmodes[bufmode],2048);
121         ok(strlen(outbuffer) == (sizeof(outbuffer)-1),"strlen/sizeof error for bufmode=%x\n", bufmodes[bufmode]);
122         ok(fgets(buffer,sizeof(buffer),file) !=0,"fgets failed unexpected for bufmode=%x\n", bufmodes[bufmode]);
123         ok(fgets(buffer,sizeof(buffer),file) ==0,"fgets didn't signal EOF for bufmode=%x\n", bufmodes[bufmode]);
124         ok(feof(file) !=0,"feof doesn't signal EOF for bufmode=%x\n", bufmodes[bufmode]);
125         rewind(file);
126         ok(fgets(buffer,strlen(outbuffer),file) !=0,"fgets failed unexpected for bufmode=%x\n", bufmodes[bufmode]);
127         ok(lstrlenA(buffer) == lstrlenA(outbuffer) -1,"fgets didn't read right size for bufmode=%x\n", bufmodes[bufmode]);
128         ok(fgets(buffer,sizeof(outbuffer),file) !=0,"fgets failed unexpected for bufmode=%x\n", bufmodes[bufmode]);
129         ok(strlen(buffer) == 1,"fgets dropped chars for bufmode=%x\n", bufmodes[bufmode]);
130         ok(buffer[0] == outbuffer[strlen(outbuffer)-1],"fgets exchanged chars for bufmode=%x\n", bufmodes[bufmode]);
131
132         rewind(file);
133         for (i = 0; i < sizeof(outbuffer); i++)
134         {
135             ok(fgetc(file) == outbuffer[i], "fgetc returned wrong data for bufmode=%x\n", bufmodes[bufmode]);
136         }
137         ok((c = fgetc(file)) == EOF, "getc did not return EOF for bufmode=%x\n", bufmodes[bufmode]);
138         ok(feof(file), "feof did not return EOF for bufmode=%x\n", bufmodes[bufmode]);
139         ok(ungetc(c, file) == EOF, "ungetc(EOF) did not return EOF for bufmode=%x\n", bufmodes[bufmode]);
140         ok(feof(file), "feof after ungetc(EOF) did not return EOF for bufmode=%x\n", bufmodes[bufmode]);
141         ok(fgetc(file) == EOF, "getc did not return EOF for bufmode=%x\n", bufmodes[bufmode]);
142         c = outbuffer[sizeof(outbuffer) - 1];
143         ok(ungetc(c, file) == c, "ungetc did not return its input for bufmode=%x\n", bufmodes[bufmode]);
144         ok(!feof(file), "feof after ungetc returned EOF for bufmode=%x\n", bufmodes[bufmode]);
145         ok((c = fgetc(file)) != EOF, "getc after ungetc returned EOF for bufmode=%x\n", bufmodes[bufmode]);
146         ok(c == outbuffer[sizeof(outbuffer) - 1],
147            "getc did not return ungetc'd data for bufmode=%x\n", bufmodes[bufmode]);
148         ok(!feof(file), "feof after getc returned EOF prematurely for bufmode=%x\n", bufmodes[bufmode]);
149         ok(fgetc(file) == EOF, "getc did not return EOF for bufmode=%x\n", bufmodes[bufmode]);
150         ok(feof(file), "feof after getc did not return EOF for bufmode=%x\n", bufmodes[bufmode]);
151
152         rewind(file);
153         ok(fgetpos(file,&pos) == 0, "fgetpos failed unexpected for bufmode=%x\n", bufmodes[bufmode]);
154         ok(pos == 0, "Unexpected result of fgetpos %x%08x for bufmode=%x\n", (DWORD)(pos >> 32), (DWORD)pos, bufmodes[bufmode]);
155         pos = sizeof (outbuffer);
156         ok(fsetpos(file, &pos) == 0, "fsetpos failed unexpected for bufmode=%x\n", bufmodes[bufmode]);
157         ok(fgetpos(file,&pos) == 0, "fgetpos failed unexpected for bufmode=%x\n", bufmodes[bufmode]);
158         ok(pos == sizeof (outbuffer), "Unexpected result of fgetpos %x%08x for bufmode=%x\n", (DWORD)(pos >> 32), (DWORD)pos, bufmodes[bufmode]);
159
160         fclose (file);
161     }
162     fd = open ("fdopen.tst", O_RDONLY | O_TEXT);
163     file = fdopen (fd, "rt"); /* open in TEXT mode */
164     ok(fgetws(wbuffer,sizeof(wbuffer)/sizeof(wbuffer[0]),file) !=0,"fgetws failed unexpected\n");
165     ok(fgetws(wbuffer,sizeof(wbuffer)/sizeof(wbuffer[0]),file) ==0,"fgetws didn't signal EOF\n");
166     ok(feof(file) !=0,"feof doesn't signal EOF\n");
167     rewind(file);
168     ok(fgetws(wbuffer,strlen(outbuffer),file) !=0,"fgetws failed unexpected\n");
169     ok(lstrlenW(wbuffer) == (lstrlenA(outbuffer) -1),"fgetws didn't read right size\n");
170     ok(fgetws(wbuffer,sizeof(outbuffer)/sizeof(outbuffer[0]),file) !=0,"fgets failed unexpected\n");
171     ok(lstrlenW(wbuffer) == 1,"fgets dropped chars\n");
172     fclose (file);
173
174     file = fopen("fdopen.tst", "rb");
175     ok( file != NULL, "fopen failed\n");
176     /* sizeof(buffer) > content of file */
177     ok(fread(buffer, sizeof(buffer), 1, file) == 0, "fread test failed\n");
178     /* feof should be set now */
179     ok(feof(file), "feof after fread failed\n");
180     fclose (file);
181
182     unlink ("fdopen.tst");
183 }
184
185 #define IOMODE (ao?"ascii mode":"binary mode")
186 static void test_readmode( BOOL ascii_mode )
187 {
188     static const char outbuffer[] = "0,1,2,3,4,5,6,7,8,9\r\n\r\nA,B,C,D,E\r\nX,Y,Z";
189     static const char padbuffer[] = "ghjghjghjghj";
190     static const char nlbuffer[] = "\r\n";
191     char buffer[2*BUFSIZ+256];
192     const char *optr;
193     int fd;
194     FILE *file;
195     const int *ip;
196     int i, j, m, ao, pl;
197     unsigned int fp;
198     LONG l;
199
200     fd = open ("fdopen.tst", O_WRONLY | O_CREAT | O_BINARY, _S_IREAD |_S_IWRITE);
201     /* an internal buffer of BUFSIZ is maintained, so make a file big
202      * enough to test operations that cross the buffer boundary 
203      */
204     j = (2*BUFSIZ-4)/strlen(padbuffer);
205     for (i=0; i<j; i++)
206         write (fd, padbuffer, strlen(padbuffer));
207     j = (2*BUFSIZ-4)%strlen(padbuffer);
208     for (i=0; i<j; i++)
209         write (fd, &padbuffer[i], 1);
210     write (fd, nlbuffer, strlen(nlbuffer));
211     write (fd, outbuffer, sizeof (outbuffer));
212     close (fd);
213     
214     if (ascii_mode) {
215         /* Open file in ascii mode */
216         fd = open ("fdopen.tst", O_RDONLY);
217         file = fdopen (fd, "r");
218         ao = -1; /* on offset to account for carriage returns */
219     }
220     else {
221         fd = open ("fdopen.tst", O_RDONLY | O_BINARY);
222         file = fdopen (fd, "rb");
223         ao = 0;
224     }
225     
226     /* first is a test of fgets, ftell, fseek */
227     ok(ftell(file) == 0,"Did not start at beginning of file in %s\n", IOMODE);
228     ok(fgets(buffer,2*BUFSIZ+256,file) !=0,"padding line fgets failed unexpected in %s\n", IOMODE);
229     l = ftell(file);
230     pl = 2*BUFSIZ-2;
231     ok(l == pl,"padding line ftell got %d should be %d in %s\n", l, pl, IOMODE);
232     ok(lstrlenA(buffer) == pl+ao,"padding line fgets got size %d should be %d in %s\n",
233      lstrlenA(buffer), pl+ao, IOMODE);
234     for (fp=0; fp<strlen(outbuffer); fp++)
235         if (outbuffer[fp] == '\n') break;
236     fp++;
237     ok(fgets(buffer,256,file) !=0,"line 1 fgets failed unexpected in %s\n", IOMODE);
238     l = ftell(file);
239     ok(l == pl+fp,"line 1 ftell got %d should be %d in %s\n", l, pl+fp, IOMODE);
240     ok(lstrlenA(buffer) == fp+ao,"line 1 fgets got size %d should be %d in %s\n",
241      lstrlenA(buffer), fp+ao, IOMODE);
242     /* test a seek back across the buffer boundary */
243     l = pl;
244     ok(fseek(file,l,SEEK_SET)==0,"seek failure in %s\n", IOMODE);
245     l = ftell(file);
246     ok(l == pl,"ftell after seek got %d should be %d in %s\n", l, pl, IOMODE);
247     ok(fgets(buffer,256,file) !=0,"second read of line 1 fgets failed unexpected in %s\n", IOMODE);
248     l = ftell(file);
249     ok(l == pl+fp,"second read of line 1 ftell got %d should be %d in %s\n", l, pl+fp, IOMODE);
250     ok(lstrlenA(buffer) == fp+ao,"second read of line 1 fgets got size %d should be %d in %s\n",
251      lstrlenA(buffer), fp+ao, IOMODE);
252     ok(fgets(buffer,256,file) !=0,"line 2 fgets failed unexpected in %s\n", IOMODE);
253     fp += 2;
254     l = ftell(file);
255     ok(l == pl+fp,"line 2 ftell got %d should be %d in %s\n", l, pl+fp, IOMODE);
256     ok(lstrlenA(buffer) == 2+ao,"line 2 fgets got size %d should be %d in %s\n",
257      lstrlenA(buffer), 2+ao, IOMODE);
258     
259     /* test fread across buffer boundary */
260     rewind(file);
261     ok(ftell(file) == 0,"Did not start at beginning of file in %s\n", IOMODE);
262     ok(fgets(buffer,BUFSIZ-6,file) !=0,"padding line fgets failed unexpected in %s\n", IOMODE);
263     j=strlen(outbuffer);
264     i=fread(buffer,1,BUFSIZ+strlen(outbuffer),file);
265     ok(i==BUFSIZ+j,"fread failed, expected %d got %d in %s\n", BUFSIZ+j, i, IOMODE);
266     l = ftell(file);
267     ok(l == pl+j-(ao*4)-5,"ftell after fread got %d should be %d in %s\n", l, pl+j-(ao*4)-5, IOMODE);
268     for (m=0; m<3; m++)
269         ok(buffer[m]==padbuffer[m+(BUFSIZ-4)%strlen(padbuffer)],"expected %c got %c\n", padbuffer[m], buffer[m]);
270     m+=BUFSIZ+2+ao;
271     optr = outbuffer;
272     for (; m<i; m++) {
273         ok(buffer[m]==*optr,"char %d expected %c got %c in %s\n", m, *optr, buffer[m], IOMODE);
274         optr++;
275         if (ao && (*optr == '\r'))
276             optr++;
277     }
278     /* fread should return the requested number of bytes if available */
279     rewind(file);
280     ok(ftell(file) == 0,"Did not start at beginning of file in %s\n", IOMODE);
281     ok(fgets(buffer,BUFSIZ-6,file) !=0,"padding line fgets failed unexpected in %s\n", IOMODE);
282     j = fp+10;
283     i=fread(buffer,1,j,file);
284     ok(i==j,"fread failed, expected %d got %d in %s\n", j, i, IOMODE);
285     /* test fread eof */
286     ok(fseek(file,0,SEEK_END)==0,"seek failure in %s\n", IOMODE);
287     ok(feof(file)==0,"feof failure in %s\n", IOMODE);
288     ok(fread(buffer,1,1,file)==0,"fread failure in %s\n", IOMODE);
289     ok(feof(file)!=0,"feof failure in %s\n", IOMODE);
290     ok(fseek(file,-3,SEEK_CUR)==0,"seek failure in %s\n", IOMODE);
291     ok(feof(file)==0,"feof failure in %s\n", IOMODE);
292     ok(fread(buffer,2,1,file)==1,"fread failed in %s\n", IOMODE);
293     ok(feof(file)==0,"feof failure in %s\n", IOMODE);
294     ok(fread(buffer,2,1,file)==0,"fread failure in %s\n",IOMODE);
295     ok(feof(file)!=0,"feof failure in %s\n", IOMODE);
296     
297     /* test some additional functions */
298     rewind(file);
299     ok(ftell(file) == 0,"Did not start at beginning of file in %s\n", IOMODE);
300     ok(fgets(buffer,2*BUFSIZ+256,file) !=0,"padding line fgets failed unexpected in %s\n", IOMODE);
301     i = _getw(file);
302     ip = (const int *)outbuffer;
303     ok(i == *ip,"_getw failed, expected %08x got %08x in %s\n", *ip, i, IOMODE);
304     for (fp=0; fp<strlen(outbuffer); fp++)
305         if (outbuffer[fp] == '\n') break;
306     fp++;
307     /* this will cause the next _getw to cross carriage return characters */
308     ok(fgets(buffer,fp-6,file) !=0,"line 1 fgets failed unexpected in %s\n", IOMODE);
309     for (i=0, j=0; i<6; i++) {
310         if (ao==0 || outbuffer[fp-3+i] != '\r')
311             buffer[j++] = outbuffer[fp-3+i];
312     }
313     i = _getw(file);
314     ip = (int *)buffer;
315     ok(i == *ip,"_getw failed, expected %08x got %08x in %s\n", *ip, i, IOMODE);
316
317     fclose (file);
318     unlink ("fdopen.tst");
319 }
320
321 static void test_asciimode(void)
322 {
323     FILE *fp;
324     char buf[64];
325     int c, i, j;
326
327     /* Simple test of CR CR LF handling.  Test both fgets and fread code paths, they're different! */
328     fp = fopen("ascii.tst", "wb");
329     fputs("\r\r\n", fp);
330     fclose(fp);
331     fp = fopen("ascii.tst", "rt");
332     ok(fgets(buf, sizeof(buf), fp) != NULL, "fgets\n");
333     ok(0 == strcmp(buf, "\r\n"), "CR CR LF not read as CR LF\n");
334     rewind(fp);
335     ok((fread(buf, 1, sizeof(buf), fp) == 2) && (0 == strcmp(buf, "\r\n")), "CR CR LF not read as CR LF\n");
336     fclose(fp);
337     unlink("ascii.tst");
338
339     /* Simple test of foo ^Z [more than one block] bar handling */
340     fp = fopen("ascii.tst", "wb");
341     fputs("foo\032", fp);  /* foo, logical EOF, ... */
342     fseek(fp, 65536L, SEEK_SET); /* ... more than MSVCRT_BUFSIZ, ... */
343     fputs("bar", fp); /* ... bar */
344     fclose(fp);
345     fp = fopen("ascii.tst", "rt");
346     ok(fgets(buf, sizeof(buf), fp) != NULL, "fgets foo\n");
347     ok(0 == strcmp(buf, "foo"), "foo ^Z not read as foo by fgets\n");
348     ok(fgets(buf, sizeof(buf), fp) == NULL, "fgets after logical EOF\n");
349     rewind(fp);
350     ok((fread(buf, 1, sizeof(buf), fp) == 3) && (0 == strcmp(buf, "foo")), "foo ^Z not read as foo by fread\n");
351     ok((fread(buf, 1, sizeof(buf), fp) == 0), "fread after logical EOF\n");
352     fclose(fp);
353
354     /* Show ASCII mode handling*/
355     fp= fopen("ascii.tst","wb");
356     fputs("0\r\n1\r\n2\r\n3\r\n4\r\n5\r\n6\r\n7\r\n8\r\n9\r\n", fp);
357     fclose(fp);
358
359     fp = fopen("ascii.tst", "r");
360     c= fgetc(fp);
361     ok(c == '0', "fgetc failed, expected '0', got '%c'\n", c);
362     c= fgetc(fp);
363     ok(c == '\n', "fgetc failed, expected '\\n', got '%c'\n", c);
364     fseek(fp,0,SEEK_CUR);
365     for(i=1; i<10; i++) {
366         ok((j = ftell(fp)) == i*3, "ftell fails in TEXT mode\n");
367         fseek(fp,0,SEEK_CUR);
368         ok((c = fgetc(fp)) == '0'+ i, "fgetc after fseek failed in line %d\n", i);
369         c= fgetc(fp);
370         ok(c == '\n', "fgetc failed, expected '\\n', got '%c'\n", c);
371     }
372     /* Show that fseek doesn't skip \\r !*/
373     rewind(fp);
374     c= fgetc(fp);
375     ok(c == '0', "fgetc failed, expected '0', got '%c'\n", c);
376     fseek(fp, 2 ,SEEK_CUR);
377     for(i=1; i<10; i++) {
378         ok((c = fgetc(fp)) == '0'+ i, "fgetc after fseek with pos Offset failed in line %d\n", i);
379         fseek(fp, 2 ,SEEK_CUR);
380     }
381     fseek(fp, 9*3 ,SEEK_SET);
382     c = fgetc(fp);
383     ok(c == '9', "fgetc failed, expected '9', got '%c'\n", c);
384     fseek(fp, -4 ,SEEK_CUR);
385     for(i= 8; i>=0; i--) {
386         ok((c = fgetc(fp)) == '0'+ i, "fgetc after fseek with neg Offset failed in line %d\n", i);
387         fseek(fp, -4 ,SEEK_CUR);
388     }
389     /* Show what happens if fseek positions filepointer on \\r */
390     fclose(fp);
391     fp = fopen("ascii.tst", "r");
392     fseek(fp, 3 ,SEEK_SET);
393     ok((c = fgetc(fp)) == '1', "fgetc fails to read next char when positioned on \\r\n");
394     fclose(fp);
395
396     unlink("ascii.tst");
397 }
398
399 static void test_asciimode2(void)
400 {
401     /* Error sequence from one app was getchar followed by small fread
402      * with one \r removed had last byte of buffer filled with
403      * next byte of *unbuffered* data rather than next byte from buffer
404      * Test case is a short string of one byte followed by a newline
405      * followed by filler to fill out the sector, then a sector of
406      * some different byte.
407      */
408
409     FILE *fp;
410     char ibuf[4];
411     int i;
412     static const char obuf[] =
413 "00\n"
414 "000000000000000000000000000000000000000000000000000000000000000000000000000000\n"
415 "000000000000000000000000000000000000000000000000000000000000000000000000000000\n"
416 "000000000000000000000000000000000000000000000000000000000000000000000000000000\n"
417 "000000000000000000000000000000000000000000000000000000000000000000000000000000\n"
418 "000000000000000000000000000000000000000000000000000000000000000000000000000000\n"
419 "000000000000000000000000000000000000000000000000000000000000000000000000000000\n"
420 "000000000000000000\n"
421 "1111111111111111111";
422
423     fp = fopen("ascii2.tst", "wt");
424     fwrite(obuf, 1, sizeof(obuf), fp);
425     fclose(fp);
426
427     fp = fopen("ascii2.tst", "rt");
428     ok(getc(fp) == '0', "first char not 0\n");
429     memset(ibuf, 0, sizeof(ibuf));
430     i = fread(ibuf, 1, sizeof(ibuf), fp);
431     ok(i == sizeof(ibuf), "fread i %d != sizeof(ibuf)\n", i);
432     ok(0 == strncmp(ibuf, obuf+1, sizeof(ibuf)), "ibuf != obuf\n");
433     fclose(fp);
434     unlink("ascii2.tst");
435 }
436
437 static void test_filemodeT(void)
438 {
439     char DATA  [] = {26, 't', 'e', 's' ,'t'};
440     char DATA2 [100];
441     char temppath[MAX_PATH];
442     char tempfile[MAX_PATH];
443     FILE* f;
444     size_t bytesWritten;
445     size_t bytesRead;
446     WIN32_FIND_DATA findData;
447     HANDLE h;
448
449     GetTempPath (MAX_PATH, temppath);
450     GetTempFileName (temppath, "", 0, tempfile);
451
452     f = fopen(tempfile, "w+bDT");
453     bytesWritten = fwrite(DATA, 1, sizeof(DATA), f);
454     rewind(f);
455     bytesRead = fread(DATA2, 1, sizeof(DATA2), f);
456     fclose(f);
457
458     ok (bytesRead == bytesWritten && bytesRead == sizeof(DATA),
459         "fopen file mode 'T' wrongly interpreted as 't'\n" );
460
461     h = FindFirstFile(tempfile, &findData);
462
463     ok (h == INVALID_HANDLE_VALUE, "file wasn't deleted when closed.\n" );
464
465     if (h != INVALID_HANDLE_VALUE) FindClose(h);
466 }
467
468 static WCHAR* AtoW( const char* p )
469 {
470     WCHAR* buffer;
471     DWORD len = MultiByteToWideChar( CP_ACP, 0, p, -1, NULL, 0 );
472     buffer = malloc( len * sizeof(WCHAR) );
473     MultiByteToWideChar( CP_ACP, 0, p, -1, buffer, len );
474     return buffer;
475 }
476
477 /* Test reading in text mode when the 512'th character read is \r*/
478 static void test_readboundary(void)
479 {
480   FILE *fp;
481   char buf[513], rbuf[513];
482   int i, j;
483   for (i = 0; i < 511; i++)
484     {
485       j = (i%('~' - ' ')+ ' ');
486       buf[i] = j;
487     }
488   buf[511] = '\n';
489   buf[512] =0;
490   fp = fopen("boundary.tst", "wt");
491   fwrite(buf, 512,1,fp);
492   fclose(fp);
493   fp = fopen("boundary.tst", "rt");
494   for(i=0; i<512; i++)
495     {
496       fseek(fp,0 , SEEK_CUR);
497       rbuf[i] = fgetc(fp);
498     }
499   rbuf[512] =0;
500   fclose(fp);
501   unlink("boundary.tst");
502
503   ok(strcmp(buf, rbuf) == 0,"CRLF on buffer boundary failure\n");
504   }
505
506 static void test_fgetc( void )
507 {
508   char* tempf;
509   FILE *tempfh;
510   int  ich=0xe0, ret;
511
512   tempf=_tempnam(".","wne");
513   tempfh = fopen(tempf,"w+");
514   fputc(ich, tempfh);
515   fputc(ich, tempfh);
516   rewind(tempfh);
517   ret = fgetc(tempfh);
518   ok(ich == ret, "First fgetc expected %x got %x\n", ich, ret);
519   ret = fgetc(tempfh);
520   ok(ich == ret, "Second fgetc expected %x got %x\n", ich, ret);
521   fclose(tempfh);
522   tempfh = fopen(tempf,"wt");
523   fputc('\n', tempfh);
524   fclose(tempfh);
525   tempfh = fopen(tempf,"wt");
526   setbuf(tempfh, NULL);
527   ret = fgetc(tempfh);
528   ok(ret == -1, "Unbuffered fgetc in text mode must failed on \\r\\n\n");
529   fclose(tempfh);
530   unlink(tempf);
531   free(tempf);
532 }
533
534 static void test_fputc( void )
535 {
536   char* tempf;
537   FILE *tempfh;
538   int  ret;
539
540   tempf=_tempnam(".","wne");
541   tempfh = fopen(tempf,"wb");
542   ret = fputc(0,tempfh);
543   ok(0 == ret, "fputc(0,tempfh) expected %x got %x\n", 0, ret);
544   ret = fputc(0xff,tempfh);
545   ok(0xff == ret, "fputc(0xff,tempfh) expected %x got %x\n", 0xff, ret);
546   ret = fputc(0xffffffff,tempfh);
547   ok(0xff == ret, "fputc(0xffffffff,tempfh) expected %x got %x\n", 0xff, ret);
548   fclose(tempfh);
549
550   tempfh = fopen(tempf,"rb");
551   ret = fputc(0,tempfh);
552   ok(EOF == ret, "fputc(0,tempfh) on r/o file expected %x got %x\n", EOF, ret);
553   fclose(tempfh);
554
555   unlink(tempf);
556   free(tempf);
557 }
558
559 static void test_flsbuf( void )
560 {
561   char* tempf;
562   FILE *tempfh;
563   int  c;
564   int  ret;
565   int  bufmode;
566   static const int bufmodes[] = {_IOFBF,_IONBF};
567
568   tempf=_tempnam(".","wne");
569   for (bufmode=0; bufmode < sizeof(bufmodes)/sizeof(bufmodes[0]); bufmode++)
570   {
571     tempfh = fopen(tempf,"wb");
572     setvbuf(tempfh,NULL,bufmodes[bufmode],2048);
573     ret = _flsbuf(0,tempfh);
574     ok(0 == ret, "_flsbuf(0,tempfh) with bufmode %x expected %x got %x\n",
575                          bufmodes[bufmode], 0, ret);
576     ret = _flsbuf(0xff,tempfh);
577     ok(0xff == ret, "_flsbuf(0xff,tempfh) with bufmode %x expected %x got %x\n",
578                          bufmodes[bufmode], 0xff, ret);
579     ret = _flsbuf(0xffffffff,tempfh);
580     ok(0xff == ret, "_flsbuf(0xffffffff,tempfh) with bufmode %x expected %x got %x\n",
581                          bufmodes[bufmode], 0xff, ret);
582     if(tempfh->_base) {
583         fputc('x', tempfh);
584         tempfh->_cnt = -1;
585         tempfh->_base[1] = 'a';
586         ret = _flsbuf(0xab,tempfh);
587         ok(ret == 0xab, "_flsbuf(0xab,tempfh) with bufmode %x expected 0xab got %x\n",
588                 bufmodes[bufmode], ret);
589         ok(tempfh->_base[1] == 'a', "tempfh->_base[1] should not be changed (%d)\n",
590                 tempfh->_base[1]);
591     }
592
593     fclose(tempfh);
594   }
595
596   tempfh = fopen(tempf,"rb");
597   ret = _flsbuf(0,tempfh);
598   ok(EOF == ret, "_flsbuf(0,tempfh) on r/o file expected %x got %x\n", EOF, ret);
599   fclose(tempfh);
600
601   /* See bug 17123, exposed by WinAVR's make */
602   tempfh = fopen(tempf,"w");
603   ok(tempfh->_cnt == 0, "_cnt on freshly opened file was %d\n", tempfh->_cnt);
604   setbuf(tempfh, NULL);
605   ok(tempfh->_cnt == 0, "_cnt on unbuffered file was %d\n", tempfh->_cnt);
606   /* Inlined putchar sets _cnt to -1.  Native seems to ignore the value... */
607   tempfh->_cnt = 1234;
608   ret = _flsbuf('Q',tempfh);
609   ok('Q' == ret, "_flsbuf('Q',tempfh) expected %x got %x\n", 'Q', ret);
610   /* ... and reset it to zero */
611   ok(tempfh->_cnt == 0, "after unbuf _flsbuf, _cnt was %d\n", tempfh->_cnt);
612   fclose(tempfh);
613   /* And just for grins, make sure the file is correct */
614   tempfh = fopen(tempf,"r");
615   c = fgetc(tempfh);
616   ok(c == 'Q', "first byte should be 'Q'\n");
617   c = fgetc(tempfh);
618   ok(c == EOF, "there should only be one byte\n");
619   fclose(tempfh);
620
621   unlink(tempf);
622   free(tempf);
623 }
624
625 static void test_fflush( void )
626 {
627   static const char obuf[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
628   char buf1[16], buf2[24];
629   char *tempf;
630   FILE *tempfh;
631   int ret;
632
633   tempf=_tempnam(".","wne");
634
635   /* Prepare the file. */
636   tempfh = fopen(tempf,"wb");
637   ok(tempfh != NULL, "Can't open test file.\n");
638   fwrite(obuf, 1, sizeof(obuf), tempfh);
639   fclose(tempfh);
640
641   /* Open the file for input. */
642   tempfh = fopen(tempf,"rb");
643   ok(tempfh != NULL, "Can't open test file.\n");
644   fread(buf1, 1, sizeof(buf1), tempfh);
645
646   /* Using fflush() on input stream is undefined in ANSI.
647    * But MSDN says that it clears input buffer. */
648   _lseek(_fileno(tempfh), 0, SEEK_SET);
649   ret = fflush(tempfh);
650   ok(ret == 0, "expected 0, got %d\n", ret);
651   memset(buf2, '?', sizeof(buf2));
652   fread(buf2, 1, sizeof(buf2), tempfh);
653   ok(memcmp(buf1, buf2, sizeof(buf1)) == 0, "Got unexpected data (%c)\n", buf2[0]);
654
655   /* fflush(NULL) doesn't clear input buffer. */
656   _lseek(_fileno(tempfh), 0, SEEK_SET);
657   ret = fflush(NULL);
658   ok(ret == 0, "expected 0, got %d\n", ret);
659   memset(buf2, '?', sizeof(buf2));
660   fread(buf2, 1, sizeof(buf2), tempfh);
661   ok(memcmp(buf1, buf2, sizeof(buf1)) != 0, "Got unexpected data (%c)\n", buf2[0]);
662
663   /* _flushall() clears input buffer. */
664   _lseek(_fileno(tempfh), 0, SEEK_SET);
665   ret = _flushall();
666   ok(ret >= 0, "unexpected ret %d\n", ret);
667   memset(buf2, '?', sizeof(buf2));
668   fread(buf2, 1, sizeof(buf2), tempfh);
669   ok(memcmp(buf1, buf2, sizeof(buf1)) == 0, "Got unexpected data (%c)\n", buf2[0]);
670
671   fclose(tempfh);
672
673   unlink(tempf);
674   free(tempf);
675 }
676
677 static void test_fgetwc( void )
678 {
679 #define LLEN 512
680
681   char* tempf;
682   FILE *tempfh;
683   static const char mytext[]= "This is test_fgetwc\r\n";
684   WCHAR wtextW[BUFSIZ+LLEN+1];
685   WCHAR *mytextW = NULL, *aptr, *wptr;
686   BOOL diff_found = FALSE;
687   int j;
688   unsigned int i;
689   LONG l;
690
691   tempf=_tempnam(".","wne");
692   tempfh = fopen(tempf,"wb");
693   j = 'a';
694   /* pad to almost the length of the internal buffer */
695   for (i=0; i<BUFSIZ-4; i++)
696     fputc(j,tempfh);
697   j = '\r';
698   fputc(j,tempfh);
699   j = '\n';
700   fputc(j,tempfh);
701   fputs(mytext,tempfh);
702   fclose(tempfh);
703   /* in text mode, getws/c expects multibyte characters */
704   /*currently Wine only supports plain ascii, and that is all that is tested here */
705   tempfh = fopen(tempf,"rt"); /* open in TEXT mode */
706   fgetws(wtextW,LLEN,tempfh);
707   l=ftell(tempfh);
708   ok(l==BUFSIZ-2, "ftell expected %d got %d\n", BUFSIZ-2, l);
709   fgetws(wtextW,LLEN,tempfh);
710   l=ftell(tempfh);
711   ok(l==BUFSIZ-2+strlen(mytext), "ftell expected %d got %d\n", BUFSIZ-2+lstrlen(mytext), l);
712   mytextW = AtoW (mytext);
713   aptr = mytextW;
714   wptr = wtextW;
715   for (i=0; i<strlen(mytext)-2; i++, aptr++, wptr++)
716     {
717       diff_found |= (*aptr != *wptr);
718     }
719   ok(!(diff_found), "fgetwc difference found in TEXT mode\n");
720   ok(*wptr == '\n', "Carriage return was not skipped\n");
721   fclose(tempfh);
722   unlink(tempf);
723   
724   tempfh = fopen(tempf,"wb");
725   j = 'a';
726   /* pad to almost the length of the internal buffer. Use an odd number of bytes
727      to test that we can read wchars that are split across the internal buffer
728      boundary */
729   for (i=0; i<BUFSIZ-3-strlen(mytext)*sizeof(WCHAR); i++)
730     fputc(j,tempfh);
731   j = '\r';
732   fputwc(j,tempfh);
733   j = '\n';
734   fputwc(j,tempfh);
735   fputws(wtextW,tempfh);
736   fputws(wtextW,tempfh);
737   fclose(tempfh);
738   /* in binary mode, getws/c expects wide characters */
739   tempfh = fopen(tempf,"rb"); /* open in BINARY mode */
740   j=(BUFSIZ-2)/sizeof(WCHAR)-strlen(mytext);
741   fgetws(wtextW,j,tempfh);
742   l=ftell(tempfh);
743   j=(j-1)*sizeof(WCHAR);
744   ok(l==j, "ftell expected %d got %d\n", j, l);
745   i=fgetc(tempfh);
746   ok(i=='a', "fgetc expected %d got %d\n", 0x61, i);
747   l=ftell(tempfh);
748   j++;
749   ok(l==j, "ftell expected %d got %d\n", j, l);
750   fgetws(wtextW,3,tempfh);
751   ok(wtextW[0]=='\r',"expected carriage return got %04hx\n", wtextW[0]);
752   ok(wtextW[1]=='\n',"expected newline got %04hx\n", wtextW[1]);
753   l=ftell(tempfh);
754   j += 4;
755   ok(l==j, "ftell expected %d got %d\n", j, l);
756   for(i=0; i<strlen(mytext); i++)
757     wtextW[i] = 0;
758   /* the first time we get the string, it should be entirely within the local buffer */
759   fgetws(wtextW,LLEN,tempfh);
760   l=ftell(tempfh);
761   j += (strlen(mytext)-1)*sizeof(WCHAR);
762   ok(l==j, "ftell expected %d got %d\n", j, l);
763   diff_found = FALSE;
764   aptr = mytextW;
765   wptr = wtextW;
766   for (i=0; i<strlen(mytext)-2; i++, aptr++, wptr++)
767     {
768       ok(*aptr == *wptr, "Char %d expected %04hx got %04hx\n", i, *aptr, *wptr);
769       diff_found |= (*aptr != *wptr);
770     }
771   ok(!(diff_found), "fgetwc difference found in BINARY mode\n");
772   ok(*wptr == '\n', "Should get newline\n");
773   for(i=0; i<strlen(mytext); i++)
774     wtextW[i] = 0;
775   /* the second time we get the string, it should cross the local buffer boundary.
776      One of the wchars should be split across the boundary */
777   fgetws(wtextW,LLEN,tempfh);
778   diff_found = FALSE;
779   aptr = mytextW;
780   wptr = wtextW;
781   for (i=0; i<strlen(mytext)-2; i++, aptr++, wptr++)
782     {
783       ok(*aptr == *wptr, "Char %d expected %04hx got %04hx\n", i, *aptr, *wptr);
784       diff_found |= (*aptr != *wptr);
785     }
786   ok(!(diff_found), "fgetwc difference found in BINARY mode\n");
787   ok(*wptr == '\n', "Should get newline\n");
788
789   free(mytextW);
790   fclose(tempfh);
791   unlink(tempf);
792   free(tempf);
793 }
794
795 static void test_ctrlz( void )
796 {
797   char* tempf;
798   FILE *tempfh;
799   static const char mytext[]= "This is test_ctrlz";
800   char buffer[256];
801   int i, j;
802   LONG l;
803
804   tempf=_tempnam(".","wne");
805   tempfh = fopen(tempf,"wb");
806   fputs(mytext,tempfh);
807   j = 0x1a; /* a ctrl-z character signals EOF in text mode */
808   fputc(j,tempfh);
809   j = '\r';
810   fputc(j,tempfh);
811   j = '\n';
812   fputc(j,tempfh);
813   j = 'a';
814   fputc(j,tempfh);
815   fclose(tempfh);
816   tempfh = fopen(tempf,"rt"); /* open in TEXT mode */
817   ok(fgets(buffer,256,tempfh) != 0,"fgets failed unexpected\n");
818   i=strlen(buffer);
819   j=strlen(mytext);
820   ok(i==j, "returned string length expected %d got %d\n", j, i);
821   j+=4; /* ftell should indicate the true end of file */
822   l=ftell(tempfh);
823   ok(l==j, "ftell expected %d got %d\n", j, l);
824   ok(feof(tempfh), "did not get EOF\n");
825   fclose(tempfh);
826   
827   tempfh = fopen(tempf,"rb"); /* open in BINARY mode */
828   ok(fgets(buffer,256,tempfh) != 0,"fgets failed unexpected\n");
829   i=strlen(buffer);
830   j=strlen(mytext)+3; /* should get through newline */
831   ok(i==j, "returned string length expected %d got %d\n", j, i);
832   l=ftell(tempfh);
833   ok(l==j, "ftell expected %d got %d\n", j, l);
834   ok(fgets(buffer,256,tempfh) != 0,"fgets failed unexpected\n");
835   i=strlen(buffer);
836   ok(i==1, "returned string length expected %d got %d\n", 1, i);
837   ok(feof(tempfh), "did not get EOF\n");
838   fclose(tempfh);
839   unlink(tempf);
840   free(tempf);
841 }
842
843 static void test_file_put_get( void )
844 {
845   char* tempf;
846   FILE *tempfh;
847   static const char mytext[]=  "This is a test_file_put_get\n";
848   static const char dostext[]= "This is a test_file_put_get\r\n";
849   char btext[LLEN];
850   WCHAR wtextW[LLEN+1];
851   WCHAR *mytextW = NULL, *aptr, *wptr;
852   BOOL diff_found = FALSE;
853   unsigned int i;
854
855   tempf=_tempnam(".","wne");
856   tempfh = fopen(tempf,"wt"); /* open in TEXT mode */
857   fputs(mytext,tempfh);
858   fclose(tempfh);
859   tempfh = fopen(tempf,"rb"); /* open in TEXT mode */
860   fgets(btext,LLEN,tempfh);
861   ok( strlen(mytext) + 1 == strlen(btext),"TEXT/BINARY mode not handled for write\n");
862   ok( btext[strlen(mytext)-1] == '\r', "CR not written\n");
863   fclose(tempfh);
864   tempfh = fopen(tempf,"wb"); /* open in BINARY mode */
865   fputs(dostext,tempfh);
866   fclose(tempfh);
867   tempfh = fopen(tempf,"rt"); /* open in TEXT mode */
868   fgets(btext,LLEN,tempfh);
869   ok(strcmp(btext, mytext) == 0,"_O_TEXT read doesn't strip CR\n");
870   fclose(tempfh);
871   tempfh = fopen(tempf,"rb"); /* open in TEXT mode */
872   fgets(btext,LLEN,tempfh);
873   ok(strcmp(btext, dostext) == 0,"_O_BINARY read doesn't preserve CR\n");
874
875   fclose(tempfh);
876   tempfh = fopen(tempf,"rt"); /* open in TEXT mode */
877   fgetws(wtextW,LLEN,tempfh);
878   mytextW = AtoW (mytext);
879   aptr = mytextW;
880   wptr = wtextW;
881
882   for (i=0; i<strlen(mytext); i++, aptr++, wptr++)
883     {
884       diff_found |= (*aptr != *wptr);
885     }
886   ok(!(diff_found), "fgetwc doesn't strip CR in TEXT mode\n");
887   free(mytextW);
888   fclose(tempfh);
889   unlink(tempf);
890   free(tempf);
891 }
892
893 static void test_file_write_read( void )
894 {
895   char* tempf;
896   int tempfd;
897   static const char mytext[]=  "This is test_file_write_read\nsecond line\n";
898   static const char dostext[]= "This is test_file_write_read\r\nsecond line\r\n";
899   char btext[LLEN];
900   int ret, i;
901
902   tempf=_tempnam(".","wne");
903   tempfd = _open(tempf,_O_CREAT|_O_TRUNC|_O_BINARY|_O_RDWR,
904                      _S_IREAD | _S_IWRITE);
905   ok( tempfd != -1,
906      "Can't open '%s': %d\n", tempf, errno); /* open in BINARY mode */
907   ok(_write(tempfd,dostext,strlen(dostext)) == lstrlenA(dostext),
908      "_write _O_BINARY bad return value\n");
909   _close(tempfd);
910   i = lstrlenA(mytext);
911   tempfd = _open(tempf,_O_RDONLY|_O_BINARY,0); /* open in BINARY mode */
912   ok(_read(tempfd,btext,i) == i,
913      "_read _O_BINARY got bad length\n");
914   ok( memcmp(dostext,btext,i) == 0,
915       "problems with _O_BINARY  _write / _read\n");
916   _close(tempfd);
917   tempfd = _open(tempf,_O_RDONLY|_O_TEXT); /* open in TEXT mode */
918   ok(_read(tempfd,btext,i) == i-1,
919      "_read _O_TEXT got bad length\n");
920   ok( memcmp(mytext,btext,i-1) == 0,
921       "problems with _O_BINARY _write / _O_TEXT _read\n");
922   _close(tempfd);
923   tempfd = _open(tempf,_O_CREAT|_O_TRUNC|_O_TEXT|_O_RDWR,
924                      _S_IREAD | _S_IWRITE);
925   ok( tempfd != -1,
926      "Can't open '%s': %d\n", tempf, errno); /* open in TEXT mode */
927   ok(_write(tempfd,mytext,strlen(mytext)) == lstrlenA(mytext),
928      "_write _O_TEXT bad return value\n");
929   _close(tempfd);
930   tempfd = _open(tempf,_O_RDONLY|_O_BINARY,0); /* open in BINARY mode */
931   ok(_read(tempfd,btext,LLEN) == lstrlenA(dostext),
932      "_read _O_BINARY got bad length\n");
933   ok( memcmp(dostext,btext,strlen(dostext)) == 0,
934       "problems with _O_TEXT _write / _O_BINARY _read\n");
935   ok( btext[strlen(dostext)-2] == '\r', "CR not written or read\n");
936   _close(tempfd);
937   tempfd = _open(tempf,_O_RDONLY|_O_TEXT); /* open in TEXT mode */
938   ok(_read(tempfd,btext,LLEN) == lstrlenA(mytext),
939      "_read _O_TEXT got bad length\n");
940   ok( memcmp(mytext,btext,strlen(mytext)) == 0,
941       "problems with _O_TEXT _write / _read\n");
942   _close(tempfd);
943
944   memset(btext, 0, LLEN);
945   tempfd = _open(tempf,_O_APPEND|_O_RDWR); /* open for APPEND in default mode */
946   ok(tell(tempfd) == 0, "bad position %u expecting 0\n", tell(tempfd));
947   ok(_read(tempfd,btext,LLEN) == lstrlenA(mytext), "_read _O_APPEND got bad length\n");
948   ok( memcmp(mytext,btext,strlen(mytext)) == 0, "problems with _O_APPEND _read\n");
949   _close(tempfd);
950
951   /* Test reading only \n or \r */
952   tempfd = _open(tempf,_O_RDONLY|_O_TEXT); /* open in TEXT mode */
953   _lseek(tempfd, -1, FILE_END);
954   ret = _read(tempfd,btext,LLEN);
955   ok(ret == 1 && *btext == '\n', "_read expected 1 got bad length: %d\n", ret);
956   _lseek(tempfd, -2, FILE_END);
957   ret = _read(tempfd,btext,LLEN);
958   ok(ret == 1 && *btext == '\n', "_read expected '\\n' got bad length: %d\n", ret);
959   _lseek(tempfd, -3, FILE_END);
960   ret = _read(tempfd,btext,1);
961   ok(ret == 1 && *btext == 'e', "_read expected 'e' got \"%.*s\" bad length: %d\n", ret, btext, ret);
962   ok(tell(tempfd) == 41, "bad position %u expecting 41\n", tell(tempfd));
963   _lseek(tempfd, -3, FILE_END);
964   ret = _read(tempfd,btext,2);
965   ok(ret == 1 && *btext == 'e', "_read expected 'e' got \"%.*s\" bad length: %d\n", ret, btext, ret);
966   ok(tell(tempfd) == 42, "bad position %u expecting 42\n", tell(tempfd));
967   _lseek(tempfd, -3, FILE_END);
968   ret = _read(tempfd,btext,3);
969   ok(ret == 2 && *btext == 'e', "_read expected 'e' got \"%.*s\" bad length: %d\n", ret, btext, ret);
970   ok(tell(tempfd) == 43, "bad position %u expecting 43\n", tell(tempfd));
971    _close(tempfd);
972
973   ret = unlink(tempf);
974   ok( ret == 0 ,"Can't unlink '%s': %d\n", tempf, errno);
975   free(tempf);
976
977   tempf=_tempnam(".","wne");
978   tempfd = _open(tempf,_O_CREAT|_O_TRUNC|_O_BINARY|_O_RDWR,0);
979   ok( tempfd != -1,
980      "Can't open '%s': %d\n", tempf, errno); /* open in BINARY mode */
981   ok(_write(tempfd,dostext,strlen(dostext)) == lstrlenA(dostext),
982      "_write _O_BINARY bad return value\n");
983   _close(tempfd);
984   tempfd = _open(tempf,_O_RDONLY|_O_BINARY,0); /* open in BINARY mode */
985   ok(_read(tempfd,btext,LLEN) == lstrlenA(dostext),
986      "_read _O_BINARY got bad length\n");
987   ok( memcmp(dostext,btext,strlen(dostext)) == 0,
988       "problems with _O_BINARY _write / _read\n");
989   ok( btext[strlen(dostext)-2] == '\r', "CR not written or read\n");
990   _close(tempfd);
991   tempfd = _open(tempf,_O_RDONLY|_O_TEXT); /* open in TEXT mode */
992   ok(_read(tempfd,btext,LLEN) == lstrlenA(mytext),
993      "_read _O_TEXT got bad length\n");
994   ok( memcmp(mytext,btext,strlen(mytext)) == 0,
995       "problems with _O_BINARY _write / _O_TEXT _read\n");
996   _close(tempfd);
997
998   /* test _read with single bytes. CR should be skipped and LF pulled in */
999   tempfd = _open(tempf,_O_RDONLY|_O_TEXT); /* open in TEXT mode */
1000   for (i=0; i<strlen(mytext); i++)  /* */
1001     {
1002       _read(tempfd,btext, 1);
1003       ok(btext[0] ==  mytext[i],"_read failed at pos %d 0x%02x vs 0x%02x\n", i, btext[0], mytext[i]);
1004     }
1005   while (_read(tempfd,btext, 1));
1006   _close(tempfd);
1007
1008   /* test _read in buffered mode. Last CR should be skipped but  LF not pulled in */
1009   tempfd = _open(tempf,_O_RDONLY|_O_TEXT); /* open in TEXT mode */
1010   i = _read(tempfd,btext, strlen(mytext));
1011   ok(i == strlen(mytext)-1, "_read_i %d\n", i);
1012   _close(tempfd);
1013
1014   ret =_chmod (tempf, _S_IREAD | _S_IWRITE);
1015   ok( ret == 0,
1016      "Can't chmod '%s' to read-write: %d\n", tempf, errno);
1017   ret = unlink(tempf);
1018   ok( ret == 0 ,"Can't unlink '%s': %d\n", tempf, errno);
1019   free(tempf);
1020 }
1021
1022 static void test_file_inherit_child(const char* fd_s)
1023 {
1024     int fd = atoi(fd_s);
1025     char buffer[32];
1026     int ret;
1027
1028     ret =write(fd, "Success", 8);
1029     ok( ret == 8, "Couldn't write in child process on %d (%s)\n", fd, strerror(errno));
1030     lseek(fd, 0, SEEK_SET);
1031     ok(read(fd, buffer, sizeof (buffer)) == 8, "Couldn't read back the data\n");
1032     ok(memcmp(buffer, "Success", 8) == 0, "Couldn't read back the data\n");
1033 }
1034
1035 static void test_file_inherit_child_no(const char* fd_s)
1036 {
1037     int fd = atoi(fd_s);
1038     int ret;
1039
1040     ret = write(fd, "Success", 8);
1041     ok( ret == -1 && errno == EBADF, 
1042        "Wrong write result in child process on %d (%s)\n", fd, strerror(errno));
1043 }
1044
1045 static void create_io_inherit_block( STARTUPINFO *startup, unsigned int count, const HANDLE *handles )
1046 {
1047     static BYTE block[1024];
1048     BYTE *wxflag_ptr;
1049     HANDLE *handle_ptr;
1050     unsigned int i;
1051
1052     startup->lpReserved2 = block;
1053     startup->cbReserved2 = sizeof(unsigned) + (sizeof(char) + sizeof(HANDLE)) * count;
1054     wxflag_ptr = block + sizeof(unsigned);
1055     handle_ptr = (HANDLE *)(wxflag_ptr + count);
1056
1057     *(unsigned*)block = count;
1058     for (i = 0; i < count; i++)
1059     {
1060         wxflag_ptr[i] = 0x81;
1061         handle_ptr[i] = handles[i];
1062     }
1063 }
1064
1065 static const char *read_file( HANDLE file )
1066 {
1067     static char buffer[128];
1068     DWORD ret;
1069     SetFilePointer( file, 0, NULL, FILE_BEGIN );
1070     if (!ReadFile( file, buffer, sizeof(buffer) - 1, &ret, NULL)) ret = 0;
1071     buffer[ret] = 0;
1072     return buffer;
1073 }
1074
1075 static void test_stdout_handle( STARTUPINFO *startup, char *cmdline, HANDLE hstdout, BOOL expect_stdout,
1076                                 const char *descr )
1077 {
1078     const char *data;
1079     HANDLE hErrorFile;
1080     SECURITY_ATTRIBUTES sa;
1081     PROCESS_INFORMATION proc;
1082
1083     /* make file handle inheritable */
1084     sa.nLength = sizeof(sa);
1085     sa.lpSecurityDescriptor = NULL;
1086     sa.bInheritHandle = TRUE;
1087
1088     hErrorFile = CreateFileA( "fdopen.err", GENERIC_READ|GENERIC_WRITE,
1089                               FILE_SHARE_READ | FILE_SHARE_WRITE, &sa, CREATE_ALWAYS, 0, NULL );
1090     startup->dwFlags    = STARTF_USESTDHANDLES;
1091     startup->hStdInput  = GetStdHandle( STD_INPUT_HANDLE );
1092     startup->hStdOutput = hErrorFile;
1093     startup->hStdError  = GetStdHandle( STD_ERROR_HANDLE );
1094
1095     CreateProcessA( NULL, cmdline, NULL, NULL, TRUE,
1096                     CREATE_DEFAULT_ERROR_MODE | NORMAL_PRIORITY_CLASS, NULL, NULL, startup, &proc );
1097     winetest_wait_child_process( proc.hProcess );
1098
1099     data = read_file( hErrorFile );
1100     if (expect_stdout)
1101         ok( strcmp( data, "Success" ), "%s: Error file shouldn't contain data\n", descr );
1102     else
1103         ok( !strcmp( data, "Success" ), "%s: Wrong error data (%s)\n", descr, data );
1104
1105     if (hstdout)
1106     {
1107         data = read_file( hstdout );
1108         if (expect_stdout)
1109             ok( !strcmp( data, "Success" ), "%s: Wrong stdout data (%s)\n", descr, data );
1110         else
1111             ok( strcmp( data, "Success" ), "%s: Stdout file shouldn't contain data\n", descr );
1112     }
1113
1114     CloseHandle( hErrorFile );
1115     DeleteFile( "fdopen.err" );
1116 }
1117
1118 static void test_file_inherit( const char* selfname )
1119 {
1120     int                 fd;
1121     const char*         arg_v[5];
1122     char                buffer[16];
1123     char cmdline[MAX_PATH];
1124     STARTUPINFO startup;
1125     SECURITY_ATTRIBUTES sa;
1126     HANDLE handles[3];
1127
1128     fd = open ("fdopen.tst", O_CREAT | O_RDWR | O_BINARY, _S_IREAD |_S_IWRITE);
1129     ok(fd != -1, "Couldn't create test file\n");
1130     arg_v[0] = selfname;
1131     arg_v[1] = "tests/file.c";
1132     arg_v[2] = "inherit";
1133     arg_v[3] = buffer; sprintf(buffer, "%d", fd);
1134     arg_v[4] = 0;
1135     _spawnvp(_P_WAIT, selfname, arg_v);
1136     ok(tell(fd) == 8, "bad position %u expecting 8\n", tell(fd));
1137     lseek(fd, 0, SEEK_SET);
1138     ok(read(fd, buffer, sizeof (buffer)) == 8 && memcmp(buffer, "Success", 8) == 0, "Couldn't read back the data\n");
1139     close (fd);
1140     ok(unlink("fdopen.tst") == 0, "Couldn't unlink\n");
1141     
1142     fd = open ("fdopen.tst", O_CREAT | O_RDWR | O_BINARY | O_NOINHERIT, _S_IREAD |_S_IWRITE);
1143     ok(fd != -1, "Couldn't create test file\n");
1144     arg_v[0] = selfname;
1145     arg_v[1] = "tests/file.c";
1146     arg_v[2] = "inherit_no";
1147     arg_v[3] = buffer; sprintf(buffer, "%d", fd);
1148     arg_v[4] = 0;
1149     _spawnvp(_P_WAIT, selfname, arg_v);
1150     ok(tell(fd) == 0, "bad position %u expecting 0\n", tell(fd));
1151     ok(read(fd, buffer, sizeof (buffer)) == 0, "Found unexpected data (%s)\n", buffer);
1152     close (fd);
1153     ok(unlink("fdopen.tst") == 0, "Couldn't unlink\n");
1154
1155     /* make file handle inheritable */
1156     sa.nLength = sizeof(sa);
1157     sa.lpSecurityDescriptor = NULL;
1158     sa.bInheritHandle = TRUE;
1159     sprintf(cmdline, "%s file inherit 1", selfname);
1160
1161     /* init an empty Reserved2, which should not be recognized as inherit-block */
1162     ZeroMemory(&startup, sizeof(STARTUPINFO));
1163     startup.cb = sizeof(startup);
1164     create_io_inherit_block( &startup, 0, NULL );
1165     test_stdout_handle( &startup, cmdline, 0, FALSE, "empty block" );
1166
1167     /* test with valid inheritblock */
1168     handles[0] = GetStdHandle( STD_INPUT_HANDLE );
1169     handles[1] = CreateFileA( "fdopen.tst", GENERIC_READ|GENERIC_WRITE,
1170                               FILE_SHARE_READ | FILE_SHARE_WRITE, &sa, CREATE_ALWAYS, 0, NULL );
1171     handles[2] = GetStdHandle( STD_ERROR_HANDLE );
1172     create_io_inherit_block( &startup, 3, handles );
1173     test_stdout_handle( &startup, cmdline, handles[1], TRUE, "valid block" );
1174     CloseHandle( handles[1] );
1175     DeleteFile("fdopen.tst");
1176
1177     /* test inherit block starting with unsigned zero */
1178     handles[1] = CreateFileA( "fdopen.tst", GENERIC_READ|GENERIC_WRITE,
1179                               FILE_SHARE_READ | FILE_SHARE_WRITE, &sa, CREATE_ALWAYS, 0, NULL );
1180     create_io_inherit_block( &startup, 3, handles );
1181     *(unsigned int *)startup.lpReserved2 = 0;
1182     test_stdout_handle( &startup, cmdline, handles[1], FALSE, "zero count block" );
1183     CloseHandle( handles[1] );
1184     DeleteFile("fdopen.tst");
1185
1186     /* test inherit block with smaller size */
1187     handles[1] = CreateFileA( "fdopen.tst", GENERIC_READ|GENERIC_WRITE,
1188                               FILE_SHARE_READ | FILE_SHARE_WRITE, &sa, CREATE_ALWAYS, 0, NULL );
1189     create_io_inherit_block( &startup, 3, handles );
1190     startup.cbReserved2 -= 3;
1191     test_stdout_handle( &startup, cmdline, handles[1], TRUE, "small size block" );
1192     CloseHandle( handles[1] );
1193     DeleteFile("fdopen.tst");
1194
1195     /* test inherit block with even smaller size */
1196     handles[1] = CreateFileA( "fdopen.tst", GENERIC_READ|GENERIC_WRITE,
1197                               FILE_SHARE_READ | FILE_SHARE_WRITE, &sa, CREATE_ALWAYS, 0, NULL );
1198     create_io_inherit_block( &startup, 3, handles );
1199     startup.cbReserved2 = sizeof(unsigned int) + sizeof(HANDLE) + sizeof(char);
1200     test_stdout_handle( &startup, cmdline, handles[1], FALSE, "smaller size block" );
1201     CloseHandle( handles[1] );
1202     DeleteFile("fdopen.tst");
1203
1204     /* test inherit block with larger size */
1205     handles[1] = CreateFileA( "fdopen.tst", GENERIC_READ|GENERIC_WRITE,
1206                               FILE_SHARE_READ | FILE_SHARE_WRITE, &sa, CREATE_ALWAYS, 0, NULL );
1207     create_io_inherit_block( &startup, 3, handles );
1208     startup.cbReserved2 += 7;
1209     test_stdout_handle( &startup, cmdline, handles[1], TRUE, "large size block" );
1210     CloseHandle( handles[1] );
1211     DeleteFile("fdopen.tst");
1212 }
1213
1214 static void test_tmpnam( void )
1215 {
1216   char name[MAX_PATH] = "abc";
1217   char *res;
1218
1219   res = tmpnam(NULL);
1220   ok(res != NULL, "tmpnam returned NULL\n");
1221   ok(res[0] == '\\', "first character is not a backslash\n");
1222   ok(strchr(res+1, '\\') == 0, "file not in the root directory\n");
1223   ok(res[strlen(res)-1] == '.', "first call - last character is not a dot\n");
1224
1225   res = tmpnam(name);
1226   ok(res != NULL, "tmpnam returned NULL\n");
1227   ok(res == name, "supplied buffer was not used\n");
1228   ok(res[0] == '\\', "first character is not a backslash\n");
1229   ok(strchr(res+1, '\\') == 0, "file not in the root directory\n");
1230   ok(res[strlen(res)-1] != '.', "second call - last character is a dot\n");
1231 }
1232
1233 static void test_chsize( void )
1234 {
1235     int fd;
1236     LONG cur, pos, count;
1237     char temptext[] = "012345678";
1238     char *tempfile = _tempnam( ".", "tst" );
1239     
1240     ok( tempfile != NULL, "Couldn't create test file: %s\n", tempfile );
1241
1242     fd = _open( tempfile, _O_CREAT|_O_TRUNC|_O_RDWR, _S_IREAD|_S_IWRITE );
1243     ok( fd > 0, "Couldn't open test file\n" );
1244
1245     count = _write( fd, temptext, sizeof(temptext) );
1246     ok( count > 0, "Couldn't write to test file\n" );
1247
1248     /* get current file pointer */
1249     cur = _lseek( fd, 0, SEEK_CUR );
1250
1251     /* make the file smaller */
1252     ok( _chsize( fd, sizeof(temptext) / 2 ) == 0, "_chsize() failed\n" );
1253
1254     pos = _lseek( fd, 0, SEEK_CUR );
1255     ok( cur == pos, "File pointer changed from: %d to: %d\n", cur, pos );
1256     ok( _filelength( fd ) == sizeof(temptext) / 2, "Wrong file size\n" );
1257
1258     /* enlarge the file */
1259     ok( _chsize( fd, sizeof(temptext) * 2 ) == 0, "_chsize() failed\n" ); 
1260
1261     pos = _lseek( fd, 0, SEEK_CUR );
1262     ok( cur == pos, "File pointer changed from: %d to: %d\n", cur, pos );
1263     ok( _filelength( fd ) == sizeof(temptext) * 2, "Wrong file size\n" );
1264
1265     _close( fd );
1266     _unlink( tempfile );
1267     free( tempfile );
1268 }
1269
1270 static void test_fopen_fclose_fcloseall( void )
1271 {
1272     char fname1[] = "empty1";
1273     char fname2[] = "empty2";
1274     char fname3[] = "empty3";
1275     FILE *stream1, *stream2, *stream3, *stream4;
1276     int ret, numclosed;
1277
1278     /* testing fopen() */
1279     stream1 = fopen(fname1, "w+");
1280     ok(stream1 != NULL, "The file '%s' was not opened\n", fname1);
1281     stream2 = fopen(fname2, "w ");
1282     ok(stream2 != NULL, "The file '%s' was not opened\n", fname2 );
1283     _unlink(fname3);
1284     stream3 = fopen(fname3, "r");
1285     ok(stream3 == NULL, "The file '%s' shouldn't exist before\n", fname3 );
1286     stream3 = fopen(fname3, "w+");
1287     ok(stream3 != NULL, "The file '%s' should be opened now\n", fname3 );
1288     errno = 0xfaceabad;
1289     stream4 = fopen("", "w+");
1290     ok(stream4 == NULL && (errno == EINVAL || errno == ENOENT),
1291        "filename is empty, errno = %d (expected 2 or 22)\n", errno);
1292     errno = 0xfaceabad;
1293     stream4 = fopen(NULL, "w+");
1294     ok(stream4 == NULL && (errno == EINVAL || errno == ENOENT), 
1295        "filename is NULL, errno = %d (expected 2 or 22)\n", errno);
1296
1297     /* testing fclose() */
1298     ret = fclose(stream2);
1299     ok(ret == 0, "The file '%s' was not closed\n", fname2);
1300     ret = fclose(stream3);
1301     ok(ret == 0, "The file '%s' was not closed\n", fname3);
1302     ret = fclose(stream2);
1303     ok(ret == EOF, "Closing file '%s' returned %d\n", fname2, ret);
1304     ret = fclose(stream3);
1305     ok(ret == EOF, "Closing file '%s' returned %d\n", fname3, ret);
1306
1307     /* testing fcloseall() */
1308     numclosed = _fcloseall();
1309     /* fname1 should be closed here */
1310     ok(numclosed == 1, "Number of files closed by fcloseall(): %u\n", numclosed);
1311     numclosed = _fcloseall();
1312     ok(numclosed == 0, "Number of files closed by fcloseall(): %u\n", numclosed);
1313
1314     ok(_unlink(fname1) == 0, "Couldn't unlink file named '%s'\n", fname1);
1315     ok(_unlink(fname2) == 0, "Couldn't unlink file named '%s'\n", fname2);
1316     ok(_unlink(fname3) == 0, "Couldn't unlink file named '%s'\n", fname3);
1317 }
1318
1319 static void test_fopen_s( void )
1320 {
1321     const char name[] = "empty1";
1322     char buff[16];
1323     FILE *file;
1324     int ret;
1325     int len;
1326
1327     if (!p_fopen_s)
1328     {
1329         win_skip("Skipping fopen_s test\n");
1330         return;
1331     }
1332     /* testing fopen_s */
1333     ret = p_fopen_s(&file, name, "w");
1334     ok(ret == 0, "fopen_s failed with %d\n", ret);
1335     ok(file != 0, "fopen_s failed to return value\n");
1336     fwrite(name, sizeof(name), 1, file);
1337
1338     ret = fclose(file);
1339     ok(ret != EOF, "File failed to close\n");
1340
1341     file = fopen(name, "r");
1342     ok(file != 0, "fopen failed\n");
1343     len = fread(buff, 1, sizeof(name), file);
1344     ok(len == sizeof(name), "File length is %d\n", len);
1345     buff[sizeof(name)] = '\0';
1346     ok(strcmp(name, buff) == 0, "File content mismatch! Got %s, expected %s\n", buff, name);
1347
1348     ret = fclose(file);
1349     ok(ret != EOF, "File failed to close\n");
1350
1351     ok(_unlink(name) == 0, "Couldn't unlink file named '%s'\n", name);
1352 }
1353
1354 static void test__wfopen_s( void )
1355 {
1356     const char name[] = "empty1";
1357     const WCHAR wname[] = {
1358        'e','m','p','t','y','1',0
1359     };
1360     const WCHAR wmode[] = {
1361        'w',0
1362     };
1363     char buff[16];
1364     FILE *file;
1365     int ret;
1366     int len;
1367
1368     if (!p__wfopen_s)
1369     {
1370         win_skip("Skipping _wfopen_s test\n");
1371         return;
1372     }
1373     /* testing _wfopen_s */
1374     ret = p__wfopen_s(&file, wname, wmode);
1375     ok(ret == 0, "_wfopen_s failed with %d\n", ret);
1376     ok(file != 0, "_wfopen_s failed to return value\n");
1377     fwrite(name, sizeof(name), 1, file);
1378
1379     ret = fclose(file);
1380     ok(ret != EOF, "File failed to close\n");
1381
1382     file = fopen(name, "r");
1383     ok(file != 0, "fopen failed\n");
1384     len = fread(buff, 1, sizeof(name), file);
1385     ok(len == sizeof(name), "File length is %d\n", len);
1386     buff[sizeof(name)] = '\0';
1387     ok(strcmp(name, buff) == 0, "File content mismatch! Got %s, expected %s\n", buff, name);
1388
1389     ret = fclose(file);
1390     ok(ret != EOF, "File failed to close\n");
1391
1392     ok(_unlink(name) == 0, "Couldn't unlink file named '%s'\n", name);
1393 }
1394
1395 static void test_get_osfhandle(void)
1396 {
1397     int fd;
1398     char fname[] = "t_get_osfhanle";
1399     DWORD bytes_written;
1400     HANDLE handle;
1401
1402     fd = _sopen(fname, _O_CREAT|_O_RDWR, _SH_DENYRW, _S_IREAD | _S_IWRITE);
1403     handle = (HANDLE)_get_osfhandle(fd);
1404     WriteFile(handle, "bar", 3, &bytes_written, NULL);
1405     _close(fd);
1406     fd = _open(fname, _O_RDONLY, 0);
1407     ok(fd != -1, "Couldn't open '%s' after _get_osfhandle()\n", fname);
1408
1409     _close(fd);
1410     _unlink(fname);
1411 }
1412
1413 static void test_setmaxstdio(void)
1414 {
1415     ok(2048 == _setmaxstdio(2048),"_setmaxstdio returned %d instead of 2048\n",_setmaxstdio(2048));
1416     ok(-1 == _setmaxstdio(2049),"_setmaxstdio returned %d instead of -1\n",_setmaxstdio(2049));
1417 }
1418
1419 static void test_stat(void)
1420 {
1421     int fd;
1422     int pipes[2];
1423     int ret;
1424     struct stat buf;
1425
1426     /* Tests for a file */
1427     fd = open("stat.tst", O_WRONLY | O_CREAT | O_BINARY, _S_IREAD |_S_IWRITE);
1428     if (fd >= 0)
1429     {
1430         ret = fstat(fd, &buf);
1431         ok(!ret, "fstat failed: errno=%d\n", errno);
1432         ok((buf.st_mode & _S_IFMT) == _S_IFREG, "bad format = %06o\n", buf.st_mode);
1433         ok((buf.st_mode & 0777) == 0666, "bad st_mode = %06o\n", buf.st_mode);
1434         ok(buf.st_dev == 0, "st_dev is %d, expected 0\n", buf.st_dev);
1435         ok(buf.st_dev == buf.st_rdev, "st_dev (%d) and st_rdev (%d) differ\n", buf.st_dev, buf.st_rdev);
1436         ok(buf.st_nlink == 1, "st_nlink is %d, expected 1\n", buf.st_nlink);
1437         ok(buf.st_size == 0, "st_size is %d, expected 0\n", buf.st_size);
1438
1439         ret = stat("stat.tst", &buf);
1440         ok(!ret, "stat failed: errno=%d\n", errno);
1441         ok((buf.st_mode & _S_IFMT) == _S_IFREG, "bad format = %06o\n", buf.st_mode);
1442         ok((buf.st_mode & 0777) == 0666, "bad st_mode = %06o\n", buf.st_mode);
1443         ok(buf.st_dev == buf.st_rdev, "st_dev (%d) and st_rdev (%d) differ\n", buf.st_dev, buf.st_rdev);
1444         ok(buf.st_nlink == 1, "st_nlink is %d, expected 1\n", buf.st_nlink);
1445         ok(buf.st_size == 0, "st_size is %d, expected 0\n", buf.st_size);
1446
1447         close(fd);
1448         remove("stat.tst");
1449     }
1450     else
1451         skip("open failed with errno %d\n", errno);
1452
1453     /* Tests for a char device */
1454     if (_dup2(0, 10) == 0)
1455     {
1456         ret = fstat(10, &buf);
1457         ok(!ret, "fstat(stdin) failed: errno=%d\n", errno);
1458         if ((buf.st_mode & _S_IFMT) == _S_IFCHR)
1459         {
1460             ok(buf.st_mode == _S_IFCHR, "bad st_mode=%06o\n", buf.st_mode);
1461             ok(buf.st_dev == 10, "st_dev is %d, expected 10\n", buf.st_dev);
1462             ok(buf.st_rdev == 10, "st_rdev is %d, expected 10\n", buf.st_rdev);
1463             ok(buf.st_nlink == 1, "st_nlink is %d, expected 1\n", buf.st_nlink);
1464         }
1465         else
1466             skip("stdin is not a char device? st_mode=%06o\n", buf.st_mode);
1467         close(10);
1468     }
1469     else
1470         skip("_dup2 failed with errno %d\n", errno);
1471
1472     /* Tests for pipes */
1473     if (_pipe(pipes, 1024, O_BINARY) == 0)
1474     {
1475         ret = fstat(pipes[0], &buf);
1476         ok(!ret, "fstat(pipe) failed: errno=%d\n", errno);
1477         ok(buf.st_mode == _S_IFIFO, "bad st_mode=%06o\n", buf.st_mode);
1478         ok(buf.st_dev == pipes[0], "st_dev is %d, expected %d\n", buf.st_dev, pipes[0]);
1479         ok(buf.st_rdev == pipes[0], "st_rdev is %d, expected %d\n", buf.st_rdev, pipes[0]);
1480         ok(buf.st_nlink == 1, "st_nlink is %d, expected 1\n", buf.st_nlink);
1481         close(pipes[0]);
1482         close(pipes[1]);
1483     }
1484     else
1485         skip("pipe failed with errno %d\n", errno);
1486 }
1487
1488 static const char* pipe_string="Hello world";
1489
1490 /* How many messages to transfer over the pipe */
1491 #define N_TEST_MESSAGES 3
1492
1493 static void test_pipes_child(int argc, char** args)
1494 {
1495     int fd;
1496     int nwritten;
1497     int i;
1498
1499     if (argc < 5)
1500     {
1501         ok(0, "not enough parameters: %d\n", argc);
1502         return;
1503     }
1504
1505     fd=atoi(args[3]);
1506     i=close(fd);
1507     ok(!i, "unable to close %d: %d\n", fd, errno);
1508
1509     fd=atoi(args[4]);
1510
1511     for (i=0; i<N_TEST_MESSAGES; i++) {
1512        nwritten=write(fd, pipe_string, strlen(pipe_string));
1513        ok(nwritten == strlen(pipe_string), "i %d, expected to write '%s' wrote %d\n", i, pipe_string, nwritten);
1514        /* let other process wake up so they can show off their "keep reading until EOF" behavior */
1515        if (i < N_TEST_MESSAGES-1)
1516            Sleep(100);
1517     }
1518
1519     i=close(fd);
1520     ok(!i, "unable to close %d: %d\n", fd, errno);
1521 }
1522
1523 static void test_pipes(const char* selfname)
1524 {
1525     int pipes[2];
1526     char str_fdr[12], str_fdw[12];
1527     FILE* file;
1528     const char* arg_v[6];
1529     char buf[4096];
1530     char expected[4096];
1531     int r;
1532     int i;
1533
1534     /* Test reading from a pipe with read() */
1535     if (_pipe(pipes, 1024, O_BINARY) < 0)
1536     {
1537         ok(0, "pipe failed with errno %d\n", errno);
1538         return;
1539     }
1540
1541     arg_v[0] = selfname;
1542     arg_v[1] = "tests/file.c";
1543     arg_v[2] = "pipes";
1544     arg_v[3] = str_fdr; sprintf(str_fdr, "%d", pipes[0]);
1545     arg_v[4] = str_fdw; sprintf(str_fdw, "%d", pipes[1]);
1546     arg_v[5] = NULL;
1547     proc_handles[0] = (HANDLE)_spawnvp(_P_NOWAIT, selfname, arg_v);
1548     i=close(pipes[1]);
1549     ok(!i, "unable to close %d: %d\n", pipes[1], errno);
1550
1551     for (i=0; i<N_TEST_MESSAGES; i++) {
1552        r=read(pipes[0], buf, sizeof(buf)-1);
1553        ok(r == strlen(pipe_string), "i %d, got %d\n", i, r);
1554        if (r > 0)
1555            buf[r]='\0';
1556        ok(strcmp(buf, pipe_string) == 0, "expected to read '%s', got '%s'\n", pipe_string, buf);
1557    }
1558
1559     r=read(pipes[0], buf, sizeof(buf)-1);
1560     ok(r == 0, "expected to read 0 bytes, got %d\n", r);
1561     i=close(pipes[0]);
1562     ok(!i, "unable to close %d: %d\n", pipes[0], errno);
1563
1564     /* Test reading from a pipe with fread() */
1565     if (_pipe(pipes, 1024, O_BINARY) < 0)
1566     {
1567         ok(0, "pipe failed with errno %d\n", errno);
1568         return;
1569     }
1570
1571     arg_v[0] = selfname;
1572     arg_v[1] = "tests/file.c";
1573     arg_v[2] = "pipes";
1574     arg_v[3] = str_fdr; sprintf(str_fdr, "%d", pipes[0]);
1575     arg_v[4] = str_fdw; sprintf(str_fdw, "%d", pipes[1]);
1576     arg_v[5] = NULL;
1577     proc_handles[1] = (HANDLE)_spawnvp(_P_NOWAIT, selfname, arg_v);
1578     i=close(pipes[1]);
1579     ok(!i, "unable to close %d: %d\n", pipes[1], errno);
1580     file=fdopen(pipes[0], "r");
1581
1582     /* In blocking mode, fread will keep calling read() until it gets
1583      * enough bytes, or EOF, even on Unix.  (If this were a Unix terminal
1584      * in cooked mode instead of a pipe, it would also stop on EOL.)
1585      */
1586     expected[0] = 0;
1587     for (i=0; i<N_TEST_MESSAGES; i++)
1588        strcat(expected, pipe_string);
1589     r=fread(buf, 1, sizeof(buf)-1, file);
1590     ok(r == strlen(expected), "fread() returned %d: ferror=%d\n", r, ferror(file));
1591     if (r > 0)
1592        buf[r]='\0';
1593     ok(strcmp(buf, expected) == 0, "got '%s' expected '%s'\n", buf, expected);
1594
1595     /* Let child close the file before we read, so we can sense EOF reliably */
1596     Sleep(100);
1597     r=fread(buf, 1, sizeof(buf)-1, file);
1598     ok(r == 0, "fread() returned %d instead of 0\n", r);
1599     ok(ferror(file) == 0, "got ferror() = %d\n", ferror(file));
1600     ok(feof(file), "feof() is false!\n");
1601
1602     i=fclose(file);
1603     ok(!i, "unable to close the pipe: %d\n", errno);
1604 }
1605
1606 static void test_unlink(void)
1607 {
1608     FILE* file;
1609     ok(mkdir("test_unlink") == 0, "unable to create test dir\n");
1610     file = fopen("test_unlink\\empty", "w");
1611     ok(file != NULL, "unable to create test file\n");
1612     if(file)
1613       fclose(file);
1614     ok(_unlink("test_unlink") != 0, "unlinking a non-empty directory must fail\n");
1615     unlink("test_unlink\\empty");
1616     rmdir("test_unlink");
1617 }
1618
1619 static void test_dup2(void)
1620 {
1621     ok(-1 == _dup2(0, -1), "expected _dup2 to fail when second arg is negative\n" );
1622 }
1623
1624 START_TEST(file)
1625 {
1626     int arg_c;
1627     char** arg_v;
1628
1629     init();
1630
1631     arg_c = winetest_get_mainargs( &arg_v );
1632
1633     /* testing low-level I/O */
1634     if (arg_c >= 3)
1635     {
1636         if (strcmp(arg_v[2], "inherit") == 0)
1637             test_file_inherit_child(arg_v[3]);
1638         else if (strcmp(arg_v[2], "inherit_no") == 0)
1639             test_file_inherit_child_no(arg_v[3]);
1640         else if (strcmp(arg_v[2], "pipes") == 0)
1641             test_pipes_child(arg_c, arg_v);
1642         else
1643             ok(0, "invalid argument '%s'\n", arg_v[2]);
1644         return;
1645     }
1646     test_dup2();
1647     test_file_inherit(arg_v[0]);
1648     test_file_write_read();
1649     test_chsize();
1650     test_stat();
1651     test_unlink();
1652
1653     /* testing stream I/O */
1654     test_filbuf();
1655     test_fdopen();
1656     test_fopen_fclose_fcloseall();
1657     test_fopen_s();
1658     test__wfopen_s();
1659     test_fileops();
1660     test_asciimode();
1661     test_asciimode2();
1662     test_filemodeT();
1663     test_readmode(FALSE); /* binary mode */
1664     test_readmode(TRUE);  /* ascii mode */
1665     test_readboundary();
1666     test_fgetc();
1667     test_fputc();
1668     test_flsbuf();
1669     test_fflush();
1670     test_fgetwc();
1671     test_ctrlz();
1672     test_file_put_get();
1673     test_tmpnam();
1674     test_get_osfhandle();
1675     test_setmaxstdio();
1676     test_pipes(arg_v[0]);
1677
1678     /* Wait for the (_P_NOWAIT) spawned processes to finish to make sure the report
1679      * file contains lines in the correct order
1680      */
1681     WaitForMultipleObjects(sizeof(proc_handles)/sizeof(proc_handles[0]), proc_handles, TRUE, 5000);
1682 }