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