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