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