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