Revert "winex11.drv: Optimise getting the bits of a DIB after calling SetDIBits."
[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 void test_fdopen( void )
40 {
41     static const char buffer[] = {0,1,2,3,4,5,6,7,8,9};
42     char ibuf[10];
43     int fd;
44     FILE *file;
45
46     fd = open ("fdopen.tst", O_WRONLY | O_CREAT | O_BINARY, _S_IREAD |_S_IWRITE);
47     write (fd, buffer, sizeof (buffer));
48     close (fd);
49
50     fd = open ("fdopen.tst", O_RDONLY | O_BINARY);
51     lseek (fd, 5, SEEK_SET);
52     file = fdopen (fd, "rb");
53     ok (fread (ibuf, 1, sizeof (buffer), file) == 5, "read wrong byte count\n");
54     ok (memcmp (ibuf, buffer + 5, 5) == 0, "read wrong bytes\n");
55     fclose (file);
56     unlink ("fdopen.tst");
57 }
58
59 static void test_fileops( void )
60 {
61     static const char outbuffer[] = "0,1,2,3,4,5,6,7,8,9";
62     char buffer[256];
63     WCHAR wbuffer[256];
64     int fd;
65     FILE *file;
66     fpos_t pos;
67     int i, c;
68
69     fd = open ("fdopen.tst", O_WRONLY | O_CREAT | O_BINARY, _S_IREAD |_S_IWRITE);
70     write (fd, outbuffer, sizeof (outbuffer));
71     close (fd);
72
73     fd = open ("fdopen.tst", O_RDONLY | O_BINARY);
74     file = fdopen (fd, "rb");
75     ok(strlen(outbuffer) == (sizeof(outbuffer)-1),"strlen/sizeof error\n");
76     ok(fgets(buffer,sizeof(buffer),file) !=0,"fgets failed unexpected\n");
77     ok(fgets(buffer,sizeof(buffer),file) ==0,"fgets didn't signal EOF\n");
78     ok(feof(file) !=0,"feof doesn't signal EOF\n");
79     rewind(file);
80     ok(fgets(buffer,strlen(outbuffer),file) !=0,"fgets failed unexpected\n");
81     ok(lstrlenA(buffer) == lstrlenA(outbuffer) -1,"fgets didn't read right size\n");
82     ok(fgets(buffer,sizeof(outbuffer),file) !=0,"fgets failed unexpected\n");
83     ok(strlen(buffer) == 1,"fgets dropped chars\n");
84     ok(buffer[0] == outbuffer[strlen(outbuffer)-1],"fgets exchanged chars\n");
85
86     rewind(file);
87     for (i = 0, c = EOF; i < sizeof(outbuffer); i++)
88     {
89         ok((c = fgetc(file)) == outbuffer[i], "fgetc returned wrong data\n");
90     }
91     ok((c = fgetc(file)) == EOF, "getc did not return EOF\n");
92     ok(feof(file), "feof did not return EOF\n");
93     ok(ungetc(c, file) == EOF, "ungetc(EOF) did not return EOF\n");
94     ok(feof(file), "feof after ungetc(EOF) did not return EOF\n");
95     ok((c = fgetc(file)) == EOF, "getc did not return EOF\n");
96     c = outbuffer[sizeof(outbuffer) - 1];
97     ok(ungetc(c, file) == c, "ungetc did not return its input\n");
98     ok(!feof(file), "feof after ungetc returned EOF\n");
99     ok((c = fgetc(file)) != EOF, "getc after ungetc returned EOF\n");
100     ok(c == outbuffer[sizeof(outbuffer) - 1],
101        "getc did not return ungetc'd data\n");
102     ok(!feof(file), "feof after getc returned EOF prematurely\n");
103     ok((c = fgetc(file)) == EOF, "getc did not return EOF\n");
104     ok(feof(file), "feof after getc did not return EOF\n");
105
106     rewind(file);
107     ok(fgetpos(file,&pos) == 0, "fgetpos failed unexpected\n");
108     ok(pos == 0, "Unexpected result of fgetpos 0x%Lx\n", pos);
109     pos = (ULONGLONG)sizeof (outbuffer);
110     ok(fsetpos(file, &pos) == 0, "fsetpos failed unexpected\n");
111     ok(fgetpos(file,&pos) == 0, "fgetpos failed unexpected\n");
112     ok(pos == (ULONGLONG)sizeof (outbuffer), "Unexpected result of fgetpos 0x%Lx\n", pos);
113
114     fclose (file);
115     fd = open ("fdopen.tst", O_RDONLY | O_TEXT);
116     file = fdopen (fd, "rt"); /* open in TEXT mode */
117     ok(fgetws(wbuffer,sizeof(wbuffer),file) !=0,"fgetws failed unexpected\n");
118     ok(fgetws(wbuffer,sizeof(wbuffer),file) ==0,"fgetws didn't signal EOF\n");
119     ok(feof(file) !=0,"feof doesn't signal EOF\n");
120     rewind(file);
121     ok(fgetws(wbuffer,strlen(outbuffer),file) !=0,"fgetws failed unexpected\n");
122     ok(lstrlenW(wbuffer) == (lstrlenA(outbuffer) -1),"fgetws didn't read right size\n");
123     ok(fgetws(wbuffer,sizeof(outbuffer),file) !=0,"fgets failed unexpected\n");
124     ok(lstrlenW(wbuffer) == 1,"fgets dropped chars\n");
125     fclose (file);
126
127     file = fopen("fdopen.tst", "rb");
128     ok( file != NULL, "fopen failed\n");
129     /* sizeof(buffer) > content of file */
130     ok(fread(buffer, sizeof(buffer), 1, file) == 0, "fread test failed\n");
131     /* feof should be set now */
132     ok(feof(file), "feof after fread failed\n");
133     fclose (file);
134
135     unlink ("fdopen.tst");
136 }
137
138 #define IOMODE (ao?"ascii mode":"binary mode")
139 static void test_readmode( BOOL ascii_mode )
140 {
141     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";
142     static const char padbuffer[] = "ghjghjghjghj";
143     static const char nlbuffer[] = "\r\n";
144     char buffer[2*BUFSIZ+256];
145     const char *optr;
146     int fd;
147     FILE *file;
148     const int *ip;
149     int i, j, m, ao, pl;
150     unsigned int fp;
151     long l;
152
153     fd = open ("fdopen.tst", O_WRONLY | O_CREAT | O_BINARY, _S_IREAD |_S_IWRITE);
154     /* an internal buffer of BUFSIZ is maintained, so make a file big
155      * enough to test operations that cross the buffer boundary 
156      */
157     j = (2*BUFSIZ-4)/strlen(padbuffer);
158     for (i=0; i<j; i++)
159         write (fd, padbuffer, strlen(padbuffer));
160     j = (2*BUFSIZ-4)%strlen(padbuffer);
161     for (i=0; i<j; i++)
162         write (fd, &padbuffer[i], 1);
163     write (fd, nlbuffer, strlen(nlbuffer));
164     write (fd, outbuffer, sizeof (outbuffer));
165     close (fd);
166     
167     if (ascii_mode) {
168         /* Open file in ascii mode */
169         fd = open ("fdopen.tst", O_RDONLY);
170         file = fdopen (fd, "r");
171         ao = -1; /* on offset to account for carriage returns */
172     }
173     else {
174         fd = open ("fdopen.tst", O_RDONLY | O_BINARY);
175         file = fdopen (fd, "rb");
176         ao = 0;
177     }
178     
179     /* first is a test of fgets, ftell, fseek */
180     ok(ftell(file) == 0,"Did not start at beginning of file in %s\n", IOMODE);
181     ok(fgets(buffer,2*BUFSIZ+256,file) !=0,"padding line fgets failed unexpected in %s\n", IOMODE);
182     l = ftell(file);
183     pl = 2*BUFSIZ-2;
184     ok(l == pl,"padding line ftell got %ld should be %d in %s\n", l, pl, IOMODE);
185     ok(lstrlenA(buffer) == pl+ao,"padding line fgets got size %d should be %d in %s\n",
186      lstrlenA(buffer), pl+ao, IOMODE);
187     for (fp=0; fp<strlen(outbuffer); fp++)
188         if (outbuffer[fp] == '\n') break;
189     fp++;
190     ok(fgets(buffer,256,file) !=0,"line 1 fgets failed unexpected in %s\n", IOMODE);
191     l = ftell(file);
192     ok(l == pl+fp,"line 1 ftell got %ld should be %d in %s\n", l, pl+fp, IOMODE);
193     ok(lstrlenA(buffer) == fp+ao,"line 1 fgets got size %d should be %d in %s\n",
194      lstrlenA(buffer), fp+ao, IOMODE);
195     /* test a seek back across the buffer boundary */
196     l = pl;
197     ok(fseek(file,l,SEEK_SET)==0,"seek failure in %s\n", IOMODE);
198     l = ftell(file);
199     ok(l == pl,"ftell after seek got %ld should be %d in %s\n", l, pl, IOMODE);
200     ok(fgets(buffer,256,file) !=0,"second read of line 1 fgets failed unexpected in %s\n", IOMODE);
201     l = ftell(file);
202     ok(l == pl+fp,"second read of line 1 ftell got %ld should be %d in %s\n", l, pl+fp, IOMODE);
203     ok(lstrlenA(buffer) == fp+ao,"second read of line 1 fgets got size %d should be %d in %s\n",
204      lstrlenA(buffer), fp+ao, IOMODE);
205     ok(fgets(buffer,256,file) !=0,"line 2 fgets failed unexpected in %s\n", IOMODE);
206     fp += 2;
207     l = ftell(file);
208     ok(l == pl+fp,"line 2 ftell got %ld should be %d in %s\n", l, pl+fp, IOMODE);
209     ok(lstrlenA(buffer) == 2+ao,"line 2 fgets got size %d should be %d in %s\n",
210      lstrlenA(buffer), 2+ao, IOMODE);
211     
212     /* test fread across buffer boundary */
213     rewind(file);
214     ok(ftell(file) == 0,"Did not start at beginning of file in %s\n", IOMODE);
215     ok(fgets(buffer,BUFSIZ-6,file) !=0,"padding line fgets failed unexpected in %s\n", IOMODE);
216     j=strlen(outbuffer);
217     i=fread(buffer,1,BUFSIZ+strlen(outbuffer),file);
218     ok(i==BUFSIZ+j,"fread failed, expected %d got %d in %s\n", BUFSIZ+j, i, IOMODE);
219     l = ftell(file);
220     ok(l == pl+j-(ao*4)-5,"ftell after fread got %ld should be %d in %s\n", l, pl+j-(ao*4)-5, IOMODE);
221     for (m=0; m<3; m++)
222         ok(buffer[m]==padbuffer[m+(BUFSIZ-4)%strlen(padbuffer)],"expected %c got %c\n", padbuffer[m], buffer[m]);
223     m+=BUFSIZ+2+ao;
224     optr = outbuffer;
225     for (; m<i; m++) {
226         ok(buffer[m]==*optr,"char %d expected %c got %c in %s\n", m, *optr, buffer[m], IOMODE);
227         optr++;
228         if (ao && (*optr == '\r'))
229             optr++;
230     }
231     /* fread should return the requested number of bytes if available */
232     rewind(file);
233     ok(ftell(file) == 0,"Did not start at beginning of file in %s\n", IOMODE);
234     ok(fgets(buffer,BUFSIZ-6,file) !=0,"padding line fgets failed unexpected in %s\n", IOMODE);
235     j = fp+10;
236     i=fread(buffer,1,j,file);
237     ok(i==j,"fread failed, expected %d got %d in %s\n", j, i, IOMODE);
238     /* test fread eof */
239     ok(fseek(file,0,SEEK_END)==0,"seek failure in %s\n", IOMODE);
240     ok(feof(file)==0,"feof failure in %s\n", IOMODE);
241     ok(fread(buffer,1,1,file)==0,"fread failure in %s\n", IOMODE);
242     ok(feof(file)!=0,"feof failure in %s\n", IOMODE);
243     ok(fseek(file,-3,SEEK_CUR)==0,"seek failure in %s\n", IOMODE);
244     ok(feof(file)==0,"feof failure in %s\n", IOMODE);
245     ok(fread(buffer,2,1,file)==1,"fread failed in %s\n", IOMODE);
246     ok(feof(file)==0,"feof failure in %s\n", IOMODE);
247     ok(fread(buffer,2,1,file)==0,"fread failure in %s\n",IOMODE);
248     ok(feof(file)!=0,"feof failure in %s\n", IOMODE);
249     
250     /* test some additional functions */
251     rewind(file);
252     ok(ftell(file) == 0,"Did not start at beginning of file in %s\n", IOMODE);
253     ok(fgets(buffer,2*BUFSIZ+256,file) !=0,"padding line fgets failed unexpected in %s\n", IOMODE);
254     i = _getw(file);
255     ip = (const int *)outbuffer;
256     ok(i == *ip,"_getw failed, expected %08x got %08x in %s\n", *ip, i, IOMODE);
257     for (fp=0; fp<strlen(outbuffer); fp++)
258         if (outbuffer[fp] == '\n') break;
259     fp++;
260     /* this will cause the next _getw to cross carriage return characters */
261     ok(fgets(buffer,fp-6,file) !=0,"line 1 fgets failed unexpected in %s\n", IOMODE);
262     for (i=0, j=0; i<6; i++) {
263         if (ao==0 || outbuffer[fp-3+i] != '\r')
264             buffer[j++] = outbuffer[fp-3+i];
265     }
266     i = _getw(file);
267     ip = (int *)buffer;
268     ok(i == *ip,"_getw failed, expected %08x got %08x in %s\n", *ip, i, IOMODE);
269
270     fclose (file);
271     unlink ("fdopen.tst");
272 }
273
274 static void test_asciimode(void)
275 {
276     FILE *fp;
277     char buf[64];
278
279     /* Simple test of CR CR LF handling.  Test both fgets and fread code paths, they're different! */
280     fp = fopen("ascii.tst", "wb");
281     fputs("\r\r\n", fp);
282     fclose(fp);
283     fp = fopen("ascii.tst", "rt");
284     ok(fgets(buf, sizeof(buf), fp) != NULL, "fgets\n");
285     ok(0 == strcmp(buf, "\r\n"), "CR CR LF not read as CR LF\n");
286     rewind(fp);
287     ok((fread(buf, 1, sizeof(buf), fp) == 2) && (0 == strcmp(buf, "\r\n")), "CR CR LF not read as CR LF\n");
288     fclose(fp);
289     unlink("ascii.tst");
290
291     /* Simple test of foo ^Z [more than one block] bar handling */
292     fp = fopen("ascii.tst", "wb");
293     fputs("foo\032", fp);  /* foo, logical EOF, ... */
294     fseek(fp, 65536L, SEEK_SET); /* ... more than MSVCRT_BUFSIZ, ... */
295     fputs("bar", fp); /* ... bar */
296     fclose(fp);
297     fp = fopen("ascii.tst", "rt");
298     ok(fgets(buf, sizeof(buf), fp) != NULL, "fgets foo\n");
299     ok(0 == strcmp(buf, "foo"), "foo ^Z not read as foo by fgets\n");
300     ok(fgets(buf, sizeof(buf), fp) == NULL, "fgets after logical EOF\n");
301     rewind(fp);
302     ok((fread(buf, 1, sizeof(buf), fp) == 3) && (0 == strcmp(buf, "foo")), "foo ^Z not read as foo by fread\n");
303     ok((fread(buf, 1, sizeof(buf), fp) == 0), "fread after logical EOF\n");
304     fclose(fp);
305
306     unlink("ascii.tst");
307 }
308
309 static WCHAR* AtoW( const char* p )
310 {
311     WCHAR* buffer;
312     DWORD len = MultiByteToWideChar( CP_ACP, 0, p, -1, NULL, 0 );
313     buffer = malloc( len * sizeof(WCHAR) );
314     MultiByteToWideChar( CP_ACP, 0, p, -1, buffer, len );
315     return buffer;
316 }
317
318 static void test_fgetc( void )
319 {
320   char* tempf;
321   FILE *tempfh;
322   int  ich=0xe0, ret;
323
324   tempf=_tempnam(".","wne");
325   tempfh = fopen(tempf,"w+");
326   fputc(ich, tempfh);
327   fputc(ich, tempfh);
328   rewind(tempfh);
329   ret = fgetc(tempfh);
330   ok(ich == ret, "First fgetc expected %x got %x\n", ich, ret);
331   ret = fgetc(tempfh);
332   ok(ich == ret, "Second fgetc expected %x got %x\n", ich, ret);
333   fclose(tempfh);
334   unlink(tempf);
335 }
336
337 static void test_fgetwc( void )
338 {
339 #define LLEN 512
340
341   char* tempf;
342   FILE *tempfh;
343   static const char mytext[]= "This is test_fgetwc\r\n";
344   WCHAR wtextW[BUFSIZ+LLEN+1];
345   WCHAR *mytextW = NULL, *aptr, *wptr;
346   BOOL diff_found = FALSE;
347   int j;
348   unsigned int i;
349   long l;
350
351   tempf=_tempnam(".","wne");
352   tempfh = fopen(tempf,"wb");
353   j = 'a';
354   /* pad to almost the length of the internal buffer */
355   for (i=0; i<BUFSIZ-4; i++)
356     fputc(j,tempfh);
357   j = '\r';
358   fputc(j,tempfh);
359   j = '\n';
360   fputc(j,tempfh);
361   fputs(mytext,tempfh);
362   fclose(tempfh);
363   /* in text mode, getws/c expects multibyte characters */
364   /*currently Wine only supports plain ascii, and that is all that is tested here */
365   tempfh = fopen(tempf,"rt"); /* open in TEXT mode */
366   fgetws(wtextW,LLEN,tempfh);
367   l=ftell(tempfh);
368   ok(l==BUFSIZ-2, "ftell expected %d got %ld\n", BUFSIZ-2, l);
369   fgetws(wtextW,LLEN,tempfh);
370   l=ftell(tempfh);
371   ok(l==BUFSIZ-2+strlen(mytext), "ftell expected %d got %ld\n",
372    BUFSIZ-2+strlen(mytext), l);
373   mytextW = AtoW (mytext);
374   aptr = mytextW;
375   wptr = wtextW;
376   for (i=0; i<strlen(mytext)-2; i++, aptr++, wptr++)
377     {
378       diff_found |= (*aptr != *wptr);
379     }
380   ok(!(diff_found), "fgetwc difference found in TEXT mode\n");
381   ok(*wptr == '\n', "Carriage return was not skipped\n");
382   fclose(tempfh);
383   unlink(tempf);
384   
385   tempfh = fopen(tempf,"wb");
386   j = 'a';
387   /* pad to almost the length of the internal buffer. Use an odd number of bytes
388      to test that we can read wchars that are split across the internal buffer
389      boundary */
390   for (i=0; i<BUFSIZ-3-strlen(mytext)*sizeof(WCHAR); i++)
391     fputc(j,tempfh);
392   j = '\r';
393   fputwc(j,tempfh);
394   j = '\n';
395   fputwc(j,tempfh);
396   fputws(wtextW,tempfh);
397   fputws(wtextW,tempfh);
398   fclose(tempfh);
399   /* in binary mode, getws/c expects wide characters */
400   tempfh = fopen(tempf,"rb"); /* open in BINARY mode */
401   j=(BUFSIZ-2)/sizeof(WCHAR)-strlen(mytext);
402   fgetws(wtextW,j,tempfh);
403   l=ftell(tempfh);
404   j=(j-1)*sizeof(WCHAR);
405   ok(l==j, "ftell expected %d got %ld\n", j, l);
406   i=fgetc(tempfh);
407   ok(i=='a', "fgetc expected %d got %d\n", 0x61, i);
408   l=ftell(tempfh);
409   j++;
410   ok(l==j, "ftell expected %d got %ld\n", j, l);
411   fgetws(wtextW,3,tempfh);
412   ok(wtextW[0]=='\r',"expected carriage return got %04hx\n", wtextW[0]);
413   ok(wtextW[1]=='\n',"expected newline got %04hx\n", wtextW[1]);
414   l=ftell(tempfh);
415   j += 4;
416   ok(l==j, "ftell expected %d got %ld\n", j, l);
417   for(i=0; i<strlen(mytext); i++)
418     wtextW[i] = 0;
419   /* the first time we get the string, it should be entirely within the local buffer */
420   fgetws(wtextW,LLEN,tempfh);
421   l=ftell(tempfh);
422   j += (strlen(mytext)-1)*sizeof(WCHAR);
423   ok(l==j, "ftell expected %d got %ld\n", j, l);
424   diff_found = FALSE;
425   aptr = mytextW;
426   wptr = wtextW;
427   for (i=0; i<strlen(mytext)-2; i++, aptr++, wptr++)
428     {
429       ok(*aptr == *wptr, "Char %d expected %04hx got %04hx\n", i, *aptr, *wptr);
430       diff_found |= (*aptr != *wptr);
431     }
432   ok(!(diff_found), "fgetwc difference found in BINARY mode\n");
433   ok(*wptr == '\n', "Should get newline\n");
434   for(i=0; i<strlen(mytext); i++)
435     wtextW[i] = 0;
436   /* the second time we get the string, it should cross the local buffer boundary.
437      One of the wchars should be split across the boundary */
438   fgetws(wtextW,LLEN,tempfh);
439   diff_found = FALSE;
440   aptr = mytextW;
441   wptr = wtextW;
442   for (i=0; i<strlen(mytext)-2; i++, aptr++, wptr++)
443     {
444       ok(*aptr == *wptr, "Char %d expected %04hx got %04hx\n", i, *aptr, *wptr);
445       diff_found |= (*aptr != *wptr);
446     }
447   ok(!(diff_found), "fgetwc difference found in BINARY mode\n");
448   ok(*wptr == '\n', "Should get newline\n");
449
450   free(mytextW);
451   fclose(tempfh);
452   unlink(tempf);
453 }
454
455 static void test_ctrlz( void )
456 {
457   char* tempf;
458   FILE *tempfh;
459   static const char mytext[]= "This is test_ctrlz";
460   char buffer[256];
461   int i, j;
462   long l;
463
464   tempf=_tempnam(".","wne");
465   tempfh = fopen(tempf,"wb");
466   fputs(mytext,tempfh);
467   j = 0x1a; /* a ctrl-z character signals EOF in text mode */
468   fputc(j,tempfh);
469   j = '\r';
470   fputc(j,tempfh);
471   j = '\n';
472   fputc(j,tempfh);
473   j = 'a';
474   fputc(j,tempfh);
475   fclose(tempfh);
476   tempfh = fopen(tempf,"rt"); /* open in TEXT mode */
477   ok(fgets(buffer,256,tempfh) != 0,"fgets failed unexpected\n");
478   i=strlen(buffer);
479   j=strlen(mytext);
480   ok(i==j, "returned string length expected %d got %d\n", j, i);
481   j+=4; /* ftell should indicate the true end of file */
482   l=ftell(tempfh);
483   ok(l==j, "ftell expected %d got %ld\n", j, l);
484   ok(feof(tempfh), "did not get EOF\n");
485   fclose(tempfh);
486   
487   tempfh = fopen(tempf,"rb"); /* open in BINARY mode */
488   ok(fgets(buffer,256,tempfh) != 0,"fgets failed unexpected\n");
489   i=strlen(buffer);
490   j=strlen(mytext)+3; /* should get through newline */
491   ok(i==j, "returned string length expected %d got %d\n", j, i);
492   l=ftell(tempfh);
493   ok(l==j, "ftell expected %d got %ld\n", j, l);
494   ok(fgets(buffer,256,tempfh) != 0,"fgets failed unexpected\n");
495   i=strlen(buffer);
496   ok(i==1, "returned string length expected %d got %d\n", 1, i);
497   ok(feof(tempfh), "did not get EOF\n");
498   fclose(tempfh);
499   unlink(tempf);
500 }
501
502 static void test_file_put_get( void )
503 {
504   char* tempf;
505   FILE *tempfh;
506   static const char mytext[]=  "This is a test_file_put_get\n";
507   static const char dostext[]= "This is a test_file_put_get\r\n";
508   char btext[LLEN];
509   WCHAR wtextW[LLEN+1];
510   WCHAR *mytextW = NULL, *aptr, *wptr;
511   BOOL diff_found = FALSE;
512   unsigned int i;
513
514   tempf=_tempnam(".","wne");
515   tempfh = fopen(tempf,"wt"); /* open in TEXT mode */
516   fputs(mytext,tempfh);
517   fclose(tempfh);
518   tempfh = fopen(tempf,"rb"); /* open in TEXT mode */
519   fgets(btext,LLEN,tempfh);
520   ok( strlen(mytext) + 1 == strlen(btext),"TEXT/BINARY mode not handled for write\n");
521   ok( btext[strlen(mytext)-1] == '\r', "CR not written\n");
522   fclose(tempfh);
523   tempfh = fopen(tempf,"wb"); /* open in BINARY mode */
524   fputs(dostext,tempfh);
525   fclose(tempfh);
526   tempfh = fopen(tempf,"rt"); /* open in TEXT mode */
527   fgets(btext,LLEN,tempfh);
528   ok(strcmp(btext, mytext) == 0,"_O_TEXT read doesn't strip CR\n");
529   fclose(tempfh);
530   tempfh = fopen(tempf,"rb"); /* open in TEXT mode */
531   fgets(btext,LLEN,tempfh);
532   ok(strcmp(btext, dostext) == 0,"_O_BINARY read doesn't preserve CR\n");
533
534   fclose(tempfh);
535   tempfh = fopen(tempf,"rt"); /* open in TEXT mode */
536   fgetws(wtextW,LLEN,tempfh);
537   mytextW = AtoW (mytext);
538   aptr = mytextW;
539   wptr = wtextW;
540
541   for (i=0; i<strlen(mytext); i++, aptr++, wptr++)
542     {
543       diff_found |= (*aptr != *wptr);
544     }
545   ok(!(diff_found), "fgetwc doesn't strip CR in TEXT mode\n");
546   free(mytextW);
547   fclose(tempfh);
548   unlink(tempf);
549 }
550
551 static void test_file_write_read( void )
552 {
553   char* tempf;
554   int tempfd;
555   static const char mytext[]=  "This is test_file_write_read\nsecond line\n";
556   static const char dostext[]= "This is test_file_write_read\r\nsecond line\r\n";
557   char btext[LLEN];
558   int ret, i;
559
560   tempf=_tempnam(".","wne");
561   tempfd = _open(tempf,_O_CREAT|_O_TRUNC|_O_BINARY|_O_RDWR,
562                      _S_IREAD | _S_IWRITE);
563   ok( tempfd != -1,
564      "Can't open '%s': %d\n", tempf, errno); /* open in BINARY mode */
565   ok(_write(tempfd,dostext,strlen(dostext)) == lstrlenA(dostext),
566      "_write _O_BINARY bad return value\n");
567   _close(tempfd);
568   i = lstrlenA(mytext);
569   tempfd = _open(tempf,_O_RDONLY|_O_BINARY,0); /* open in BINARY mode */
570   ok(_read(tempfd,btext,i) == i,
571      "_read _O_BINARY got bad length\n");
572   ok( memcmp(dostext,btext,i) == 0,
573       "problems with _O_BINARY  _write / _read\n");
574   _close(tempfd);
575   tempfd = _open(tempf,_O_RDONLY|_O_TEXT); /* open in TEXT mode */
576   ok(_read(tempfd,btext,i) == i-1,
577      "_read _O_TEXT got bad length\n");
578   ok( memcmp(mytext,btext,i-1) == 0,
579       "problems with _O_BINARY _write / _O_TEXT _read\n");
580   _close(tempfd);
581   tempfd = _open(tempf,_O_CREAT|_O_TRUNC|_O_TEXT|_O_RDWR,
582                      _S_IREAD | _S_IWRITE);
583   ok( tempfd != -1,
584      "Can't open '%s': %d\n", tempf, errno); /* open in TEXT mode */
585   ok(_write(tempfd,mytext,strlen(mytext)) == lstrlenA(mytext),
586      "_write _O_TEXT bad return value\n");
587   _close(tempfd);
588   tempfd = _open(tempf,_O_RDONLY|_O_BINARY,0); /* open in BINARY mode */
589   ok(_read(tempfd,btext,LLEN) == lstrlenA(dostext),
590      "_read _O_BINARY got bad length\n");
591   ok( memcmp(dostext,btext,strlen(dostext)) == 0,
592       "problems with _O_TEXT _write / _O_BINARY _read\n");
593   ok( btext[strlen(dostext)-2] == '\r', "CR not written or read\n");
594   _close(tempfd);
595   tempfd = _open(tempf,_O_RDONLY|_O_TEXT); /* open in TEXT mode */
596   ok(_read(tempfd,btext,LLEN) == lstrlenA(mytext),
597      "_read _O_TEXT got bad length\n");
598   ok( memcmp(mytext,btext,strlen(mytext)) == 0,
599       "problems with _O_TEXT _write / _read\n");
600   _close(tempfd);
601
602   memset(btext, 0, LLEN);
603   tempfd = _open(tempf,_O_APPEND|_O_RDWR); /* open for APPEND in default mode */
604   ok(tell(tempfd) == 0, "bad position %lu expecting 0\n", tell(tempfd));
605   ok(_read(tempfd,btext,LLEN) == lstrlenA(mytext), "_read _O_APPEND got bad length\n");
606   ok( memcmp(mytext,btext,strlen(mytext)) == 0, "problems with _O_APPEND _read\n");
607   _close(tempfd);
608
609   /* Test reading only \n or \r */
610   tempfd = _open(tempf,_O_RDONLY|_O_TEXT); /* open in TEXT mode */
611   _lseek(tempfd, -1, FILE_END);
612   ret = _read(tempfd,btext,LLEN);
613   ok(ret == 1, "_read expected 1 got bad length: %d\n", ret);
614   _lseek(tempfd, -2, FILE_END);
615   ret = _read(tempfd,btext,LLEN);
616   ok(ret == 1 && *btext == '\n', "_read expected '\\n' got bad length: %d\n", ret);
617   _lseek(tempfd, -3, FILE_END);
618   ret = _read(tempfd,btext,2);
619   ok(ret == 1 && *btext == 'e', "_read expected 'e' got \"%.*s\" bad length: %d\n", ret, btext, ret);
620   ok(tell(tempfd) == 42, "bad position %lu expecting 42\n", tell(tempfd));
621   _close(tempfd);
622
623   ret = unlink(tempf);
624   ok( ret == 0 ,"Can't unlink '%s': %d\n", tempf, errno);
625
626   tempf=_tempnam(".","wne");
627   tempfd = _open(tempf,_O_CREAT|_O_TRUNC|_O_BINARY|_O_RDWR,0);
628   ok( tempfd != -1,
629      "Can't open '%s': %d\n", tempf, errno); /* open in BINARY mode */
630   ok(_write(tempfd,dostext,strlen(dostext)) == lstrlenA(dostext),
631      "_write _O_BINARY bad return value\n");
632   _close(tempfd);
633   tempfd = _open(tempf,_O_RDONLY|_O_BINARY,0); /* open in BINARY mode */
634   ok(_read(tempfd,btext,LLEN) == lstrlenA(dostext),
635      "_read _O_BINARY got bad length\n");
636   ok( memcmp(dostext,btext,strlen(dostext)) == 0,
637       "problems with _O_BINARY _write / _read\n");
638   ok( btext[strlen(dostext)-2] == '\r', "CR not written or read\n");
639   _close(tempfd);
640   tempfd = _open(tempf,_O_RDONLY|_O_TEXT); /* open in TEXT mode */
641   ok(_read(tempfd,btext,LLEN) == lstrlenA(mytext),
642      "_read _O_TEXT got bad length\n");
643   ok( memcmp(mytext,btext,strlen(mytext)) == 0,
644       "problems with _O_BINARY _write / _O_TEXT _read\n");
645   _close(tempfd);
646
647    ret =_chmod (tempf, _S_IREAD | _S_IWRITE);
648   ok( ret == 0,
649      "Can't chmod '%s' to read-write: %d\n", tempf, errno);
650   ret = unlink(tempf);
651   ok( ret == 0 ,"Can't unlink '%s': %d\n", tempf, errno);
652 }
653
654 static void test_file_inherit_child(const char* fd_s)
655 {
656     int fd = atoi(fd_s);
657     char buffer[32];
658     int ret;
659
660     ret =write(fd, "Success", 8);
661     ok( ret == 8, "Couldn't write in child process on %d (%s)\n", fd, strerror(errno));
662     lseek(fd, 0, SEEK_SET);
663     ok(read(fd, buffer, sizeof (buffer)) == 8, "Couldn't read back the data\n");
664     ok(memcmp(buffer, "Success", 8) == 0, "Couldn't read back the data\n");
665 }
666
667 static void test_file_inherit_child_no(const char* fd_s)
668 {
669     int fd = atoi(fd_s);
670     int ret;
671
672     ret = write(fd, "Success", 8);
673     ok( ret == -1 && errno == EBADF, 
674        "Wrong write result in child process on %d (%s)\n", fd, strerror(errno));
675 }
676  
677 static void test_file_inherit( const char* selfname )
678 {
679     int                 fd;
680     const char*         arg_v[5];
681     char                buffer[16];
682
683     fd = open ("fdopen.tst", O_CREAT | O_RDWR | O_BINARY, _S_IREAD |_S_IWRITE);
684     ok(fd != -1, "Couldn't create test file\n");
685     arg_v[0] = selfname;
686     arg_v[1] = "tests/file.c";
687     arg_v[2] = "inherit";
688     arg_v[3] = buffer; sprintf(buffer, "%d", fd);
689     arg_v[4] = 0;
690     _spawnvp(_P_WAIT, selfname, arg_v);
691     ok(tell(fd) == 8, "bad position %lu expecting 8\n", tell(fd));
692     lseek(fd, 0, SEEK_SET);
693     ok(read(fd, buffer, sizeof (buffer)) == 8 && memcmp(buffer, "Success", 8) == 0, "Couldn't read back the data\n");
694     close (fd);
695     ok(unlink("fdopen.tst") == 0, "Couldn't unlink\n");
696     
697     fd = open ("fdopen.tst", O_CREAT | O_RDWR | O_BINARY | O_NOINHERIT, _S_IREAD |_S_IWRITE);
698     ok(fd != -1, "Couldn't create test file\n");
699     arg_v[0] = selfname;
700     arg_v[1] = "tests/file.c";
701     arg_v[2] = "inherit_no";
702     arg_v[3] = buffer; sprintf(buffer, "%d", fd);
703     arg_v[4] = 0;
704     _spawnvp(_P_WAIT, selfname, arg_v);
705     ok(tell(fd) == 0, "bad position %lu expecting 0\n", tell(fd));
706     ok(read(fd, buffer, sizeof (buffer)) == 0, "Found unexpected data (%s)\n", buffer);
707     close (fd);
708     ok(unlink("fdopen.tst") == 0, "Couldn't unlink\n");
709 }
710
711 static void test_tmpnam( void )
712 {
713   char name[MAX_PATH] = "abc";
714   char *res;
715
716   res = tmpnam(NULL);
717   ok(res != NULL, "tmpnam returned NULL\n");
718   ok(res[0] == '\\', "first character is not a backslash\n");
719   ok(strchr(res+1, '\\') == 0, "file not in the root directory\n");
720   ok(res[strlen(res)-1] == '.', "first call - last character is not a dot\n");
721
722   res = tmpnam(name);
723   ok(res != NULL, "tmpnam returned NULL\n");
724   ok(res == name, "supplied buffer was not used\n");
725   ok(res[0] == '\\', "first character is not a backslash\n");
726   ok(strchr(res+1, '\\') == 0, "file not in the root directory\n");
727   ok(res[strlen(res)-1] != '.', "second call - last character is a dot\n");
728 }
729
730 static void test_chsize( void )
731 {
732     int fd;
733     long cur, pos, count;
734     char temptext[] = "012345678";
735     char *tempfile = _tempnam( ".", "tst" );
736     
737     ok( tempfile != NULL, "Couldn't create test file: %s\n", tempfile );
738
739     fd = _open( tempfile, _O_CREAT|_O_TRUNC|_O_RDWR, _S_IREAD|_S_IWRITE );
740     ok( fd > 0, "Couldn't open test file\n" );
741
742     count = _write( fd, temptext, sizeof(temptext) );
743     ok( count > 0, "Couldn't write to test file\n" );
744
745     /* get current file pointer */
746     cur = _lseek( fd, 0, SEEK_CUR );
747
748     /* make the file smaller */
749     ok( _chsize( fd, sizeof(temptext) / 2 ) == 0, "_chsize() failed\n" );
750
751     pos = _lseek( fd, 0, SEEK_CUR );
752     ok( cur == pos, "File pointer changed from: %ld to: %ld\n", cur, pos );
753     ok( _filelength( fd ) == sizeof(temptext) / 2, "Wrong file size\n" );
754
755     /* enlarge the file */
756     ok( _chsize( fd, sizeof(temptext) * 2 ) == 0, "_chsize() failed\n" ); 
757
758     pos = _lseek( fd, 0, SEEK_CUR );
759     ok( cur == pos, "File pointer changed from: %ld to: %ld\n", cur, pos );
760     ok( _filelength( fd ) == sizeof(temptext) * 2, "Wrong file size\n" );
761
762     _close( fd );
763     _unlink( tempfile );
764 }
765
766 static void test_fopen_fclose_fcloseall( void )
767 {
768     char fname1[] = "empty1";
769     char fname2[] = "empty2";
770     char fname3[] = "empty3";
771     FILE *stream1, *stream2, *stream3, *stream4;
772     int ret, numclosed;
773
774     /* testing fopen() */
775     stream1 = fopen(fname1, "w+");
776     ok(stream1 != NULL, "The file '%s' was not opened\n", fname1);
777     stream2 = fopen(fname2, "w ");
778     ok(stream2 != NULL, "The file '%s' was not opened\n", fname2 );
779     _unlink(fname3);
780     stream3 = fopen(fname3, "r");
781     ok(stream3 == NULL, "The file '%s' shouldn't exist before\n", fname3 );
782     stream3 = fopen(fname3, "w+");
783     ok(stream3 != NULL, "The file '%s' should be opened now\n", fname3 );
784     errno = 0xfaceabad;
785     stream4 = fopen("", "w+");
786     ok(stream4 == NULL && (errno == EINVAL || errno == ENOENT),
787        "filename is empty, errno = %d (expected 2 or 22)\n", errno);
788     errno = 0xfaceabad;
789     stream4 = fopen(NULL, "w+");
790     ok(stream4 == NULL && (errno == EINVAL || errno == ENOENT), 
791        "filename is NULL, errno = %d (expected 2 or 22)\n", errno);
792
793     /* testing fclose() */
794     ret = fclose(stream2);
795     ok(ret == 0, "The file '%s' was not closed\n", fname2);
796     ret = fclose(stream3);
797     ok(ret == 0, "The file '%s' was not closed\n", fname3);
798     ret = fclose(stream2);
799     ok(ret == EOF, "Closing file '%s' returned %d\n", fname2, ret);
800     ret = fclose(stream3);
801     ok(ret == EOF, "Closing file '%s' returned %d\n", fname3, ret);
802
803     /* testing fcloseall() */
804     numclosed = _fcloseall();
805     /* fname1 should be closed here */
806     ok(numclosed == 1, "Number of files closed by fcloseall(): %u\n", numclosed);
807     numclosed = _fcloseall();
808     ok(numclosed == 0, "Number of files closed by fcloseall(): %u\n", numclosed);
809
810     ok(_unlink(fname1) == 0, "Couldn't unlink file named '%s'\n", fname1);
811     ok(_unlink(fname2) == 0, "Couldn't unlink file named '%s'\n", fname2);
812     ok(_unlink(fname3) == 0, "Couldn't unlink file named '%s'\n", fname3);
813 }
814
815 static void test_get_osfhandle(void)
816 {
817     int fd;
818     char fname[] = "t_get_osfhanle";
819     DWORD bytes_written;
820     HANDLE handle;
821
822     fd = _sopen(fname, _O_CREAT|_O_RDWR, _SH_DENYRW, _S_IREAD | _S_IWRITE);
823     handle = (HANDLE)_get_osfhandle(fd);
824     WriteFile(handle, "bar", 3, &bytes_written, NULL);
825     _close(fd);
826     fd = _open(fname, _O_RDONLY, 0);
827     ok(fd != -1, "Coudn't open '%s' after _get_osfhanle()\n", fname);
828
829     _close(fd);
830     _unlink(fname);
831 }
832
833 static void test_setmaxstdio(void)
834 {
835     ok(2048 == _setmaxstdio(2048),"_setmaxstdio returned %d instead of 2048\n",_setmaxstdio(2048));
836     ok(-1 == _setmaxstdio(2049),"_setmaxstdio returned %d instead of -1\n",_setmaxstdio(2049));
837 }
838
839 static void test_stat(void)
840 {
841     int fd;
842     int pipes[2];
843     struct stat buf;
844
845     /* Tests for a file */
846     fd = open("stat.tst", O_WRONLY | O_CREAT | O_BINARY, _S_IREAD |_S_IWRITE);
847     if (fd >= 0)
848     {
849         if (fstat(fd, &buf) == 0)
850         {
851             if ((buf.st_mode & _S_IFMT) == _S_IFREG)
852             {
853                 ok(buf.st_dev == 0, "st_dev is %d, expected 0\n", buf.st_dev);
854                 ok(buf.st_dev == buf.st_rdev, "st_dev (%d) and st_rdev (%d) differ\n",
855                     buf.st_dev, buf.st_rdev);
856                 ok(buf.st_nlink == 1, "st_nlink is %d, expected 1\n",
857                     buf.st_nlink);
858                 ok(buf.st_size == 0, "st_size is %d, expected 0\n",
859                     buf.st_size);
860             }
861             else
862                 skip("file is not a file?\n");
863         }
864         else
865             skip("fstat failed, errno %d\n", errno);
866         close(fd);
867         remove("stat.tst");
868     }
869     else
870         skip("open failed with errno %d\n", errno);
871
872     /* Tests for a char device */
873     if (_dup2(0, 10) == 0)
874     {
875         if (fstat(10, &buf) == 0)
876         {
877             if (buf.st_mode == _S_IFCHR)
878             {
879                 ok(buf.st_dev == 10, "st_dev is %d, expected 10\n", buf.st_dev);
880                 ok(buf.st_rdev == 10, "st_rdev is %d, expected 10\n", buf.st_rdev);
881                 ok(buf.st_nlink == 1, "st_nlink is %d, expected 1\n", buf.st_nlink);
882             }
883             else
884                 skip("stdin is not a char device?\n");
885         }
886         else
887             skip("fstat failed with errno %d\n", errno);
888         close(10);
889     }
890     else
891         skip("_dup2 failed with errno %d\n", errno);
892
893     /* Tests for pipes */
894     if (_pipe(pipes, 1024, O_BINARY) == 0)
895     {
896         if (fstat(pipes[0], &buf) == 0)
897         {
898             if (buf.st_mode == _S_IFIFO)
899             {
900                 ok(buf.st_dev == pipes[0], "st_dev is %d, expected %d\n",
901                     buf.st_dev, pipes[0]);
902                 ok(buf.st_rdev == pipes[0], "st_rdev is %d, expected %d\n",
903                     buf.st_rdev, pipes[0]);
904                 ok(buf.st_nlink == 1, "st_nlink is %d, expected 1\n",
905                     buf.st_nlink);
906             }
907             else
908                 skip("pipe() didn't make a pipe?\n");
909         }
910         else
911             skip("fstat failed with errno %d\n", errno);
912         close(pipes[0]);
913         close(pipes[1]);
914     }
915     else
916         skip("pipe failed with errno %d\n", errno);
917 }
918
919 static const char* pipe_string="Hello world";
920
921 /* How many messages to transfer over the pipe */
922 #define N_TEST_MESSAGES 3
923
924 static void test_pipes_child(int argc, char** args)
925 {
926     int fd;
927     int nwritten;
928     int i;
929
930     if (argc < 5)
931     {
932         ok(0, "not enough parameters: %d\n", argc);
933         return;
934     }
935
936     fd=atoi(args[3]);
937     ok(close(fd) == 0, "unable to close %d: %d\n", fd, errno);
938
939     fd=atoi(args[4]);
940
941     for (i=0; i<N_TEST_MESSAGES; i++) {
942        nwritten=write(fd, pipe_string, strlen(pipe_string));
943        ok(nwritten == strlen(pipe_string), "i %d, expected to write %d bytes, wrote %d\n", i, strlen(pipe_string), nwritten);
944        /* let other process wake up so they can show off their "keep reading until EOF" behavior */
945        if (i < N_TEST_MESSAGES-1)
946            Sleep(100);
947     }
948
949     ok(close(fd) == 0, "unable to close %d: %d\n", fd, errno);
950 }
951
952 static void test_pipes(const char* selfname)
953 {
954     int pipes[2];
955     char str_fdr[12], str_fdw[12];
956     FILE* file;
957     const char* arg_v[6];
958     char buf[4096];
959     char expected[4096];
960     int r;
961     int i;
962
963     /* Test reading from a pipe with read() */
964     if (_pipe(pipes, 1024, O_BINARY) < 0)
965     {
966         ok(0, "pipe failed with errno %d\n", errno);
967         return;
968     }
969
970     arg_v[0] = selfname;
971     arg_v[1] = "tests/file.c";
972     arg_v[2] = "pipes";
973     arg_v[3] = str_fdr; sprintf(str_fdr, "%d", pipes[0]);
974     arg_v[4] = str_fdw; sprintf(str_fdw, "%d", pipes[1]);
975     arg_v[5] = NULL;
976     proc_handles[0] = (HANDLE)_spawnvp(_P_NOWAIT, selfname, arg_v);
977     ok(close(pipes[1]) == 0, "unable to close %d: %d\n", pipes[1], errno);
978
979     for (i=0; i<N_TEST_MESSAGES; i++) {
980        r=read(pipes[0], buf, sizeof(buf)-1);
981        ok(r == strlen(pipe_string), "i %d, expected to read %d bytes, got %d\n", i, strlen(pipe_string)+1, r);
982        if (r > 0)
983            buf[r]='\0';
984        ok(strcmp(buf, pipe_string) == 0, "expected to read '%s', got '%s'\n", pipe_string, buf);
985    }
986
987     r=read(pipes[0], buf, sizeof(buf)-1);
988     ok(r == 0, "expected to read 0 bytes, got %d\n", r);
989     ok(close(pipes[0]) == 0, "unable to close %d: %d\n", pipes[0], errno);
990
991     /* Test reading from a pipe with fread() */
992     if (_pipe(pipes, 1024, O_BINARY) < 0)
993     {
994         ok(0, "pipe failed with errno %d\n", errno);
995         return;
996     }
997
998     arg_v[0] = selfname;
999     arg_v[1] = "tests/file.c";
1000     arg_v[2] = "pipes";
1001     arg_v[3] = str_fdr; sprintf(str_fdr, "%d", pipes[0]);
1002     arg_v[4] = str_fdw; sprintf(str_fdw, "%d", pipes[1]);
1003     arg_v[5] = NULL;
1004     proc_handles[1] = (HANDLE)_spawnvp(_P_NOWAIT, selfname, arg_v);
1005     ok(close(pipes[1]) == 0, "unable to close %d: %d\n", pipes[1], errno);
1006     file=fdopen(pipes[0], "r");
1007
1008     /* In blocking mode, fread will keep calling read() until it gets
1009      * enough bytes, or EOF, even on Unix.  (If this were a Unix terminal
1010      * in cooked mode instead of a pipe, it would also stop on EOL.)
1011      */
1012     expected[0] = 0;
1013     for (i=0; i<N_TEST_MESSAGES; i++)
1014        strcat(expected, pipe_string);
1015     r=fread(buf, 1, sizeof(buf)-1, file);
1016     ok(r == strlen(expected), "fread() returned %d instead of %d: ferror=%d\n", r, strlen(expected), ferror(file));
1017     if (r > 0)
1018        buf[r]='\0';
1019     ok(strcmp(buf, expected) == 0, "got '%s' expected '%s'\n", buf, expected);
1020
1021     /* Let child close the file before we read, so we can sense EOF reliably */
1022     Sleep(100);
1023     r=fread(buf, 1, sizeof(buf)-1, file);
1024     ok(r == 0, "fread() returned %d instead of 0\n", r);
1025     ok(ferror(file) == 0, "got ferror() = %d\n", ferror(file));
1026     ok(feof(file), "feof() is false!\n");
1027
1028     ok(fclose(file) == 0, "unable to close the pipe: %d\n", errno);
1029 }
1030
1031 START_TEST(file)
1032 {
1033     int arg_c;
1034     char** arg_v;
1035
1036     arg_c = winetest_get_mainargs( &arg_v );
1037
1038     /* testing low-level I/O */
1039     if (arg_c >= 3)
1040     {
1041         if (strcmp(arg_v[2], "inherit") == 0)
1042             test_file_inherit_child(arg_v[3]);
1043         else if (strcmp(arg_v[2], "inherit_no") == 0)
1044             test_file_inherit_child_no(arg_v[3]);
1045         else if (strcmp(arg_v[2], "pipes") == 0)
1046             test_pipes_child(arg_c, arg_v);
1047         else
1048             ok(0, "invalid argument '%s'\n", arg_v[2]);
1049         return;
1050     }
1051     test_file_inherit(arg_v[0]);
1052     test_file_write_read();
1053     test_chsize();
1054     test_stat();
1055
1056     /* testing stream I/O */
1057     test_fdopen();
1058     test_fopen_fclose_fcloseall();
1059     test_fileops();
1060     test_asciimode();
1061     test_readmode(FALSE); /* binary mode */
1062     test_readmode(TRUE);  /* ascii mode */
1063     test_fgetc();
1064     test_fgetwc();
1065     test_ctrlz();
1066     test_file_put_get();
1067     test_tmpnam();
1068     test_get_osfhandle();
1069     test_setmaxstdio();
1070     test_pipes(arg_v[0]);
1071
1072     /* Wait for the (_P_NOWAIT) spawned processes to finish to make sure the report
1073      * file contains lines in the correct order
1074      */
1075     WaitForMultipleObjects(sizeof(proc_handles)/sizeof(proc_handles[0]), proc_handles, TRUE, 5000);
1076 }