crosstest: Fix the crosstest dependencies.
[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 void test_filbuf( void )
40 {
41     FILE *fp;
42     int c;
43     fpos_t pos;
44
45     fp = fopen("filbuf.tst", "wb");
46     fwrite("\n\n\n\n", 1, 4, fp);
47     fclose(fp);
48
49     fp = fopen("filbuf.tst", "rt");
50     c = _filbuf(fp);
51     ok(c == '\n', "read wrong byte\n");
52     /* See bug 16970 for why we care about _filbuf.
53      * ftell returns screwy values on files with lots
54      * of bare LFs in ascii mode because it assumes
55      * that ascii files contain only CRLFs, removes
56      * the CR's early in _filbuf, and adjusts the return
57      * value of ftell to compensate.
58      * native _filbuf will read the whole file, then consume and return
59      * the first one.  That leaves fp->_fd at offset 4, and fp->_ptr
60      * pointing to a buffer of three bare LFs, so
61      * ftell will return 4 - 3 - 3 = -2.
62      */
63     ok(ftell(fp) == -2, "ascii crlf removal does not match native\n");
64     ok(fgetpos(fp, &pos) == 0, "fgetpos fail\n");
65     ok(pos == -2, "ftell does not match fgetpos\n");
66     fclose(fp);
67     unlink("filbuf.tst");
68 }
69
70 static void test_fdopen( void )
71 {
72     static const char buffer[] = {0,1,2,3,4,5,6,7,8,9};
73     char ibuf[10];
74     int fd;
75     FILE *file;
76
77     fd = open ("fdopen.tst", O_WRONLY | O_CREAT | O_BINARY, _S_IREAD |_S_IWRITE);
78     write (fd, buffer, sizeof (buffer));
79     close (fd);
80
81     fd = open ("fdopen.tst", O_RDONLY | O_BINARY);
82     lseek (fd, 5, SEEK_SET);
83     file = fdopen (fd, "rb");
84     ok (fread (ibuf, 1, sizeof (buffer), file) == 5, "read wrong byte count\n");
85     ok (memcmp (ibuf, buffer + 5, 5) == 0, "read wrong bytes\n");
86     fclose (file);
87     unlink ("fdopen.tst");
88 }
89
90 static void test_fileops( void )
91 {
92     static const char outbuffer[] = "0,1,2,3,4,5,6,7,8,9";
93     char buffer[256];
94     WCHAR wbuffer[256];
95     int fd;
96     FILE *file;
97     fpos_t pos;
98     int i, c;
99
100     fd = open ("fdopen.tst", O_WRONLY | O_CREAT | O_BINARY, _S_IREAD |_S_IWRITE);
101     write (fd, outbuffer, sizeof (outbuffer));
102     close (fd);
103
104     fd = open ("fdopen.tst", O_RDONLY | O_BINARY);
105     file = fdopen (fd, "rb");
106     ok(strlen(outbuffer) == (sizeof(outbuffer)-1),"strlen/sizeof error\n");
107     ok(fgets(buffer,sizeof(buffer),file) !=0,"fgets failed unexpected\n");
108     ok(fgets(buffer,sizeof(buffer),file) ==0,"fgets didn't signal EOF\n");
109     ok(feof(file) !=0,"feof doesn't signal EOF\n");
110     rewind(file);
111     ok(fgets(buffer,strlen(outbuffer),file) !=0,"fgets failed unexpected\n");
112     ok(lstrlenA(buffer) == lstrlenA(outbuffer) -1,"fgets didn't read right size\n");
113     ok(fgets(buffer,sizeof(outbuffer),file) !=0,"fgets failed unexpected\n");
114     ok(strlen(buffer) == 1,"fgets dropped chars\n");
115     ok(buffer[0] == outbuffer[strlen(outbuffer)-1],"fgets exchanged chars\n");
116
117     rewind(file);
118     for (i = 0, c = EOF; i < sizeof(outbuffer); i++)
119     {
120         ok((c = fgetc(file)) == outbuffer[i], "fgetc returned wrong data\n");
121     }
122     ok((c = fgetc(file)) == EOF, "getc did not return EOF\n");
123     ok(feof(file), "feof did not return EOF\n");
124     ok(ungetc(c, file) == EOF, "ungetc(EOF) did not return EOF\n");
125     ok(feof(file), "feof after ungetc(EOF) did not return EOF\n");
126     ok((c = fgetc(file)) == EOF, "getc did not return EOF\n");
127     c = outbuffer[sizeof(outbuffer) - 1];
128     ok(ungetc(c, file) == c, "ungetc did not return its input\n");
129     ok(!feof(file), "feof after ungetc returned EOF\n");
130     ok((c = fgetc(file)) != EOF, "getc after ungetc returned EOF\n");
131     ok(c == outbuffer[sizeof(outbuffer) - 1],
132        "getc did not return ungetc'd data\n");
133     ok(!feof(file), "feof after getc returned EOF prematurely\n");
134     ok((c = fgetc(file)) == EOF, "getc did not return EOF\n");
135     ok(feof(file), "feof after getc did not return EOF\n");
136
137     rewind(file);
138     ok(fgetpos(file,&pos) == 0, "fgetpos failed unexpected\n");
139     ok(pos == 0, "Unexpected result of fgetpos %x%08x\n", (DWORD)(pos >> 32), (DWORD)pos);
140     pos = sizeof (outbuffer);
141     ok(fsetpos(file, &pos) == 0, "fsetpos failed unexpected\n");
142     ok(fgetpos(file,&pos) == 0, "fgetpos failed unexpected\n");
143     ok(pos == sizeof (outbuffer), "Unexpected result of fgetpos %x%08x\n", (DWORD)(pos >> 32), (DWORD)pos);
144
145     fclose (file);
146     fd = open ("fdopen.tst", O_RDONLY | O_TEXT);
147     file = fdopen (fd, "rt"); /* open in TEXT mode */
148     ok(fgetws(wbuffer,sizeof(wbuffer)/sizeof(wbuffer[0]),file) !=0,"fgetws failed unexpected\n");
149     ok(fgetws(wbuffer,sizeof(wbuffer)/sizeof(wbuffer[0]),file) ==0,"fgetws didn't signal EOF\n");
150     ok(feof(file) !=0,"feof doesn't signal EOF\n");
151     rewind(file);
152     ok(fgetws(wbuffer,strlen(outbuffer),file) !=0,"fgetws failed unexpected\n");
153     ok(lstrlenW(wbuffer) == (lstrlenA(outbuffer) -1),"fgetws didn't read right size\n");
154     ok(fgetws(wbuffer,sizeof(outbuffer)/sizeof(outbuffer[0]),file) !=0,"fgets failed unexpected\n");
155     ok(lstrlenW(wbuffer) == 1,"fgets dropped chars\n");
156     fclose (file);
157
158     file = fopen("fdopen.tst", "rb");
159     ok( file != NULL, "fopen failed\n");
160     /* sizeof(buffer) > content of file */
161     ok(fread(buffer, sizeof(buffer), 1, file) == 0, "fread test failed\n");
162     /* feof should be set now */
163     ok(feof(file), "feof after fread failed\n");
164     fclose (file);
165
166     unlink ("fdopen.tst");
167 }
168
169 #define IOMODE (ao?"ascii mode":"binary mode")
170 static void test_readmode( BOOL ascii_mode )
171 {
172     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";
173     static const char padbuffer[] = "ghjghjghjghj";
174     static const char nlbuffer[] = "\r\n";
175     char buffer[2*BUFSIZ+256];
176     const char *optr;
177     int fd;
178     FILE *file;
179     const int *ip;
180     int i, j, m, ao, pl;
181     unsigned int fp;
182     LONG l;
183
184     fd = open ("fdopen.tst", O_WRONLY | O_CREAT | O_BINARY, _S_IREAD |_S_IWRITE);
185     /* an internal buffer of BUFSIZ is maintained, so make a file big
186      * enough to test operations that cross the buffer boundary 
187      */
188     j = (2*BUFSIZ-4)/strlen(padbuffer);
189     for (i=0; i<j; i++)
190         write (fd, padbuffer, strlen(padbuffer));
191     j = (2*BUFSIZ-4)%strlen(padbuffer);
192     for (i=0; i<j; i++)
193         write (fd, &padbuffer[i], 1);
194     write (fd, nlbuffer, strlen(nlbuffer));
195     write (fd, outbuffer, sizeof (outbuffer));
196     close (fd);
197     
198     if (ascii_mode) {
199         /* Open file in ascii mode */
200         fd = open ("fdopen.tst", O_RDONLY);
201         file = fdopen (fd, "r");
202         ao = -1; /* on offset to account for carriage returns */
203     }
204     else {
205         fd = open ("fdopen.tst", O_RDONLY | O_BINARY);
206         file = fdopen (fd, "rb");
207         ao = 0;
208     }
209     
210     /* first is a test of fgets, ftell, fseek */
211     ok(ftell(file) == 0,"Did not start at beginning of file in %s\n", IOMODE);
212     ok(fgets(buffer,2*BUFSIZ+256,file) !=0,"padding line fgets failed unexpected in %s\n", IOMODE);
213     l = ftell(file);
214     pl = 2*BUFSIZ-2;
215     ok(l == pl,"padding line ftell got %d should be %d in %s\n", l, pl, IOMODE);
216     ok(lstrlenA(buffer) == pl+ao,"padding line fgets got size %d should be %d in %s\n",
217      lstrlenA(buffer), pl+ao, IOMODE);
218     for (fp=0; fp<strlen(outbuffer); fp++)
219         if (outbuffer[fp] == '\n') break;
220     fp++;
221     ok(fgets(buffer,256,file) !=0,"line 1 fgets failed unexpected in %s\n", IOMODE);
222     l = ftell(file);
223     ok(l == pl+fp,"line 1 ftell got %d should be %d in %s\n", l, pl+fp, IOMODE);
224     ok(lstrlenA(buffer) == fp+ao,"line 1 fgets got size %d should be %d in %s\n",
225      lstrlenA(buffer), fp+ao, IOMODE);
226     /* test a seek back across the buffer boundary */
227     l = pl;
228     ok(fseek(file,l,SEEK_SET)==0,"seek failure in %s\n", IOMODE);
229     l = ftell(file);
230     ok(l == pl,"ftell after seek got %d should be %d in %s\n", l, pl, IOMODE);
231     ok(fgets(buffer,256,file) !=0,"second read of line 1 fgets failed unexpected in %s\n", IOMODE);
232     l = ftell(file);
233     ok(l == pl+fp,"second read of line 1 ftell got %d should be %d in %s\n", l, pl+fp, IOMODE);
234     ok(lstrlenA(buffer) == fp+ao,"second read of line 1 fgets got size %d should be %d in %s\n",
235      lstrlenA(buffer), fp+ao, IOMODE);
236     ok(fgets(buffer,256,file) !=0,"line 2 fgets failed unexpected in %s\n", IOMODE);
237     fp += 2;
238     l = ftell(file);
239     ok(l == pl+fp,"line 2 ftell got %d should be %d in %s\n", l, pl+fp, IOMODE);
240     ok(lstrlenA(buffer) == 2+ao,"line 2 fgets got size %d should be %d in %s\n",
241      lstrlenA(buffer), 2+ao, IOMODE);
242     
243     /* test fread across buffer boundary */
244     rewind(file);
245     ok(ftell(file) == 0,"Did not start at beginning of file in %s\n", IOMODE);
246     ok(fgets(buffer,BUFSIZ-6,file) !=0,"padding line fgets failed unexpected in %s\n", IOMODE);
247     j=strlen(outbuffer);
248     i=fread(buffer,1,BUFSIZ+strlen(outbuffer),file);
249     ok(i==BUFSIZ+j,"fread failed, expected %d got %d in %s\n", BUFSIZ+j, i, IOMODE);
250     l = ftell(file);
251     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);
252     for (m=0; m<3; m++)
253         ok(buffer[m]==padbuffer[m+(BUFSIZ-4)%strlen(padbuffer)],"expected %c got %c\n", padbuffer[m], buffer[m]);
254     m+=BUFSIZ+2+ao;
255     optr = outbuffer;
256     for (; m<i; m++) {
257         ok(buffer[m]==*optr,"char %d expected %c got %c in %s\n", m, *optr, buffer[m], IOMODE);
258         optr++;
259         if (ao && (*optr == '\r'))
260             optr++;
261     }
262     /* fread should return the requested number of bytes if available */
263     rewind(file);
264     ok(ftell(file) == 0,"Did not start at beginning of file in %s\n", IOMODE);
265     ok(fgets(buffer,BUFSIZ-6,file) !=0,"padding line fgets failed unexpected in %s\n", IOMODE);
266     j = fp+10;
267     i=fread(buffer,1,j,file);
268     ok(i==j,"fread failed, expected %d got %d in %s\n", j, i, IOMODE);
269     /* test fread eof */
270     ok(fseek(file,0,SEEK_END)==0,"seek failure in %s\n", IOMODE);
271     ok(feof(file)==0,"feof failure in %s\n", IOMODE);
272     ok(fread(buffer,1,1,file)==0,"fread failure in %s\n", IOMODE);
273     ok(feof(file)!=0,"feof failure in %s\n", IOMODE);
274     ok(fseek(file,-3,SEEK_CUR)==0,"seek failure in %s\n", IOMODE);
275     ok(feof(file)==0,"feof failure in %s\n", IOMODE);
276     ok(fread(buffer,2,1,file)==1,"fread failed in %s\n", IOMODE);
277     ok(feof(file)==0,"feof failure in %s\n", IOMODE);
278     ok(fread(buffer,2,1,file)==0,"fread failure in %s\n",IOMODE);
279     ok(feof(file)!=0,"feof failure in %s\n", IOMODE);
280     
281     /* test some additional functions */
282     rewind(file);
283     ok(ftell(file) == 0,"Did not start at beginning of file in %s\n", IOMODE);
284     ok(fgets(buffer,2*BUFSIZ+256,file) !=0,"padding line fgets failed unexpected in %s\n", IOMODE);
285     i = _getw(file);
286     ip = (const int *)outbuffer;
287     ok(i == *ip,"_getw failed, expected %08x got %08x in %s\n", *ip, i, IOMODE);
288     for (fp=0; fp<strlen(outbuffer); fp++)
289         if (outbuffer[fp] == '\n') break;
290     fp++;
291     /* this will cause the next _getw to cross carriage return characters */
292     ok(fgets(buffer,fp-6,file) !=0,"line 1 fgets failed unexpected in %s\n", IOMODE);
293     for (i=0, j=0; i<6; i++) {
294         if (ao==0 || outbuffer[fp-3+i] != '\r')
295             buffer[j++] = outbuffer[fp-3+i];
296     }
297     i = _getw(file);
298     ip = (int *)buffer;
299     ok(i == *ip,"_getw failed, expected %08x got %08x in %s\n", *ip, i, IOMODE);
300
301     fclose (file);
302     unlink ("fdopen.tst");
303 }
304
305 static void test_asciimode(void)
306 {
307     FILE *fp;
308     char buf[64];
309     int c, i, j;
310
311     /* Simple test of CR CR LF handling.  Test both fgets and fread code paths, they're different! */
312     fp = fopen("ascii.tst", "wb");
313     fputs("\r\r\n", fp);
314     fclose(fp);
315     fp = fopen("ascii.tst", "rt");
316     ok(fgets(buf, sizeof(buf), fp) != NULL, "fgets\n");
317     ok(0 == strcmp(buf, "\r\n"), "CR CR LF not read as CR LF\n");
318     rewind(fp);
319     ok((fread(buf, 1, sizeof(buf), fp) == 2) && (0 == strcmp(buf, "\r\n")), "CR CR LF not read as CR LF\n");
320     fclose(fp);
321     unlink("ascii.tst");
322
323     /* Simple test of foo ^Z [more than one block] bar handling */
324     fp = fopen("ascii.tst", "wb");
325     fputs("foo\032", fp);  /* foo, logical EOF, ... */
326     fseek(fp, 65536L, SEEK_SET); /* ... more than MSVCRT_BUFSIZ, ... */
327     fputs("bar", fp); /* ... bar */
328     fclose(fp);
329     fp = fopen("ascii.tst", "rt");
330     ok(fgets(buf, sizeof(buf), fp) != NULL, "fgets foo\n");
331     ok(0 == strcmp(buf, "foo"), "foo ^Z not read as foo by fgets\n");
332     ok(fgets(buf, sizeof(buf), fp) == NULL, "fgets after logical EOF\n");
333     rewind(fp);
334     ok((fread(buf, 1, sizeof(buf), fp) == 3) && (0 == strcmp(buf, "foo")), "foo ^Z not read as foo by fread\n");
335     ok((fread(buf, 1, sizeof(buf), fp) == 0), "fread after logical EOF\n");
336     fclose(fp);
337
338     /* Show ASCII mode handling*/
339     fp= fopen("ascii.tst","wb");
340     fputs("0\r\n1\r\n2\r\n3\r\n4\r\n5\r\n6\r\n7\r\n8\r\n9\r\n", fp);
341     fclose(fp);
342
343     fp = fopen("ascii.tst", "r");
344     c= fgetc(fp);
345     c= fgetc(fp);
346     fseek(fp,0,SEEK_CUR);
347     for(i=1; i<10; i++) {
348         ok((j = ftell(fp)) == i*3, "ftell fails in TEXT mode\n");
349         fseek(fp,0,SEEK_CUR);
350         ok((c = fgetc(fp)) == '0'+ i, "fgetc after fseek failed in line %d\n", i);
351         c= fgetc(fp);
352     }
353     /* Show that fseek doesn't skip \\r !*/
354     rewind(fp);
355     c= fgetc(fp);
356     fseek(fp, 2 ,SEEK_CUR);
357     for(i=1; i<10; i++) {
358         ok((c = fgetc(fp)) == '0'+ i, "fgetc after fseek with pos Offset failed in line %d\n", i);
359         fseek(fp, 2 ,SEEK_CUR);
360     }
361     fseek(fp, 9*3 ,SEEK_SET);
362     c = fgetc(fp);
363     fseek(fp, -4 ,SEEK_CUR);
364     for(i= 8; i>=0; i--) {
365         ok((c = fgetc(fp)) == '0'+ i, "fgetc after fseek with neg Offset failed in line %d\n", i);
366         fseek(fp, -4 ,SEEK_CUR);
367     }
368     /* Show what happens if fseek positions filepointer on \\r */
369     fclose(fp);
370     fp = fopen("ascii.tst", "r");
371     fseek(fp, 3 ,SEEK_SET);
372     ok((c = fgetc(fp)) == '1', "fgetc fails to read next char when positioned on \\r\n");
373     fclose(fp);
374
375     unlink("ascii.tst");
376 }
377
378 static void test_asciimode2(void)
379 {
380     /* Error sequence from one app was getchar followed by small fread
381      * with one \r removed had last byte of buffer filled with
382      * next byte of *unbuffered* data rather than next byte from buffer
383      * Test case is a short string of one byte followed by a newline
384      * followed by filler to fill out the sector, then a sector of
385      * some different byte.
386      */
387
388     FILE *fp;
389     char ibuf[4];
390     int i;
391     static const char obuf[] =
392 "00\n"
393 "000000000000000000000000000000000000000000000000000000000000000000000000000000\n"
394 "000000000000000000000000000000000000000000000000000000000000000000000000000000\n"
395 "000000000000000000000000000000000000000000000000000000000000000000000000000000\n"
396 "000000000000000000000000000000000000000000000000000000000000000000000000000000\n"
397 "000000000000000000000000000000000000000000000000000000000000000000000000000000\n"
398 "000000000000000000000000000000000000000000000000000000000000000000000000000000\n"
399 "000000000000000000\n"
400 "1111111111111111111";
401
402     fp = fopen("ascii2.tst", "wt");
403     fwrite(obuf, 1, sizeof(obuf), fp);
404     fclose(fp);
405
406     fp = fopen("ascii2.tst", "rt");
407     ok(getc(fp) == '0', "first char not 0\n");
408     memset(ibuf, 0, sizeof(ibuf));
409     i = fread(ibuf, 1, sizeof(ibuf), fp);
410     ok(i == sizeof(ibuf), "fread i %d != sizeof(ibuf)\n", i);
411     ok(0 == strncmp(ibuf, obuf+1, sizeof(ibuf)), "ibuf != obuf\n");
412     fclose(fp);
413     unlink("ascii2.tst");
414 }
415
416 static WCHAR* AtoW( const char* p )
417 {
418     WCHAR* buffer;
419     DWORD len = MultiByteToWideChar( CP_ACP, 0, p, -1, NULL, 0 );
420     buffer = malloc( len * sizeof(WCHAR) );
421     MultiByteToWideChar( CP_ACP, 0, p, -1, buffer, len );
422     return buffer;
423 }
424
425 static void test_fgetc( void )
426 {
427   char* tempf;
428   FILE *tempfh;
429   int  ich=0xe0, ret;
430
431   tempf=_tempnam(".","wne");
432   tempfh = fopen(tempf,"w+");
433   fputc(ich, tempfh);
434   fputc(ich, tempfh);
435   rewind(tempfh);
436   ret = fgetc(tempfh);
437   ok(ich == ret, "First fgetc expected %x got %x\n", ich, ret);
438   ret = fgetc(tempfh);
439   ok(ich == ret, "Second fgetc expected %x got %x\n", ich, ret);
440   fclose(tempfh);
441   unlink(tempf);
442 }
443
444 static void test_fputc( void )
445 {
446   char* tempf;
447   FILE *tempfh;
448   int  ret;
449
450   tempf=_tempnam(".","wne");
451   tempfh = fopen(tempf,"wb");
452   ret = fputc(0,tempfh);
453   ok(0 == ret, "fputc(0,tempfh) expected %x got %x\n", 0, ret);
454   ret = fputc(0xff,tempfh);
455   ok(0xff == ret, "fputc(0xff,tempfh) expected %x got %x\n", 0xff, ret);
456   ret = fputc(0xffffffff,tempfh);
457   ok(0xff == ret, "fputc(0xffffffff,tempfh) expected %x got %x\n", 0xff, ret);
458   fclose(tempfh);
459
460   tempfh = fopen(tempf,"rb");
461   ret = fputc(0,tempfh);
462   ok(EOF == ret, "fputc(0,tempfh) on r/o file expected %x got %x\n", EOF, ret);
463   fclose(tempfh);
464
465   unlink(tempf);
466 }
467
468 static void test_flsbuf( void )
469 {
470   char* tempf;
471   FILE *tempfh;
472   int  c;
473   int  ret;
474   int  bufmode;
475   static const int bufmodes[] = {_IOFBF,_IONBF};
476
477   tempf=_tempnam(".","wne");
478   for (bufmode=0; bufmode < sizeof(bufmodes)/sizeof(bufmodes[0]); bufmode++)
479   {
480     tempfh = fopen(tempf,"wb");
481     setvbuf(tempfh,NULL,bufmodes[bufmode],2048);
482     ret = _flsbuf(0,tempfh);
483     ok(0 == ret, "_flsbuf(0,tempfh) with bufmode %x expected %x got %x\n",
484                          bufmodes[bufmode], 0, ret);
485     ret = _flsbuf(0xff,tempfh);
486     ok(0xff == ret, "_flsbuf(0xff,tempfh) with bufmode %x expected %x got %x\n",
487                          bufmodes[bufmode], 0, ret);
488     ret = _flsbuf(0xffffffff,tempfh);
489     ok(0xff == ret, "_flsbuf(0xffffffff,tempfh) with bufmode %x expected %x got %x\n",
490                          bufmodes[bufmode], 0, ret);
491     fclose(tempfh);
492   }
493
494   tempfh = fopen(tempf,"rb");
495   ret = _flsbuf(0,tempfh);
496   ok(EOF == ret, "_flsbuf(0,tempfh) on r/o file expected %x got %x\n", EOF, ret);
497   fclose(tempfh);
498
499   /* See bug 17123, exposed by WinAVR's make */
500   tempfh = fopen(tempf,"w");
501   ok(tempfh->_cnt == 0, "_cnt on freshly opened file was %d\n", tempfh->_cnt);
502   setbuf(tempfh, NULL);
503   ok(tempfh->_cnt == 0, "_cnt on unbuffered file was %d\n", tempfh->_cnt);
504   /* Inlined putchar sets _cnt to -1.  Native seems to ignore the value... */
505   tempfh->_cnt = 1234;
506   ret = _flsbuf('Q',tempfh);
507   ok('Q' == ret, "_flsbuf('Q',tempfh) expected %x got %x\n", 'Q', ret);
508   /* ... and reset it to zero */
509   ok(tempfh->_cnt == 0, "after unbuf _flsbuf, _cnt was %d\n", tempfh->_cnt);
510   fclose(tempfh);
511   /* And just for grins, make sure the file is correct */
512   tempfh = fopen(tempf,"r");
513   c = fgetc(tempfh);
514   ok(c == 'Q', "first byte should be 'Q'\n");
515   c = fgetc(tempfh);
516   ok(c == EOF, "there should only be one byte\n");
517   fclose(tempfh);
518
519   unlink(tempf);
520 }
521
522 static void test_fgetwc( void )
523 {
524 #define LLEN 512
525
526   char* tempf;
527   FILE *tempfh;
528   static const char mytext[]= "This is test_fgetwc\r\n";
529   WCHAR wtextW[BUFSIZ+LLEN+1];
530   WCHAR *mytextW = NULL, *aptr, *wptr;
531   BOOL diff_found = FALSE;
532   int j;
533   unsigned int i;
534   LONG l;
535
536   tempf=_tempnam(".","wne");
537   tempfh = fopen(tempf,"wb");
538   j = 'a';
539   /* pad to almost the length of the internal buffer */
540   for (i=0; i<BUFSIZ-4; i++)
541     fputc(j,tempfh);
542   j = '\r';
543   fputc(j,tempfh);
544   j = '\n';
545   fputc(j,tempfh);
546   fputs(mytext,tempfh);
547   fclose(tempfh);
548   /* in text mode, getws/c expects multibyte characters */
549   /*currently Wine only supports plain ascii, and that is all that is tested here */
550   tempfh = fopen(tempf,"rt"); /* open in TEXT mode */
551   fgetws(wtextW,LLEN,tempfh);
552   l=ftell(tempfh);
553   ok(l==BUFSIZ-2, "ftell expected %d got %d\n", BUFSIZ-2, l);
554   fgetws(wtextW,LLEN,tempfh);
555   l=ftell(tempfh);
556   ok(l==BUFSIZ-2+strlen(mytext), "ftell expected %d got %d\n", BUFSIZ-2+lstrlen(mytext), l);
557   mytextW = AtoW (mytext);
558   aptr = mytextW;
559   wptr = wtextW;
560   for (i=0; i<strlen(mytext)-2; i++, aptr++, wptr++)
561     {
562       diff_found |= (*aptr != *wptr);
563     }
564   ok(!(diff_found), "fgetwc difference found in TEXT mode\n");
565   ok(*wptr == '\n', "Carriage return was not skipped\n");
566   fclose(tempfh);
567   unlink(tempf);
568   
569   tempfh = fopen(tempf,"wb");
570   j = 'a';
571   /* pad to almost the length of the internal buffer. Use an odd number of bytes
572      to test that we can read wchars that are split across the internal buffer
573      boundary */
574   for (i=0; i<BUFSIZ-3-strlen(mytext)*sizeof(WCHAR); i++)
575     fputc(j,tempfh);
576   j = '\r';
577   fputwc(j,tempfh);
578   j = '\n';
579   fputwc(j,tempfh);
580   fputws(wtextW,tempfh);
581   fputws(wtextW,tempfh);
582   fclose(tempfh);
583   /* in binary mode, getws/c expects wide characters */
584   tempfh = fopen(tempf,"rb"); /* open in BINARY mode */
585   j=(BUFSIZ-2)/sizeof(WCHAR)-strlen(mytext);
586   fgetws(wtextW,j,tempfh);
587   l=ftell(tempfh);
588   j=(j-1)*sizeof(WCHAR);
589   ok(l==j, "ftell expected %d got %d\n", j, l);
590   i=fgetc(tempfh);
591   ok(i=='a', "fgetc expected %d got %d\n", 0x61, i);
592   l=ftell(tempfh);
593   j++;
594   ok(l==j, "ftell expected %d got %d\n", j, l);
595   fgetws(wtextW,3,tempfh);
596   ok(wtextW[0]=='\r',"expected carriage return got %04hx\n", wtextW[0]);
597   ok(wtextW[1]=='\n',"expected newline got %04hx\n", wtextW[1]);
598   l=ftell(tempfh);
599   j += 4;
600   ok(l==j, "ftell expected %d got %d\n", j, l);
601   for(i=0; i<strlen(mytext); i++)
602     wtextW[i] = 0;
603   /* the first time we get the string, it should be entirely within the local buffer */
604   fgetws(wtextW,LLEN,tempfh);
605   l=ftell(tempfh);
606   j += (strlen(mytext)-1)*sizeof(WCHAR);
607   ok(l==j, "ftell expected %d got %d\n", j, l);
608   diff_found = FALSE;
609   aptr = mytextW;
610   wptr = wtextW;
611   for (i=0; i<strlen(mytext)-2; i++, aptr++, wptr++)
612     {
613       ok(*aptr == *wptr, "Char %d expected %04hx got %04hx\n", i, *aptr, *wptr);
614       diff_found |= (*aptr != *wptr);
615     }
616   ok(!(diff_found), "fgetwc difference found in BINARY mode\n");
617   ok(*wptr == '\n', "Should get newline\n");
618   for(i=0; i<strlen(mytext); i++)
619     wtextW[i] = 0;
620   /* the second time we get the string, it should cross the local buffer boundary.
621      One of the wchars should be split across the boundary */
622   fgetws(wtextW,LLEN,tempfh);
623   diff_found = FALSE;
624   aptr = mytextW;
625   wptr = wtextW;
626   for (i=0; i<strlen(mytext)-2; i++, aptr++, wptr++)
627     {
628       ok(*aptr == *wptr, "Char %d expected %04hx got %04hx\n", i, *aptr, *wptr);
629       diff_found |= (*aptr != *wptr);
630     }
631   ok(!(diff_found), "fgetwc difference found in BINARY mode\n");
632   ok(*wptr == '\n', "Should get newline\n");
633
634   free(mytextW);
635   fclose(tempfh);
636   unlink(tempf);
637 }
638
639 static void test_ctrlz( void )
640 {
641   char* tempf;
642   FILE *tempfh;
643   static const char mytext[]= "This is test_ctrlz";
644   char buffer[256];
645   int i, j;
646   LONG l;
647
648   tempf=_tempnam(".","wne");
649   tempfh = fopen(tempf,"wb");
650   fputs(mytext,tempfh);
651   j = 0x1a; /* a ctrl-z character signals EOF in text mode */
652   fputc(j,tempfh);
653   j = '\r';
654   fputc(j,tempfh);
655   j = '\n';
656   fputc(j,tempfh);
657   j = 'a';
658   fputc(j,tempfh);
659   fclose(tempfh);
660   tempfh = fopen(tempf,"rt"); /* open in TEXT mode */
661   ok(fgets(buffer,256,tempfh) != 0,"fgets failed unexpected\n");
662   i=strlen(buffer);
663   j=strlen(mytext);
664   ok(i==j, "returned string length expected %d got %d\n", j, i);
665   j+=4; /* ftell should indicate the true end of file */
666   l=ftell(tempfh);
667   ok(l==j, "ftell expected %d got %d\n", j, l);
668   ok(feof(tempfh), "did not get EOF\n");
669   fclose(tempfh);
670   
671   tempfh = fopen(tempf,"rb"); /* open in BINARY mode */
672   ok(fgets(buffer,256,tempfh) != 0,"fgets failed unexpected\n");
673   i=strlen(buffer);
674   j=strlen(mytext)+3; /* should get through newline */
675   ok(i==j, "returned string length expected %d got %d\n", j, i);
676   l=ftell(tempfh);
677   ok(l==j, "ftell expected %d got %d\n", j, l);
678   ok(fgets(buffer,256,tempfh) != 0,"fgets failed unexpected\n");
679   i=strlen(buffer);
680   ok(i==1, "returned string length expected %d got %d\n", 1, i);
681   ok(feof(tempfh), "did not get EOF\n");
682   fclose(tempfh);
683   unlink(tempf);
684 }
685
686 static void test_file_put_get( void )
687 {
688   char* tempf;
689   FILE *tempfh;
690   static const char mytext[]=  "This is a test_file_put_get\n";
691   static const char dostext[]= "This is a test_file_put_get\r\n";
692   char btext[LLEN];
693   WCHAR wtextW[LLEN+1];
694   WCHAR *mytextW = NULL, *aptr, *wptr;
695   BOOL diff_found = FALSE;
696   unsigned int i;
697
698   tempf=_tempnam(".","wne");
699   tempfh = fopen(tempf,"wt"); /* open in TEXT mode */
700   fputs(mytext,tempfh);
701   fclose(tempfh);
702   tempfh = fopen(tempf,"rb"); /* open in TEXT mode */
703   fgets(btext,LLEN,tempfh);
704   ok( strlen(mytext) + 1 == strlen(btext),"TEXT/BINARY mode not handled for write\n");
705   ok( btext[strlen(mytext)-1] == '\r', "CR not written\n");
706   fclose(tempfh);
707   tempfh = fopen(tempf,"wb"); /* open in BINARY mode */
708   fputs(dostext,tempfh);
709   fclose(tempfh);
710   tempfh = fopen(tempf,"rt"); /* open in TEXT mode */
711   fgets(btext,LLEN,tempfh);
712   ok(strcmp(btext, mytext) == 0,"_O_TEXT read doesn't strip CR\n");
713   fclose(tempfh);
714   tempfh = fopen(tempf,"rb"); /* open in TEXT mode */
715   fgets(btext,LLEN,tempfh);
716   ok(strcmp(btext, dostext) == 0,"_O_BINARY read doesn't preserve CR\n");
717
718   fclose(tempfh);
719   tempfh = fopen(tempf,"rt"); /* open in TEXT mode */
720   fgetws(wtextW,LLEN,tempfh);
721   mytextW = AtoW (mytext);
722   aptr = mytextW;
723   wptr = wtextW;
724
725   for (i=0; i<strlen(mytext); i++, aptr++, wptr++)
726     {
727       diff_found |= (*aptr != *wptr);
728     }
729   ok(!(diff_found), "fgetwc doesn't strip CR in TEXT mode\n");
730   free(mytextW);
731   fclose(tempfh);
732   unlink(tempf);
733 }
734
735 static void test_file_write_read( void )
736 {
737   char* tempf;
738   int tempfd;
739   static const char mytext[]=  "This is test_file_write_read\nsecond line\n";
740   static const char dostext[]= "This is test_file_write_read\r\nsecond line\r\n";
741   char btext[LLEN];
742   int ret, i;
743
744   tempf=_tempnam(".","wne");
745   tempfd = _open(tempf,_O_CREAT|_O_TRUNC|_O_BINARY|_O_RDWR,
746                      _S_IREAD | _S_IWRITE);
747   ok( tempfd != -1,
748      "Can't open '%s': %d\n", tempf, errno); /* open in BINARY mode */
749   ok(_write(tempfd,dostext,strlen(dostext)) == lstrlenA(dostext),
750      "_write _O_BINARY bad return value\n");
751   _close(tempfd);
752   i = lstrlenA(mytext);
753   tempfd = _open(tempf,_O_RDONLY|_O_BINARY,0); /* open in BINARY mode */
754   ok(_read(tempfd,btext,i) == i,
755      "_read _O_BINARY got bad length\n");
756   ok( memcmp(dostext,btext,i) == 0,
757       "problems with _O_BINARY  _write / _read\n");
758   _close(tempfd);
759   tempfd = _open(tempf,_O_RDONLY|_O_TEXT); /* open in TEXT mode */
760   ok(_read(tempfd,btext,i) == i-1,
761      "_read _O_TEXT got bad length\n");
762   ok( memcmp(mytext,btext,i-1) == 0,
763       "problems with _O_BINARY _write / _O_TEXT _read\n");
764   _close(tempfd);
765   tempfd = _open(tempf,_O_CREAT|_O_TRUNC|_O_TEXT|_O_RDWR,
766                      _S_IREAD | _S_IWRITE);
767   ok( tempfd != -1,
768      "Can't open '%s': %d\n", tempf, errno); /* open in TEXT mode */
769   ok(_write(tempfd,mytext,strlen(mytext)) == lstrlenA(mytext),
770      "_write _O_TEXT bad return value\n");
771   _close(tempfd);
772   tempfd = _open(tempf,_O_RDONLY|_O_BINARY,0); /* open in BINARY mode */
773   ok(_read(tempfd,btext,LLEN) == lstrlenA(dostext),
774      "_read _O_BINARY got bad length\n");
775   ok( memcmp(dostext,btext,strlen(dostext)) == 0,
776       "problems with _O_TEXT _write / _O_BINARY _read\n");
777   ok( btext[strlen(dostext)-2] == '\r', "CR not written or read\n");
778   _close(tempfd);
779   tempfd = _open(tempf,_O_RDONLY|_O_TEXT); /* open in TEXT mode */
780   ok(_read(tempfd,btext,LLEN) == lstrlenA(mytext),
781      "_read _O_TEXT got bad length\n");
782   ok( memcmp(mytext,btext,strlen(mytext)) == 0,
783       "problems with _O_TEXT _write / _read\n");
784   _close(tempfd);
785
786   memset(btext, 0, LLEN);
787   tempfd = _open(tempf,_O_APPEND|_O_RDWR); /* open for APPEND in default mode */
788   ok(tell(tempfd) == 0, "bad position %u expecting 0\n", tell(tempfd));
789   ok(_read(tempfd,btext,LLEN) == lstrlenA(mytext), "_read _O_APPEND got bad length\n");
790   ok( memcmp(mytext,btext,strlen(mytext)) == 0, "problems with _O_APPEND _read\n");
791   _close(tempfd);
792
793   /* Test reading only \n or \r */
794   tempfd = _open(tempf,_O_RDONLY|_O_TEXT); /* open in TEXT mode */
795   _lseek(tempfd, -1, FILE_END);
796   ret = _read(tempfd,btext,LLEN);
797   ok(ret == 1, "_read expected 1 got bad length: %d\n", ret);
798   _lseek(tempfd, -2, FILE_END);
799   ret = _read(tempfd,btext,LLEN);
800   ok(ret == 1 && *btext == '\n', "_read expected '\\n' got bad length: %d\n", ret);
801   _lseek(tempfd, -3, FILE_END);
802   ret = _read(tempfd,btext,2);
803   ok(ret == 1 && *btext == 'e', "_read expected 'e' got \"%.*s\" bad length: %d\n", ret, btext, ret);
804   ok(tell(tempfd) == 42, "bad position %u expecting 42\n", tell(tempfd));
805   _close(tempfd);
806
807   ret = unlink(tempf);
808   ok( ret == 0 ,"Can't unlink '%s': %d\n", tempf, errno);
809
810   tempf=_tempnam(".","wne");
811   tempfd = _open(tempf,_O_CREAT|_O_TRUNC|_O_BINARY|_O_RDWR,0);
812   ok( tempfd != -1,
813      "Can't open '%s': %d\n", tempf, errno); /* open in BINARY mode */
814   ok(_write(tempfd,dostext,strlen(dostext)) == lstrlenA(dostext),
815      "_write _O_BINARY bad return value\n");
816   _close(tempfd);
817   tempfd = _open(tempf,_O_RDONLY|_O_BINARY,0); /* open in BINARY mode */
818   ok(_read(tempfd,btext,LLEN) == lstrlenA(dostext),
819      "_read _O_BINARY got bad length\n");
820   ok( memcmp(dostext,btext,strlen(dostext)) == 0,
821       "problems with _O_BINARY _write / _read\n");
822   ok( btext[strlen(dostext)-2] == '\r', "CR not written or read\n");
823   _close(tempfd);
824   tempfd = _open(tempf,_O_RDONLY|_O_TEXT); /* open in TEXT mode */
825   ok(_read(tempfd,btext,LLEN) == lstrlenA(mytext),
826      "_read _O_TEXT got bad length\n");
827   ok( memcmp(mytext,btext,strlen(mytext)) == 0,
828       "problems with _O_BINARY _write / _O_TEXT _read\n");
829   _close(tempfd);
830
831    ret =_chmod (tempf, _S_IREAD | _S_IWRITE);
832   ok( ret == 0,
833      "Can't chmod '%s' to read-write: %d\n", tempf, errno);
834   ret = unlink(tempf);
835   ok( ret == 0 ,"Can't unlink '%s': %d\n", tempf, errno);
836 }
837
838 static void test_file_inherit_child(const char* fd_s)
839 {
840     int fd = atoi(fd_s);
841     char buffer[32];
842     int ret;
843
844     ret =write(fd, "Success", 8);
845     ok( ret == 8, "Couldn't write in child process on %d (%s)\n", fd, strerror(errno));
846     lseek(fd, 0, SEEK_SET);
847     ok(read(fd, buffer, sizeof (buffer)) == 8, "Couldn't read back the data\n");
848     ok(memcmp(buffer, "Success", 8) == 0, "Couldn't read back the data\n");
849 }
850
851 static void test_file_inherit_child_no(const char* fd_s)
852 {
853     int fd = atoi(fd_s);
854     int ret;
855
856     ret = write(fd, "Success", 8);
857     ok( ret == -1 && errno == EBADF, 
858        "Wrong write result in child process on %d (%s)\n", fd, strerror(errno));
859 }
860  
861 static void test_file_inherit( const char* selfname )
862 {
863     int                 fd;
864     const char*         arg_v[5];
865     char                buffer[16];
866
867     fd = open ("fdopen.tst", O_CREAT | O_RDWR | O_BINARY, _S_IREAD |_S_IWRITE);
868     ok(fd != -1, "Couldn't create test file\n");
869     arg_v[0] = selfname;
870     arg_v[1] = "tests/file.c";
871     arg_v[2] = "inherit";
872     arg_v[3] = buffer; sprintf(buffer, "%d", fd);
873     arg_v[4] = 0;
874     _spawnvp(_P_WAIT, selfname, arg_v);
875     ok(tell(fd) == 8, "bad position %u expecting 8\n", tell(fd));
876     lseek(fd, 0, SEEK_SET);
877     ok(read(fd, buffer, sizeof (buffer)) == 8 && memcmp(buffer, "Success", 8) == 0, "Couldn't read back the data\n");
878     close (fd);
879     ok(unlink("fdopen.tst") == 0, "Couldn't unlink\n");
880     
881     fd = open ("fdopen.tst", O_CREAT | O_RDWR | O_BINARY | O_NOINHERIT, _S_IREAD |_S_IWRITE);
882     ok(fd != -1, "Couldn't create test file\n");
883     arg_v[0] = selfname;
884     arg_v[1] = "tests/file.c";
885     arg_v[2] = "inherit_no";
886     arg_v[3] = buffer; sprintf(buffer, "%d", fd);
887     arg_v[4] = 0;
888     _spawnvp(_P_WAIT, selfname, arg_v);
889     ok(tell(fd) == 0, "bad position %u expecting 0\n", tell(fd));
890     ok(read(fd, buffer, sizeof (buffer)) == 0, "Found unexpected data (%s)\n", buffer);
891     close (fd);
892     ok(unlink("fdopen.tst") == 0, "Couldn't unlink\n");
893 }
894
895 static void test_tmpnam( void )
896 {
897   char name[MAX_PATH] = "abc";
898   char *res;
899
900   res = tmpnam(NULL);
901   ok(res != NULL, "tmpnam returned NULL\n");
902   ok(res[0] == '\\', "first character is not a backslash\n");
903   ok(strchr(res+1, '\\') == 0, "file not in the root directory\n");
904   ok(res[strlen(res)-1] == '.', "first call - last character is not a dot\n");
905
906   res = tmpnam(name);
907   ok(res != NULL, "tmpnam returned NULL\n");
908   ok(res == name, "supplied buffer was not used\n");
909   ok(res[0] == '\\', "first character is not a backslash\n");
910   ok(strchr(res+1, '\\') == 0, "file not in the root directory\n");
911   ok(res[strlen(res)-1] != '.', "second call - last character is a dot\n");
912 }
913
914 static void test_chsize( void )
915 {
916     int fd;
917     LONG cur, pos, count;
918     char temptext[] = "012345678";
919     char *tempfile = _tempnam( ".", "tst" );
920     
921     ok( tempfile != NULL, "Couldn't create test file: %s\n", tempfile );
922
923     fd = _open( tempfile, _O_CREAT|_O_TRUNC|_O_RDWR, _S_IREAD|_S_IWRITE );
924     ok( fd > 0, "Couldn't open test file\n" );
925
926     count = _write( fd, temptext, sizeof(temptext) );
927     ok( count > 0, "Couldn't write to test file\n" );
928
929     /* get current file pointer */
930     cur = _lseek( fd, 0, SEEK_CUR );
931
932     /* make the file smaller */
933     ok( _chsize( fd, sizeof(temptext) / 2 ) == 0, "_chsize() failed\n" );
934
935     pos = _lseek( fd, 0, SEEK_CUR );
936     ok( cur == pos, "File pointer changed from: %d to: %d\n", cur, pos );
937     ok( _filelength( fd ) == sizeof(temptext) / 2, "Wrong file size\n" );
938
939     /* enlarge the file */
940     ok( _chsize( fd, sizeof(temptext) * 2 ) == 0, "_chsize() failed\n" ); 
941
942     pos = _lseek( fd, 0, SEEK_CUR );
943     ok( cur == pos, "File pointer changed from: %d to: %d\n", cur, pos );
944     ok( _filelength( fd ) == sizeof(temptext) * 2, "Wrong file size\n" );
945
946     _close( fd );
947     _unlink( tempfile );
948 }
949
950 static void test_fopen_fclose_fcloseall( void )
951 {
952     char fname1[] = "empty1";
953     char fname2[] = "empty2";
954     char fname3[] = "empty3";
955     FILE *stream1, *stream2, *stream3, *stream4;
956     int ret, numclosed;
957
958     /* testing fopen() */
959     stream1 = fopen(fname1, "w+");
960     ok(stream1 != NULL, "The file '%s' was not opened\n", fname1);
961     stream2 = fopen(fname2, "w ");
962     ok(stream2 != NULL, "The file '%s' was not opened\n", fname2 );
963     _unlink(fname3);
964     stream3 = fopen(fname3, "r");
965     ok(stream3 == NULL, "The file '%s' shouldn't exist before\n", fname3 );
966     stream3 = fopen(fname3, "w+");
967     ok(stream3 != NULL, "The file '%s' should be opened now\n", fname3 );
968     errno = 0xfaceabad;
969     stream4 = fopen("", "w+");
970     ok(stream4 == NULL && (errno == EINVAL || errno == ENOENT),
971        "filename is empty, errno = %d (expected 2 or 22)\n", errno);
972     errno = 0xfaceabad;
973     stream4 = fopen(NULL, "w+");
974     ok(stream4 == NULL && (errno == EINVAL || errno == ENOENT), 
975        "filename is NULL, errno = %d (expected 2 or 22)\n", errno);
976
977     /* testing fclose() */
978     ret = fclose(stream2);
979     ok(ret == 0, "The file '%s' was not closed\n", fname2);
980     ret = fclose(stream3);
981     ok(ret == 0, "The file '%s' was not closed\n", fname3);
982     ret = fclose(stream2);
983     ok(ret == EOF, "Closing file '%s' returned %d\n", fname2, ret);
984     ret = fclose(stream3);
985     ok(ret == EOF, "Closing file '%s' returned %d\n", fname3, ret);
986
987     /* testing fcloseall() */
988     numclosed = _fcloseall();
989     /* fname1 should be closed here */
990     ok(numclosed == 1, "Number of files closed by fcloseall(): %u\n", numclosed);
991     numclosed = _fcloseall();
992     ok(numclosed == 0, "Number of files closed by fcloseall(): %u\n", numclosed);
993
994     ok(_unlink(fname1) == 0, "Couldn't unlink file named '%s'\n", fname1);
995     ok(_unlink(fname2) == 0, "Couldn't unlink file named '%s'\n", fname2);
996     ok(_unlink(fname3) == 0, "Couldn't unlink file named '%s'\n", fname3);
997 }
998
999 static void test_get_osfhandle(void)
1000 {
1001     int fd;
1002     char fname[] = "t_get_osfhanle";
1003     DWORD bytes_written;
1004     HANDLE handle;
1005
1006     fd = _sopen(fname, _O_CREAT|_O_RDWR, _SH_DENYRW, _S_IREAD | _S_IWRITE);
1007     handle = (HANDLE)_get_osfhandle(fd);
1008     WriteFile(handle, "bar", 3, &bytes_written, NULL);
1009     _close(fd);
1010     fd = _open(fname, _O_RDONLY, 0);
1011     ok(fd != -1, "Coudn't open '%s' after _get_osfhanle()\n", fname);
1012
1013     _close(fd);
1014     _unlink(fname);
1015 }
1016
1017 static void test_setmaxstdio(void)
1018 {
1019     ok(2048 == _setmaxstdio(2048),"_setmaxstdio returned %d instead of 2048\n",_setmaxstdio(2048));
1020     ok(-1 == _setmaxstdio(2049),"_setmaxstdio returned %d instead of -1\n",_setmaxstdio(2049));
1021 }
1022
1023 static void test_stat(void)
1024 {
1025     int fd;
1026     int pipes[2];
1027     struct stat buf;
1028
1029     /* Tests for a file */
1030     fd = open("stat.tst", O_WRONLY | O_CREAT | O_BINARY, _S_IREAD |_S_IWRITE);
1031     if (fd >= 0)
1032     {
1033         ok(fstat(fd, &buf) == 0, "fstat failed: errno=%d\n", errno);
1034         ok((buf.st_mode & _S_IFMT) == _S_IFREG, "bad format = %06o\n", buf.st_mode);
1035         ok((buf.st_mode & 0777) == 0666, "bad st_mode = %06o\n", buf.st_mode);
1036         ok(buf.st_dev == 0, "st_dev is %d, expected 0\n", buf.st_dev);
1037         ok(buf.st_dev == buf.st_rdev, "st_dev (%d) and st_rdev (%d) differ\n", buf.st_dev, buf.st_rdev);
1038         ok(buf.st_nlink == 1, "st_nlink is %d, expected 1\n", buf.st_nlink);
1039         ok(buf.st_size == 0, "st_size is %d, expected 0\n", buf.st_size);
1040
1041         ok(stat("stat.tst", &buf) == 0, "stat failed: errno=%d\n", errno);
1042         ok((buf.st_mode & _S_IFMT) == _S_IFREG, "bad format = %06o\n", buf.st_mode);
1043         ok((buf.st_mode & 0777) == 0666, "bad st_mode = %06o\n", buf.st_mode);
1044         ok(buf.st_dev == buf.st_rdev, "st_dev (%d) and st_rdev (%d) differ\n", buf.st_dev, buf.st_rdev);
1045         ok(buf.st_nlink == 1, "st_nlink is %d, expected 1\n", buf.st_nlink);
1046         ok(buf.st_size == 0, "st_size is %d, expected 0\n", buf.st_size);
1047
1048         close(fd);
1049         remove("stat.tst");
1050     }
1051     else
1052         skip("open failed with errno %d\n", errno);
1053
1054     /* Tests for a char device */
1055     if (_dup2(0, 10) == 0)
1056     {
1057         ok(fstat(10, &buf) == 0, "fstat(stdin) failed: errno=%d\n", errno);
1058         if ((buf.st_mode & _S_IFMT) == _S_IFCHR)
1059         {
1060             ok(buf.st_mode == _S_IFCHR, "bad st_mode=%06o\n", buf.st_mode);
1061             ok(buf.st_dev == 10, "st_dev is %d, expected 10\n", buf.st_dev);
1062             ok(buf.st_rdev == 10, "st_rdev is %d, expected 10\n", buf.st_rdev);
1063             ok(buf.st_nlink == 1, "st_nlink is %d, expected 1\n", buf.st_nlink);
1064         }
1065         else
1066             skip("stdin is not a char device? st_mode=%06o\n", buf.st_mode);
1067         close(10);
1068     }
1069     else
1070         skip("_dup2 failed with errno %d\n", errno);
1071
1072     /* Tests for pipes */
1073     if (_pipe(pipes, 1024, O_BINARY) == 0)
1074     {
1075         ok(fstat(pipes[0], &buf) == 0, "fstat(pipe) failed: errno=%d\n", errno);
1076         ok(buf.st_mode == _S_IFIFO, "bad st_mode=%06o\n", buf.st_mode);
1077         ok(buf.st_dev == pipes[0], "st_dev is %d, expected %d\n", buf.st_dev, pipes[0]);
1078         ok(buf.st_rdev == pipes[0], "st_rdev is %d, expected %d\n", buf.st_rdev, pipes[0]);
1079         ok(buf.st_nlink == 1, "st_nlink is %d, expected 1\n", buf.st_nlink);
1080         close(pipes[0]);
1081         close(pipes[1]);
1082     }
1083     else
1084         skip("pipe failed with errno %d\n", errno);
1085 }
1086
1087 static const char* pipe_string="Hello world";
1088
1089 /* How many messages to transfer over the pipe */
1090 #define N_TEST_MESSAGES 3
1091
1092 static void test_pipes_child(int argc, char** args)
1093 {
1094     int fd;
1095     int nwritten;
1096     int i;
1097
1098     if (argc < 5)
1099     {
1100         ok(0, "not enough parameters: %d\n", argc);
1101         return;
1102     }
1103
1104     fd=atoi(args[3]);
1105     ok(close(fd) == 0, "unable to close %d: %d\n", fd, errno);
1106
1107     fd=atoi(args[4]);
1108
1109     for (i=0; i<N_TEST_MESSAGES; i++) {
1110        nwritten=write(fd, pipe_string, strlen(pipe_string));
1111        ok(nwritten == strlen(pipe_string), "i %d, expected to write '%s' wrote %d\n", i, pipe_string, nwritten);
1112        /* let other process wake up so they can show off their "keep reading until EOF" behavior */
1113        if (i < N_TEST_MESSAGES-1)
1114            Sleep(100);
1115     }
1116
1117     ok(close(fd) == 0, "unable to close %d: %d\n", fd, errno);
1118 }
1119
1120 static void test_pipes(const char* selfname)
1121 {
1122     int pipes[2];
1123     char str_fdr[12], str_fdw[12];
1124     FILE* file;
1125     const char* arg_v[6];
1126     char buf[4096];
1127     char expected[4096];
1128     int r;
1129     int i;
1130
1131     /* Test reading from a pipe with read() */
1132     if (_pipe(pipes, 1024, O_BINARY) < 0)
1133     {
1134         ok(0, "pipe failed with errno %d\n", errno);
1135         return;
1136     }
1137
1138     arg_v[0] = selfname;
1139     arg_v[1] = "tests/file.c";
1140     arg_v[2] = "pipes";
1141     arg_v[3] = str_fdr; sprintf(str_fdr, "%d", pipes[0]);
1142     arg_v[4] = str_fdw; sprintf(str_fdw, "%d", pipes[1]);
1143     arg_v[5] = NULL;
1144     proc_handles[0] = (HANDLE)_spawnvp(_P_NOWAIT, selfname, arg_v);
1145     ok(close(pipes[1]) == 0, "unable to close %d: %d\n", pipes[1], errno);
1146
1147     for (i=0; i<N_TEST_MESSAGES; i++) {
1148        r=read(pipes[0], buf, sizeof(buf)-1);
1149        ok(r == strlen(pipe_string), "i %d, got %d\n", i, r);
1150        if (r > 0)
1151            buf[r]='\0';
1152        ok(strcmp(buf, pipe_string) == 0, "expected to read '%s', got '%s'\n", pipe_string, buf);
1153    }
1154
1155     r=read(pipes[0], buf, sizeof(buf)-1);
1156     ok(r == 0, "expected to read 0 bytes, got %d\n", r);
1157     ok(close(pipes[0]) == 0, "unable to close %d: %d\n", pipes[0], errno);
1158
1159     /* Test reading from a pipe with fread() */
1160     if (_pipe(pipes, 1024, O_BINARY) < 0)
1161     {
1162         ok(0, "pipe failed with errno %d\n", errno);
1163         return;
1164     }
1165
1166     arg_v[0] = selfname;
1167     arg_v[1] = "tests/file.c";
1168     arg_v[2] = "pipes";
1169     arg_v[3] = str_fdr; sprintf(str_fdr, "%d", pipes[0]);
1170     arg_v[4] = str_fdw; sprintf(str_fdw, "%d", pipes[1]);
1171     arg_v[5] = NULL;
1172     proc_handles[1] = (HANDLE)_spawnvp(_P_NOWAIT, selfname, arg_v);
1173     ok(close(pipes[1]) == 0, "unable to close %d: %d\n", pipes[1], errno);
1174     file=fdopen(pipes[0], "r");
1175
1176     /* In blocking mode, fread will keep calling read() until it gets
1177      * enough bytes, or EOF, even on Unix.  (If this were a Unix terminal
1178      * in cooked mode instead of a pipe, it would also stop on EOL.)
1179      */
1180     expected[0] = 0;
1181     for (i=0; i<N_TEST_MESSAGES; i++)
1182        strcat(expected, pipe_string);
1183     r=fread(buf, 1, sizeof(buf)-1, file);
1184     ok(r == strlen(expected), "fread() returned %d: ferror=%d\n", r, ferror(file));
1185     if (r > 0)
1186        buf[r]='\0';
1187     ok(strcmp(buf, expected) == 0, "got '%s' expected '%s'\n", buf, expected);
1188
1189     /* Let child close the file before we read, so we can sense EOF reliably */
1190     Sleep(100);
1191     r=fread(buf, 1, sizeof(buf)-1, file);
1192     ok(r == 0, "fread() returned %d instead of 0\n", r);
1193     ok(ferror(file) == 0, "got ferror() = %d\n", ferror(file));
1194     ok(feof(file), "feof() is false!\n");
1195
1196     ok(fclose(file) == 0, "unable to close the pipe: %d\n", errno);
1197 }
1198
1199 static void test_unlink(void)
1200 {
1201     FILE* file;
1202     ok(mkdir("test_unlink") == 0, "unable to create test dir\n");
1203     file = fopen("test_unlink\\empty", "w");
1204     ok(file != NULL, "unable to create test file\n");
1205     if(file)
1206       fclose(file);
1207     ok(_unlink("test_unlink") != 0, "unlinking a non-empty directory must fail\n");
1208     unlink("test_unlink\\empty");
1209     rmdir("test_unlink");
1210 }
1211
1212 START_TEST(file)
1213 {
1214     int arg_c;
1215     char** arg_v;
1216
1217     arg_c = winetest_get_mainargs( &arg_v );
1218
1219     /* testing low-level I/O */
1220     if (arg_c >= 3)
1221     {
1222         if (strcmp(arg_v[2], "inherit") == 0)
1223             test_file_inherit_child(arg_v[3]);
1224         else if (strcmp(arg_v[2], "inherit_no") == 0)
1225             test_file_inherit_child_no(arg_v[3]);
1226         else if (strcmp(arg_v[2], "pipes") == 0)
1227             test_pipes_child(arg_c, arg_v);
1228         else
1229             ok(0, "invalid argument '%s'\n", arg_v[2]);
1230         return;
1231     }
1232     test_file_inherit(arg_v[0]);
1233     test_file_write_read();
1234     test_chsize();
1235     test_stat();
1236     test_unlink();
1237
1238     /* testing stream I/O */
1239     test_filbuf();
1240     test_fdopen();
1241     test_fopen_fclose_fcloseall();
1242     test_fileops();
1243     test_asciimode();
1244     test_asciimode2();
1245     test_readmode(FALSE); /* binary mode */
1246     test_readmode(TRUE);  /* ascii mode */
1247     test_fgetc();
1248     test_fputc();
1249     test_flsbuf();
1250     test_fgetwc();
1251     test_ctrlz();
1252     test_file_put_get();
1253     test_tmpnam();
1254     test_get_osfhandle();
1255     test_setmaxstdio();
1256     test_pipes(arg_v[0]);
1257
1258     /* Wait for the (_P_NOWAIT) spawned processes to finish to make sure the report
1259      * file contains lines in the correct order
1260      */
1261     WaitForMultipleObjects(sizeof(proc_handles)/sizeof(proc_handles[0]), proc_handles, TRUE, 5000);
1262 }