ddraw: Get rid of ddcomimpl.h.
[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 %ld 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 %ld 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 %ld 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 %ld 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 %ld 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 %ld 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
310     /* Simple test of CR CR LF handling.  Test both fgets and fread code paths, they're different! */
311     fp = fopen("ascii.tst", "wb");
312     fputs("\r\r\n", fp);
313     fclose(fp);
314     fp = fopen("ascii.tst", "rt");
315     ok(fgets(buf, sizeof(buf), fp) != NULL, "fgets\n");
316     ok(0 == strcmp(buf, "\r\n"), "CR CR LF not read as CR LF\n");
317     rewind(fp);
318     ok((fread(buf, 1, sizeof(buf), fp) == 2) && (0 == strcmp(buf, "\r\n")), "CR CR LF not read as CR LF\n");
319     fclose(fp);
320     unlink("ascii.tst");
321
322     /* Simple test of foo ^Z [more than one block] bar handling */
323     fp = fopen("ascii.tst", "wb");
324     fputs("foo\032", fp);  /* foo, logical EOF, ... */
325     fseek(fp, 65536L, SEEK_SET); /* ... more than MSVCRT_BUFSIZ, ... */
326     fputs("bar", fp); /* ... bar */
327     fclose(fp);
328     fp = fopen("ascii.tst", "rt");
329     ok(fgets(buf, sizeof(buf), fp) != NULL, "fgets foo\n");
330     ok(0 == strcmp(buf, "foo"), "foo ^Z not read as foo by fgets\n");
331     ok(fgets(buf, sizeof(buf), fp) == NULL, "fgets after logical EOF\n");
332     rewind(fp);
333     ok((fread(buf, 1, sizeof(buf), fp) == 3) && (0 == strcmp(buf, "foo")), "foo ^Z not read as foo by fread\n");
334     ok((fread(buf, 1, sizeof(buf), fp) == 0), "fread after logical EOF\n");
335     fclose(fp);
336
337     unlink("ascii.tst");
338 }
339
340 static void test_asciimode2(void)
341 {
342     /* Error sequence from one app was getchar followed by small fread
343      * with one \r removed had last byte of buffer filled with
344      * next byte of *unbuffered* data rather than next byte from buffer
345      * Test case is a short string of one byte followed by a newline
346      * followed by filler to fill out the sector, then a sector of
347      * some different byte.
348      */
349
350     FILE *fp;
351     char ibuf[4];
352     int i;
353     static const char obuf[] =
354 "00\n"
355 "000000000000000000000000000000000000000000000000000000000000000000000000000000\n"
356 "000000000000000000000000000000000000000000000000000000000000000000000000000000\n"
357 "000000000000000000000000000000000000000000000000000000000000000000000000000000\n"
358 "000000000000000000000000000000000000000000000000000000000000000000000000000000\n"
359 "000000000000000000000000000000000000000000000000000000000000000000000000000000\n"
360 "000000000000000000000000000000000000000000000000000000000000000000000000000000\n"
361 "000000000000000000\n"
362 "1111111111111111111";
363
364     fp = fopen("ascii2.tst", "wt");
365     fwrite(obuf, 1, sizeof(obuf), fp);
366     fclose(fp);
367
368     fp = fopen("ascii2.tst", "rt");
369     ok(getc(fp) == '0', "first char not 0\n");
370     memset(ibuf, 0, sizeof(ibuf));
371     i = fread(ibuf, 1, sizeof(ibuf), fp);
372     ok(i == sizeof(ibuf), "fread i %d != sizeof(ibuf)\n", i);
373     ok(0 == strncmp(ibuf, obuf+1, sizeof(ibuf)), "ibuf != obuf\n");
374     fclose(fp);
375     unlink("ascii2.tst");
376 }
377
378 static WCHAR* AtoW( const char* p )
379 {
380     WCHAR* buffer;
381     DWORD len = MultiByteToWideChar( CP_ACP, 0, p, -1, NULL, 0 );
382     buffer = malloc( len * sizeof(WCHAR) );
383     MultiByteToWideChar( CP_ACP, 0, p, -1, buffer, len );
384     return buffer;
385 }
386
387 static void test_fgetc( void )
388 {
389   char* tempf;
390   FILE *tempfh;
391   int  ich=0xe0, ret;
392
393   tempf=_tempnam(".","wne");
394   tempfh = fopen(tempf,"w+");
395   fputc(ich, tempfh);
396   fputc(ich, tempfh);
397   rewind(tempfh);
398   ret = fgetc(tempfh);
399   ok(ich == ret, "First fgetc expected %x got %x\n", ich, ret);
400   ret = fgetc(tempfh);
401   ok(ich == ret, "Second fgetc expected %x got %x\n", ich, ret);
402   fclose(tempfh);
403   unlink(tempf);
404 }
405
406 static void test_fputc( void )
407 {
408   char* tempf;
409   FILE *tempfh;
410   int  ret;
411
412   tempf=_tempnam(".","wne");
413   tempfh = fopen(tempf,"wb");
414   ret = fputc(0,tempfh);
415   ok(0 == ret, "fputc(0,tempfh) expected %x got %x\n", 0, ret);
416   ret = fputc(0xff,tempfh);
417   ok(0xff == ret, "fputc(0xff,tempfh) expected %x got %x\n", 0xff, ret);
418   ret = fputc(0xffffffff,tempfh);
419   ok(0xff == ret, "fputc(0xffffffff,tempfh) expected %x got %x\n", 0xff, ret);
420   fclose(tempfh);
421
422   tempfh = fopen(tempf,"rb");
423   ret = fputc(0,tempfh);
424   ok(EOF == ret, "fputc(0,tempfh) on r/o file expected %x got %x\n", EOF, ret);
425   fclose(tempfh);
426
427   unlink(tempf);
428 }
429
430 static void test_flsbuf( void )
431 {
432   char* tempf;
433   FILE *tempfh;
434   int  ret;
435   int  bufmode;
436   int  bufmodes[] = {_IOFBF,_IONBF};
437
438   tempf=_tempnam(".","wne");
439   for (bufmode=0; bufmode < sizeof(bufmodes)/sizeof(bufmodes[0]); bufmode++)
440   {
441     tempfh = fopen(tempf,"wb");
442     setvbuf(tempfh,NULL,bufmodes[bufmode],2048);
443     ret = _flsbuf(0,tempfh);
444     ok(0 == ret, "_flsbuf(0,tempfh) with bufmode %x expected %x got %x\n",
445                          bufmodes[bufmode], 0, ret);
446     ret = _flsbuf(0xff,tempfh);
447     ok(0xff == ret, "_flsbuf(0xff,tempfh) with bufmode %x expected %x got %x\n",
448                          bufmodes[bufmode], 0, ret);
449     ret = _flsbuf(0xffffffff,tempfh);
450     ok(0xff == ret, "_flsbuf(0xffffffff,tempfh) with bufmode %x expected %x got %x\n",
451                          bufmodes[bufmode], 0, ret);
452     fclose(tempfh);
453   }
454
455   tempfh = fopen(tempf,"rb");
456   ret = _flsbuf(0,tempfh);
457   ok(EOF == ret, "_flsbuf(0,tempfh) on r/o file expected %x got %x\n", EOF, ret);
458   fclose(tempfh);
459
460   unlink(tempf);
461 }
462
463 static void test_fgetwc( void )
464 {
465 #define LLEN 512
466
467   char* tempf;
468   FILE *tempfh;
469   static const char mytext[]= "This is test_fgetwc\r\n";
470   WCHAR wtextW[BUFSIZ+LLEN+1];
471   WCHAR *mytextW = NULL, *aptr, *wptr;
472   BOOL diff_found = FALSE;
473   int j;
474   unsigned int i;
475   long l;
476
477   tempf=_tempnam(".","wne");
478   tempfh = fopen(tempf,"wb");
479   j = 'a';
480   /* pad to almost the length of the internal buffer */
481   for (i=0; i<BUFSIZ-4; i++)
482     fputc(j,tempfh);
483   j = '\r';
484   fputc(j,tempfh);
485   j = '\n';
486   fputc(j,tempfh);
487   fputs(mytext,tempfh);
488   fclose(tempfh);
489   /* in text mode, getws/c expects multibyte characters */
490   /*currently Wine only supports plain ascii, and that is all that is tested here */
491   tempfh = fopen(tempf,"rt"); /* open in TEXT mode */
492   fgetws(wtextW,LLEN,tempfh);
493   l=ftell(tempfh);
494   ok(l==BUFSIZ-2, "ftell expected %d got %ld\n", BUFSIZ-2, l);
495   fgetws(wtextW,LLEN,tempfh);
496   l=ftell(tempfh);
497   ok(l==BUFSIZ-2+strlen(mytext), "ftell expected %d got %ld\n", BUFSIZ-2+strlen(mytext), l);
498   mytextW = AtoW (mytext);
499   aptr = mytextW;
500   wptr = wtextW;
501   for (i=0; i<strlen(mytext)-2; i++, aptr++, wptr++)
502     {
503       diff_found |= (*aptr != *wptr);
504     }
505   ok(!(diff_found), "fgetwc difference found in TEXT mode\n");
506   ok(*wptr == '\n', "Carriage return was not skipped\n");
507   fclose(tempfh);
508   unlink(tempf);
509   
510   tempfh = fopen(tempf,"wb");
511   j = 'a';
512   /* pad to almost the length of the internal buffer. Use an odd number of bytes
513      to test that we can read wchars that are split across the internal buffer
514      boundary */
515   for (i=0; i<BUFSIZ-3-strlen(mytext)*sizeof(WCHAR); i++)
516     fputc(j,tempfh);
517   j = '\r';
518   fputwc(j,tempfh);
519   j = '\n';
520   fputwc(j,tempfh);
521   fputws(wtextW,tempfh);
522   fputws(wtextW,tempfh);
523   fclose(tempfh);
524   /* in binary mode, getws/c expects wide characters */
525   tempfh = fopen(tempf,"rb"); /* open in BINARY mode */
526   j=(BUFSIZ-2)/sizeof(WCHAR)-strlen(mytext);
527   fgetws(wtextW,j,tempfh);
528   l=ftell(tempfh);
529   j=(j-1)*sizeof(WCHAR);
530   ok(l==j, "ftell expected %d got %ld\n", j, l);
531   i=fgetc(tempfh);
532   ok(i=='a', "fgetc expected %d got %d\n", 0x61, i);
533   l=ftell(tempfh);
534   j++;
535   ok(l==j, "ftell expected %d got %ld\n", j, l);
536   fgetws(wtextW,3,tempfh);
537   ok(wtextW[0]=='\r',"expected carriage return got %04hx\n", wtextW[0]);
538   ok(wtextW[1]=='\n',"expected newline got %04hx\n", wtextW[1]);
539   l=ftell(tempfh);
540   j += 4;
541   ok(l==j, "ftell expected %d got %ld\n", j, l);
542   for(i=0; i<strlen(mytext); i++)
543     wtextW[i] = 0;
544   /* the first time we get the string, it should be entirely within the local buffer */
545   fgetws(wtextW,LLEN,tempfh);
546   l=ftell(tempfh);
547   j += (strlen(mytext)-1)*sizeof(WCHAR);
548   ok(l==j, "ftell expected %d got %ld\n", j, l);
549   diff_found = FALSE;
550   aptr = mytextW;
551   wptr = wtextW;
552   for (i=0; i<strlen(mytext)-2; i++, aptr++, wptr++)
553     {
554       ok(*aptr == *wptr, "Char %d expected %04hx got %04hx\n", i, *aptr, *wptr);
555       diff_found |= (*aptr != *wptr);
556     }
557   ok(!(diff_found), "fgetwc difference found in BINARY mode\n");
558   ok(*wptr == '\n', "Should get newline\n");
559   for(i=0; i<strlen(mytext); i++)
560     wtextW[i] = 0;
561   /* the second time we get the string, it should cross the local buffer boundary.
562      One of the wchars should be split across the boundary */
563   fgetws(wtextW,LLEN,tempfh);
564   diff_found = FALSE;
565   aptr = mytextW;
566   wptr = wtextW;
567   for (i=0; i<strlen(mytext)-2; i++, aptr++, wptr++)
568     {
569       ok(*aptr == *wptr, "Char %d expected %04hx got %04hx\n", i, *aptr, *wptr);
570       diff_found |= (*aptr != *wptr);
571     }
572   ok(!(diff_found), "fgetwc difference found in BINARY mode\n");
573   ok(*wptr == '\n', "Should get newline\n");
574
575   free(mytextW);
576   fclose(tempfh);
577   unlink(tempf);
578 }
579
580 static void test_ctrlz( void )
581 {
582   char* tempf;
583   FILE *tempfh;
584   static const char mytext[]= "This is test_ctrlz";
585   char buffer[256];
586   int i, j;
587   long l;
588
589   tempf=_tempnam(".","wne");
590   tempfh = fopen(tempf,"wb");
591   fputs(mytext,tempfh);
592   j = 0x1a; /* a ctrl-z character signals EOF in text mode */
593   fputc(j,tempfh);
594   j = '\r';
595   fputc(j,tempfh);
596   j = '\n';
597   fputc(j,tempfh);
598   j = 'a';
599   fputc(j,tempfh);
600   fclose(tempfh);
601   tempfh = fopen(tempf,"rt"); /* open in TEXT mode */
602   ok(fgets(buffer,256,tempfh) != 0,"fgets failed unexpected\n");
603   i=strlen(buffer);
604   j=strlen(mytext);
605   ok(i==j, "returned string length expected %d got %d\n", j, i);
606   j+=4; /* ftell should indicate the true end of file */
607   l=ftell(tempfh);
608   ok(l==j, "ftell expected %d got %ld\n", j, l);
609   ok(feof(tempfh), "did not get EOF\n");
610   fclose(tempfh);
611   
612   tempfh = fopen(tempf,"rb"); /* open in BINARY mode */
613   ok(fgets(buffer,256,tempfh) != 0,"fgets failed unexpected\n");
614   i=strlen(buffer);
615   j=strlen(mytext)+3; /* should get through newline */
616   ok(i==j, "returned string length expected %d got %d\n", j, i);
617   l=ftell(tempfh);
618   ok(l==j, "ftell expected %d got %ld\n", j, l);
619   ok(fgets(buffer,256,tempfh) != 0,"fgets failed unexpected\n");
620   i=strlen(buffer);
621   ok(i==1, "returned string length expected %d got %d\n", 1, i);
622   ok(feof(tempfh), "did not get EOF\n");
623   fclose(tempfh);
624   unlink(tempf);
625 }
626
627 static void test_file_put_get( void )
628 {
629   char* tempf;
630   FILE *tempfh;
631   static const char mytext[]=  "This is a test_file_put_get\n";
632   static const char dostext[]= "This is a test_file_put_get\r\n";
633   char btext[LLEN];
634   WCHAR wtextW[LLEN+1];
635   WCHAR *mytextW = NULL, *aptr, *wptr;
636   BOOL diff_found = FALSE;
637   unsigned int i;
638
639   tempf=_tempnam(".","wne");
640   tempfh = fopen(tempf,"wt"); /* open in TEXT mode */
641   fputs(mytext,tempfh);
642   fclose(tempfh);
643   tempfh = fopen(tempf,"rb"); /* open in TEXT mode */
644   fgets(btext,LLEN,tempfh);
645   ok( strlen(mytext) + 1 == strlen(btext),"TEXT/BINARY mode not handled for write\n");
646   ok( btext[strlen(mytext)-1] == '\r', "CR not written\n");
647   fclose(tempfh);
648   tempfh = fopen(tempf,"wb"); /* open in BINARY mode */
649   fputs(dostext,tempfh);
650   fclose(tempfh);
651   tempfh = fopen(tempf,"rt"); /* open in TEXT mode */
652   fgets(btext,LLEN,tempfh);
653   ok(strcmp(btext, mytext) == 0,"_O_TEXT read doesn't strip CR\n");
654   fclose(tempfh);
655   tempfh = fopen(tempf,"rb"); /* open in TEXT mode */
656   fgets(btext,LLEN,tempfh);
657   ok(strcmp(btext, dostext) == 0,"_O_BINARY read doesn't preserve CR\n");
658
659   fclose(tempfh);
660   tempfh = fopen(tempf,"rt"); /* open in TEXT mode */
661   fgetws(wtextW,LLEN,tempfh);
662   mytextW = AtoW (mytext);
663   aptr = mytextW;
664   wptr = wtextW;
665
666   for (i=0; i<strlen(mytext); i++, aptr++, wptr++)
667     {
668       diff_found |= (*aptr != *wptr);
669     }
670   ok(!(diff_found), "fgetwc doesn't strip CR in TEXT mode\n");
671   free(mytextW);
672   fclose(tempfh);
673   unlink(tempf);
674 }
675
676 static void test_file_write_read( void )
677 {
678   char* tempf;
679   int tempfd;
680   static const char mytext[]=  "This is test_file_write_read\nsecond line\n";
681   static const char dostext[]= "This is test_file_write_read\r\nsecond line\r\n";
682   char btext[LLEN];
683   int ret, i;
684
685   tempf=_tempnam(".","wne");
686   tempfd = _open(tempf,_O_CREAT|_O_TRUNC|_O_BINARY|_O_RDWR,
687                      _S_IREAD | _S_IWRITE);
688   ok( tempfd != -1,
689      "Can't open '%s': %d\n", tempf, errno); /* open in BINARY mode */
690   ok(_write(tempfd,dostext,strlen(dostext)) == lstrlenA(dostext),
691      "_write _O_BINARY bad return value\n");
692   _close(tempfd);
693   i = lstrlenA(mytext);
694   tempfd = _open(tempf,_O_RDONLY|_O_BINARY,0); /* open in BINARY mode */
695   ok(_read(tempfd,btext,i) == i,
696      "_read _O_BINARY got bad length\n");
697   ok( memcmp(dostext,btext,i) == 0,
698       "problems with _O_BINARY  _write / _read\n");
699   _close(tempfd);
700   tempfd = _open(tempf,_O_RDONLY|_O_TEXT); /* open in TEXT mode */
701   ok(_read(tempfd,btext,i) == i-1,
702      "_read _O_TEXT got bad length\n");
703   ok( memcmp(mytext,btext,i-1) == 0,
704       "problems with _O_BINARY _write / _O_TEXT _read\n");
705   _close(tempfd);
706   tempfd = _open(tempf,_O_CREAT|_O_TRUNC|_O_TEXT|_O_RDWR,
707                      _S_IREAD | _S_IWRITE);
708   ok( tempfd != -1,
709      "Can't open '%s': %d\n", tempf, errno); /* open in TEXT mode */
710   ok(_write(tempfd,mytext,strlen(mytext)) == lstrlenA(mytext),
711      "_write _O_TEXT bad return value\n");
712   _close(tempfd);
713   tempfd = _open(tempf,_O_RDONLY|_O_BINARY,0); /* open in BINARY mode */
714   ok(_read(tempfd,btext,LLEN) == lstrlenA(dostext),
715      "_read _O_BINARY got bad length\n");
716   ok( memcmp(dostext,btext,strlen(dostext)) == 0,
717       "problems with _O_TEXT _write / _O_BINARY _read\n");
718   ok( btext[strlen(dostext)-2] == '\r', "CR not written or read\n");
719   _close(tempfd);
720   tempfd = _open(tempf,_O_RDONLY|_O_TEXT); /* open in TEXT mode */
721   ok(_read(tempfd,btext,LLEN) == lstrlenA(mytext),
722      "_read _O_TEXT got bad length\n");
723   ok( memcmp(mytext,btext,strlen(mytext)) == 0,
724       "problems with _O_TEXT _write / _read\n");
725   _close(tempfd);
726
727   memset(btext, 0, LLEN);
728   tempfd = _open(tempf,_O_APPEND|_O_RDWR); /* open for APPEND in default mode */
729   ok(tell(tempfd) == 0, "bad position %lu expecting 0\n", tell(tempfd));
730   ok(_read(tempfd,btext,LLEN) == lstrlenA(mytext), "_read _O_APPEND got bad length\n");
731   ok( memcmp(mytext,btext,strlen(mytext)) == 0, "problems with _O_APPEND _read\n");
732   _close(tempfd);
733
734   /* Test reading only \n or \r */
735   tempfd = _open(tempf,_O_RDONLY|_O_TEXT); /* open in TEXT mode */
736   _lseek(tempfd, -1, FILE_END);
737   ret = _read(tempfd,btext,LLEN);
738   ok(ret == 1, "_read expected 1 got bad length: %d\n", ret);
739   _lseek(tempfd, -2, FILE_END);
740   ret = _read(tempfd,btext,LLEN);
741   ok(ret == 1 && *btext == '\n', "_read expected '\\n' got bad length: %d\n", ret);
742   _lseek(tempfd, -3, FILE_END);
743   ret = _read(tempfd,btext,2);
744   ok(ret == 1 && *btext == 'e', "_read expected 'e' got \"%.*s\" bad length: %d\n", ret, btext, ret);
745   ok(tell(tempfd) == 42, "bad position %lu expecting 42\n", tell(tempfd));
746   _close(tempfd);
747
748   ret = unlink(tempf);
749   ok( ret == 0 ,"Can't unlink '%s': %d\n", tempf, errno);
750
751   tempf=_tempnam(".","wne");
752   tempfd = _open(tempf,_O_CREAT|_O_TRUNC|_O_BINARY|_O_RDWR,0);
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   tempfd = _open(tempf,_O_RDONLY|_O_BINARY,0); /* open in BINARY mode */
759   ok(_read(tempfd,btext,LLEN) == lstrlenA(dostext),
760      "_read _O_BINARY got bad length\n");
761   ok( memcmp(dostext,btext,strlen(dostext)) == 0,
762       "problems with _O_BINARY _write / _read\n");
763   ok( btext[strlen(dostext)-2] == '\r', "CR not written or read\n");
764   _close(tempfd);
765   tempfd = _open(tempf,_O_RDONLY|_O_TEXT); /* open in TEXT mode */
766   ok(_read(tempfd,btext,LLEN) == lstrlenA(mytext),
767      "_read _O_TEXT got bad length\n");
768   ok( memcmp(mytext,btext,strlen(mytext)) == 0,
769       "problems with _O_BINARY _write / _O_TEXT _read\n");
770   _close(tempfd);
771
772    ret =_chmod (tempf, _S_IREAD | _S_IWRITE);
773   ok( ret == 0,
774      "Can't chmod '%s' to read-write: %d\n", tempf, errno);
775   ret = unlink(tempf);
776   ok( ret == 0 ,"Can't unlink '%s': %d\n", tempf, errno);
777 }
778
779 static void test_file_inherit_child(const char* fd_s)
780 {
781     int fd = atoi(fd_s);
782     char buffer[32];
783     int ret;
784
785     ret =write(fd, "Success", 8);
786     ok( ret == 8, "Couldn't write in child process on %d (%s)\n", fd, strerror(errno));
787     lseek(fd, 0, SEEK_SET);
788     ok(read(fd, buffer, sizeof (buffer)) == 8, "Couldn't read back the data\n");
789     ok(memcmp(buffer, "Success", 8) == 0, "Couldn't read back the data\n");
790 }
791
792 static void test_file_inherit_child_no(const char* fd_s)
793 {
794     int fd = atoi(fd_s);
795     int ret;
796
797     ret = write(fd, "Success", 8);
798     ok( ret == -1 && errno == EBADF, 
799        "Wrong write result in child process on %d (%s)\n", fd, strerror(errno));
800 }
801  
802 static void test_file_inherit( const char* selfname )
803 {
804     int                 fd;
805     const char*         arg_v[5];
806     char                buffer[16];
807
808     fd = open ("fdopen.tst", O_CREAT | O_RDWR | O_BINARY, _S_IREAD |_S_IWRITE);
809     ok(fd != -1, "Couldn't create test file\n");
810     arg_v[0] = selfname;
811     arg_v[1] = "tests/file.c";
812     arg_v[2] = "inherit";
813     arg_v[3] = buffer; sprintf(buffer, "%d", fd);
814     arg_v[4] = 0;
815     _spawnvp(_P_WAIT, selfname, arg_v);
816     ok(tell(fd) == 8, "bad position %lu expecting 8\n", tell(fd));
817     lseek(fd, 0, SEEK_SET);
818     ok(read(fd, buffer, sizeof (buffer)) == 8 && memcmp(buffer, "Success", 8) == 0, "Couldn't read back the data\n");
819     close (fd);
820     ok(unlink("fdopen.tst") == 0, "Couldn't unlink\n");
821     
822     fd = open ("fdopen.tst", O_CREAT | O_RDWR | O_BINARY | O_NOINHERIT, _S_IREAD |_S_IWRITE);
823     ok(fd != -1, "Couldn't create test file\n");
824     arg_v[0] = selfname;
825     arg_v[1] = "tests/file.c";
826     arg_v[2] = "inherit_no";
827     arg_v[3] = buffer; sprintf(buffer, "%d", fd);
828     arg_v[4] = 0;
829     _spawnvp(_P_WAIT, selfname, arg_v);
830     ok(tell(fd) == 0, "bad position %lu expecting 0\n", tell(fd));
831     ok(read(fd, buffer, sizeof (buffer)) == 0, "Found unexpected data (%s)\n", buffer);
832     close (fd);
833     ok(unlink("fdopen.tst") == 0, "Couldn't unlink\n");
834 }
835
836 static void test_tmpnam( void )
837 {
838   char name[MAX_PATH] = "abc";
839   char *res;
840
841   res = tmpnam(NULL);
842   ok(res != NULL, "tmpnam returned NULL\n");
843   ok(res[0] == '\\', "first character is not a backslash\n");
844   ok(strchr(res+1, '\\') == 0, "file not in the root directory\n");
845   ok(res[strlen(res)-1] == '.', "first call - last character is not a dot\n");
846
847   res = tmpnam(name);
848   ok(res != NULL, "tmpnam returned NULL\n");
849   ok(res == name, "supplied buffer was not used\n");
850   ok(res[0] == '\\', "first character is not a backslash\n");
851   ok(strchr(res+1, '\\') == 0, "file not in the root directory\n");
852   ok(res[strlen(res)-1] != '.', "second call - last character is a dot\n");
853 }
854
855 static void test_chsize( void )
856 {
857     int fd;
858     long cur, pos, count;
859     char temptext[] = "012345678";
860     char *tempfile = _tempnam( ".", "tst" );
861     
862     ok( tempfile != NULL, "Couldn't create test file: %s\n", tempfile );
863
864     fd = _open( tempfile, _O_CREAT|_O_TRUNC|_O_RDWR, _S_IREAD|_S_IWRITE );
865     ok( fd > 0, "Couldn't open test file\n" );
866
867     count = _write( fd, temptext, sizeof(temptext) );
868     ok( count > 0, "Couldn't write to test file\n" );
869
870     /* get current file pointer */
871     cur = _lseek( fd, 0, SEEK_CUR );
872
873     /* make the file smaller */
874     ok( _chsize( fd, sizeof(temptext) / 2 ) == 0, "_chsize() failed\n" );
875
876     pos = _lseek( fd, 0, SEEK_CUR );
877     ok( cur == pos, "File pointer changed from: %ld to: %ld\n", cur, pos );
878     ok( _filelength( fd ) == sizeof(temptext) / 2, "Wrong file size\n" );
879
880     /* enlarge the file */
881     ok( _chsize( fd, sizeof(temptext) * 2 ) == 0, "_chsize() failed\n" ); 
882
883     pos = _lseek( fd, 0, SEEK_CUR );
884     ok( cur == pos, "File pointer changed from: %ld to: %ld\n", cur, pos );
885     ok( _filelength( fd ) == sizeof(temptext) * 2, "Wrong file size\n" );
886
887     _close( fd );
888     _unlink( tempfile );
889 }
890
891 static void test_fopen_fclose_fcloseall( void )
892 {
893     char fname1[] = "empty1";
894     char fname2[] = "empty2";
895     char fname3[] = "empty3";
896     FILE *stream1, *stream2, *stream3, *stream4;
897     int ret, numclosed;
898
899     /* testing fopen() */
900     stream1 = fopen(fname1, "w+");
901     ok(stream1 != NULL, "The file '%s' was not opened\n", fname1);
902     stream2 = fopen(fname2, "w ");
903     ok(stream2 != NULL, "The file '%s' was not opened\n", fname2 );
904     _unlink(fname3);
905     stream3 = fopen(fname3, "r");
906     ok(stream3 == NULL, "The file '%s' shouldn't exist before\n", fname3 );
907     stream3 = fopen(fname3, "w+");
908     ok(stream3 != NULL, "The file '%s' should be opened now\n", fname3 );
909     errno = 0xfaceabad;
910     stream4 = fopen("", "w+");
911     ok(stream4 == NULL && (errno == EINVAL || errno == ENOENT),
912        "filename is empty, errno = %d (expected 2 or 22)\n", errno);
913     errno = 0xfaceabad;
914     stream4 = fopen(NULL, "w+");
915     ok(stream4 == NULL && (errno == EINVAL || errno == ENOENT), 
916        "filename is NULL, errno = %d (expected 2 or 22)\n", errno);
917
918     /* testing fclose() */
919     ret = fclose(stream2);
920     ok(ret == 0, "The file '%s' was not closed\n", fname2);
921     ret = fclose(stream3);
922     ok(ret == 0, "The file '%s' was not closed\n", fname3);
923     ret = fclose(stream2);
924     ok(ret == EOF, "Closing file '%s' returned %d\n", fname2, ret);
925     ret = fclose(stream3);
926     ok(ret == EOF, "Closing file '%s' returned %d\n", fname3, ret);
927
928     /* testing fcloseall() */
929     numclosed = _fcloseall();
930     /* fname1 should be closed here */
931     ok(numclosed == 1, "Number of files closed by fcloseall(): %u\n", numclosed);
932     numclosed = _fcloseall();
933     ok(numclosed == 0, "Number of files closed by fcloseall(): %u\n", numclosed);
934
935     ok(_unlink(fname1) == 0, "Couldn't unlink file named '%s'\n", fname1);
936     ok(_unlink(fname2) == 0, "Couldn't unlink file named '%s'\n", fname2);
937     ok(_unlink(fname3) == 0, "Couldn't unlink file named '%s'\n", fname3);
938 }
939
940 static void test_get_osfhandle(void)
941 {
942     int fd;
943     char fname[] = "t_get_osfhanle";
944     DWORD bytes_written;
945     HANDLE handle;
946
947     fd = _sopen(fname, _O_CREAT|_O_RDWR, _SH_DENYRW, _S_IREAD | _S_IWRITE);
948     handle = (HANDLE)_get_osfhandle(fd);
949     WriteFile(handle, "bar", 3, &bytes_written, NULL);
950     _close(fd);
951     fd = _open(fname, _O_RDONLY, 0);
952     ok(fd != -1, "Coudn't open '%s' after _get_osfhanle()\n", fname);
953
954     _close(fd);
955     _unlink(fname);
956 }
957
958 static void test_setmaxstdio(void)
959 {
960     ok(2048 == _setmaxstdio(2048),"_setmaxstdio returned %d instead of 2048\n",_setmaxstdio(2048));
961     ok(-1 == _setmaxstdio(2049),"_setmaxstdio returned %d instead of -1\n",_setmaxstdio(2049));
962 }
963
964 static void test_stat(void)
965 {
966     int fd;
967     int pipes[2];
968     struct stat buf;
969
970     /* Tests for a file */
971     fd = open("stat.tst", O_WRONLY | O_CREAT | O_BINARY, _S_IREAD |_S_IWRITE);
972     if (fd >= 0)
973     {
974         ok(fstat(fd, &buf) == 0, "fstat failed: errno=%d\n", errno);
975         ok((buf.st_mode & _S_IFMT) == _S_IFREG, "bad format = %06o\n", buf.st_mode);
976         ok((buf.st_mode & 0777) == 0666, "bad st_mode = %06o\n", buf.st_mode);
977         ok(buf.st_dev == 0, "st_dev is %d, expected 0\n", buf.st_dev);
978         ok(buf.st_dev == buf.st_rdev, "st_dev (%d) and st_rdev (%d) differ\n", buf.st_dev, buf.st_rdev);
979         ok(buf.st_nlink == 1, "st_nlink is %d, expected 1\n", buf.st_nlink);
980         ok(buf.st_size == 0, "st_size is %d, expected 0\n", buf.st_size);
981
982         ok(stat("stat.tst", &buf) == 0, "stat failed: errno=%d\n", errno);
983         ok((buf.st_mode & _S_IFMT) == _S_IFREG, "bad format = %06o\n", buf.st_mode);
984         ok((buf.st_mode & 0777) == 0666, "bad st_mode = %06o\n", buf.st_mode);
985         ok(buf.st_dev == buf.st_rdev, "st_dev (%d) and st_rdev (%d) differ\n", buf.st_dev, buf.st_rdev);
986         ok(buf.st_nlink == 1, "st_nlink is %d, expected 1\n", buf.st_nlink);
987         ok(buf.st_size == 0, "st_size is %d, expected 0\n", buf.st_size);
988
989         close(fd);
990         remove("stat.tst");
991     }
992     else
993         skip("open failed with errno %d\n", errno);
994
995     /* Tests for a char device */
996     if (_dup2(0, 10) == 0)
997     {
998         ok(fstat(10, &buf) == 0, "fstat(stdin) failed: errno=%d\n", errno);
999         if ((buf.st_mode & _S_IFMT) == _S_IFCHR)
1000         {
1001             ok(buf.st_mode == _S_IFCHR, "bad st_mode=%06o\n", buf.st_mode);
1002             ok(buf.st_dev == 10, "st_dev is %d, expected 10\n", buf.st_dev);
1003             ok(buf.st_rdev == 10, "st_rdev is %d, expected 10\n", buf.st_rdev);
1004             ok(buf.st_nlink == 1, "st_nlink is %d, expected 1\n", buf.st_nlink);
1005         }
1006         else
1007             skip("stdin is not a char device? st_mode=%06o\n", buf.st_mode);
1008         close(10);
1009     }
1010     else
1011         skip("_dup2 failed with errno %d\n", errno);
1012
1013     /* Tests for pipes */
1014     if (_pipe(pipes, 1024, O_BINARY) == 0)
1015     {
1016         ok(fstat(pipes[0], &buf) == 0, "fstat(pipe) failed: errno=%d\n", errno);
1017         ok(buf.st_mode == _S_IFIFO, "bad st_mode=%06o\n", buf.st_mode);
1018         ok(buf.st_dev == pipes[0], "st_dev is %d, expected %d\n", buf.st_dev, pipes[0]);
1019         ok(buf.st_rdev == pipes[0], "st_rdev is %d, expected %d\n", buf.st_rdev, pipes[0]);
1020         ok(buf.st_nlink == 1, "st_nlink is %d, expected 1\n", buf.st_nlink);
1021         close(pipes[0]);
1022         close(pipes[1]);
1023     }
1024     else
1025         skip("pipe failed with errno %d\n", errno);
1026 }
1027
1028 static const char* pipe_string="Hello world";
1029
1030 /* How many messages to transfer over the pipe */
1031 #define N_TEST_MESSAGES 3
1032
1033 static void test_pipes_child(int argc, char** args)
1034 {
1035     int fd;
1036     int nwritten;
1037     int i;
1038
1039     if (argc < 5)
1040     {
1041         ok(0, "not enough parameters: %d\n", argc);
1042         return;
1043     }
1044
1045     fd=atoi(args[3]);
1046     ok(close(fd) == 0, "unable to close %d: %d\n", fd, errno);
1047
1048     fd=atoi(args[4]);
1049
1050     for (i=0; i<N_TEST_MESSAGES; i++) {
1051        nwritten=write(fd, pipe_string, strlen(pipe_string));
1052        ok(nwritten == strlen(pipe_string), "i %d, expected to write '%s' wrote %d\n", i, pipe_string, nwritten);
1053        /* let other process wake up so they can show off their "keep reading until EOF" behavior */
1054        if (i < N_TEST_MESSAGES-1)
1055            Sleep(100);
1056     }
1057
1058     ok(close(fd) == 0, "unable to close %d: %d\n", fd, errno);
1059 }
1060
1061 static void test_pipes(const char* selfname)
1062 {
1063     int pipes[2];
1064     char str_fdr[12], str_fdw[12];
1065     FILE* file;
1066     const char* arg_v[6];
1067     char buf[4096];
1068     char expected[4096];
1069     int r;
1070     int i;
1071
1072     /* Test reading from a pipe with read() */
1073     if (_pipe(pipes, 1024, O_BINARY) < 0)
1074     {
1075         ok(0, "pipe failed with errno %d\n", errno);
1076         return;
1077     }
1078
1079     arg_v[0] = selfname;
1080     arg_v[1] = "tests/file.c";
1081     arg_v[2] = "pipes";
1082     arg_v[3] = str_fdr; sprintf(str_fdr, "%d", pipes[0]);
1083     arg_v[4] = str_fdw; sprintf(str_fdw, "%d", pipes[1]);
1084     arg_v[5] = NULL;
1085     proc_handles[0] = (HANDLE)_spawnvp(_P_NOWAIT, selfname, arg_v);
1086     ok(close(pipes[1]) == 0, "unable to close %d: %d\n", pipes[1], errno);
1087
1088     for (i=0; i<N_TEST_MESSAGES; i++) {
1089        r=read(pipes[0], buf, sizeof(buf)-1);
1090        ok(r == strlen(pipe_string), "i %d, got %d\n", i, r);
1091        if (r > 0)
1092            buf[r]='\0';
1093        ok(strcmp(buf, pipe_string) == 0, "expected to read '%s', got '%s'\n", pipe_string, buf);
1094    }
1095
1096     r=read(pipes[0], buf, sizeof(buf)-1);
1097     ok(r == 0, "expected to read 0 bytes, got %d\n", r);
1098     ok(close(pipes[0]) == 0, "unable to close %d: %d\n", pipes[0], errno);
1099
1100     /* Test reading from a pipe with fread() */
1101     if (_pipe(pipes, 1024, O_BINARY) < 0)
1102     {
1103         ok(0, "pipe failed with errno %d\n", errno);
1104         return;
1105     }
1106
1107     arg_v[0] = selfname;
1108     arg_v[1] = "tests/file.c";
1109     arg_v[2] = "pipes";
1110     arg_v[3] = str_fdr; sprintf(str_fdr, "%d", pipes[0]);
1111     arg_v[4] = str_fdw; sprintf(str_fdw, "%d", pipes[1]);
1112     arg_v[5] = NULL;
1113     proc_handles[1] = (HANDLE)_spawnvp(_P_NOWAIT, selfname, arg_v);
1114     ok(close(pipes[1]) == 0, "unable to close %d: %d\n", pipes[1], errno);
1115     file=fdopen(pipes[0], "r");
1116
1117     /* In blocking mode, fread will keep calling read() until it gets
1118      * enough bytes, or EOF, even on Unix.  (If this were a Unix terminal
1119      * in cooked mode instead of a pipe, it would also stop on EOL.)
1120      */
1121     expected[0] = 0;
1122     for (i=0; i<N_TEST_MESSAGES; i++)
1123        strcat(expected, pipe_string);
1124     r=fread(buf, 1, sizeof(buf)-1, file);
1125     ok(r == strlen(expected), "fread() returned %d: ferror=%d\n", r, ferror(file));
1126     if (r > 0)
1127        buf[r]='\0';
1128     ok(strcmp(buf, expected) == 0, "got '%s' expected '%s'\n", buf, expected);
1129
1130     /* Let child close the file before we read, so we can sense EOF reliably */
1131     Sleep(100);
1132     r=fread(buf, 1, sizeof(buf)-1, file);
1133     ok(r == 0, "fread() returned %d instead of 0\n", r);
1134     ok(ferror(file) == 0, "got ferror() = %d\n", ferror(file));
1135     ok(feof(file), "feof() is false!\n");
1136
1137     ok(fclose(file) == 0, "unable to close the pipe: %d\n", errno);
1138 }
1139
1140 static void test_unlink(void)
1141 {
1142     FILE* file;
1143     ok(mkdir("test_unlink") == 0, "unable to create test dir\n");
1144     file = fopen("test_unlink\\empty", "w");
1145     ok(file != NULL, "unable to create test file\n");
1146     if(file)
1147       fclose(file);
1148     ok(_unlink("test_unlink") != 0, "unlinking a non-empty directory must fail\n");
1149     unlink("test_unlink\\empty");
1150     rmdir("test_unlink");
1151 }
1152
1153 START_TEST(file)
1154 {
1155     int arg_c;
1156     char** arg_v;
1157
1158     arg_c = winetest_get_mainargs( &arg_v );
1159
1160     /* testing low-level I/O */
1161     if (arg_c >= 3)
1162     {
1163         if (strcmp(arg_v[2], "inherit") == 0)
1164             test_file_inherit_child(arg_v[3]);
1165         else if (strcmp(arg_v[2], "inherit_no") == 0)
1166             test_file_inherit_child_no(arg_v[3]);
1167         else if (strcmp(arg_v[2], "pipes") == 0)
1168             test_pipes_child(arg_c, arg_v);
1169         else
1170             ok(0, "invalid argument '%s'\n", arg_v[2]);
1171         return;
1172     }
1173     test_file_inherit(arg_v[0]);
1174     test_file_write_read();
1175     test_chsize();
1176     test_stat();
1177     test_unlink();
1178
1179     /* testing stream I/O */
1180     test_filbuf();
1181     test_fdopen();
1182     test_fopen_fclose_fcloseall();
1183     test_fileops();
1184     test_asciimode();
1185     test_asciimode2();
1186     test_readmode(FALSE); /* binary mode */
1187     test_readmode(TRUE);  /* ascii mode */
1188     test_fgetc();
1189     test_fputc();
1190     test_flsbuf();
1191     test_fgetwc();
1192     test_ctrlz();
1193     test_file_put_get();
1194     test_tmpnam();
1195     test_get_osfhandle();
1196     test_setmaxstdio();
1197     test_pipes(arg_v[0]);
1198
1199     /* Wait for the (_P_NOWAIT) spawned processes to finish to make sure the report
1200      * file contains lines in the correct order
1201      */
1202     WaitForMultipleObjects(sizeof(proc_handles)/sizeof(proc_handles[0]), proc_handles, TRUE, 5000);
1203 }