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