crypt32: Add additional path for Solaris 11 Express.
[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, c = EOF; i < sizeof(outbuffer); i++)
134         {
135             ok((c = 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((c = 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((c = 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     c= fgetc(fp);
362     fseek(fp,0,SEEK_CUR);
363     for(i=1; i<10; i++) {
364         ok((j = ftell(fp)) == i*3, "ftell fails in TEXT mode\n");
365         fseek(fp,0,SEEK_CUR);
366         ok((c = fgetc(fp)) == '0'+ i, "fgetc after fseek failed in line %d\n", i);
367         c= fgetc(fp);
368     }
369     /* Show that fseek doesn't skip \\r !*/
370     rewind(fp);
371     c= fgetc(fp);
372     fseek(fp, 2 ,SEEK_CUR);
373     for(i=1; i<10; i++) {
374         ok((c = fgetc(fp)) == '0'+ i, "fgetc after fseek with pos Offset failed in line %d\n", i);
375         fseek(fp, 2 ,SEEK_CUR);
376     }
377     fseek(fp, 9*3 ,SEEK_SET);
378     c = fgetc(fp);
379     fseek(fp, -4 ,SEEK_CUR);
380     for(i= 8; i>=0; i--) {
381         ok((c = fgetc(fp)) == '0'+ i, "fgetc after fseek with neg Offset failed in line %d\n", i);
382         fseek(fp, -4 ,SEEK_CUR);
383     }
384     /* Show what happens if fseek positions filepointer on \\r */
385     fclose(fp);
386     fp = fopen("ascii.tst", "r");
387     fseek(fp, 3 ,SEEK_SET);
388     ok((c = fgetc(fp)) == '1', "fgetc fails to read next char when positioned on \\r\n");
389     fclose(fp);
390
391     unlink("ascii.tst");
392 }
393
394 static void test_asciimode2(void)
395 {
396     /* Error sequence from one app was getchar followed by small fread
397      * with one \r removed had last byte of buffer filled with
398      * next byte of *unbuffered* data rather than next byte from buffer
399      * Test case is a short string of one byte followed by a newline
400      * followed by filler to fill out the sector, then a sector of
401      * some different byte.
402      */
403
404     FILE *fp;
405     char ibuf[4];
406     int i;
407     static const char obuf[] =
408 "00\n"
409 "000000000000000000000000000000000000000000000000000000000000000000000000000000\n"
410 "000000000000000000000000000000000000000000000000000000000000000000000000000000\n"
411 "000000000000000000000000000000000000000000000000000000000000000000000000000000\n"
412 "000000000000000000000000000000000000000000000000000000000000000000000000000000\n"
413 "000000000000000000000000000000000000000000000000000000000000000000000000000000\n"
414 "000000000000000000000000000000000000000000000000000000000000000000000000000000\n"
415 "000000000000000000\n"
416 "1111111111111111111";
417
418     fp = fopen("ascii2.tst", "wt");
419     fwrite(obuf, 1, sizeof(obuf), fp);
420     fclose(fp);
421
422     fp = fopen("ascii2.tst", "rt");
423     ok(getc(fp) == '0', "first char not 0\n");
424     memset(ibuf, 0, sizeof(ibuf));
425     i = fread(ibuf, 1, sizeof(ibuf), fp);
426     ok(i == sizeof(ibuf), "fread i %d != sizeof(ibuf)\n", i);
427     ok(0 == strncmp(ibuf, obuf+1, sizeof(ibuf)), "ibuf != obuf\n");
428     fclose(fp);
429     unlink("ascii2.tst");
430 }
431
432 static WCHAR* AtoW( const char* p )
433 {
434     WCHAR* buffer;
435     DWORD len = MultiByteToWideChar( CP_ACP, 0, p, -1, NULL, 0 );
436     buffer = malloc( len * sizeof(WCHAR) );
437     MultiByteToWideChar( CP_ACP, 0, p, -1, buffer, len );
438     return buffer;
439 }
440
441 /* Test reading in text mode when the 512'th character read is \r*/
442 static void test_readboundary(void)
443 {
444   FILE *fp;
445   char buf[513], rbuf[513];
446   int i, j;
447   for (i = 0; i < 511; i++)
448     {
449       j = (i%('~' - ' ')+ ' ');
450       buf[i] = j;
451     }
452   buf[511] = '\n';
453   buf[512] =0;
454   fp = fopen("boundary.tst", "wt");
455   fwrite(buf, 512,1,fp);
456   fclose(fp);
457   fp = fopen("boundary.tst", "rt");
458   for(i=0; i<512; i++)
459     {
460       fseek(fp,0 , SEEK_CUR);
461       rbuf[i] = fgetc(fp);
462     }
463   rbuf[512] =0;
464   fclose(fp);
465   unlink("boundary.tst");
466
467   ok(strcmp(buf, rbuf) == 0,"CRLF on buffer boundary failure\n");
468   }
469
470 static void test_fgetc( void )
471 {
472   char* tempf;
473   FILE *tempfh;
474   int  ich=0xe0, ret;
475
476   tempf=_tempnam(".","wne");
477   tempfh = fopen(tempf,"w+");
478   fputc(ich, tempfh);
479   fputc(ich, tempfh);
480   rewind(tempfh);
481   ret = fgetc(tempfh);
482   ok(ich == ret, "First fgetc expected %x got %x\n", ich, ret);
483   ret = fgetc(tempfh);
484   ok(ich == ret, "Second fgetc expected %x got %x\n", ich, ret);
485   fclose(tempfh);
486   tempfh = fopen(tempf,"wt");
487   fputc('\n', tempfh);
488   fclose(tempfh);
489   tempfh = fopen(tempf,"wt");
490   setbuf(tempfh, NULL);
491   ret = fgetc(tempfh);
492   ok(ret == -1, "Unbuffered fgetc in text mode must failed on \\r\\n\n");
493   fclose(tempfh);
494   unlink(tempf);
495   free(tempf);
496 }
497
498 static void test_fputc( void )
499 {
500   char* tempf;
501   FILE *tempfh;
502   int  ret;
503
504   tempf=_tempnam(".","wne");
505   tempfh = fopen(tempf,"wb");
506   ret = fputc(0,tempfh);
507   ok(0 == ret, "fputc(0,tempfh) expected %x got %x\n", 0, ret);
508   ret = fputc(0xff,tempfh);
509   ok(0xff == ret, "fputc(0xff,tempfh) expected %x got %x\n", 0xff, ret);
510   ret = fputc(0xffffffff,tempfh);
511   ok(0xff == ret, "fputc(0xffffffff,tempfh) expected %x got %x\n", 0xff, ret);
512   fclose(tempfh);
513
514   tempfh = fopen(tempf,"rb");
515   ret = fputc(0,tempfh);
516   ok(EOF == ret, "fputc(0,tempfh) on r/o file expected %x got %x\n", EOF, ret);
517   fclose(tempfh);
518
519   unlink(tempf);
520   free(tempf);
521 }
522
523 static void test_flsbuf( void )
524 {
525   char* tempf;
526   FILE *tempfh;
527   int  c;
528   int  ret;
529   int  bufmode;
530   static const int bufmodes[] = {_IOFBF,_IONBF};
531
532   tempf=_tempnam(".","wne");
533   for (bufmode=0; bufmode < sizeof(bufmodes)/sizeof(bufmodes[0]); bufmode++)
534   {
535     tempfh = fopen(tempf,"wb");
536     setvbuf(tempfh,NULL,bufmodes[bufmode],2048);
537     ret = _flsbuf(0,tempfh);
538     ok(0 == ret, "_flsbuf(0,tempfh) with bufmode %x expected %x got %x\n",
539                          bufmodes[bufmode], 0, ret);
540     ret = _flsbuf(0xff,tempfh);
541     ok(0xff == ret, "_flsbuf(0xff,tempfh) with bufmode %x expected %x got %x\n",
542                          bufmodes[bufmode], 0, ret);
543     ret = _flsbuf(0xffffffff,tempfh);
544     ok(0xff == ret, "_flsbuf(0xffffffff,tempfh) with bufmode %x expected %x got %x\n",
545                          bufmodes[bufmode], 0, ret);
546     fclose(tempfh);
547   }
548
549   tempfh = fopen(tempf,"rb");
550   ret = _flsbuf(0,tempfh);
551   ok(EOF == ret, "_flsbuf(0,tempfh) on r/o file expected %x got %x\n", EOF, ret);
552   fclose(tempfh);
553
554   /* See bug 17123, exposed by WinAVR's make */
555   tempfh = fopen(tempf,"w");
556   ok(tempfh->_cnt == 0, "_cnt on freshly opened file was %d\n", tempfh->_cnt);
557   setbuf(tempfh, NULL);
558   ok(tempfh->_cnt == 0, "_cnt on unbuffered file was %d\n", tempfh->_cnt);
559   /* Inlined putchar sets _cnt to -1.  Native seems to ignore the value... */
560   tempfh->_cnt = 1234;
561   ret = _flsbuf('Q',tempfh);
562   ok('Q' == ret, "_flsbuf('Q',tempfh) expected %x got %x\n", 'Q', ret);
563   /* ... and reset it to zero */
564   ok(tempfh->_cnt == 0, "after unbuf _flsbuf, _cnt was %d\n", tempfh->_cnt);
565   fclose(tempfh);
566   /* And just for grins, make sure the file is correct */
567   tempfh = fopen(tempf,"r");
568   c = fgetc(tempfh);
569   ok(c == 'Q', "first byte should be 'Q'\n");
570   c = fgetc(tempfh);
571   ok(c == EOF, "there should only be one byte\n");
572   fclose(tempfh);
573
574   unlink(tempf);
575   free(tempf);
576 }
577
578 static void test_fgetwc( void )
579 {
580 #define LLEN 512
581
582   char* tempf;
583   FILE *tempfh;
584   static const char mytext[]= "This is test_fgetwc\r\n";
585   WCHAR wtextW[BUFSIZ+LLEN+1];
586   WCHAR *mytextW = NULL, *aptr, *wptr;
587   BOOL diff_found = FALSE;
588   int j;
589   unsigned int i;
590   LONG l;
591
592   tempf=_tempnam(".","wne");
593   tempfh = fopen(tempf,"wb");
594   j = 'a';
595   /* pad to almost the length of the internal buffer */
596   for (i=0; i<BUFSIZ-4; i++)
597     fputc(j,tempfh);
598   j = '\r';
599   fputc(j,tempfh);
600   j = '\n';
601   fputc(j,tempfh);
602   fputs(mytext,tempfh);
603   fclose(tempfh);
604   /* in text mode, getws/c expects multibyte characters */
605   /*currently Wine only supports plain ascii, and that is all that is tested here */
606   tempfh = fopen(tempf,"rt"); /* open in TEXT mode */
607   fgetws(wtextW,LLEN,tempfh);
608   l=ftell(tempfh);
609   ok(l==BUFSIZ-2, "ftell expected %d got %d\n", BUFSIZ-2, l);
610   fgetws(wtextW,LLEN,tempfh);
611   l=ftell(tempfh);
612   ok(l==BUFSIZ-2+strlen(mytext), "ftell expected %d got %d\n", BUFSIZ-2+lstrlen(mytext), l);
613   mytextW = AtoW (mytext);
614   aptr = mytextW;
615   wptr = wtextW;
616   for (i=0; i<strlen(mytext)-2; i++, aptr++, wptr++)
617     {
618       diff_found |= (*aptr != *wptr);
619     }
620   ok(!(diff_found), "fgetwc difference found in TEXT mode\n");
621   ok(*wptr == '\n', "Carriage return was not skipped\n");
622   fclose(tempfh);
623   unlink(tempf);
624   
625   tempfh = fopen(tempf,"wb");
626   j = 'a';
627   /* pad to almost the length of the internal buffer. Use an odd number of bytes
628      to test that we can read wchars that are split across the internal buffer
629      boundary */
630   for (i=0; i<BUFSIZ-3-strlen(mytext)*sizeof(WCHAR); i++)
631     fputc(j,tempfh);
632   j = '\r';
633   fputwc(j,tempfh);
634   j = '\n';
635   fputwc(j,tempfh);
636   fputws(wtextW,tempfh);
637   fputws(wtextW,tempfh);
638   fclose(tempfh);
639   /* in binary mode, getws/c expects wide characters */
640   tempfh = fopen(tempf,"rb"); /* open in BINARY mode */
641   j=(BUFSIZ-2)/sizeof(WCHAR)-strlen(mytext);
642   fgetws(wtextW,j,tempfh);
643   l=ftell(tempfh);
644   j=(j-1)*sizeof(WCHAR);
645   ok(l==j, "ftell expected %d got %d\n", j, l);
646   i=fgetc(tempfh);
647   ok(i=='a', "fgetc expected %d got %d\n", 0x61, i);
648   l=ftell(tempfh);
649   j++;
650   ok(l==j, "ftell expected %d got %d\n", j, l);
651   fgetws(wtextW,3,tempfh);
652   ok(wtextW[0]=='\r',"expected carriage return got %04hx\n", wtextW[0]);
653   ok(wtextW[1]=='\n',"expected newline got %04hx\n", wtextW[1]);
654   l=ftell(tempfh);
655   j += 4;
656   ok(l==j, "ftell expected %d got %d\n", j, l);
657   for(i=0; i<strlen(mytext); i++)
658     wtextW[i] = 0;
659   /* the first time we get the string, it should be entirely within the local buffer */
660   fgetws(wtextW,LLEN,tempfh);
661   l=ftell(tempfh);
662   j += (strlen(mytext)-1)*sizeof(WCHAR);
663   ok(l==j, "ftell expected %d got %d\n", j, l);
664   diff_found = FALSE;
665   aptr = mytextW;
666   wptr = wtextW;
667   for (i=0; i<strlen(mytext)-2; i++, aptr++, wptr++)
668     {
669       ok(*aptr == *wptr, "Char %d expected %04hx got %04hx\n", i, *aptr, *wptr);
670       diff_found |= (*aptr != *wptr);
671     }
672   ok(!(diff_found), "fgetwc difference found in BINARY mode\n");
673   ok(*wptr == '\n', "Should get newline\n");
674   for(i=0; i<strlen(mytext); i++)
675     wtextW[i] = 0;
676   /* the second time we get the string, it should cross the local buffer boundary.
677      One of the wchars should be split across the boundary */
678   fgetws(wtextW,LLEN,tempfh);
679   diff_found = FALSE;
680   aptr = mytextW;
681   wptr = wtextW;
682   for (i=0; i<strlen(mytext)-2; i++, aptr++, wptr++)
683     {
684       ok(*aptr == *wptr, "Char %d expected %04hx got %04hx\n", i, *aptr, *wptr);
685       diff_found |= (*aptr != *wptr);
686     }
687   ok(!(diff_found), "fgetwc difference found in BINARY mode\n");
688   ok(*wptr == '\n', "Should get newline\n");
689
690   free(mytextW);
691   fclose(tempfh);
692   unlink(tempf);
693   free(tempf);
694 }
695
696 static void test_ctrlz( void )
697 {
698   char* tempf;
699   FILE *tempfh;
700   static const char mytext[]= "This is test_ctrlz";
701   char buffer[256];
702   int i, j;
703   LONG l;
704
705   tempf=_tempnam(".","wne");
706   tempfh = fopen(tempf,"wb");
707   fputs(mytext,tempfh);
708   j = 0x1a; /* a ctrl-z character signals EOF in text mode */
709   fputc(j,tempfh);
710   j = '\r';
711   fputc(j,tempfh);
712   j = '\n';
713   fputc(j,tempfh);
714   j = 'a';
715   fputc(j,tempfh);
716   fclose(tempfh);
717   tempfh = fopen(tempf,"rt"); /* open in TEXT mode */
718   ok(fgets(buffer,256,tempfh) != 0,"fgets failed unexpected\n");
719   i=strlen(buffer);
720   j=strlen(mytext);
721   ok(i==j, "returned string length expected %d got %d\n", j, i);
722   j+=4; /* ftell should indicate the true end of file */
723   l=ftell(tempfh);
724   ok(l==j, "ftell expected %d got %d\n", j, l);
725   ok(feof(tempfh), "did not get EOF\n");
726   fclose(tempfh);
727   
728   tempfh = fopen(tempf,"rb"); /* open in BINARY mode */
729   ok(fgets(buffer,256,tempfh) != 0,"fgets failed unexpected\n");
730   i=strlen(buffer);
731   j=strlen(mytext)+3; /* should get through newline */
732   ok(i==j, "returned string length expected %d got %d\n", j, i);
733   l=ftell(tempfh);
734   ok(l==j, "ftell expected %d got %d\n", j, l);
735   ok(fgets(buffer,256,tempfh) != 0,"fgets failed unexpected\n");
736   i=strlen(buffer);
737   ok(i==1, "returned string length expected %d got %d\n", 1, i);
738   ok(feof(tempfh), "did not get EOF\n");
739   fclose(tempfh);
740   unlink(tempf);
741   free(tempf);
742 }
743
744 static void test_file_put_get( void )
745 {
746   char* tempf;
747   FILE *tempfh;
748   static const char mytext[]=  "This is a test_file_put_get\n";
749   static const char dostext[]= "This is a test_file_put_get\r\n";
750   char btext[LLEN];
751   WCHAR wtextW[LLEN+1];
752   WCHAR *mytextW = NULL, *aptr, *wptr;
753   BOOL diff_found = FALSE;
754   unsigned int i;
755
756   tempf=_tempnam(".","wne");
757   tempfh = fopen(tempf,"wt"); /* open in TEXT mode */
758   fputs(mytext,tempfh);
759   fclose(tempfh);
760   tempfh = fopen(tempf,"rb"); /* open in TEXT mode */
761   fgets(btext,LLEN,tempfh);
762   ok( strlen(mytext) + 1 == strlen(btext),"TEXT/BINARY mode not handled for write\n");
763   ok( btext[strlen(mytext)-1] == '\r', "CR not written\n");
764   fclose(tempfh);
765   tempfh = fopen(tempf,"wb"); /* open in BINARY mode */
766   fputs(dostext,tempfh);
767   fclose(tempfh);
768   tempfh = fopen(tempf,"rt"); /* open in TEXT mode */
769   fgets(btext,LLEN,tempfh);
770   ok(strcmp(btext, mytext) == 0,"_O_TEXT read doesn't strip CR\n");
771   fclose(tempfh);
772   tempfh = fopen(tempf,"rb"); /* open in TEXT mode */
773   fgets(btext,LLEN,tempfh);
774   ok(strcmp(btext, dostext) == 0,"_O_BINARY read doesn't preserve CR\n");
775
776   fclose(tempfh);
777   tempfh = fopen(tempf,"rt"); /* open in TEXT mode */
778   fgetws(wtextW,LLEN,tempfh);
779   mytextW = AtoW (mytext);
780   aptr = mytextW;
781   wptr = wtextW;
782
783   for (i=0; i<strlen(mytext); i++, aptr++, wptr++)
784     {
785       diff_found |= (*aptr != *wptr);
786     }
787   ok(!(diff_found), "fgetwc doesn't strip CR in TEXT mode\n");
788   free(mytextW);
789   fclose(tempfh);
790   unlink(tempf);
791   free(tempf);
792 }
793
794 static void test_file_write_read( void )
795 {
796   char* tempf;
797   int tempfd;
798   static const char mytext[]=  "This is test_file_write_read\nsecond line\n";
799   static const char dostext[]= "This is test_file_write_read\r\nsecond line\r\n";
800   char btext[LLEN];
801   int ret, i;
802
803   tempf=_tempnam(".","wne");
804   tempfd = _open(tempf,_O_CREAT|_O_TRUNC|_O_BINARY|_O_RDWR,
805                      _S_IREAD | _S_IWRITE);
806   ok( tempfd != -1,
807      "Can't open '%s': %d\n", tempf, errno); /* open in BINARY mode */
808   ok(_write(tempfd,dostext,strlen(dostext)) == lstrlenA(dostext),
809      "_write _O_BINARY bad return value\n");
810   _close(tempfd);
811   i = lstrlenA(mytext);
812   tempfd = _open(tempf,_O_RDONLY|_O_BINARY,0); /* open in BINARY mode */
813   ok(_read(tempfd,btext,i) == i,
814      "_read _O_BINARY got bad length\n");
815   ok( memcmp(dostext,btext,i) == 0,
816       "problems with _O_BINARY  _write / _read\n");
817   _close(tempfd);
818   tempfd = _open(tempf,_O_RDONLY|_O_TEXT); /* open in TEXT mode */
819   ok(_read(tempfd,btext,i) == i-1,
820      "_read _O_TEXT got bad length\n");
821   ok( memcmp(mytext,btext,i-1) == 0,
822       "problems with _O_BINARY _write / _O_TEXT _read\n");
823   _close(tempfd);
824   tempfd = _open(tempf,_O_CREAT|_O_TRUNC|_O_TEXT|_O_RDWR,
825                      _S_IREAD | _S_IWRITE);
826   ok( tempfd != -1,
827      "Can't open '%s': %d\n", tempf, errno); /* open in TEXT mode */
828   ok(_write(tempfd,mytext,strlen(mytext)) == lstrlenA(mytext),
829      "_write _O_TEXT bad return value\n");
830   _close(tempfd);
831   tempfd = _open(tempf,_O_RDONLY|_O_BINARY,0); /* open in BINARY mode */
832   ok(_read(tempfd,btext,LLEN) == lstrlenA(dostext),
833      "_read _O_BINARY got bad length\n");
834   ok( memcmp(dostext,btext,strlen(dostext)) == 0,
835       "problems with _O_TEXT _write / _O_BINARY _read\n");
836   ok( btext[strlen(dostext)-2] == '\r', "CR not written or read\n");
837   _close(tempfd);
838   tempfd = _open(tempf,_O_RDONLY|_O_TEXT); /* open in TEXT mode */
839   ok(_read(tempfd,btext,LLEN) == lstrlenA(mytext),
840      "_read _O_TEXT got bad length\n");
841   ok( memcmp(mytext,btext,strlen(mytext)) == 0,
842       "problems with _O_TEXT _write / _read\n");
843   _close(tempfd);
844
845   memset(btext, 0, LLEN);
846   tempfd = _open(tempf,_O_APPEND|_O_RDWR); /* open for APPEND in default mode */
847   ok(tell(tempfd) == 0, "bad position %u expecting 0\n", tell(tempfd));
848   ok(_read(tempfd,btext,LLEN) == lstrlenA(mytext), "_read _O_APPEND got bad length\n");
849   ok( memcmp(mytext,btext,strlen(mytext)) == 0, "problems with _O_APPEND _read\n");
850   _close(tempfd);
851
852   /* Test reading only \n or \r */
853   tempfd = _open(tempf,_O_RDONLY|_O_TEXT); /* open in TEXT mode */
854   _lseek(tempfd, -1, FILE_END);
855   ret = _read(tempfd,btext,LLEN);
856   ok(ret == 1 && *btext == '\n', "_read expected 1 got bad length: %d\n", ret);
857   _lseek(tempfd, -2, FILE_END);
858   ret = _read(tempfd,btext,LLEN);
859   ok(ret == 1 && *btext == '\n', "_read expected '\\n' got bad length: %d\n", ret);
860   _lseek(tempfd, -3, FILE_END);
861   ret = _read(tempfd,btext,1);
862   ok(ret == 1 && *btext == 'e', "_read expected 'e' got \"%.*s\" bad length: %d\n", ret, btext, ret);
863   ok(tell(tempfd) == 41, "bad position %u expecting 41\n", tell(tempfd));
864   _lseek(tempfd, -3, FILE_END);
865   ret = _read(tempfd,btext,2);
866   ok(ret == 1 && *btext == 'e', "_read expected 'e' got \"%.*s\" bad length: %d\n", ret, btext, ret);
867   ok(tell(tempfd) == 42, "bad position %u expecting 42\n", tell(tempfd));
868   _lseek(tempfd, -3, FILE_END);
869   ret = _read(tempfd,btext,3);
870   ok(ret == 2 && *btext == 'e', "_read expected 'e' got \"%.*s\" bad length: %d\n", ret, btext, ret);
871   ok(tell(tempfd) == 43, "bad position %u expecting 43\n", tell(tempfd));
872    _close(tempfd);
873
874   ret = unlink(tempf);
875   ok( ret == 0 ,"Can't unlink '%s': %d\n", tempf, errno);
876   free(tempf);
877
878   tempf=_tempnam(".","wne");
879   tempfd = _open(tempf,_O_CREAT|_O_TRUNC|_O_BINARY|_O_RDWR,0);
880   ok( tempfd != -1,
881      "Can't open '%s': %d\n", tempf, errno); /* open in BINARY mode */
882   ok(_write(tempfd,dostext,strlen(dostext)) == lstrlenA(dostext),
883      "_write _O_BINARY bad return value\n");
884   _close(tempfd);
885   tempfd = _open(tempf,_O_RDONLY|_O_BINARY,0); /* open in BINARY mode */
886   ok(_read(tempfd,btext,LLEN) == lstrlenA(dostext),
887      "_read _O_BINARY got bad length\n");
888   ok( memcmp(dostext,btext,strlen(dostext)) == 0,
889       "problems with _O_BINARY _write / _read\n");
890   ok( btext[strlen(dostext)-2] == '\r', "CR not written or read\n");
891   _close(tempfd);
892   tempfd = _open(tempf,_O_RDONLY|_O_TEXT); /* open in TEXT mode */
893   ok(_read(tempfd,btext,LLEN) == lstrlenA(mytext),
894      "_read _O_TEXT got bad length\n");
895   ok( memcmp(mytext,btext,strlen(mytext)) == 0,
896       "problems with _O_BINARY _write / _O_TEXT _read\n");
897   _close(tempfd);
898
899   /* test _read with single bytes. CR should be skipped and LF pulled in */
900   tempfd = _open(tempf,_O_RDONLY|_O_TEXT); /* open in TEXT mode */
901   for (i=0; i<strlen(mytext); i++)  /* */
902     {
903       _read(tempfd,btext, 1);
904       ok(btext[0] ==  mytext[i],"_read failed at pos %d 0x%02x vs 0x%02x\n", i, btext[0], mytext[i]);
905     }
906   while (_read(tempfd,btext, 1));
907   _close(tempfd);
908
909   /* test _read in buffered mode. Last CR should be skipped but  LF not pulled in */
910   tempfd = _open(tempf,_O_RDONLY|_O_TEXT); /* open in TEXT mode */
911   i = _read(tempfd,btext, strlen(mytext));
912   ok(i == strlen(mytext)-1, "_read_i %d\n", i);
913   _close(tempfd);
914
915   ret =_chmod (tempf, _S_IREAD | _S_IWRITE);
916   ok( ret == 0,
917      "Can't chmod '%s' to read-write: %d\n", tempf, errno);
918   ret = unlink(tempf);
919   ok( ret == 0 ,"Can't unlink '%s': %d\n", tempf, errno);
920   free(tempf);
921 }
922
923 static void test_file_inherit_child(const char* fd_s)
924 {
925     int fd = atoi(fd_s);
926     char buffer[32];
927     int ret;
928
929     ret =write(fd, "Success", 8);
930     ok( ret == 8, "Couldn't write in child process on %d (%s)\n", fd, strerror(errno));
931     lseek(fd, 0, SEEK_SET);
932     ok(read(fd, buffer, sizeof (buffer)) == 8, "Couldn't read back the data\n");
933     ok(memcmp(buffer, "Success", 8) == 0, "Couldn't read back the data\n");
934 }
935
936 static void test_file_inherit_child_no(const char* fd_s)
937 {
938     int fd = atoi(fd_s);
939     int ret;
940
941     ret = write(fd, "Success", 8);
942     ok( ret == -1 && errno == EBADF, 
943        "Wrong write result in child process on %d (%s)\n", fd, strerror(errno));
944 }
945
946 static void create_io_inherit_block( STARTUPINFO *startup, unsigned int count, const HANDLE *handles )
947 {
948     static BYTE block[1024];
949     BYTE *wxflag_ptr;
950     HANDLE *handle_ptr;
951     unsigned int i;
952
953     startup->lpReserved2 = block;
954     startup->cbReserved2 = sizeof(unsigned) + (sizeof(char) + sizeof(HANDLE)) * count;
955     wxflag_ptr = block + sizeof(unsigned);
956     handle_ptr = (HANDLE *)(wxflag_ptr + count);
957
958     *(unsigned*)block = count;
959     for (i = 0; i < count; i++)
960     {
961         wxflag_ptr[i] = 0x81;
962         handle_ptr[i] = handles[i];
963     }
964 }
965
966 static const char *read_file( HANDLE file )
967 {
968     static char buffer[128];
969     DWORD ret;
970     SetFilePointer( file, 0, NULL, FILE_BEGIN );
971     if (!ReadFile( file, buffer, sizeof(buffer) - 1, &ret, NULL)) ret = 0;
972     buffer[ret] = 0;
973     return buffer;
974 }
975
976 static void test_stdout_handle( STARTUPINFO *startup, char *cmdline, HANDLE hstdout, BOOL expect_stdout,
977                                 const char *descr )
978 {
979     const char *data;
980     HANDLE hErrorFile;
981     SECURITY_ATTRIBUTES sa;
982     PROCESS_INFORMATION proc;
983
984     /* make file handle inheritable */
985     sa.nLength = sizeof(sa);
986     sa.lpSecurityDescriptor = NULL;
987     sa.bInheritHandle = TRUE;
988
989     hErrorFile = CreateFileA( "fdopen.err", GENERIC_READ|GENERIC_WRITE,
990                               FILE_SHARE_READ | FILE_SHARE_WRITE, &sa, CREATE_ALWAYS, 0, NULL );
991     startup->dwFlags    = STARTF_USESTDHANDLES;
992     startup->hStdInput  = GetStdHandle( STD_INPUT_HANDLE );
993     startup->hStdOutput = hErrorFile;
994     startup->hStdError  = GetStdHandle( STD_ERROR_HANDLE );
995
996     CreateProcessA( NULL, cmdline, NULL, NULL, TRUE,
997                     CREATE_DEFAULT_ERROR_MODE | NORMAL_PRIORITY_CLASS, NULL, NULL, startup, &proc );
998     winetest_wait_child_process( proc.hProcess );
999
1000     data = read_file( hErrorFile );
1001     if (expect_stdout)
1002         ok( strcmp( data, "Success" ), "%s: Error file shouldn't contain data\n", descr );
1003     else
1004         ok( !strcmp( data, "Success" ), "%s: Wrong error data (%s)\n", descr, data );
1005
1006     if (hstdout)
1007     {
1008         data = read_file( hstdout );
1009         if (expect_stdout)
1010             ok( !strcmp( data, "Success" ), "%s: Wrong stdout data (%s)\n", descr, data );
1011         else
1012             ok( strcmp( data, "Success" ), "%s: Stdout file shouldn't contain data\n", descr );
1013     }
1014
1015     CloseHandle( hErrorFile );
1016     DeleteFile( "fdopen.err" );
1017 }
1018
1019 static void test_file_inherit( const char* selfname )
1020 {
1021     int                 fd;
1022     const char*         arg_v[5];
1023     char                buffer[16];
1024     char cmdline[MAX_PATH];
1025     STARTUPINFO startup;
1026     SECURITY_ATTRIBUTES sa;
1027     HANDLE handles[3];
1028
1029     fd = open ("fdopen.tst", O_CREAT | O_RDWR | O_BINARY, _S_IREAD |_S_IWRITE);
1030     ok(fd != -1, "Couldn't create test file\n");
1031     arg_v[0] = selfname;
1032     arg_v[1] = "tests/file.c";
1033     arg_v[2] = "inherit";
1034     arg_v[3] = buffer; sprintf(buffer, "%d", fd);
1035     arg_v[4] = 0;
1036     _spawnvp(_P_WAIT, selfname, arg_v);
1037     ok(tell(fd) == 8, "bad position %u expecting 8\n", tell(fd));
1038     lseek(fd, 0, SEEK_SET);
1039     ok(read(fd, buffer, sizeof (buffer)) == 8 && memcmp(buffer, "Success", 8) == 0, "Couldn't read back the data\n");
1040     close (fd);
1041     ok(unlink("fdopen.tst") == 0, "Couldn't unlink\n");
1042     
1043     fd = open ("fdopen.tst", O_CREAT | O_RDWR | O_BINARY | O_NOINHERIT, _S_IREAD |_S_IWRITE);
1044     ok(fd != -1, "Couldn't create test file\n");
1045     arg_v[0] = selfname;
1046     arg_v[1] = "tests/file.c";
1047     arg_v[2] = "inherit_no";
1048     arg_v[3] = buffer; sprintf(buffer, "%d", fd);
1049     arg_v[4] = 0;
1050     _spawnvp(_P_WAIT, selfname, arg_v);
1051     ok(tell(fd) == 0, "bad position %u expecting 0\n", tell(fd));
1052     ok(read(fd, buffer, sizeof (buffer)) == 0, "Found unexpected data (%s)\n", buffer);
1053     close (fd);
1054     ok(unlink("fdopen.tst") == 0, "Couldn't unlink\n");
1055
1056     /* make file handle inheritable */
1057     sa.nLength = sizeof(sa);
1058     sa.lpSecurityDescriptor = NULL;
1059     sa.bInheritHandle = TRUE;
1060     sprintf(cmdline, "%s file inherit 1", selfname);
1061
1062     /* init an empty Reserved2, which should not be recognized as inherit-block */
1063     ZeroMemory(&startup, sizeof(STARTUPINFO));
1064     startup.cb = sizeof(startup);
1065     create_io_inherit_block( &startup, 0, NULL );
1066     test_stdout_handle( &startup, cmdline, 0, FALSE, "empty block" );
1067
1068     /* test with valid inheritblock */
1069     handles[0] = GetStdHandle( STD_INPUT_HANDLE );
1070     handles[1] = CreateFileA( "fdopen.tst", GENERIC_READ|GENERIC_WRITE,
1071                               FILE_SHARE_READ | FILE_SHARE_WRITE, &sa, CREATE_ALWAYS, 0, NULL );
1072     handles[2] = GetStdHandle( STD_ERROR_HANDLE );
1073     create_io_inherit_block( &startup, 3, handles );
1074     test_stdout_handle( &startup, cmdline, handles[1], TRUE, "valid block" );
1075     CloseHandle( handles[1] );
1076     DeleteFile("fdopen.tst");
1077
1078     /* test inherit block starting with unsigned zero */
1079     handles[1] = CreateFileA( "fdopen.tst", GENERIC_READ|GENERIC_WRITE,
1080                               FILE_SHARE_READ | FILE_SHARE_WRITE, &sa, CREATE_ALWAYS, 0, NULL );
1081     create_io_inherit_block( &startup, 3, handles );
1082     *(unsigned int *)startup.lpReserved2 = 0;
1083     test_stdout_handle( &startup, cmdline, handles[1], FALSE, "zero count block" );
1084     CloseHandle( handles[1] );
1085     DeleteFile("fdopen.tst");
1086
1087     /* test inherit block with smaller size */
1088     handles[1] = CreateFileA( "fdopen.tst", GENERIC_READ|GENERIC_WRITE,
1089                               FILE_SHARE_READ | FILE_SHARE_WRITE, &sa, CREATE_ALWAYS, 0, NULL );
1090     create_io_inherit_block( &startup, 3, handles );
1091     startup.cbReserved2 -= 3;
1092     test_stdout_handle( &startup, cmdline, handles[1], TRUE, "small size block" );
1093     CloseHandle( handles[1] );
1094     DeleteFile("fdopen.tst");
1095
1096     /* test inherit block with even smaller size */
1097     handles[1] = CreateFileA( "fdopen.tst", GENERIC_READ|GENERIC_WRITE,
1098                               FILE_SHARE_READ | FILE_SHARE_WRITE, &sa, CREATE_ALWAYS, 0, NULL );
1099     create_io_inherit_block( &startup, 3, handles );
1100     startup.cbReserved2 = sizeof(unsigned int) + sizeof(HANDLE) + sizeof(char);
1101     test_stdout_handle( &startup, cmdline, handles[1], FALSE, "smaller size block" );
1102     CloseHandle( handles[1] );
1103     DeleteFile("fdopen.tst");
1104
1105     /* test inherit block with larger size */
1106     handles[1] = CreateFileA( "fdopen.tst", GENERIC_READ|GENERIC_WRITE,
1107                               FILE_SHARE_READ | FILE_SHARE_WRITE, &sa, CREATE_ALWAYS, 0, NULL );
1108     create_io_inherit_block( &startup, 3, handles );
1109     startup.cbReserved2 += 7;
1110     test_stdout_handle( &startup, cmdline, handles[1], TRUE, "large size block" );
1111     CloseHandle( handles[1] );
1112     DeleteFile("fdopen.tst");
1113 }
1114
1115 static void test_tmpnam( void )
1116 {
1117   char name[MAX_PATH] = "abc";
1118   char *res;
1119
1120   res = tmpnam(NULL);
1121   ok(res != NULL, "tmpnam returned NULL\n");
1122   ok(res[0] == '\\', "first character is not a backslash\n");
1123   ok(strchr(res+1, '\\') == 0, "file not in the root directory\n");
1124   ok(res[strlen(res)-1] == '.', "first call - last character is not a dot\n");
1125
1126   res = tmpnam(name);
1127   ok(res != NULL, "tmpnam returned NULL\n");
1128   ok(res == name, "supplied buffer was not used\n");
1129   ok(res[0] == '\\', "first character is not a backslash\n");
1130   ok(strchr(res+1, '\\') == 0, "file not in the root directory\n");
1131   ok(res[strlen(res)-1] != '.', "second call - last character is a dot\n");
1132 }
1133
1134 static void test_chsize( void )
1135 {
1136     int fd;
1137     LONG cur, pos, count;
1138     char temptext[] = "012345678";
1139     char *tempfile = _tempnam( ".", "tst" );
1140     
1141     ok( tempfile != NULL, "Couldn't create test file: %s\n", tempfile );
1142
1143     fd = _open( tempfile, _O_CREAT|_O_TRUNC|_O_RDWR, _S_IREAD|_S_IWRITE );
1144     ok( fd > 0, "Couldn't open test file\n" );
1145
1146     count = _write( fd, temptext, sizeof(temptext) );
1147     ok( count > 0, "Couldn't write to test file\n" );
1148
1149     /* get current file pointer */
1150     cur = _lseek( fd, 0, SEEK_CUR );
1151
1152     /* make the file smaller */
1153     ok( _chsize( fd, sizeof(temptext) / 2 ) == 0, "_chsize() failed\n" );
1154
1155     pos = _lseek( fd, 0, SEEK_CUR );
1156     ok( cur == pos, "File pointer changed from: %d to: %d\n", cur, pos );
1157     ok( _filelength( fd ) == sizeof(temptext) / 2, "Wrong file size\n" );
1158
1159     /* enlarge the file */
1160     ok( _chsize( fd, sizeof(temptext) * 2 ) == 0, "_chsize() failed\n" ); 
1161
1162     pos = _lseek( fd, 0, SEEK_CUR );
1163     ok( cur == pos, "File pointer changed from: %d to: %d\n", cur, pos );
1164     ok( _filelength( fd ) == sizeof(temptext) * 2, "Wrong file size\n" );
1165
1166     _close( fd );
1167     _unlink( tempfile );
1168     free( tempfile );
1169 }
1170
1171 static void test_fopen_fclose_fcloseall( void )
1172 {
1173     char fname1[] = "empty1";
1174     char fname2[] = "empty2";
1175     char fname3[] = "empty3";
1176     FILE *stream1, *stream2, *stream3, *stream4;
1177     int ret, numclosed;
1178
1179     /* testing fopen() */
1180     stream1 = fopen(fname1, "w+");
1181     ok(stream1 != NULL, "The file '%s' was not opened\n", fname1);
1182     stream2 = fopen(fname2, "w ");
1183     ok(stream2 != NULL, "The file '%s' was not opened\n", fname2 );
1184     _unlink(fname3);
1185     stream3 = fopen(fname3, "r");
1186     ok(stream3 == NULL, "The file '%s' shouldn't exist before\n", fname3 );
1187     stream3 = fopen(fname3, "w+");
1188     ok(stream3 != NULL, "The file '%s' should be opened now\n", fname3 );
1189     errno = 0xfaceabad;
1190     stream4 = fopen("", "w+");
1191     ok(stream4 == NULL && (errno == EINVAL || errno == ENOENT),
1192        "filename is empty, errno = %d (expected 2 or 22)\n", errno);
1193     errno = 0xfaceabad;
1194     stream4 = fopen(NULL, "w+");
1195     ok(stream4 == NULL && (errno == EINVAL || errno == ENOENT), 
1196        "filename is NULL, errno = %d (expected 2 or 22)\n", errno);
1197
1198     /* testing fclose() */
1199     ret = fclose(stream2);
1200     ok(ret == 0, "The file '%s' was not closed\n", fname2);
1201     ret = fclose(stream3);
1202     ok(ret == 0, "The file '%s' was not closed\n", fname3);
1203     ret = fclose(stream2);
1204     ok(ret == EOF, "Closing file '%s' returned %d\n", fname2, ret);
1205     ret = fclose(stream3);
1206     ok(ret == EOF, "Closing file '%s' returned %d\n", fname3, ret);
1207
1208     /* testing fcloseall() */
1209     numclosed = _fcloseall();
1210     /* fname1 should be closed here */
1211     ok(numclosed == 1, "Number of files closed by fcloseall(): %u\n", numclosed);
1212     numclosed = _fcloseall();
1213     ok(numclosed == 0, "Number of files closed by fcloseall(): %u\n", numclosed);
1214
1215     ok(_unlink(fname1) == 0, "Couldn't unlink file named '%s'\n", fname1);
1216     ok(_unlink(fname2) == 0, "Couldn't unlink file named '%s'\n", fname2);
1217     ok(_unlink(fname3) == 0, "Couldn't unlink file named '%s'\n", fname3);
1218 }
1219
1220 static void test_fopen_s( void )
1221 {
1222     const char name[] = "empty1";
1223     char buff[16];
1224     FILE *file;
1225     int ret;
1226     int len;
1227
1228     if (!p_fopen_s)
1229     {
1230         win_skip("Skipping fopen_s test\n");
1231         return;
1232     }
1233     /* testing fopen_s */
1234     ret = p_fopen_s(&file, name, "w");
1235     ok(ret == 0, "fopen_s failed with %d\n", ret);
1236     ok(file != 0, "fopen_s failed to return value\n");
1237     fwrite(name, sizeof(name), 1, file);
1238
1239     ret = fclose(file);
1240     ok(ret != EOF, "File failed to close\n");
1241
1242     file = fopen(name, "r");
1243     ok(file != 0, "fopen failed\n");
1244     len = fread(buff, 1, sizeof(name), file);
1245     ok(len == sizeof(name), "File length is %d\n", len);
1246     buff[sizeof(name)] = '\0';
1247     ok(strcmp(name, buff) == 0, "File content mismatch! Got %s, expected %s\n", buff, name);
1248
1249     ret = fclose(file);
1250     ok(ret != EOF, "File failed to close\n");
1251
1252     ok(_unlink(name) == 0, "Couldn't unlink file named '%s'\n", name);
1253 }
1254
1255 static void test__wfopen_s( void )
1256 {
1257     const char name[] = "empty1";
1258     const WCHAR wname[] = {
1259        'e','m','p','t','y','1',0
1260     };
1261     const WCHAR wmode[] = {
1262        'w',0
1263     };
1264     char buff[16];
1265     FILE *file;
1266     int ret;
1267     int len;
1268
1269     if (!p__wfopen_s)
1270     {
1271         win_skip("Skipping _wfopen_s test\n");
1272         return;
1273     }
1274     /* testing _wfopen_s */
1275     ret = p__wfopen_s(&file, wname, wmode);
1276     ok(ret == 0, "_wfopen_s failed with %d\n", ret);
1277     ok(file != 0, "_wfopen_s failed to return value\n");
1278     fwrite(name, sizeof(name), 1, file);
1279
1280     ret = fclose(file);
1281     ok(ret != EOF, "File failed to close\n");
1282
1283     file = fopen(name, "r");
1284     ok(file != 0, "fopen failed\n");
1285     len = fread(buff, 1, sizeof(name), file);
1286     ok(len == sizeof(name), "File length is %d\n", len);
1287     buff[sizeof(name)] = '\0';
1288     ok(strcmp(name, buff) == 0, "File content mismatch! Got %s, expected %s\n", buff, name);
1289
1290     ret = fclose(file);
1291     ok(ret != EOF, "File failed to close\n");
1292
1293     ok(_unlink(name) == 0, "Couldn't unlink file named '%s'\n", name);
1294 }
1295
1296 static void test_get_osfhandle(void)
1297 {
1298     int fd;
1299     char fname[] = "t_get_osfhanle";
1300     DWORD bytes_written;
1301     HANDLE handle;
1302
1303     fd = _sopen(fname, _O_CREAT|_O_RDWR, _SH_DENYRW, _S_IREAD | _S_IWRITE);
1304     handle = (HANDLE)_get_osfhandle(fd);
1305     WriteFile(handle, "bar", 3, &bytes_written, NULL);
1306     _close(fd);
1307     fd = _open(fname, _O_RDONLY, 0);
1308     ok(fd != -1, "Coudn't open '%s' after _get_osfhanle()\n", fname);
1309
1310     _close(fd);
1311     _unlink(fname);
1312 }
1313
1314 static void test_setmaxstdio(void)
1315 {
1316     ok(2048 == _setmaxstdio(2048),"_setmaxstdio returned %d instead of 2048\n",_setmaxstdio(2048));
1317     ok(-1 == _setmaxstdio(2049),"_setmaxstdio returned %d instead of -1\n",_setmaxstdio(2049));
1318 }
1319
1320 static void test_stat(void)
1321 {
1322     int fd;
1323     int pipes[2];
1324     int ret;
1325     struct stat buf;
1326
1327     /* Tests for a file */
1328     fd = open("stat.tst", O_WRONLY | O_CREAT | O_BINARY, _S_IREAD |_S_IWRITE);
1329     if (fd >= 0)
1330     {
1331         ret = fstat(fd, &buf);
1332         ok(!ret, "fstat failed: errno=%d\n", errno);
1333         ok((buf.st_mode & _S_IFMT) == _S_IFREG, "bad format = %06o\n", buf.st_mode);
1334         ok((buf.st_mode & 0777) == 0666, "bad st_mode = %06o\n", buf.st_mode);
1335         ok(buf.st_dev == 0, "st_dev is %d, expected 0\n", buf.st_dev);
1336         ok(buf.st_dev == buf.st_rdev, "st_dev (%d) and st_rdev (%d) differ\n", buf.st_dev, buf.st_rdev);
1337         ok(buf.st_nlink == 1, "st_nlink is %d, expected 1\n", buf.st_nlink);
1338         ok(buf.st_size == 0, "st_size is %d, expected 0\n", buf.st_size);
1339
1340         ret = stat("stat.tst", &buf);
1341         ok(!ret, "stat failed: errno=%d\n", errno);
1342         ok((buf.st_mode & _S_IFMT) == _S_IFREG, "bad format = %06o\n", buf.st_mode);
1343         ok((buf.st_mode & 0777) == 0666, "bad st_mode = %06o\n", buf.st_mode);
1344         ok(buf.st_dev == buf.st_rdev, "st_dev (%d) and st_rdev (%d) differ\n", buf.st_dev, buf.st_rdev);
1345         ok(buf.st_nlink == 1, "st_nlink is %d, expected 1\n", buf.st_nlink);
1346         ok(buf.st_size == 0, "st_size is %d, expected 0\n", buf.st_size);
1347
1348         close(fd);
1349         remove("stat.tst");
1350     }
1351     else
1352         skip("open failed with errno %d\n", errno);
1353
1354     /* Tests for a char device */
1355     if (_dup2(0, 10) == 0)
1356     {
1357         ret = fstat(10, &buf);
1358         ok(!ret, "fstat(stdin) failed: errno=%d\n", errno);
1359         if ((buf.st_mode & _S_IFMT) == _S_IFCHR)
1360         {
1361             ok(buf.st_mode == _S_IFCHR, "bad st_mode=%06o\n", buf.st_mode);
1362             ok(buf.st_dev == 10, "st_dev is %d, expected 10\n", buf.st_dev);
1363             ok(buf.st_rdev == 10, "st_rdev is %d, expected 10\n", buf.st_rdev);
1364             ok(buf.st_nlink == 1, "st_nlink is %d, expected 1\n", buf.st_nlink);
1365         }
1366         else
1367             skip("stdin is not a char device? st_mode=%06o\n", buf.st_mode);
1368         close(10);
1369     }
1370     else
1371         skip("_dup2 failed with errno %d\n", errno);
1372
1373     /* Tests for pipes */
1374     if (_pipe(pipes, 1024, O_BINARY) == 0)
1375     {
1376         ret = fstat(pipes[0], &buf);
1377         ok(!ret, "fstat(pipe) failed: errno=%d\n", errno);
1378         ok(buf.st_mode == _S_IFIFO, "bad st_mode=%06o\n", buf.st_mode);
1379         ok(buf.st_dev == pipes[0], "st_dev is %d, expected %d\n", buf.st_dev, pipes[0]);
1380         ok(buf.st_rdev == pipes[0], "st_rdev is %d, expected %d\n", buf.st_rdev, pipes[0]);
1381         ok(buf.st_nlink == 1, "st_nlink is %d, expected 1\n", buf.st_nlink);
1382         close(pipes[0]);
1383         close(pipes[1]);
1384     }
1385     else
1386         skip("pipe failed with errno %d\n", errno);
1387 }
1388
1389 static const char* pipe_string="Hello world";
1390
1391 /* How many messages to transfer over the pipe */
1392 #define N_TEST_MESSAGES 3
1393
1394 static void test_pipes_child(int argc, char** args)
1395 {
1396     int fd;
1397     int nwritten;
1398     int i;
1399
1400     if (argc < 5)
1401     {
1402         ok(0, "not enough parameters: %d\n", argc);
1403         return;
1404     }
1405
1406     fd=atoi(args[3]);
1407     i=close(fd);
1408     ok(!i, "unable to close %d: %d\n", fd, errno);
1409
1410     fd=atoi(args[4]);
1411
1412     for (i=0; i<N_TEST_MESSAGES; i++) {
1413        nwritten=write(fd, pipe_string, strlen(pipe_string));
1414        ok(nwritten == strlen(pipe_string), "i %d, expected to write '%s' wrote %d\n", i, pipe_string, nwritten);
1415        /* let other process wake up so they can show off their "keep reading until EOF" behavior */
1416        if (i < N_TEST_MESSAGES-1)
1417            Sleep(100);
1418     }
1419
1420     i=close(fd);
1421     ok(!i, "unable to close %d: %d\n", fd, errno);
1422 }
1423
1424 static void test_pipes(const char* selfname)
1425 {
1426     int pipes[2];
1427     char str_fdr[12], str_fdw[12];
1428     FILE* file;
1429     const char* arg_v[6];
1430     char buf[4096];
1431     char expected[4096];
1432     int r;
1433     int i;
1434
1435     /* Test reading from a pipe with read() */
1436     if (_pipe(pipes, 1024, O_BINARY) < 0)
1437     {
1438         ok(0, "pipe failed with errno %d\n", errno);
1439         return;
1440     }
1441
1442     arg_v[0] = selfname;
1443     arg_v[1] = "tests/file.c";
1444     arg_v[2] = "pipes";
1445     arg_v[3] = str_fdr; sprintf(str_fdr, "%d", pipes[0]);
1446     arg_v[4] = str_fdw; sprintf(str_fdw, "%d", pipes[1]);
1447     arg_v[5] = NULL;
1448     proc_handles[0] = (HANDLE)_spawnvp(_P_NOWAIT, selfname, arg_v);
1449     i=close(pipes[1]);
1450     ok(!i, "unable to close %d: %d\n", pipes[1], errno);
1451
1452     for (i=0; i<N_TEST_MESSAGES; i++) {
1453        r=read(pipes[0], buf, sizeof(buf)-1);
1454        ok(r == strlen(pipe_string), "i %d, got %d\n", i, r);
1455        if (r > 0)
1456            buf[r]='\0';
1457        ok(strcmp(buf, pipe_string) == 0, "expected to read '%s', got '%s'\n", pipe_string, buf);
1458    }
1459
1460     r=read(pipes[0], buf, sizeof(buf)-1);
1461     ok(r == 0, "expected to read 0 bytes, got %d\n", r);
1462     i=close(pipes[0]);
1463     ok(!i, "unable to close %d: %d\n", pipes[0], errno);
1464
1465     /* Test reading from a pipe with fread() */
1466     if (_pipe(pipes, 1024, O_BINARY) < 0)
1467     {
1468         ok(0, "pipe failed with errno %d\n", errno);
1469         return;
1470     }
1471
1472     arg_v[0] = selfname;
1473     arg_v[1] = "tests/file.c";
1474     arg_v[2] = "pipes";
1475     arg_v[3] = str_fdr; sprintf(str_fdr, "%d", pipes[0]);
1476     arg_v[4] = str_fdw; sprintf(str_fdw, "%d", pipes[1]);
1477     arg_v[5] = NULL;
1478     proc_handles[1] = (HANDLE)_spawnvp(_P_NOWAIT, selfname, arg_v);
1479     i=close(pipes[1]);
1480     ok(!i, "unable to close %d: %d\n", pipes[1], errno);
1481     file=fdopen(pipes[0], "r");
1482
1483     /* In blocking mode, fread will keep calling read() until it gets
1484      * enough bytes, or EOF, even on Unix.  (If this were a Unix terminal
1485      * in cooked mode instead of a pipe, it would also stop on EOL.)
1486      */
1487     expected[0] = 0;
1488     for (i=0; i<N_TEST_MESSAGES; i++)
1489        strcat(expected, pipe_string);
1490     r=fread(buf, 1, sizeof(buf)-1, file);
1491     ok(r == strlen(expected), "fread() returned %d: ferror=%d\n", r, ferror(file));
1492     if (r > 0)
1493        buf[r]='\0';
1494     ok(strcmp(buf, expected) == 0, "got '%s' expected '%s'\n", buf, expected);
1495
1496     /* Let child close the file before we read, so we can sense EOF reliably */
1497     Sleep(100);
1498     r=fread(buf, 1, sizeof(buf)-1, file);
1499     ok(r == 0, "fread() returned %d instead of 0\n", r);
1500     ok(ferror(file) == 0, "got ferror() = %d\n", ferror(file));
1501     ok(feof(file), "feof() is false!\n");
1502
1503     i=fclose(file);
1504     ok(!i, "unable to close the pipe: %d\n", errno);
1505 }
1506
1507 static void test_unlink(void)
1508 {
1509     FILE* file;
1510     ok(mkdir("test_unlink") == 0, "unable to create test dir\n");
1511     file = fopen("test_unlink\\empty", "w");
1512     ok(file != NULL, "unable to create test file\n");
1513     if(file)
1514       fclose(file);
1515     ok(_unlink("test_unlink") != 0, "unlinking a non-empty directory must fail\n");
1516     unlink("test_unlink\\empty");
1517     rmdir("test_unlink");
1518 }
1519
1520 static void test_dup2(void)
1521 {
1522     ok(-1 == _dup2(0, -1), "expected _dup2 to fail when second arg is negative\n" );
1523 }
1524
1525 START_TEST(file)
1526 {
1527     int arg_c;
1528     char** arg_v;
1529
1530     init();
1531
1532     arg_c = winetest_get_mainargs( &arg_v );
1533
1534     /* testing low-level I/O */
1535     if (arg_c >= 3)
1536     {
1537         if (strcmp(arg_v[2], "inherit") == 0)
1538             test_file_inherit_child(arg_v[3]);
1539         else if (strcmp(arg_v[2], "inherit_no") == 0)
1540             test_file_inherit_child_no(arg_v[3]);
1541         else if (strcmp(arg_v[2], "pipes") == 0)
1542             test_pipes_child(arg_c, arg_v);
1543         else
1544             ok(0, "invalid argument '%s'\n", arg_v[2]);
1545         return;
1546     }
1547     test_dup2();
1548     test_file_inherit(arg_v[0]);
1549     test_file_write_read();
1550     test_chsize();
1551     test_stat();
1552     test_unlink();
1553
1554     /* testing stream I/O */
1555     test_filbuf();
1556     test_fdopen();
1557     test_fopen_fclose_fcloseall();
1558     test_fopen_s();
1559     test__wfopen_s();
1560     test_fileops();
1561     test_asciimode();
1562     test_asciimode2();
1563     test_readmode(FALSE); /* binary mode */
1564     test_readmode(TRUE);  /* ascii mode */
1565     test_readboundary();
1566     test_fgetc();
1567     test_fputc();
1568     test_flsbuf();
1569     test_fgetwc();
1570     test_ctrlz();
1571     test_file_put_get();
1572     test_tmpnam();
1573     test_get_osfhandle();
1574     test_setmaxstdio();
1575     test_pipes(arg_v[0]);
1576
1577     /* Wait for the (_P_NOWAIT) spawned processes to finish to make sure the report
1578      * file contains lines in the correct order
1579      */
1580     WaitForMultipleObjects(sizeof(proc_handles)/sizeof(proc_handles[0]), proc_handles, TRUE, 5000);
1581 }