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