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