2 * Unit test suite for file functions
4 * Copyright 2002 Bill Currie
5 * Copyright 2005 Paul Rupe
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.
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.
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
22 #include "wine/test.h"
37 static HANDLE proc_handles[2];
39 static void test_filbuf( void )
45 fp = fopen("filbuf.tst", "wb");
46 fwrite("\n\n\n\n", 1, 4, fp);
49 fp = fopen("filbuf.tst", "rt");
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.
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");
70 static void test_fdopen( void )
72 static const char buffer[] = {0,1,2,3,4,5,6,7,8,9};
77 fd = open ("fdopen.tst", O_WRONLY | O_CREAT | O_BINARY, _S_IREAD |_S_IWRITE);
78 write (fd, buffer, sizeof (buffer));
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");
87 unlink ("fdopen.tst");
90 static void test_fileops( void )
92 static const char outbuffer[] = "0,1,2,3,4,5,6,7,8,9";
100 fd = open ("fdopen.tst", O_WRONLY | O_CREAT | O_BINARY, _S_IREAD |_S_IWRITE);
101 write (fd, outbuffer, sizeof (outbuffer));
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");
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");
118 for (i = 0, c = EOF; i < sizeof(outbuffer); i++)
120 ok((c = fgetc(file)) == outbuffer[i], "fgetc returned wrong data\n");
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");
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);
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");
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");
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");
166 unlink ("fdopen.tst");
169 #define IOMODE (ao?"ascii mode":"binary mode")
170 static void test_readmode( BOOL ascii_mode )
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];
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
188 j = (2*BUFSIZ-4)/strlen(padbuffer);
190 write (fd, padbuffer, strlen(padbuffer));
191 j = (2*BUFSIZ-4)%strlen(padbuffer);
193 write (fd, &padbuffer[i], 1);
194 write (fd, nlbuffer, strlen(nlbuffer));
195 write (fd, outbuffer, sizeof (outbuffer));
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 */
205 fd = open ("fdopen.tst", O_RDONLY | O_BINARY);
206 file = fdopen (fd, "rb");
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);
215 ok(l == pl,"padding line ftell got %d should be %d in %s\n", l, pl, IOMODE);
216 ok(lstrlenA(buffer) == pl+ao,"padding line fgets got size %d should be %d in %s\n",
217 lstrlenA(buffer), pl+ao, IOMODE);
218 for (fp=0; fp<strlen(outbuffer); fp++)
219 if (outbuffer[fp] == '\n') break;
221 ok(fgets(buffer,256,file) !=0,"line 1 fgets failed unexpected in %s\n", IOMODE);
223 ok(l == pl+fp,"line 1 ftell got %d should be %d in %s\n", l, pl+fp, IOMODE);
224 ok(lstrlenA(buffer) == fp+ao,"line 1 fgets got size %d should be %d in %s\n",
225 lstrlenA(buffer), fp+ao, IOMODE);
226 /* test a seek back across the buffer boundary */
228 ok(fseek(file,l,SEEK_SET)==0,"seek failure in %s\n", IOMODE);
230 ok(l == pl,"ftell after seek got %d should be %d in %s\n", l, pl, IOMODE);
231 ok(fgets(buffer,256,file) !=0,"second read of line 1 fgets failed unexpected in %s\n", IOMODE);
233 ok(l == pl+fp,"second read of line 1 ftell got %d should be %d in %s\n", l, pl+fp, IOMODE);
234 ok(lstrlenA(buffer) == fp+ao,"second read of line 1 fgets got size %d should be %d in %s\n",
235 lstrlenA(buffer), fp+ao, IOMODE);
236 ok(fgets(buffer,256,file) !=0,"line 2 fgets failed unexpected in %s\n", IOMODE);
239 ok(l == pl+fp,"line 2 ftell got %d should be %d in %s\n", l, pl+fp, IOMODE);
240 ok(lstrlenA(buffer) == 2+ao,"line 2 fgets got size %d should be %d in %s\n",
241 lstrlenA(buffer), 2+ao, IOMODE);
243 /* test fread across buffer boundary */
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);
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);
251 ok(l == pl+j-(ao*4)-5,"ftell after fread got %d should be %d in %s\n", l, pl+j-(ao*4)-5, IOMODE);
253 ok(buffer[m]==padbuffer[m+(BUFSIZ-4)%strlen(padbuffer)],"expected %c got %c\n", padbuffer[m], buffer[m]);
257 ok(buffer[m]==*optr,"char %d expected %c got %c in %s\n", m, *optr, buffer[m], IOMODE);
259 if (ao && (*optr == '\r'))
262 /* fread should return the requested number of bytes if available */
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);
267 i=fread(buffer,1,j,file);
268 ok(i==j,"fread failed, expected %d got %d in %s\n", j, i, IOMODE);
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);
281 /* test some additional functions */
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);
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;
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];
299 ok(i == *ip,"_getw failed, expected %08x got %08x in %s\n", *ip, i, IOMODE);
302 unlink ("fdopen.tst");
305 static void test_asciimode(void)
311 /* Simple test of CR CR LF handling. Test both fgets and fread code paths, they're different! */
312 fp = fopen("ascii.tst", "wb");
315 fp = fopen("ascii.tst", "rt");
316 ok(fgets(buf, sizeof(buf), fp) != NULL, "fgets\n");
317 ok(0 == strcmp(buf, "\r\n"), "CR CR LF not read as CR LF\n");
319 ok((fread(buf, 1, sizeof(buf), fp) == 2) && (0 == strcmp(buf, "\r\n")), "CR CR LF not read as CR LF\n");
323 /* Simple test of foo ^Z [more than one block] bar handling */
324 fp = fopen("ascii.tst", "wb");
325 fputs("foo\032", fp); /* foo, logical EOF, ... */
326 fseek(fp, 65536L, SEEK_SET); /* ... more than MSVCRT_BUFSIZ, ... */
327 fputs("bar", fp); /* ... bar */
329 fp = fopen("ascii.tst", "rt");
330 ok(fgets(buf, sizeof(buf), fp) != NULL, "fgets foo\n");
331 ok(0 == strcmp(buf, "foo"), "foo ^Z not read as foo by fgets\n");
332 ok(fgets(buf, sizeof(buf), fp) == NULL, "fgets after logical EOF\n");
334 ok((fread(buf, 1, sizeof(buf), fp) == 3) && (0 == strcmp(buf, "foo")), "foo ^Z not read as foo by fread\n");
335 ok((fread(buf, 1, sizeof(buf), fp) == 0), "fread after logical EOF\n");
338 /* Show ASCII mode handling*/
339 fp= fopen("ascii.tst","wb");
340 fputs("0\r\n1\r\n2\r\n3\r\n4\r\n5\r\n6\r\n7\r\n8\r\n9\r\n", fp);
343 fp = fopen("ascii.tst", "r");
346 fseek(fp,0,SEEK_CUR);
347 for(i=1; i<10; i++) {
348 ok((j = ftell(fp)) == i*3, "ftell fails in TEXT mode\n");
349 fseek(fp,0,SEEK_CUR);
350 ok((c = fgetc(fp)) == '0'+ i, "fgetc after fseek failed in line %d\n", i);
353 /* Show that fseek doesn't skip \\r !*/
356 fseek(fp, 2 ,SEEK_CUR);
357 for(i=1; i<10; i++) {
358 ok((c = fgetc(fp)) == '0'+ i, "fgetc after fseek with pos Offset failed in line %d\n", i);
359 fseek(fp, 2 ,SEEK_CUR);
361 fseek(fp, 9*3 ,SEEK_SET);
363 fseek(fp, -4 ,SEEK_CUR);
364 for(i= 8; i>=0; i--) {
365 ok((c = fgetc(fp)) == '0'+ i, "fgetc after fseek with neg Offset failed in line %d\n", i);
366 fseek(fp, -4 ,SEEK_CUR);
368 /* Show what happens if fseek positions filepointer on \\r */
370 fp = fopen("ascii.tst", "r");
371 fseek(fp, 3 ,SEEK_SET);
372 ok((c = fgetc(fp)) == '1', "fgetc fails to read next char when positioned on \\r\n");
378 static void test_asciimode2(void)
380 /* Error sequence from one app was getchar followed by small fread
381 * with one \r removed had last byte of buffer filled with
382 * next byte of *unbuffered* data rather than next byte from buffer
383 * Test case is a short string of one byte followed by a newline
384 * followed by filler to fill out the sector, then a sector of
385 * some different byte.
391 static const char obuf[] =
393 "000000000000000000000000000000000000000000000000000000000000000000000000000000\n"
394 "000000000000000000000000000000000000000000000000000000000000000000000000000000\n"
395 "000000000000000000000000000000000000000000000000000000000000000000000000000000\n"
396 "000000000000000000000000000000000000000000000000000000000000000000000000000000\n"
397 "000000000000000000000000000000000000000000000000000000000000000000000000000000\n"
398 "000000000000000000000000000000000000000000000000000000000000000000000000000000\n"
399 "000000000000000000\n"
400 "1111111111111111111";
402 fp = fopen("ascii2.tst", "wt");
403 fwrite(obuf, 1, sizeof(obuf), fp);
406 fp = fopen("ascii2.tst", "rt");
407 ok(getc(fp) == '0', "first char not 0\n");
408 memset(ibuf, 0, sizeof(ibuf));
409 i = fread(ibuf, 1, sizeof(ibuf), fp);
410 ok(i == sizeof(ibuf), "fread i %d != sizeof(ibuf)\n", i);
411 ok(0 == strncmp(ibuf, obuf+1, sizeof(ibuf)), "ibuf != obuf\n");
413 unlink("ascii2.tst");
416 static WCHAR* AtoW( const char* p )
419 DWORD len = MultiByteToWideChar( CP_ACP, 0, p, -1, NULL, 0 );
420 buffer = malloc( len * sizeof(WCHAR) );
421 MultiByteToWideChar( CP_ACP, 0, p, -1, buffer, len );
425 /* Test reading in text mode when the 512'th character read is \r*/
426 static void test_readboundary(void)
429 char buf[513], rbuf[513];
431 for (i = 0; i < 511; i++)
433 j = (i%('~' - ' ')+ ' ');
438 fp = fopen("boundary.tst", "wt");
439 fwrite(buf, 512,1,fp);
441 fp = fopen("boundary.tst", "rt");
444 fseek(fp,0 , SEEK_CUR);
449 unlink("boundary.tst");
451 ok(strcmp(buf, rbuf) == 0,"CRLF on buffer boundary failure\n");
454 static void test_fgetc( void )
460 tempf=_tempnam(".","wne");
461 tempfh = fopen(tempf,"w+");
466 ok(ich == ret, "First fgetc expected %x got %x\n", ich, ret);
468 ok(ich == ret, "Second fgetc expected %x got %x\n", ich, ret);
470 tempfh = fopen(tempf,"wt");
473 tempfh = fopen(tempf,"wt");
474 setbuf(tempfh, NULL);
476 ok(ret == -1, "Unbuffered fgetc in text mode must failed on \\r\\n\n");
482 static void test_fputc( void )
488 tempf=_tempnam(".","wne");
489 tempfh = fopen(tempf,"wb");
490 ret = fputc(0,tempfh);
491 ok(0 == ret, "fputc(0,tempfh) expected %x got %x\n", 0, ret);
492 ret = fputc(0xff,tempfh);
493 ok(0xff == ret, "fputc(0xff,tempfh) expected %x got %x\n", 0xff, ret);
494 ret = fputc(0xffffffff,tempfh);
495 ok(0xff == ret, "fputc(0xffffffff,tempfh) expected %x got %x\n", 0xff, ret);
498 tempfh = fopen(tempf,"rb");
499 ret = fputc(0,tempfh);
500 ok(EOF == ret, "fputc(0,tempfh) on r/o file expected %x got %x\n", EOF, ret);
507 static void test_flsbuf( void )
514 static const int bufmodes[] = {_IOFBF,_IONBF};
516 tempf=_tempnam(".","wne");
517 for (bufmode=0; bufmode < sizeof(bufmodes)/sizeof(bufmodes[0]); bufmode++)
519 tempfh = fopen(tempf,"wb");
520 setvbuf(tempfh,NULL,bufmodes[bufmode],2048);
521 ret = _flsbuf(0,tempfh);
522 ok(0 == ret, "_flsbuf(0,tempfh) with bufmode %x expected %x got %x\n",
523 bufmodes[bufmode], 0, ret);
524 ret = _flsbuf(0xff,tempfh);
525 ok(0xff == ret, "_flsbuf(0xff,tempfh) with bufmode %x expected %x got %x\n",
526 bufmodes[bufmode], 0, ret);
527 ret = _flsbuf(0xffffffff,tempfh);
528 ok(0xff == ret, "_flsbuf(0xffffffff,tempfh) with bufmode %x expected %x got %x\n",
529 bufmodes[bufmode], 0, ret);
533 tempfh = fopen(tempf,"rb");
534 ret = _flsbuf(0,tempfh);
535 ok(EOF == ret, "_flsbuf(0,tempfh) on r/o file expected %x got %x\n", EOF, ret);
538 /* See bug 17123, exposed by WinAVR's make */
539 tempfh = fopen(tempf,"w");
540 ok(tempfh->_cnt == 0, "_cnt on freshly opened file was %d\n", tempfh->_cnt);
541 setbuf(tempfh, NULL);
542 ok(tempfh->_cnt == 0, "_cnt on unbuffered file was %d\n", tempfh->_cnt);
543 /* Inlined putchar sets _cnt to -1. Native seems to ignore the value... */
545 ret = _flsbuf('Q',tempfh);
546 ok('Q' == ret, "_flsbuf('Q',tempfh) expected %x got %x\n", 'Q', ret);
547 /* ... and reset it to zero */
548 ok(tempfh->_cnt == 0, "after unbuf _flsbuf, _cnt was %d\n", tempfh->_cnt);
550 /* And just for grins, make sure the file is correct */
551 tempfh = fopen(tempf,"r");
553 ok(c == 'Q', "first byte should be 'Q'\n");
555 ok(c == EOF, "there should only be one byte\n");
562 static void test_fgetwc( void )
568 static const char mytext[]= "This is test_fgetwc\r\n";
569 WCHAR wtextW[BUFSIZ+LLEN+1];
570 WCHAR *mytextW = NULL, *aptr, *wptr;
571 BOOL diff_found = FALSE;
576 tempf=_tempnam(".","wne");
577 tempfh = fopen(tempf,"wb");
579 /* pad to almost the length of the internal buffer */
580 for (i=0; i<BUFSIZ-4; i++)
586 fputs(mytext,tempfh);
588 /* in text mode, getws/c expects multibyte characters */
589 /*currently Wine only supports plain ascii, and that is all that is tested here */
590 tempfh = fopen(tempf,"rt"); /* open in TEXT mode */
591 fgetws(wtextW,LLEN,tempfh);
593 ok(l==BUFSIZ-2, "ftell expected %d got %d\n", BUFSIZ-2, l);
594 fgetws(wtextW,LLEN,tempfh);
596 ok(l==BUFSIZ-2+strlen(mytext), "ftell expected %d got %d\n", BUFSIZ-2+lstrlen(mytext), l);
597 mytextW = AtoW (mytext);
600 for (i=0; i<strlen(mytext)-2; i++, aptr++, wptr++)
602 diff_found |= (*aptr != *wptr);
604 ok(!(diff_found), "fgetwc difference found in TEXT mode\n");
605 ok(*wptr == '\n', "Carriage return was not skipped\n");
609 tempfh = fopen(tempf,"wb");
611 /* pad to almost the length of the internal buffer. Use an odd number of bytes
612 to test that we can read wchars that are split across the internal buffer
614 for (i=0; i<BUFSIZ-3-strlen(mytext)*sizeof(WCHAR); i++)
620 fputws(wtextW,tempfh);
621 fputws(wtextW,tempfh);
623 /* in binary mode, getws/c expects wide characters */
624 tempfh = fopen(tempf,"rb"); /* open in BINARY mode */
625 j=(BUFSIZ-2)/sizeof(WCHAR)-strlen(mytext);
626 fgetws(wtextW,j,tempfh);
628 j=(j-1)*sizeof(WCHAR);
629 ok(l==j, "ftell expected %d got %d\n", j, l);
631 ok(i=='a', "fgetc expected %d got %d\n", 0x61, i);
634 ok(l==j, "ftell expected %d got %d\n", j, l);
635 fgetws(wtextW,3,tempfh);
636 ok(wtextW[0]=='\r',"expected carriage return got %04hx\n", wtextW[0]);
637 ok(wtextW[1]=='\n',"expected newline got %04hx\n", wtextW[1]);
640 ok(l==j, "ftell expected %d got %d\n", j, l);
641 for(i=0; i<strlen(mytext); i++)
643 /* the first time we get the string, it should be entirely within the local buffer */
644 fgetws(wtextW,LLEN,tempfh);
646 j += (strlen(mytext)-1)*sizeof(WCHAR);
647 ok(l==j, "ftell expected %d got %d\n", j, l);
651 for (i=0; i<strlen(mytext)-2; i++, aptr++, wptr++)
653 ok(*aptr == *wptr, "Char %d expected %04hx got %04hx\n", i, *aptr, *wptr);
654 diff_found |= (*aptr != *wptr);
656 ok(!(diff_found), "fgetwc difference found in BINARY mode\n");
657 ok(*wptr == '\n', "Should get newline\n");
658 for(i=0; i<strlen(mytext); i++)
660 /* the second time we get the string, it should cross the local buffer boundary.
661 One of the wchars should be split across the boundary */
662 fgetws(wtextW,LLEN,tempfh);
666 for (i=0; i<strlen(mytext)-2; i++, aptr++, wptr++)
668 ok(*aptr == *wptr, "Char %d expected %04hx got %04hx\n", i, *aptr, *wptr);
669 diff_found |= (*aptr != *wptr);
671 ok(!(diff_found), "fgetwc difference found in BINARY mode\n");
672 ok(*wptr == '\n', "Should get newline\n");
680 static void test_ctrlz( void )
684 static const char mytext[]= "This is test_ctrlz";
689 tempf=_tempnam(".","wne");
690 tempfh = fopen(tempf,"wb");
691 fputs(mytext,tempfh);
692 j = 0x1a; /* a ctrl-z character signals EOF in text mode */
701 tempfh = fopen(tempf,"rt"); /* open in TEXT mode */
702 ok(fgets(buffer,256,tempfh) != 0,"fgets failed unexpected\n");
705 ok(i==j, "returned string length expected %d got %d\n", j, i);
706 j+=4; /* ftell should indicate the true end of file */
708 ok(l==j, "ftell expected %d got %d\n", j, l);
709 ok(feof(tempfh), "did not get EOF\n");
712 tempfh = fopen(tempf,"rb"); /* open in BINARY mode */
713 ok(fgets(buffer,256,tempfh) != 0,"fgets failed unexpected\n");
715 j=strlen(mytext)+3; /* should get through newline */
716 ok(i==j, "returned string length expected %d got %d\n", j, i);
718 ok(l==j, "ftell expected %d got %d\n", j, l);
719 ok(fgets(buffer,256,tempfh) != 0,"fgets failed unexpected\n");
721 ok(i==1, "returned string length expected %d got %d\n", 1, i);
722 ok(feof(tempfh), "did not get EOF\n");
728 static void test_file_put_get( void )
732 static const char mytext[]= "This is a test_file_put_get\n";
733 static const char dostext[]= "This is a test_file_put_get\r\n";
735 WCHAR wtextW[LLEN+1];
736 WCHAR *mytextW = NULL, *aptr, *wptr;
737 BOOL diff_found = FALSE;
740 tempf=_tempnam(".","wne");
741 tempfh = fopen(tempf,"wt"); /* open in TEXT mode */
742 fputs(mytext,tempfh);
744 tempfh = fopen(tempf,"rb"); /* open in TEXT mode */
745 fgets(btext,LLEN,tempfh);
746 ok( strlen(mytext) + 1 == strlen(btext),"TEXT/BINARY mode not handled for write\n");
747 ok( btext[strlen(mytext)-1] == '\r', "CR not written\n");
749 tempfh = fopen(tempf,"wb"); /* open in BINARY mode */
750 fputs(dostext,tempfh);
752 tempfh = fopen(tempf,"rt"); /* open in TEXT mode */
753 fgets(btext,LLEN,tempfh);
754 ok(strcmp(btext, mytext) == 0,"_O_TEXT read doesn't strip CR\n");
756 tempfh = fopen(tempf,"rb"); /* open in TEXT mode */
757 fgets(btext,LLEN,tempfh);
758 ok(strcmp(btext, dostext) == 0,"_O_BINARY read doesn't preserve CR\n");
761 tempfh = fopen(tempf,"rt"); /* open in TEXT mode */
762 fgetws(wtextW,LLEN,tempfh);
763 mytextW = AtoW (mytext);
767 for (i=0; i<strlen(mytext); i++, aptr++, wptr++)
769 diff_found |= (*aptr != *wptr);
771 ok(!(diff_found), "fgetwc doesn't strip CR in TEXT mode\n");
778 static void test_file_write_read( void )
782 static const char mytext[]= "This is test_file_write_read\nsecond line\n";
783 static const char dostext[]= "This is test_file_write_read\r\nsecond line\r\n";
787 tempf=_tempnam(".","wne");
788 tempfd = _open(tempf,_O_CREAT|_O_TRUNC|_O_BINARY|_O_RDWR,
789 _S_IREAD | _S_IWRITE);
791 "Can't open '%s': %d\n", tempf, errno); /* open in BINARY mode */
792 ok(_write(tempfd,dostext,strlen(dostext)) == lstrlenA(dostext),
793 "_write _O_BINARY bad return value\n");
795 i = lstrlenA(mytext);
796 tempfd = _open(tempf,_O_RDONLY|_O_BINARY,0); /* open in BINARY mode */
797 ok(_read(tempfd,btext,i) == i,
798 "_read _O_BINARY got bad length\n");
799 ok( memcmp(dostext,btext,i) == 0,
800 "problems with _O_BINARY _write / _read\n");
802 tempfd = _open(tempf,_O_RDONLY|_O_TEXT); /* open in TEXT mode */
803 ok(_read(tempfd,btext,i) == i-1,
804 "_read _O_TEXT got bad length\n");
805 ok( memcmp(mytext,btext,i-1) == 0,
806 "problems with _O_BINARY _write / _O_TEXT _read\n");
808 tempfd = _open(tempf,_O_CREAT|_O_TRUNC|_O_TEXT|_O_RDWR,
809 _S_IREAD | _S_IWRITE);
811 "Can't open '%s': %d\n", tempf, errno); /* open in TEXT mode */
812 ok(_write(tempfd,mytext,strlen(mytext)) == lstrlenA(mytext),
813 "_write _O_TEXT bad return value\n");
815 tempfd = _open(tempf,_O_RDONLY|_O_BINARY,0); /* open in BINARY mode */
816 ok(_read(tempfd,btext,LLEN) == lstrlenA(dostext),
817 "_read _O_BINARY got bad length\n");
818 ok( memcmp(dostext,btext,strlen(dostext)) == 0,
819 "problems with _O_TEXT _write / _O_BINARY _read\n");
820 ok( btext[strlen(dostext)-2] == '\r', "CR not written or read\n");
822 tempfd = _open(tempf,_O_RDONLY|_O_TEXT); /* open in TEXT mode */
823 ok(_read(tempfd,btext,LLEN) == lstrlenA(mytext),
824 "_read _O_TEXT got bad length\n");
825 ok( memcmp(mytext,btext,strlen(mytext)) == 0,
826 "problems with _O_TEXT _write / _read\n");
829 memset(btext, 0, LLEN);
830 tempfd = _open(tempf,_O_APPEND|_O_RDWR); /* open for APPEND in default mode */
831 ok(tell(tempfd) == 0, "bad position %u expecting 0\n", tell(tempfd));
832 ok(_read(tempfd,btext,LLEN) == lstrlenA(mytext), "_read _O_APPEND got bad length\n");
833 ok( memcmp(mytext,btext,strlen(mytext)) == 0, "problems with _O_APPEND _read\n");
836 /* Test reading only \n or \r */
837 tempfd = _open(tempf,_O_RDONLY|_O_TEXT); /* open in TEXT mode */
838 _lseek(tempfd, -1, FILE_END);
839 ret = _read(tempfd,btext,LLEN);
840 ok(ret == 1 && *btext == '\n', "_read expected 1 got bad length: %d\n", ret);
841 _lseek(tempfd, -2, FILE_END);
842 ret = _read(tempfd,btext,LLEN);
843 ok(ret == 1 && *btext == '\n', "_read expected '\\n' got bad length: %d\n", ret);
844 _lseek(tempfd, -3, FILE_END);
845 ret = _read(tempfd,btext,1);
846 ok(ret == 1 && *btext == 'e', "_read expected 'e' got \"%.*s\" bad length: %d\n", ret, btext, ret);
847 ok(tell(tempfd) == 41, "bad position %u expecting 41\n", tell(tempfd));
848 _lseek(tempfd, -3, FILE_END);
849 ret = _read(tempfd,btext,2);
850 ok(ret == 1 && *btext == 'e', "_read expected 'e' got \"%.*s\" bad length: %d\n", ret, btext, ret);
851 ok(tell(tempfd) == 42, "bad position %u expecting 42\n", tell(tempfd));
852 _lseek(tempfd, -3, FILE_END);
853 ret = _read(tempfd,btext,3);
854 ok(ret == 2 && *btext == 'e', "_read expected 'e' got \"%.*s\" bad length: %d\n", ret, btext, ret);
855 ok(tell(tempfd) == 43, "bad position %u expecting 43\n", tell(tempfd));
859 ok( ret == 0 ,"Can't unlink '%s': %d\n", tempf, errno);
862 tempf=_tempnam(".","wne");
863 tempfd = _open(tempf,_O_CREAT|_O_TRUNC|_O_BINARY|_O_RDWR,0);
865 "Can't open '%s': %d\n", tempf, errno); /* open in BINARY mode */
866 ok(_write(tempfd,dostext,strlen(dostext)) == lstrlenA(dostext),
867 "_write _O_BINARY bad return value\n");
869 tempfd = _open(tempf,_O_RDONLY|_O_BINARY,0); /* open in BINARY mode */
870 ok(_read(tempfd,btext,LLEN) == lstrlenA(dostext),
871 "_read _O_BINARY got bad length\n");
872 ok( memcmp(dostext,btext,strlen(dostext)) == 0,
873 "problems with _O_BINARY _write / _read\n");
874 ok( btext[strlen(dostext)-2] == '\r', "CR not written or read\n");
876 tempfd = _open(tempf,_O_RDONLY|_O_TEXT); /* open in TEXT mode */
877 ok(_read(tempfd,btext,LLEN) == lstrlenA(mytext),
878 "_read _O_TEXT got bad length\n");
879 ok( memcmp(mytext,btext,strlen(mytext)) == 0,
880 "problems with _O_BINARY _write / _O_TEXT _read\n");
883 ret =_chmod (tempf, _S_IREAD | _S_IWRITE);
885 "Can't chmod '%s' to read-write: %d\n", tempf, errno);
887 ok( ret == 0 ,"Can't unlink '%s': %d\n", tempf, errno);
891 static void test_file_inherit_child(const char* fd_s)
897 ret =write(fd, "Success", 8);
898 ok( ret == 8, "Couldn't write in child process on %d (%s)\n", fd, strerror(errno));
899 lseek(fd, 0, SEEK_SET);
900 ok(read(fd, buffer, sizeof (buffer)) == 8, "Couldn't read back the data\n");
901 ok(memcmp(buffer, "Success", 8) == 0, "Couldn't read back the data\n");
904 static void test_file_inherit_child_no(const char* fd_s)
909 ret = write(fd, "Success", 8);
910 ok( ret == -1 && errno == EBADF,
911 "Wrong write result in child process on %d (%s)\n", fd, strerror(errno));
914 static void create_io_inherit_block( STARTUPINFO *startup, unsigned int count, const HANDLE *handles )
916 static BYTE block[1024];
921 startup->lpReserved2 = block;
922 startup->cbReserved2 = sizeof(unsigned) + (sizeof(char) + sizeof(HANDLE)) * count;
923 wxflag_ptr = block + sizeof(unsigned);
924 handle_ptr = (HANDLE *)(wxflag_ptr + count);
926 *(unsigned*)block = count;
927 for (i = 0; i < count; i++)
929 wxflag_ptr[i] = 0x81;
930 handle_ptr[i] = handles[i];
934 static const char *read_file( HANDLE file )
936 static char buffer[128];
938 SetFilePointer( file, 0, NULL, FILE_BEGIN );
939 if (!ReadFile( file, buffer, sizeof(buffer) - 1, &ret, NULL)) ret = 0;
944 static void test_stdout_handle( STARTUPINFO *startup, char *cmdline, HANDLE hstdout, BOOL expect_stdout,
949 SECURITY_ATTRIBUTES sa;
950 PROCESS_INFORMATION proc;
952 /* make file handle inheritable */
953 sa.nLength = sizeof(sa);
954 sa.lpSecurityDescriptor = NULL;
955 sa.bInheritHandle = TRUE;
957 hErrorFile = CreateFileA( "fdopen.err", GENERIC_READ|GENERIC_WRITE,
958 FILE_SHARE_READ | FILE_SHARE_WRITE, &sa, CREATE_ALWAYS, 0, NULL );
959 startup->dwFlags = STARTF_USESTDHANDLES;
960 startup->hStdInput = GetStdHandle( STD_INPUT_HANDLE );
961 startup->hStdOutput = hErrorFile;
962 startup->hStdError = GetStdHandle( STD_ERROR_HANDLE );
964 CreateProcessA( NULL, cmdline, NULL, NULL, TRUE,
965 CREATE_DEFAULT_ERROR_MODE | NORMAL_PRIORITY_CLASS, NULL, NULL, startup, &proc );
966 winetest_wait_child_process( proc.hProcess );
968 data = read_file( hErrorFile );
970 ok( strcmp( data, "Success" ), "%s: Error file shouldn't contain data\n", descr );
972 ok( !strcmp( data, "Success" ), "%s: Wrong error data (%s)\n", descr, data );
976 data = read_file( hstdout );
978 ok( !strcmp( data, "Success" ), "%s: Wrong stdout data (%s)\n", descr, data );
980 ok( strcmp( data, "Success" ), "%s: Stdout file shouldn't contain data\n", descr );
983 CloseHandle( hErrorFile );
984 DeleteFile( "fdopen.err" );
987 static void test_file_inherit( const char* selfname )
990 const char* arg_v[5];
992 char cmdline[MAX_PATH];
994 SECURITY_ATTRIBUTES sa;
997 fd = open ("fdopen.tst", O_CREAT | O_RDWR | O_BINARY, _S_IREAD |_S_IWRITE);
998 ok(fd != -1, "Couldn't create test file\n");
1000 arg_v[1] = "tests/file.c";
1001 arg_v[2] = "inherit";
1002 arg_v[3] = buffer; sprintf(buffer, "%d", fd);
1004 _spawnvp(_P_WAIT, selfname, arg_v);
1005 ok(tell(fd) == 8, "bad position %u expecting 8\n", tell(fd));
1006 lseek(fd, 0, SEEK_SET);
1007 ok(read(fd, buffer, sizeof (buffer)) == 8 && memcmp(buffer, "Success", 8) == 0, "Couldn't read back the data\n");
1009 ok(unlink("fdopen.tst") == 0, "Couldn't unlink\n");
1011 fd = open ("fdopen.tst", O_CREAT | O_RDWR | O_BINARY | O_NOINHERIT, _S_IREAD |_S_IWRITE);
1012 ok(fd != -1, "Couldn't create test file\n");
1013 arg_v[0] = selfname;
1014 arg_v[1] = "tests/file.c";
1015 arg_v[2] = "inherit_no";
1016 arg_v[3] = buffer; sprintf(buffer, "%d", fd);
1018 _spawnvp(_P_WAIT, selfname, arg_v);
1019 ok(tell(fd) == 0, "bad position %u expecting 0\n", tell(fd));
1020 ok(read(fd, buffer, sizeof (buffer)) == 0, "Found unexpected data (%s)\n", buffer);
1022 ok(unlink("fdopen.tst") == 0, "Couldn't unlink\n");
1024 /* make file handle inheritable */
1025 sa.nLength = sizeof(sa);
1026 sa.lpSecurityDescriptor = NULL;
1027 sa.bInheritHandle = TRUE;
1028 sprintf(cmdline, "%s file inherit 1", selfname);
1030 /* init an empty Reserved2, which should not be recognized as inherit-block */
1031 ZeroMemory(&startup, sizeof(STARTUPINFO));
1032 startup.cb = sizeof(startup);
1033 create_io_inherit_block( &startup, 0, NULL );
1034 test_stdout_handle( &startup, cmdline, 0, FALSE, "empty block" );
1036 /* test with valid inheritblock */
1037 handles[0] = GetStdHandle( STD_INPUT_HANDLE );
1038 handles[1] = CreateFileA( "fdopen.tst", GENERIC_READ|GENERIC_WRITE,
1039 FILE_SHARE_READ | FILE_SHARE_WRITE, &sa, CREATE_ALWAYS, 0, NULL );
1040 handles[2] = GetStdHandle( STD_ERROR_HANDLE );
1041 create_io_inherit_block( &startup, 3, handles );
1042 test_stdout_handle( &startup, cmdline, handles[1], TRUE, "valid block" );
1043 CloseHandle( handles[1] );
1044 DeleteFile("fdopen.tst");
1046 /* test inherit block starting with unsigned zero */
1047 handles[1] = CreateFileA( "fdopen.tst", GENERIC_READ|GENERIC_WRITE,
1048 FILE_SHARE_READ | FILE_SHARE_WRITE, &sa, CREATE_ALWAYS, 0, NULL );
1049 create_io_inherit_block( &startup, 3, handles );
1050 *(unsigned int *)startup.lpReserved2 = 0;
1051 test_stdout_handle( &startup, cmdline, handles[1], FALSE, "zero count block" );
1052 CloseHandle( handles[1] );
1053 DeleteFile("fdopen.tst");
1055 /* test inherit block with smaller size */
1056 handles[1] = CreateFileA( "fdopen.tst", GENERIC_READ|GENERIC_WRITE,
1057 FILE_SHARE_READ | FILE_SHARE_WRITE, &sa, CREATE_ALWAYS, 0, NULL );
1058 create_io_inherit_block( &startup, 3, handles );
1059 startup.cbReserved2 -= 3;
1060 test_stdout_handle( &startup, cmdline, handles[1], TRUE, "small size block" );
1061 CloseHandle( handles[1] );
1062 DeleteFile("fdopen.tst");
1064 /* test inherit block with even smaller size */
1065 handles[1] = CreateFileA( "fdopen.tst", GENERIC_READ|GENERIC_WRITE,
1066 FILE_SHARE_READ | FILE_SHARE_WRITE, &sa, CREATE_ALWAYS, 0, NULL );
1067 create_io_inherit_block( &startup, 3, handles );
1068 startup.cbReserved2 = sizeof(unsigned int) + sizeof(HANDLE) + sizeof(char);
1069 test_stdout_handle( &startup, cmdline, handles[1], FALSE, "smaller size block" );
1070 CloseHandle( handles[1] );
1071 DeleteFile("fdopen.tst");
1073 /* test inherit block with larger size */
1074 handles[1] = CreateFileA( "fdopen.tst", GENERIC_READ|GENERIC_WRITE,
1075 FILE_SHARE_READ | FILE_SHARE_WRITE, &sa, CREATE_ALWAYS, 0, NULL );
1076 create_io_inherit_block( &startup, 3, handles );
1077 startup.cbReserved2 += 7;
1078 test_stdout_handle( &startup, cmdline, handles[1], TRUE, "large size block" );
1079 CloseHandle( handles[1] );
1080 DeleteFile("fdopen.tst");
1083 static void test_tmpnam( void )
1085 char name[MAX_PATH] = "abc";
1089 ok(res != NULL, "tmpnam returned NULL\n");
1090 ok(res[0] == '\\', "first character is not a backslash\n");
1091 ok(strchr(res+1, '\\') == 0, "file not in the root directory\n");
1092 ok(res[strlen(res)-1] == '.', "first call - last character is not a dot\n");
1095 ok(res != NULL, "tmpnam returned NULL\n");
1096 ok(res == name, "supplied buffer was not used\n");
1097 ok(res[0] == '\\', "first character is not a backslash\n");
1098 ok(strchr(res+1, '\\') == 0, "file not in the root directory\n");
1099 ok(res[strlen(res)-1] != '.', "second call - last character is a dot\n");
1102 static void test_chsize( void )
1105 LONG cur, pos, count;
1106 char temptext[] = "012345678";
1107 char *tempfile = _tempnam( ".", "tst" );
1109 ok( tempfile != NULL, "Couldn't create test file: %s\n", tempfile );
1111 fd = _open( tempfile, _O_CREAT|_O_TRUNC|_O_RDWR, _S_IREAD|_S_IWRITE );
1112 ok( fd > 0, "Couldn't open test file\n" );
1114 count = _write( fd, temptext, sizeof(temptext) );
1115 ok( count > 0, "Couldn't write to test file\n" );
1117 /* get current file pointer */
1118 cur = _lseek( fd, 0, SEEK_CUR );
1120 /* make the file smaller */
1121 ok( _chsize( fd, sizeof(temptext) / 2 ) == 0, "_chsize() failed\n" );
1123 pos = _lseek( fd, 0, SEEK_CUR );
1124 ok( cur == pos, "File pointer changed from: %d to: %d\n", cur, pos );
1125 ok( _filelength( fd ) == sizeof(temptext) / 2, "Wrong file size\n" );
1127 /* enlarge the file */
1128 ok( _chsize( fd, sizeof(temptext) * 2 ) == 0, "_chsize() failed\n" );
1130 pos = _lseek( fd, 0, SEEK_CUR );
1131 ok( cur == pos, "File pointer changed from: %d to: %d\n", cur, pos );
1132 ok( _filelength( fd ) == sizeof(temptext) * 2, "Wrong file size\n" );
1135 _unlink( tempfile );
1139 static void test_fopen_fclose_fcloseall( void )
1141 char fname1[] = "empty1";
1142 char fname2[] = "empty2";
1143 char fname3[] = "empty3";
1144 FILE *stream1, *stream2, *stream3, *stream4;
1147 /* testing fopen() */
1148 stream1 = fopen(fname1, "w+");
1149 ok(stream1 != NULL, "The file '%s' was not opened\n", fname1);
1150 stream2 = fopen(fname2, "w ");
1151 ok(stream2 != NULL, "The file '%s' was not opened\n", fname2 );
1153 stream3 = fopen(fname3, "r");
1154 ok(stream3 == NULL, "The file '%s' shouldn't exist before\n", fname3 );
1155 stream3 = fopen(fname3, "w+");
1156 ok(stream3 != NULL, "The file '%s' should be opened now\n", fname3 );
1158 stream4 = fopen("", "w+");
1159 ok(stream4 == NULL && (errno == EINVAL || errno == ENOENT),
1160 "filename is empty, errno = %d (expected 2 or 22)\n", errno);
1162 stream4 = fopen(NULL, "w+");
1163 ok(stream4 == NULL && (errno == EINVAL || errno == ENOENT),
1164 "filename is NULL, errno = %d (expected 2 or 22)\n", errno);
1166 /* testing fclose() */
1167 ret = fclose(stream2);
1168 ok(ret == 0, "The file '%s' was not closed\n", fname2);
1169 ret = fclose(stream3);
1170 ok(ret == 0, "The file '%s' was not closed\n", fname3);
1171 ret = fclose(stream2);
1172 ok(ret == EOF, "Closing file '%s' returned %d\n", fname2, ret);
1173 ret = fclose(stream3);
1174 ok(ret == EOF, "Closing file '%s' returned %d\n", fname3, ret);
1176 /* testing fcloseall() */
1177 numclosed = _fcloseall();
1178 /* fname1 should be closed here */
1179 ok(numclosed == 1, "Number of files closed by fcloseall(): %u\n", numclosed);
1180 numclosed = _fcloseall();
1181 ok(numclosed == 0, "Number of files closed by fcloseall(): %u\n", numclosed);
1183 ok(_unlink(fname1) == 0, "Couldn't unlink file named '%s'\n", fname1);
1184 ok(_unlink(fname2) == 0, "Couldn't unlink file named '%s'\n", fname2);
1185 ok(_unlink(fname3) == 0, "Couldn't unlink file named '%s'\n", fname3);
1188 static void test_get_osfhandle(void)
1191 char fname[] = "t_get_osfhanle";
1192 DWORD bytes_written;
1195 fd = _sopen(fname, _O_CREAT|_O_RDWR, _SH_DENYRW, _S_IREAD | _S_IWRITE);
1196 handle = (HANDLE)_get_osfhandle(fd);
1197 WriteFile(handle, "bar", 3, &bytes_written, NULL);
1199 fd = _open(fname, _O_RDONLY, 0);
1200 ok(fd != -1, "Coudn't open '%s' after _get_osfhanle()\n", fname);
1206 static void test_setmaxstdio(void)
1208 ok(2048 == _setmaxstdio(2048),"_setmaxstdio returned %d instead of 2048\n",_setmaxstdio(2048));
1209 ok(-1 == _setmaxstdio(2049),"_setmaxstdio returned %d instead of -1\n",_setmaxstdio(2049));
1212 static void test_stat(void)
1218 /* Tests for a file */
1219 fd = open("stat.tst", O_WRONLY | O_CREAT | O_BINARY, _S_IREAD |_S_IWRITE);
1222 ok(fstat(fd, &buf) == 0, "fstat failed: errno=%d\n", errno);
1223 ok((buf.st_mode & _S_IFMT) == _S_IFREG, "bad format = %06o\n", buf.st_mode);
1224 ok((buf.st_mode & 0777) == 0666, "bad st_mode = %06o\n", buf.st_mode);
1225 ok(buf.st_dev == 0, "st_dev is %d, expected 0\n", buf.st_dev);
1226 ok(buf.st_dev == buf.st_rdev, "st_dev (%d) and st_rdev (%d) differ\n", buf.st_dev, buf.st_rdev);
1227 ok(buf.st_nlink == 1, "st_nlink is %d, expected 1\n", buf.st_nlink);
1228 ok(buf.st_size == 0, "st_size is %d, expected 0\n", buf.st_size);
1230 ok(stat("stat.tst", &buf) == 0, "stat failed: errno=%d\n", errno);
1231 ok((buf.st_mode & _S_IFMT) == _S_IFREG, "bad format = %06o\n", buf.st_mode);
1232 ok((buf.st_mode & 0777) == 0666, "bad st_mode = %06o\n", buf.st_mode);
1233 ok(buf.st_dev == buf.st_rdev, "st_dev (%d) and st_rdev (%d) differ\n", buf.st_dev, buf.st_rdev);
1234 ok(buf.st_nlink == 1, "st_nlink is %d, expected 1\n", buf.st_nlink);
1235 ok(buf.st_size == 0, "st_size is %d, expected 0\n", buf.st_size);
1241 skip("open failed with errno %d\n", errno);
1243 /* Tests for a char device */
1244 if (_dup2(0, 10) == 0)
1246 ok(fstat(10, &buf) == 0, "fstat(stdin) failed: errno=%d\n", errno);
1247 if ((buf.st_mode & _S_IFMT) == _S_IFCHR)
1249 ok(buf.st_mode == _S_IFCHR, "bad st_mode=%06o\n", buf.st_mode);
1250 ok(buf.st_dev == 10, "st_dev is %d, expected 10\n", buf.st_dev);
1251 ok(buf.st_rdev == 10, "st_rdev is %d, expected 10\n", buf.st_rdev);
1252 ok(buf.st_nlink == 1, "st_nlink is %d, expected 1\n", buf.st_nlink);
1255 skip("stdin is not a char device? st_mode=%06o\n", buf.st_mode);
1259 skip("_dup2 failed with errno %d\n", errno);
1261 /* Tests for pipes */
1262 if (_pipe(pipes, 1024, O_BINARY) == 0)
1264 ok(fstat(pipes[0], &buf) == 0, "fstat(pipe) failed: errno=%d\n", errno);
1265 ok(buf.st_mode == _S_IFIFO, "bad st_mode=%06o\n", buf.st_mode);
1266 ok(buf.st_dev == pipes[0], "st_dev is %d, expected %d\n", buf.st_dev, pipes[0]);
1267 ok(buf.st_rdev == pipes[0], "st_rdev is %d, expected %d\n", buf.st_rdev, pipes[0]);
1268 ok(buf.st_nlink == 1, "st_nlink is %d, expected 1\n", buf.st_nlink);
1273 skip("pipe failed with errno %d\n", errno);
1276 static const char* pipe_string="Hello world";
1278 /* How many messages to transfer over the pipe */
1279 #define N_TEST_MESSAGES 3
1281 static void test_pipes_child(int argc, char** args)
1289 ok(0, "not enough parameters: %d\n", argc);
1294 ok(close(fd) == 0, "unable to close %d: %d\n", fd, errno);
1298 for (i=0; i<N_TEST_MESSAGES; i++) {
1299 nwritten=write(fd, pipe_string, strlen(pipe_string));
1300 ok(nwritten == strlen(pipe_string), "i %d, expected to write '%s' wrote %d\n", i, pipe_string, nwritten);
1301 /* let other process wake up so they can show off their "keep reading until EOF" behavior */
1302 if (i < N_TEST_MESSAGES-1)
1306 ok(close(fd) == 0, "unable to close %d: %d\n", fd, errno);
1309 static void test_pipes(const char* selfname)
1312 char str_fdr[12], str_fdw[12];
1314 const char* arg_v[6];
1316 char expected[4096];
1320 /* Test reading from a pipe with read() */
1321 if (_pipe(pipes, 1024, O_BINARY) < 0)
1323 ok(0, "pipe failed with errno %d\n", errno);
1327 arg_v[0] = selfname;
1328 arg_v[1] = "tests/file.c";
1330 arg_v[3] = str_fdr; sprintf(str_fdr, "%d", pipes[0]);
1331 arg_v[4] = str_fdw; sprintf(str_fdw, "%d", pipes[1]);
1333 proc_handles[0] = (HANDLE)_spawnvp(_P_NOWAIT, selfname, arg_v);
1334 ok(close(pipes[1]) == 0, "unable to close %d: %d\n", pipes[1], errno);
1336 for (i=0; i<N_TEST_MESSAGES; i++) {
1337 r=read(pipes[0], buf, sizeof(buf)-1);
1338 ok(r == strlen(pipe_string), "i %d, got %d\n", i, r);
1341 ok(strcmp(buf, pipe_string) == 0, "expected to read '%s', got '%s'\n", pipe_string, buf);
1344 r=read(pipes[0], buf, sizeof(buf)-1);
1345 ok(r == 0, "expected to read 0 bytes, got %d\n", r);
1346 ok(close(pipes[0]) == 0, "unable to close %d: %d\n", pipes[0], errno);
1348 /* Test reading from a pipe with fread() */
1349 if (_pipe(pipes, 1024, O_BINARY) < 0)
1351 ok(0, "pipe failed with errno %d\n", errno);
1355 arg_v[0] = selfname;
1356 arg_v[1] = "tests/file.c";
1358 arg_v[3] = str_fdr; sprintf(str_fdr, "%d", pipes[0]);
1359 arg_v[4] = str_fdw; sprintf(str_fdw, "%d", pipes[1]);
1361 proc_handles[1] = (HANDLE)_spawnvp(_P_NOWAIT, selfname, arg_v);
1362 ok(close(pipes[1]) == 0, "unable to close %d: %d\n", pipes[1], errno);
1363 file=fdopen(pipes[0], "r");
1365 /* In blocking mode, fread will keep calling read() until it gets
1366 * enough bytes, or EOF, even on Unix. (If this were a Unix terminal
1367 * in cooked mode instead of a pipe, it would also stop on EOL.)
1370 for (i=0; i<N_TEST_MESSAGES; i++)
1371 strcat(expected, pipe_string);
1372 r=fread(buf, 1, sizeof(buf)-1, file);
1373 ok(r == strlen(expected), "fread() returned %d: ferror=%d\n", r, ferror(file));
1376 ok(strcmp(buf, expected) == 0, "got '%s' expected '%s'\n", buf, expected);
1378 /* Let child close the file before we read, so we can sense EOF reliably */
1380 r=fread(buf, 1, sizeof(buf)-1, file);
1381 ok(r == 0, "fread() returned %d instead of 0\n", r);
1382 ok(ferror(file) == 0, "got ferror() = %d\n", ferror(file));
1383 ok(feof(file), "feof() is false!\n");
1385 ok(fclose(file) == 0, "unable to close the pipe: %d\n", errno);
1388 static void test_unlink(void)
1391 ok(mkdir("test_unlink") == 0, "unable to create test dir\n");
1392 file = fopen("test_unlink\\empty", "w");
1393 ok(file != NULL, "unable to create test file\n");
1396 ok(_unlink("test_unlink") != 0, "unlinking a non-empty directory must fail\n");
1397 unlink("test_unlink\\empty");
1398 rmdir("test_unlink");
1401 void test_dup2(void)
1403 ok(-1 == _dup2(0, -1), "expected _dup2 to fail when second arg is negative\n" );
1411 arg_c = winetest_get_mainargs( &arg_v );
1413 /* testing low-level I/O */
1416 if (strcmp(arg_v[2], "inherit") == 0)
1417 test_file_inherit_child(arg_v[3]);
1418 else if (strcmp(arg_v[2], "inherit_no") == 0)
1419 test_file_inherit_child_no(arg_v[3]);
1420 else if (strcmp(arg_v[2], "pipes") == 0)
1421 test_pipes_child(arg_c, arg_v);
1423 ok(0, "invalid argument '%s'\n", arg_v[2]);
1427 test_file_inherit(arg_v[0]);
1428 test_file_write_read();
1433 /* testing stream I/O */
1436 test_fopen_fclose_fcloseall();
1440 test_readmode(FALSE); /* binary mode */
1441 test_readmode(TRUE); /* ascii mode */
1442 test_readboundary();
1448 test_file_put_get();
1450 test_get_osfhandle();
1452 test_pipes(arg_v[0]);
1454 /* Wait for the (_P_NOWAIT) spawned processes to finish to make sure the report
1455 * file contains lines in the correct order
1457 WaitForMultipleObjects(sizeof(proc_handles)/sizeof(proc_handles[0]), proc_handles, TRUE, 5000);