comctl32/listview: Free ID array when removing all items.
[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 create_io_inherit_block( STARTUPINFO *startup, unsigned int count, const HANDLE *handles )
862 {
863     static BYTE block[1024];
864     BYTE *wxflag_ptr;
865     HANDLE *handle_ptr;
866     unsigned int i;
867
868     startup->lpReserved2 = block;
869     startup->cbReserved2 = sizeof(unsigned) + (sizeof(char) + sizeof(HANDLE)) * count;
870     wxflag_ptr = block + sizeof(unsigned);
871     handle_ptr = (HANDLE *)(wxflag_ptr + count);
872
873     *(unsigned*)block = count;
874     for (i = 0; i < count; i++)
875     {
876         wxflag_ptr[i] = 0x81;
877         handle_ptr[i] = handles[i];
878     }
879 }
880
881 static const char *read_file( HANDLE file )
882 {
883     static char buffer[128];
884     DWORD ret;
885     SetFilePointer( file, 0, NULL, FILE_BEGIN );
886     if (!ReadFile( file, buffer, sizeof(buffer) - 1, &ret, NULL)) ret = 0;
887     buffer[ret] = 0;
888     return buffer;
889 }
890
891 static void test_stdout_handle( STARTUPINFO *startup, char *cmdline, HANDLE hstdout, BOOL expect_stdout,
892                                 const char *descr )
893 {
894     const char *data;
895     HANDLE hErrorFile;
896     SECURITY_ATTRIBUTES sa;
897     PROCESS_INFORMATION proc;
898
899     /* make file handle inheritable */
900     sa.nLength = sizeof(sa);
901     sa.lpSecurityDescriptor = NULL;
902     sa.bInheritHandle = TRUE;
903
904     hErrorFile = CreateFileA( "fdopen.err", GENERIC_READ|GENERIC_WRITE,
905                               FILE_SHARE_READ | FILE_SHARE_WRITE, &sa, CREATE_ALWAYS, 0, NULL );
906     startup->dwFlags    = STARTF_USESTDHANDLES;
907     startup->hStdInput  = GetStdHandle( STD_INPUT_HANDLE );
908     startup->hStdOutput = hErrorFile;
909     startup->hStdError  = GetStdHandle( STD_ERROR_HANDLE );
910
911     CreateProcessA( NULL, cmdline, NULL, NULL, TRUE,
912                     CREATE_DEFAULT_ERROR_MODE | NORMAL_PRIORITY_CLASS, NULL, NULL, startup, &proc );
913     winetest_wait_child_process( proc.hProcess );
914
915     data = read_file( hErrorFile );
916     if (expect_stdout)
917         ok( strcmp( data, "Success" ), "%s: Error file shouldn't contain data\n", descr );
918     else
919         ok( !strcmp( data, "Success" ), "%s: Wrong error data (%s)\n", descr, data );
920
921     if (hstdout)
922     {
923         data = read_file( hstdout );
924         if (expect_stdout)
925             ok( !strcmp( data, "Success" ), "%s: Wrong stdout data (%s)\n", descr, data );
926         else
927             ok( strcmp( data, "Success" ), "%s: Stdout file shouldn't contain data\n", descr );
928     }
929
930     CloseHandle( hErrorFile );
931     DeleteFile( "fdopen.err" );
932 }
933
934 static void test_file_inherit( const char* selfname )
935 {
936     int                 fd;
937     const char*         arg_v[5];
938     char                buffer[16];
939     char cmdline[MAX_PATH];
940     STARTUPINFO startup;
941     SECURITY_ATTRIBUTES sa;
942     HANDLE handles[3];
943
944     fd = open ("fdopen.tst", O_CREAT | O_RDWR | O_BINARY, _S_IREAD |_S_IWRITE);
945     ok(fd != -1, "Couldn't create test file\n");
946     arg_v[0] = selfname;
947     arg_v[1] = "tests/file.c";
948     arg_v[2] = "inherit";
949     arg_v[3] = buffer; sprintf(buffer, "%d", fd);
950     arg_v[4] = 0;
951     _spawnvp(_P_WAIT, selfname, arg_v);
952     ok(tell(fd) == 8, "bad position %u expecting 8\n", tell(fd));
953     lseek(fd, 0, SEEK_SET);
954     ok(read(fd, buffer, sizeof (buffer)) == 8 && memcmp(buffer, "Success", 8) == 0, "Couldn't read back the data\n");
955     close (fd);
956     ok(unlink("fdopen.tst") == 0, "Couldn't unlink\n");
957     
958     fd = open ("fdopen.tst", O_CREAT | O_RDWR | O_BINARY | O_NOINHERIT, _S_IREAD |_S_IWRITE);
959     ok(fd != -1, "Couldn't create test file\n");
960     arg_v[0] = selfname;
961     arg_v[1] = "tests/file.c";
962     arg_v[2] = "inherit_no";
963     arg_v[3] = buffer; sprintf(buffer, "%d", fd);
964     arg_v[4] = 0;
965     _spawnvp(_P_WAIT, selfname, arg_v);
966     ok(tell(fd) == 0, "bad position %u expecting 0\n", tell(fd));
967     ok(read(fd, buffer, sizeof (buffer)) == 0, "Found unexpected data (%s)\n", buffer);
968     close (fd);
969     ok(unlink("fdopen.tst") == 0, "Couldn't unlink\n");
970
971     /* make file handle inheritable */
972     sa.nLength = sizeof(sa);
973     sa.lpSecurityDescriptor = NULL;
974     sa.bInheritHandle = TRUE;
975     sprintf(cmdline, "%s file inherit 1", selfname);
976
977     /* init an empty Reserved2, which should not be recognized as inherit-block */
978     ZeroMemory(&startup, sizeof(STARTUPINFO));
979     startup.cb = sizeof(startup);
980     create_io_inherit_block( &startup, 0, NULL );
981     test_stdout_handle( &startup, cmdline, 0, FALSE, "empty block" );
982
983     /* test with valid inheritblock */
984     handles[0] = GetStdHandle( STD_INPUT_HANDLE );
985     handles[1] = CreateFileA( "fdopen.tst", GENERIC_READ|GENERIC_WRITE,
986                               FILE_SHARE_READ | FILE_SHARE_WRITE, &sa, CREATE_ALWAYS, 0, NULL );
987     handles[2] = GetStdHandle( STD_ERROR_HANDLE );
988     create_io_inherit_block( &startup, 3, handles );
989     test_stdout_handle( &startup, cmdline, handles[1], TRUE, "valid block" );
990     CloseHandle( handles[1] );
991     DeleteFile("fdopen.tst");
992
993     /* test inherit block starting with unsigned zero */
994     handles[1] = CreateFileA( "fdopen.tst", GENERIC_READ|GENERIC_WRITE,
995                               FILE_SHARE_READ | FILE_SHARE_WRITE, &sa, CREATE_ALWAYS, 0, NULL );
996     create_io_inherit_block( &startup, 3, handles );
997     *(unsigned int *)startup.lpReserved2 = 0;
998     test_stdout_handle( &startup, cmdline, handles[1], FALSE, "zero count block" );
999     CloseHandle( handles[1] );
1000     DeleteFile("fdopen.tst");
1001
1002     /* test inherit block with smaller size */
1003     handles[1] = CreateFileA( "fdopen.tst", GENERIC_READ|GENERIC_WRITE,
1004                               FILE_SHARE_READ | FILE_SHARE_WRITE, &sa, CREATE_ALWAYS, 0, NULL );
1005     create_io_inherit_block( &startup, 3, handles );
1006     startup.cbReserved2 -= 3;
1007     test_stdout_handle( &startup, cmdline, handles[1], TRUE, "small size block" );
1008     CloseHandle( handles[1] );
1009     DeleteFile("fdopen.tst");
1010
1011     /* test inherit block with even smaller size */
1012     handles[1] = CreateFileA( "fdopen.tst", GENERIC_READ|GENERIC_WRITE,
1013                               FILE_SHARE_READ | FILE_SHARE_WRITE, &sa, CREATE_ALWAYS, 0, NULL );
1014     create_io_inherit_block( &startup, 3, handles );
1015     startup.cbReserved2 = sizeof(unsigned int) + sizeof(HANDLE) + sizeof(char);
1016     test_stdout_handle( &startup, cmdline, handles[1], FALSE, "smaller size block" );
1017     CloseHandle( handles[1] );
1018     DeleteFile("fdopen.tst");
1019
1020     /* test inherit block with larger size */
1021     handles[1] = CreateFileA( "fdopen.tst", GENERIC_READ|GENERIC_WRITE,
1022                               FILE_SHARE_READ | FILE_SHARE_WRITE, &sa, CREATE_ALWAYS, 0, NULL );
1023     create_io_inherit_block( &startup, 3, handles );
1024     startup.cbReserved2 += 7;
1025     test_stdout_handle( &startup, cmdline, handles[1], TRUE, "large size block" );
1026     CloseHandle( handles[1] );
1027     DeleteFile("fdopen.tst");
1028 }
1029
1030 static void test_tmpnam( void )
1031 {
1032   char name[MAX_PATH] = "abc";
1033   char *res;
1034
1035   res = tmpnam(NULL);
1036   ok(res != NULL, "tmpnam returned NULL\n");
1037   ok(res[0] == '\\', "first character is not a backslash\n");
1038   ok(strchr(res+1, '\\') == 0, "file not in the root directory\n");
1039   ok(res[strlen(res)-1] == '.', "first call - last character is not a dot\n");
1040
1041   res = tmpnam(name);
1042   ok(res != NULL, "tmpnam returned NULL\n");
1043   ok(res == name, "supplied buffer was not used\n");
1044   ok(res[0] == '\\', "first character is not a backslash\n");
1045   ok(strchr(res+1, '\\') == 0, "file not in the root directory\n");
1046   ok(res[strlen(res)-1] != '.', "second call - last character is a dot\n");
1047 }
1048
1049 static void test_chsize( void )
1050 {
1051     int fd;
1052     LONG cur, pos, count;
1053     char temptext[] = "012345678";
1054     char *tempfile = _tempnam( ".", "tst" );
1055     
1056     ok( tempfile != NULL, "Couldn't create test file: %s\n", tempfile );
1057
1058     fd = _open( tempfile, _O_CREAT|_O_TRUNC|_O_RDWR, _S_IREAD|_S_IWRITE );
1059     ok( fd > 0, "Couldn't open test file\n" );
1060
1061     count = _write( fd, temptext, sizeof(temptext) );
1062     ok( count > 0, "Couldn't write to test file\n" );
1063
1064     /* get current file pointer */
1065     cur = _lseek( fd, 0, SEEK_CUR );
1066
1067     /* make the file smaller */
1068     ok( _chsize( fd, sizeof(temptext) / 2 ) == 0, "_chsize() failed\n" );
1069
1070     pos = _lseek( fd, 0, SEEK_CUR );
1071     ok( cur == pos, "File pointer changed from: %d to: %d\n", cur, pos );
1072     ok( _filelength( fd ) == sizeof(temptext) / 2, "Wrong file size\n" );
1073
1074     /* enlarge the file */
1075     ok( _chsize( fd, sizeof(temptext) * 2 ) == 0, "_chsize() failed\n" ); 
1076
1077     pos = _lseek( fd, 0, SEEK_CUR );
1078     ok( cur == pos, "File pointer changed from: %d to: %d\n", cur, pos );
1079     ok( _filelength( fd ) == sizeof(temptext) * 2, "Wrong file size\n" );
1080
1081     _close( fd );
1082     _unlink( tempfile );
1083 }
1084
1085 static void test_fopen_fclose_fcloseall( void )
1086 {
1087     char fname1[] = "empty1";
1088     char fname2[] = "empty2";
1089     char fname3[] = "empty3";
1090     FILE *stream1, *stream2, *stream3, *stream4;
1091     int ret, numclosed;
1092
1093     /* testing fopen() */
1094     stream1 = fopen(fname1, "w+");
1095     ok(stream1 != NULL, "The file '%s' was not opened\n", fname1);
1096     stream2 = fopen(fname2, "w ");
1097     ok(stream2 != NULL, "The file '%s' was not opened\n", fname2 );
1098     _unlink(fname3);
1099     stream3 = fopen(fname3, "r");
1100     ok(stream3 == NULL, "The file '%s' shouldn't exist before\n", fname3 );
1101     stream3 = fopen(fname3, "w+");
1102     ok(stream3 != NULL, "The file '%s' should be opened now\n", fname3 );
1103     errno = 0xfaceabad;
1104     stream4 = fopen("", "w+");
1105     ok(stream4 == NULL && (errno == EINVAL || errno == ENOENT),
1106        "filename is empty, errno = %d (expected 2 or 22)\n", errno);
1107     errno = 0xfaceabad;
1108     stream4 = fopen(NULL, "w+");
1109     ok(stream4 == NULL && (errno == EINVAL || errno == ENOENT), 
1110        "filename is NULL, errno = %d (expected 2 or 22)\n", errno);
1111
1112     /* testing fclose() */
1113     ret = fclose(stream2);
1114     ok(ret == 0, "The file '%s' was not closed\n", fname2);
1115     ret = fclose(stream3);
1116     ok(ret == 0, "The file '%s' was not closed\n", fname3);
1117     ret = fclose(stream2);
1118     ok(ret == EOF, "Closing file '%s' returned %d\n", fname2, ret);
1119     ret = fclose(stream3);
1120     ok(ret == EOF, "Closing file '%s' returned %d\n", fname3, ret);
1121
1122     /* testing fcloseall() */
1123     numclosed = _fcloseall();
1124     /* fname1 should be closed here */
1125     ok(numclosed == 1, "Number of files closed by fcloseall(): %u\n", numclosed);
1126     numclosed = _fcloseall();
1127     ok(numclosed == 0, "Number of files closed by fcloseall(): %u\n", numclosed);
1128
1129     ok(_unlink(fname1) == 0, "Couldn't unlink file named '%s'\n", fname1);
1130     ok(_unlink(fname2) == 0, "Couldn't unlink file named '%s'\n", fname2);
1131     ok(_unlink(fname3) == 0, "Couldn't unlink file named '%s'\n", fname3);
1132 }
1133
1134 static void test_get_osfhandle(void)
1135 {
1136     int fd;
1137     char fname[] = "t_get_osfhanle";
1138     DWORD bytes_written;
1139     HANDLE handle;
1140
1141     fd = _sopen(fname, _O_CREAT|_O_RDWR, _SH_DENYRW, _S_IREAD | _S_IWRITE);
1142     handle = (HANDLE)_get_osfhandle(fd);
1143     WriteFile(handle, "bar", 3, &bytes_written, NULL);
1144     _close(fd);
1145     fd = _open(fname, _O_RDONLY, 0);
1146     ok(fd != -1, "Coudn't open '%s' after _get_osfhanle()\n", fname);
1147
1148     _close(fd);
1149     _unlink(fname);
1150 }
1151
1152 static void test_setmaxstdio(void)
1153 {
1154     ok(2048 == _setmaxstdio(2048),"_setmaxstdio returned %d instead of 2048\n",_setmaxstdio(2048));
1155     ok(-1 == _setmaxstdio(2049),"_setmaxstdio returned %d instead of -1\n",_setmaxstdio(2049));
1156 }
1157
1158 static void test_stat(void)
1159 {
1160     int fd;
1161     int pipes[2];
1162     struct stat buf;
1163
1164     /* Tests for a file */
1165     fd = open("stat.tst", O_WRONLY | O_CREAT | O_BINARY, _S_IREAD |_S_IWRITE);
1166     if (fd >= 0)
1167     {
1168         ok(fstat(fd, &buf) == 0, "fstat failed: errno=%d\n", errno);
1169         ok((buf.st_mode & _S_IFMT) == _S_IFREG, "bad format = %06o\n", buf.st_mode);
1170         ok((buf.st_mode & 0777) == 0666, "bad st_mode = %06o\n", buf.st_mode);
1171         ok(buf.st_dev == 0, "st_dev is %d, expected 0\n", buf.st_dev);
1172         ok(buf.st_dev == buf.st_rdev, "st_dev (%d) and st_rdev (%d) differ\n", buf.st_dev, buf.st_rdev);
1173         ok(buf.st_nlink == 1, "st_nlink is %d, expected 1\n", buf.st_nlink);
1174         ok(buf.st_size == 0, "st_size is %d, expected 0\n", buf.st_size);
1175
1176         ok(stat("stat.tst", &buf) == 0, "stat failed: errno=%d\n", errno);
1177         ok((buf.st_mode & _S_IFMT) == _S_IFREG, "bad format = %06o\n", buf.st_mode);
1178         ok((buf.st_mode & 0777) == 0666, "bad st_mode = %06o\n", buf.st_mode);
1179         ok(buf.st_dev == buf.st_rdev, "st_dev (%d) and st_rdev (%d) differ\n", buf.st_dev, buf.st_rdev);
1180         ok(buf.st_nlink == 1, "st_nlink is %d, expected 1\n", buf.st_nlink);
1181         ok(buf.st_size == 0, "st_size is %d, expected 0\n", buf.st_size);
1182
1183         close(fd);
1184         remove("stat.tst");
1185     }
1186     else
1187         skip("open failed with errno %d\n", errno);
1188
1189     /* Tests for a char device */
1190     if (_dup2(0, 10) == 0)
1191     {
1192         ok(fstat(10, &buf) == 0, "fstat(stdin) failed: errno=%d\n", errno);
1193         if ((buf.st_mode & _S_IFMT) == _S_IFCHR)
1194         {
1195             ok(buf.st_mode == _S_IFCHR, "bad st_mode=%06o\n", buf.st_mode);
1196             ok(buf.st_dev == 10, "st_dev is %d, expected 10\n", buf.st_dev);
1197             ok(buf.st_rdev == 10, "st_rdev is %d, expected 10\n", buf.st_rdev);
1198             ok(buf.st_nlink == 1, "st_nlink is %d, expected 1\n", buf.st_nlink);
1199         }
1200         else
1201             skip("stdin is not a char device? st_mode=%06o\n", buf.st_mode);
1202         close(10);
1203     }
1204     else
1205         skip("_dup2 failed with errno %d\n", errno);
1206
1207     /* Tests for pipes */
1208     if (_pipe(pipes, 1024, O_BINARY) == 0)
1209     {
1210         ok(fstat(pipes[0], &buf) == 0, "fstat(pipe) failed: errno=%d\n", errno);
1211         ok(buf.st_mode == _S_IFIFO, "bad st_mode=%06o\n", buf.st_mode);
1212         ok(buf.st_dev == pipes[0], "st_dev is %d, expected %d\n", buf.st_dev, pipes[0]);
1213         ok(buf.st_rdev == pipes[0], "st_rdev is %d, expected %d\n", buf.st_rdev, pipes[0]);
1214         ok(buf.st_nlink == 1, "st_nlink is %d, expected 1\n", buf.st_nlink);
1215         close(pipes[0]);
1216         close(pipes[1]);
1217     }
1218     else
1219         skip("pipe failed with errno %d\n", errno);
1220 }
1221
1222 static const char* pipe_string="Hello world";
1223
1224 /* How many messages to transfer over the pipe */
1225 #define N_TEST_MESSAGES 3
1226
1227 static void test_pipes_child(int argc, char** args)
1228 {
1229     int fd;
1230     int nwritten;
1231     int i;
1232
1233     if (argc < 5)
1234     {
1235         ok(0, "not enough parameters: %d\n", argc);
1236         return;
1237     }
1238
1239     fd=atoi(args[3]);
1240     ok(close(fd) == 0, "unable to close %d: %d\n", fd, errno);
1241
1242     fd=atoi(args[4]);
1243
1244     for (i=0; i<N_TEST_MESSAGES; i++) {
1245        nwritten=write(fd, pipe_string, strlen(pipe_string));
1246        ok(nwritten == strlen(pipe_string), "i %d, expected to write '%s' wrote %d\n", i, pipe_string, nwritten);
1247        /* let other process wake up so they can show off their "keep reading until EOF" behavior */
1248        if (i < N_TEST_MESSAGES-1)
1249            Sleep(100);
1250     }
1251
1252     ok(close(fd) == 0, "unable to close %d: %d\n", fd, errno);
1253 }
1254
1255 static void test_pipes(const char* selfname)
1256 {
1257     int pipes[2];
1258     char str_fdr[12], str_fdw[12];
1259     FILE* file;
1260     const char* arg_v[6];
1261     char buf[4096];
1262     char expected[4096];
1263     int r;
1264     int i;
1265
1266     /* Test reading from a pipe with read() */
1267     if (_pipe(pipes, 1024, O_BINARY) < 0)
1268     {
1269         ok(0, "pipe failed with errno %d\n", errno);
1270         return;
1271     }
1272
1273     arg_v[0] = selfname;
1274     arg_v[1] = "tests/file.c";
1275     arg_v[2] = "pipes";
1276     arg_v[3] = str_fdr; sprintf(str_fdr, "%d", pipes[0]);
1277     arg_v[4] = str_fdw; sprintf(str_fdw, "%d", pipes[1]);
1278     arg_v[5] = NULL;
1279     proc_handles[0] = (HANDLE)_spawnvp(_P_NOWAIT, selfname, arg_v);
1280     ok(close(pipes[1]) == 0, "unable to close %d: %d\n", pipes[1], errno);
1281
1282     for (i=0; i<N_TEST_MESSAGES; i++) {
1283        r=read(pipes[0], buf, sizeof(buf)-1);
1284        ok(r == strlen(pipe_string), "i %d, got %d\n", i, r);
1285        if (r > 0)
1286            buf[r]='\0';
1287        ok(strcmp(buf, pipe_string) == 0, "expected to read '%s', got '%s'\n", pipe_string, buf);
1288    }
1289
1290     r=read(pipes[0], buf, sizeof(buf)-1);
1291     ok(r == 0, "expected to read 0 bytes, got %d\n", r);
1292     ok(close(pipes[0]) == 0, "unable to close %d: %d\n", pipes[0], errno);
1293
1294     /* Test reading from a pipe with fread() */
1295     if (_pipe(pipes, 1024, O_BINARY) < 0)
1296     {
1297         ok(0, "pipe failed with errno %d\n", errno);
1298         return;
1299     }
1300
1301     arg_v[0] = selfname;
1302     arg_v[1] = "tests/file.c";
1303     arg_v[2] = "pipes";
1304     arg_v[3] = str_fdr; sprintf(str_fdr, "%d", pipes[0]);
1305     arg_v[4] = str_fdw; sprintf(str_fdw, "%d", pipes[1]);
1306     arg_v[5] = NULL;
1307     proc_handles[1] = (HANDLE)_spawnvp(_P_NOWAIT, selfname, arg_v);
1308     ok(close(pipes[1]) == 0, "unable to close %d: %d\n", pipes[1], errno);
1309     file=fdopen(pipes[0], "r");
1310
1311     /* In blocking mode, fread will keep calling read() until it gets
1312      * enough bytes, or EOF, even on Unix.  (If this were a Unix terminal
1313      * in cooked mode instead of a pipe, it would also stop on EOL.)
1314      */
1315     expected[0] = 0;
1316     for (i=0; i<N_TEST_MESSAGES; i++)
1317        strcat(expected, pipe_string);
1318     r=fread(buf, 1, sizeof(buf)-1, file);
1319     ok(r == strlen(expected), "fread() returned %d: ferror=%d\n", r, ferror(file));
1320     if (r > 0)
1321        buf[r]='\0';
1322     ok(strcmp(buf, expected) == 0, "got '%s' expected '%s'\n", buf, expected);
1323
1324     /* Let child close the file before we read, so we can sense EOF reliably */
1325     Sleep(100);
1326     r=fread(buf, 1, sizeof(buf)-1, file);
1327     ok(r == 0, "fread() returned %d instead of 0\n", r);
1328     ok(ferror(file) == 0, "got ferror() = %d\n", ferror(file));
1329     ok(feof(file), "feof() is false!\n");
1330
1331     ok(fclose(file) == 0, "unable to close the pipe: %d\n", errno);
1332 }
1333
1334 static void test_unlink(void)
1335 {
1336     FILE* file;
1337     ok(mkdir("test_unlink") == 0, "unable to create test dir\n");
1338     file = fopen("test_unlink\\empty", "w");
1339     ok(file != NULL, "unable to create test file\n");
1340     if(file)
1341       fclose(file);
1342     ok(_unlink("test_unlink") != 0, "unlinking a non-empty directory must fail\n");
1343     unlink("test_unlink\\empty");
1344     rmdir("test_unlink");
1345 }
1346
1347 START_TEST(file)
1348 {
1349     int arg_c;
1350     char** arg_v;
1351
1352     arg_c = winetest_get_mainargs( &arg_v );
1353
1354     /* testing low-level I/O */
1355     if (arg_c >= 3)
1356     {
1357         if (strcmp(arg_v[2], "inherit") == 0)
1358             test_file_inherit_child(arg_v[3]);
1359         else if (strcmp(arg_v[2], "inherit_no") == 0)
1360             test_file_inherit_child_no(arg_v[3]);
1361         else if (strcmp(arg_v[2], "pipes") == 0)
1362             test_pipes_child(arg_c, arg_v);
1363         else
1364             ok(0, "invalid argument '%s'\n", arg_v[2]);
1365         return;
1366     }
1367     test_file_inherit(arg_v[0]);
1368     test_file_write_read();
1369     test_chsize();
1370     test_stat();
1371     test_unlink();
1372
1373     /* testing stream I/O */
1374     test_filbuf();
1375     test_fdopen();
1376     test_fopen_fclose_fcloseall();
1377     test_fileops();
1378     test_asciimode();
1379     test_asciimode2();
1380     test_readmode(FALSE); /* binary mode */
1381     test_readmode(TRUE);  /* ascii mode */
1382     test_fgetc();
1383     test_fputc();
1384     test_flsbuf();
1385     test_fgetwc();
1386     test_ctrlz();
1387     test_file_put_get();
1388     test_tmpnam();
1389     test_get_osfhandle();
1390     test_setmaxstdio();
1391     test_pipes(arg_v[0]);
1392
1393     /* Wait for the (_P_NOWAIT) spawned processes to finish to make sure the report
1394      * file contains lines in the correct order
1395      */
1396     WaitForMultipleObjects(sizeof(proc_handles)/sizeof(proc_handles[0]), proc_handles, TRUE, 5000);
1397 }