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