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