wininet: Support the Cache-Control max-age directive for setting url cache entry...
[wine/testsucceed.git] / dlls / msvcrt / tests / file.c
blobf70285b5e8e8c5b34279805e1b61f56b201413f4
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 int (__cdecl *p_fopen_s)(FILE**, const char*, const char*);
40 static int (__cdecl *p__wfopen_s)(FILE**, const wchar_t*, const wchar_t*);
42 static void init(void)
44 HMODULE hmod = GetModuleHandleA("msvcrt.dll");
46 p_fopen_s = (void*)GetProcAddress(hmod, "fopen_s");
47 p__wfopen_s = (void*)GetProcAddress(hmod, "_wfopen_s");
50 static void test_filbuf( void )
52 FILE *fp;
53 int c;
54 fpos_t pos;
56 fp = fopen("filbuf.tst", "wb");
57 fwrite("\n\n\n\n", 1, 4, fp);
58 fclose(fp);
60 fp = fopen("filbuf.tst", "rt");
61 c = _filbuf(fp);
62 ok(c == '\n', "read wrong byte\n");
63 /* See bug 16970 for why we care about _filbuf.
64 * ftell returns screwy values on files with lots
65 * of bare LFs in ascii mode because it assumes
66 * that ascii files contain only CRLFs, removes
67 * the CR's early in _filbuf, and adjusts the return
68 * value of ftell to compensate.
69 * native _filbuf will read the whole file, then consume and return
70 * the first one. That leaves fp->_fd at offset 4, and fp->_ptr
71 * pointing to a buffer of three bare LFs, so
72 * ftell will return 4 - 3 - 3 = -2.
74 ok(ftell(fp) == -2, "ascii crlf removal does not match native\n");
75 ok(fgetpos(fp, &pos) == 0, "fgetpos fail\n");
76 ok(pos == -2, "ftell does not match fgetpos\n");
77 fclose(fp);
78 unlink("filbuf.tst");
81 static void test_fdopen( void )
83 static const char buffer[] = {0,1,2,3,4,5,6,7,8,9};
84 char ibuf[10];
85 int fd;
86 FILE *file;
88 fd = open ("fdopen.tst", O_WRONLY | O_CREAT | O_BINARY, _S_IREAD |_S_IWRITE);
89 write (fd, buffer, sizeof (buffer));
90 close (fd);
92 fd = open ("fdopen.tst", O_RDONLY | O_BINARY);
93 lseek (fd, 5, SEEK_SET);
94 file = fdopen (fd, "rb");
95 ok (fread (ibuf, 1, sizeof (buffer), file) == 5, "read wrong byte count\n");
96 ok (memcmp (ibuf, buffer + 5, 5) == 0, "read wrong bytes\n");
97 fclose (file);
98 unlink ("fdopen.tst");
101 static void test_fileops( void )
103 static const char outbuffer[] = "0,1,2,3,4,5,6,7,8,9";
104 char buffer[256];
105 WCHAR wbuffer[256];
106 int fd;
107 FILE *file;
108 fpos_t pos;
109 int i, c;
111 fd = open ("fdopen.tst", O_WRONLY | O_CREAT | O_BINARY, _S_IREAD |_S_IWRITE);
112 write (fd, outbuffer, sizeof (outbuffer));
113 close (fd);
115 fd = open ("fdopen.tst", O_RDONLY | O_BINARY);
116 file = fdopen (fd, "rb");
117 ok(strlen(outbuffer) == (sizeof(outbuffer)-1),"strlen/sizeof error\n");
118 ok(fgets(buffer,sizeof(buffer),file) !=0,"fgets failed unexpected\n");
119 ok(fgets(buffer,sizeof(buffer),file) ==0,"fgets didn't signal EOF\n");
120 ok(feof(file) !=0,"feof doesn't signal EOF\n");
121 rewind(file);
122 ok(fgets(buffer,strlen(outbuffer),file) !=0,"fgets failed unexpected\n");
123 ok(lstrlenA(buffer) == lstrlenA(outbuffer) -1,"fgets didn't read right size\n");
124 ok(fgets(buffer,sizeof(outbuffer),file) !=0,"fgets failed unexpected\n");
125 ok(strlen(buffer) == 1,"fgets dropped chars\n");
126 ok(buffer[0] == outbuffer[strlen(outbuffer)-1],"fgets exchanged chars\n");
128 rewind(file);
129 for (i = 0, c = EOF; i < sizeof(outbuffer); i++)
131 ok((c = fgetc(file)) == outbuffer[i], "fgetc returned wrong data\n");
133 ok((c = fgetc(file)) == EOF, "getc did not return EOF\n");
134 ok(feof(file), "feof did not return EOF\n");
135 ok(ungetc(c, file) == EOF, "ungetc(EOF) did not return EOF\n");
136 ok(feof(file), "feof after ungetc(EOF) did not return EOF\n");
137 ok((c = fgetc(file)) == EOF, "getc did not return EOF\n");
138 c = outbuffer[sizeof(outbuffer) - 1];
139 ok(ungetc(c, file) == c, "ungetc did not return its input\n");
140 ok(!feof(file), "feof after ungetc returned EOF\n");
141 ok((c = fgetc(file)) != EOF, "getc after ungetc returned EOF\n");
142 ok(c == outbuffer[sizeof(outbuffer) - 1],
143 "getc did not return ungetc'd data\n");
144 ok(!feof(file), "feof after getc returned EOF prematurely\n");
145 ok((c = fgetc(file)) == EOF, "getc did not return EOF\n");
146 ok(feof(file), "feof after getc did not return EOF\n");
148 rewind(file);
149 ok(fgetpos(file,&pos) == 0, "fgetpos failed unexpected\n");
150 ok(pos == 0, "Unexpected result of fgetpos %x%08x\n", (DWORD)(pos >> 32), (DWORD)pos);
151 pos = sizeof (outbuffer);
152 ok(fsetpos(file, &pos) == 0, "fsetpos failed unexpected\n");
153 ok(fgetpos(file,&pos) == 0, "fgetpos failed unexpected\n");
154 ok(pos == sizeof (outbuffer), "Unexpected result of fgetpos %x%08x\n", (DWORD)(pos >> 32), (DWORD)pos);
156 fclose (file);
157 fd = open ("fdopen.tst", O_RDONLY | O_TEXT);
158 file = fdopen (fd, "rt"); /* open in TEXT mode */
159 ok(fgetws(wbuffer,sizeof(wbuffer)/sizeof(wbuffer[0]),file) !=0,"fgetws failed unexpected\n");
160 ok(fgetws(wbuffer,sizeof(wbuffer)/sizeof(wbuffer[0]),file) ==0,"fgetws didn't signal EOF\n");
161 ok(feof(file) !=0,"feof doesn't signal EOF\n");
162 rewind(file);
163 ok(fgetws(wbuffer,strlen(outbuffer),file) !=0,"fgetws failed unexpected\n");
164 ok(lstrlenW(wbuffer) == (lstrlenA(outbuffer) -1),"fgetws didn't read right size\n");
165 ok(fgetws(wbuffer,sizeof(outbuffer)/sizeof(outbuffer[0]),file) !=0,"fgets failed unexpected\n");
166 ok(lstrlenW(wbuffer) == 1,"fgets dropped chars\n");
167 fclose (file);
169 file = fopen("fdopen.tst", "rb");
170 ok( file != NULL, "fopen failed\n");
171 /* sizeof(buffer) > content of file */
172 ok(fread(buffer, sizeof(buffer), 1, file) == 0, "fread test failed\n");
173 /* feof should be set now */
174 ok(feof(file), "feof after fread failed\n");
175 fclose (file);
177 unlink ("fdopen.tst");
180 #define IOMODE (ao?"ascii mode":"binary mode")
181 static void test_readmode( BOOL ascii_mode )
183 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";
184 static const char padbuffer[] = "ghjghjghjghj";
185 static const char nlbuffer[] = "\r\n";
186 char buffer[2*BUFSIZ+256];
187 const char *optr;
188 int fd;
189 FILE *file;
190 const int *ip;
191 int i, j, m, ao, pl;
192 unsigned int fp;
193 LONG l;
195 fd = open ("fdopen.tst", O_WRONLY | O_CREAT | O_BINARY, _S_IREAD |_S_IWRITE);
196 /* an internal buffer of BUFSIZ is maintained, so make a file big
197 * enough to test operations that cross the buffer boundary
199 j = (2*BUFSIZ-4)/strlen(padbuffer);
200 for (i=0; i<j; i++)
201 write (fd, padbuffer, strlen(padbuffer));
202 j = (2*BUFSIZ-4)%strlen(padbuffer);
203 for (i=0; i<j; i++)
204 write (fd, &padbuffer[i], 1);
205 write (fd, nlbuffer, strlen(nlbuffer));
206 write (fd, outbuffer, sizeof (outbuffer));
207 close (fd);
209 if (ascii_mode) {
210 /* Open file in ascii mode */
211 fd = open ("fdopen.tst", O_RDONLY);
212 file = fdopen (fd, "r");
213 ao = -1; /* on offset to account for carriage returns */
215 else {
216 fd = open ("fdopen.tst", O_RDONLY | O_BINARY);
217 file = fdopen (fd, "rb");
218 ao = 0;
221 /* first is a test of fgets, ftell, fseek */
222 ok(ftell(file) == 0,"Did not start at beginning of file in %s\n", IOMODE);
223 ok(fgets(buffer,2*BUFSIZ+256,file) !=0,"padding line fgets failed unexpected in %s\n", IOMODE);
224 l = ftell(file);
225 pl = 2*BUFSIZ-2;
226 ok(l == pl,"padding line ftell got %d should be %d in %s\n", l, pl, IOMODE);
227 ok(lstrlenA(buffer) == pl+ao,"padding line fgets got size %d should be %d in %s\n",
228 lstrlenA(buffer), pl+ao, IOMODE);
229 for (fp=0; fp<strlen(outbuffer); fp++)
230 if (outbuffer[fp] == '\n') break;
231 fp++;
232 ok(fgets(buffer,256,file) !=0,"line 1 fgets failed unexpected in %s\n", IOMODE);
233 l = ftell(file);
234 ok(l == pl+fp,"line 1 ftell got %d should be %d in %s\n", l, pl+fp, IOMODE);
235 ok(lstrlenA(buffer) == fp+ao,"line 1 fgets got size %d should be %d in %s\n",
236 lstrlenA(buffer), fp+ao, IOMODE);
237 /* test a seek back across the buffer boundary */
238 l = pl;
239 ok(fseek(file,l,SEEK_SET)==0,"seek failure in %s\n", IOMODE);
240 l = ftell(file);
241 ok(l == pl,"ftell after seek got %d should be %d in %s\n", l, pl, IOMODE);
242 ok(fgets(buffer,256,file) !=0,"second read of line 1 fgets failed unexpected in %s\n", IOMODE);
243 l = ftell(file);
244 ok(l == pl+fp,"second read of line 1 ftell got %d should be %d in %s\n", l, pl+fp, IOMODE);
245 ok(lstrlenA(buffer) == fp+ao,"second read of line 1 fgets got size %d should be %d in %s\n",
246 lstrlenA(buffer), fp+ao, IOMODE);
247 ok(fgets(buffer,256,file) !=0,"line 2 fgets failed unexpected in %s\n", IOMODE);
248 fp += 2;
249 l = ftell(file);
250 ok(l == pl+fp,"line 2 ftell got %d should be %d in %s\n", l, pl+fp, IOMODE);
251 ok(lstrlenA(buffer) == 2+ao,"line 2 fgets got size %d should be %d in %s\n",
252 lstrlenA(buffer), 2+ao, IOMODE);
254 /* test fread across buffer boundary */
255 rewind(file);
256 ok(ftell(file) == 0,"Did not start at beginning of file in %s\n", IOMODE);
257 ok(fgets(buffer,BUFSIZ-6,file) !=0,"padding line fgets failed unexpected in %s\n", IOMODE);
258 j=strlen(outbuffer);
259 i=fread(buffer,1,BUFSIZ+strlen(outbuffer),file);
260 ok(i==BUFSIZ+j,"fread failed, expected %d got %d in %s\n", BUFSIZ+j, i, IOMODE);
261 l = ftell(file);
262 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);
263 for (m=0; m<3; m++)
264 ok(buffer[m]==padbuffer[m+(BUFSIZ-4)%strlen(padbuffer)],"expected %c got %c\n", padbuffer[m], buffer[m]);
265 m+=BUFSIZ+2+ao;
266 optr = outbuffer;
267 for (; m<i; m++) {
268 ok(buffer[m]==*optr,"char %d expected %c got %c in %s\n", m, *optr, buffer[m], IOMODE);
269 optr++;
270 if (ao && (*optr == '\r'))
271 optr++;
273 /* fread should return the requested number of bytes if available */
274 rewind(file);
275 ok(ftell(file) == 0,"Did not start at beginning of file in %s\n", IOMODE);
276 ok(fgets(buffer,BUFSIZ-6,file) !=0,"padding line fgets failed unexpected in %s\n", IOMODE);
277 j = fp+10;
278 i=fread(buffer,1,j,file);
279 ok(i==j,"fread failed, expected %d got %d in %s\n", j, i, IOMODE);
280 /* test fread eof */
281 ok(fseek(file,0,SEEK_END)==0,"seek failure in %s\n", IOMODE);
282 ok(feof(file)==0,"feof failure in %s\n", IOMODE);
283 ok(fread(buffer,1,1,file)==0,"fread failure in %s\n", IOMODE);
284 ok(feof(file)!=0,"feof failure in %s\n", IOMODE);
285 ok(fseek(file,-3,SEEK_CUR)==0,"seek failure in %s\n", IOMODE);
286 ok(feof(file)==0,"feof failure in %s\n", IOMODE);
287 ok(fread(buffer,2,1,file)==1,"fread failed in %s\n", IOMODE);
288 ok(feof(file)==0,"feof failure in %s\n", IOMODE);
289 ok(fread(buffer,2,1,file)==0,"fread failure in %s\n",IOMODE);
290 ok(feof(file)!=0,"feof failure in %s\n", IOMODE);
292 /* test some additional functions */
293 rewind(file);
294 ok(ftell(file) == 0,"Did not start at beginning of file in %s\n", IOMODE);
295 ok(fgets(buffer,2*BUFSIZ+256,file) !=0,"padding line fgets failed unexpected in %s\n", IOMODE);
296 i = _getw(file);
297 ip = (const int *)outbuffer;
298 ok(i == *ip,"_getw failed, expected %08x got %08x in %s\n", *ip, i, IOMODE);
299 for (fp=0; fp<strlen(outbuffer); fp++)
300 if (outbuffer[fp] == '\n') break;
301 fp++;
302 /* this will cause the next _getw to cross carriage return characters */
303 ok(fgets(buffer,fp-6,file) !=0,"line 1 fgets failed unexpected in %s\n", IOMODE);
304 for (i=0, j=0; i<6; i++) {
305 if (ao==0 || outbuffer[fp-3+i] != '\r')
306 buffer[j++] = outbuffer[fp-3+i];
308 i = _getw(file);
309 ip = (int *)buffer;
310 ok(i == *ip,"_getw failed, expected %08x got %08x in %s\n", *ip, i, IOMODE);
312 fclose (file);
313 unlink ("fdopen.tst");
316 static void test_asciimode(void)
318 FILE *fp;
319 char buf[64];
320 int c, i, j;
322 /* Simple test of CR CR LF handling. Test both fgets and fread code paths, they're different! */
323 fp = fopen("ascii.tst", "wb");
324 fputs("\r\r\n", fp);
325 fclose(fp);
326 fp = fopen("ascii.tst", "rt");
327 ok(fgets(buf, sizeof(buf), fp) != NULL, "fgets\n");
328 ok(0 == strcmp(buf, "\r\n"), "CR CR LF not read as CR LF\n");
329 rewind(fp);
330 ok((fread(buf, 1, sizeof(buf), fp) == 2) && (0 == strcmp(buf, "\r\n")), "CR CR LF not read as CR LF\n");
331 fclose(fp);
332 unlink("ascii.tst");
334 /* Simple test of foo ^Z [more than one block] bar handling */
335 fp = fopen("ascii.tst", "wb");
336 fputs("foo\032", fp); /* foo, logical EOF, ... */
337 fseek(fp, 65536L, SEEK_SET); /* ... more than MSVCRT_BUFSIZ, ... */
338 fputs("bar", fp); /* ... bar */
339 fclose(fp);
340 fp = fopen("ascii.tst", "rt");
341 ok(fgets(buf, sizeof(buf), fp) != NULL, "fgets foo\n");
342 ok(0 == strcmp(buf, "foo"), "foo ^Z not read as foo by fgets\n");
343 ok(fgets(buf, sizeof(buf), fp) == NULL, "fgets after logical EOF\n");
344 rewind(fp);
345 ok((fread(buf, 1, sizeof(buf), fp) == 3) && (0 == strcmp(buf, "foo")), "foo ^Z not read as foo by fread\n");
346 ok((fread(buf, 1, sizeof(buf), fp) == 0), "fread after logical EOF\n");
347 fclose(fp);
349 /* Show ASCII mode handling*/
350 fp= fopen("ascii.tst","wb");
351 fputs("0\r\n1\r\n2\r\n3\r\n4\r\n5\r\n6\r\n7\r\n8\r\n9\r\n", fp);
352 fclose(fp);
354 fp = fopen("ascii.tst", "r");
355 c= fgetc(fp);
356 c= fgetc(fp);
357 fseek(fp,0,SEEK_CUR);
358 for(i=1; i<10; i++) {
359 ok((j = ftell(fp)) == i*3, "ftell fails in TEXT mode\n");
360 fseek(fp,0,SEEK_CUR);
361 ok((c = fgetc(fp)) == '0'+ i, "fgetc after fseek failed in line %d\n", i);
362 c= fgetc(fp);
364 /* Show that fseek doesn't skip \\r !*/
365 rewind(fp);
366 c= fgetc(fp);
367 fseek(fp, 2 ,SEEK_CUR);
368 for(i=1; i<10; i++) {
369 ok((c = fgetc(fp)) == '0'+ i, "fgetc after fseek with pos Offset failed in line %d\n", i);
370 fseek(fp, 2 ,SEEK_CUR);
372 fseek(fp, 9*3 ,SEEK_SET);
373 c = fgetc(fp);
374 fseek(fp, -4 ,SEEK_CUR);
375 for(i= 8; i>=0; i--) {
376 ok((c = fgetc(fp)) == '0'+ i, "fgetc after fseek with neg Offset failed in line %d\n", i);
377 fseek(fp, -4 ,SEEK_CUR);
379 /* Show what happens if fseek positions filepointer on \\r */
380 fclose(fp);
381 fp = fopen("ascii.tst", "r");
382 fseek(fp, 3 ,SEEK_SET);
383 ok((c = fgetc(fp)) == '1', "fgetc fails to read next char when positioned on \\r\n");
384 fclose(fp);
386 unlink("ascii.tst");
389 static void test_asciimode2(void)
391 /* Error sequence from one app was getchar followed by small fread
392 * with one \r removed had last byte of buffer filled with
393 * next byte of *unbuffered* data rather than next byte from buffer
394 * Test case is a short string of one byte followed by a newline
395 * followed by filler to fill out the sector, then a sector of
396 * some different byte.
399 FILE *fp;
400 char ibuf[4];
401 int i;
402 static const char obuf[] =
403 "00\n"
404 "000000000000000000000000000000000000000000000000000000000000000000000000000000\n"
405 "000000000000000000000000000000000000000000000000000000000000000000000000000000\n"
406 "000000000000000000000000000000000000000000000000000000000000000000000000000000\n"
407 "000000000000000000000000000000000000000000000000000000000000000000000000000000\n"
408 "000000000000000000000000000000000000000000000000000000000000000000000000000000\n"
409 "000000000000000000000000000000000000000000000000000000000000000000000000000000\n"
410 "000000000000000000\n"
411 "1111111111111111111";
413 fp = fopen("ascii2.tst", "wt");
414 fwrite(obuf, 1, sizeof(obuf), fp);
415 fclose(fp);
417 fp = fopen("ascii2.tst", "rt");
418 ok(getc(fp) == '0', "first char not 0\n");
419 memset(ibuf, 0, sizeof(ibuf));
420 i = fread(ibuf, 1, sizeof(ibuf), fp);
421 ok(i == sizeof(ibuf), "fread i %d != sizeof(ibuf)\n", i);
422 ok(0 == strncmp(ibuf, obuf+1, sizeof(ibuf)), "ibuf != obuf\n");
423 fclose(fp);
424 unlink("ascii2.tst");
427 static WCHAR* AtoW( const char* p )
429 WCHAR* buffer;
430 DWORD len = MultiByteToWideChar( CP_ACP, 0, p, -1, NULL, 0 );
431 buffer = malloc( len * sizeof(WCHAR) );
432 MultiByteToWideChar( CP_ACP, 0, p, -1, buffer, len );
433 return buffer;
436 /* Test reading in text mode when the 512'th character read is \r*/
437 static void test_readboundary(void)
439 FILE *fp;
440 char buf[513], rbuf[513];
441 int i, j;
442 for (i = 0; i < 511; i++)
444 j = (i%('~' - ' ')+ ' ');
445 buf[i] = j;
447 buf[511] = '\n';
448 buf[512] =0;
449 fp = fopen("boundary.tst", "wt");
450 fwrite(buf, 512,1,fp);
451 fclose(fp);
452 fp = fopen("boundary.tst", "rt");
453 for(i=0; i<512; i++)
455 fseek(fp,0 , SEEK_CUR);
456 rbuf[i] = fgetc(fp);
458 rbuf[512] =0;
459 fclose(fp);
460 unlink("boundary.tst");
462 ok(strcmp(buf, rbuf) == 0,"CRLF on buffer boundary failure\n");
465 static void test_fgetc( void )
467 char* tempf;
468 FILE *tempfh;
469 int ich=0xe0, ret;
471 tempf=_tempnam(".","wne");
472 tempfh = fopen(tempf,"w+");
473 fputc(ich, tempfh);
474 fputc(ich, tempfh);
475 rewind(tempfh);
476 ret = fgetc(tempfh);
477 ok(ich == ret, "First fgetc expected %x got %x\n", ich, ret);
478 ret = fgetc(tempfh);
479 ok(ich == ret, "Second fgetc expected %x got %x\n", ich, ret);
480 fclose(tempfh);
481 tempfh = fopen(tempf,"wt");
482 fputc('\n', tempfh);
483 fclose(tempfh);
484 tempfh = fopen(tempf,"wt");
485 setbuf(tempfh, NULL);
486 ret = fgetc(tempfh);
487 ok(ret == -1, "Unbuffered fgetc in text mode must failed on \\r\\n\n");
488 fclose(tempfh);
489 unlink(tempf);
490 free(tempf);
493 static void test_fputc( void )
495 char* tempf;
496 FILE *tempfh;
497 int ret;
499 tempf=_tempnam(".","wne");
500 tempfh = fopen(tempf,"wb");
501 ret = fputc(0,tempfh);
502 ok(0 == ret, "fputc(0,tempfh) expected %x got %x\n", 0, ret);
503 ret = fputc(0xff,tempfh);
504 ok(0xff == ret, "fputc(0xff,tempfh) expected %x got %x\n", 0xff, ret);
505 ret = fputc(0xffffffff,tempfh);
506 ok(0xff == ret, "fputc(0xffffffff,tempfh) expected %x got %x\n", 0xff, ret);
507 fclose(tempfh);
509 tempfh = fopen(tempf,"rb");
510 ret = fputc(0,tempfh);
511 ok(EOF == ret, "fputc(0,tempfh) on r/o file expected %x got %x\n", EOF, ret);
512 fclose(tempfh);
514 unlink(tempf);
515 free(tempf);
518 static void test_flsbuf( void )
520 char* tempf;
521 FILE *tempfh;
522 int c;
523 int ret;
524 int bufmode;
525 static const int bufmodes[] = {_IOFBF,_IONBF};
527 tempf=_tempnam(".","wne");
528 for (bufmode=0; bufmode < sizeof(bufmodes)/sizeof(bufmodes[0]); bufmode++)
530 tempfh = fopen(tempf,"wb");
531 setvbuf(tempfh,NULL,bufmodes[bufmode],2048);
532 ret = _flsbuf(0,tempfh);
533 ok(0 == ret, "_flsbuf(0,tempfh) with bufmode %x expected %x got %x\n",
534 bufmodes[bufmode], 0, ret);
535 ret = _flsbuf(0xff,tempfh);
536 ok(0xff == ret, "_flsbuf(0xff,tempfh) with bufmode %x expected %x got %x\n",
537 bufmodes[bufmode], 0, ret);
538 ret = _flsbuf(0xffffffff,tempfh);
539 ok(0xff == ret, "_flsbuf(0xffffffff,tempfh) with bufmode %x expected %x got %x\n",
540 bufmodes[bufmode], 0, ret);
541 fclose(tempfh);
544 tempfh = fopen(tempf,"rb");
545 ret = _flsbuf(0,tempfh);
546 ok(EOF == ret, "_flsbuf(0,tempfh) on r/o file expected %x got %x\n", EOF, ret);
547 fclose(tempfh);
549 /* See bug 17123, exposed by WinAVR's make */
550 tempfh = fopen(tempf,"w");
551 ok(tempfh->_cnt == 0, "_cnt on freshly opened file was %d\n", tempfh->_cnt);
552 setbuf(tempfh, NULL);
553 ok(tempfh->_cnt == 0, "_cnt on unbuffered file was %d\n", tempfh->_cnt);
554 /* Inlined putchar sets _cnt to -1. Native seems to ignore the value... */
555 tempfh->_cnt = 1234;
556 ret = _flsbuf('Q',tempfh);
557 ok('Q' == ret, "_flsbuf('Q',tempfh) expected %x got %x\n", 'Q', ret);
558 /* ... and reset it to zero */
559 ok(tempfh->_cnt == 0, "after unbuf _flsbuf, _cnt was %d\n", tempfh->_cnt);
560 fclose(tempfh);
561 /* And just for grins, make sure the file is correct */
562 tempfh = fopen(tempf,"r");
563 c = fgetc(tempfh);
564 ok(c == 'Q', "first byte should be 'Q'\n");
565 c = fgetc(tempfh);
566 ok(c == EOF, "there should only be one byte\n");
567 fclose(tempfh);
569 unlink(tempf);
570 free(tempf);
573 static void test_fgetwc( void )
575 #define LLEN 512
577 char* tempf;
578 FILE *tempfh;
579 static const char mytext[]= "This is test_fgetwc\r\n";
580 WCHAR wtextW[BUFSIZ+LLEN+1];
581 WCHAR *mytextW = NULL, *aptr, *wptr;
582 BOOL diff_found = FALSE;
583 int j;
584 unsigned int i;
585 LONG l;
587 tempf=_tempnam(".","wne");
588 tempfh = fopen(tempf,"wb");
589 j = 'a';
590 /* pad to almost the length of the internal buffer */
591 for (i=0; i<BUFSIZ-4; i++)
592 fputc(j,tempfh);
593 j = '\r';
594 fputc(j,tempfh);
595 j = '\n';
596 fputc(j,tempfh);
597 fputs(mytext,tempfh);
598 fclose(tempfh);
599 /* in text mode, getws/c expects multibyte characters */
600 /*currently Wine only supports plain ascii, and that is all that is tested here */
601 tempfh = fopen(tempf,"rt"); /* open in TEXT mode */
602 fgetws(wtextW,LLEN,tempfh);
603 l=ftell(tempfh);
604 ok(l==BUFSIZ-2, "ftell expected %d got %d\n", BUFSIZ-2, l);
605 fgetws(wtextW,LLEN,tempfh);
606 l=ftell(tempfh);
607 ok(l==BUFSIZ-2+strlen(mytext), "ftell expected %d got %d\n", BUFSIZ-2+lstrlen(mytext), l);
608 mytextW = AtoW (mytext);
609 aptr = mytextW;
610 wptr = wtextW;
611 for (i=0; i<strlen(mytext)-2; i++, aptr++, wptr++)
613 diff_found |= (*aptr != *wptr);
615 ok(!(diff_found), "fgetwc difference found in TEXT mode\n");
616 ok(*wptr == '\n', "Carriage return was not skipped\n");
617 fclose(tempfh);
618 unlink(tempf);
620 tempfh = fopen(tempf,"wb");
621 j = 'a';
622 /* pad to almost the length of the internal buffer. Use an odd number of bytes
623 to test that we can read wchars that are split across the internal buffer
624 boundary */
625 for (i=0; i<BUFSIZ-3-strlen(mytext)*sizeof(WCHAR); i++)
626 fputc(j,tempfh);
627 j = '\r';
628 fputwc(j,tempfh);
629 j = '\n';
630 fputwc(j,tempfh);
631 fputws(wtextW,tempfh);
632 fputws(wtextW,tempfh);
633 fclose(tempfh);
634 /* in binary mode, getws/c expects wide characters */
635 tempfh = fopen(tempf,"rb"); /* open in BINARY mode */
636 j=(BUFSIZ-2)/sizeof(WCHAR)-strlen(mytext);
637 fgetws(wtextW,j,tempfh);
638 l=ftell(tempfh);
639 j=(j-1)*sizeof(WCHAR);
640 ok(l==j, "ftell expected %d got %d\n", j, l);
641 i=fgetc(tempfh);
642 ok(i=='a', "fgetc expected %d got %d\n", 0x61, i);
643 l=ftell(tempfh);
644 j++;
645 ok(l==j, "ftell expected %d got %d\n", j, l);
646 fgetws(wtextW,3,tempfh);
647 ok(wtextW[0]=='\r',"expected carriage return got %04hx\n", wtextW[0]);
648 ok(wtextW[1]=='\n',"expected newline got %04hx\n", wtextW[1]);
649 l=ftell(tempfh);
650 j += 4;
651 ok(l==j, "ftell expected %d got %d\n", j, l);
652 for(i=0; i<strlen(mytext); i++)
653 wtextW[i] = 0;
654 /* the first time we get the string, it should be entirely within the local buffer */
655 fgetws(wtextW,LLEN,tempfh);
656 l=ftell(tempfh);
657 j += (strlen(mytext)-1)*sizeof(WCHAR);
658 ok(l==j, "ftell expected %d got %d\n", j, l);
659 diff_found = FALSE;
660 aptr = mytextW;
661 wptr = wtextW;
662 for (i=0; i<strlen(mytext)-2; i++, aptr++, wptr++)
664 ok(*aptr == *wptr, "Char %d expected %04hx got %04hx\n", i, *aptr, *wptr);
665 diff_found |= (*aptr != *wptr);
667 ok(!(diff_found), "fgetwc difference found in BINARY mode\n");
668 ok(*wptr == '\n', "Should get newline\n");
669 for(i=0; i<strlen(mytext); i++)
670 wtextW[i] = 0;
671 /* the second time we get the string, it should cross the local buffer boundary.
672 One of the wchars should be split across the boundary */
673 fgetws(wtextW,LLEN,tempfh);
674 diff_found = FALSE;
675 aptr = mytextW;
676 wptr = wtextW;
677 for (i=0; i<strlen(mytext)-2; i++, aptr++, wptr++)
679 ok(*aptr == *wptr, "Char %d expected %04hx got %04hx\n", i, *aptr, *wptr);
680 diff_found |= (*aptr != *wptr);
682 ok(!(diff_found), "fgetwc difference found in BINARY mode\n");
683 ok(*wptr == '\n', "Should get newline\n");
685 free(mytextW);
686 fclose(tempfh);
687 unlink(tempf);
688 free(tempf);
691 static void test_ctrlz( void )
693 char* tempf;
694 FILE *tempfh;
695 static const char mytext[]= "This is test_ctrlz";
696 char buffer[256];
697 int i, j;
698 LONG l;
700 tempf=_tempnam(".","wne");
701 tempfh = fopen(tempf,"wb");
702 fputs(mytext,tempfh);
703 j = 0x1a; /* a ctrl-z character signals EOF in text mode */
704 fputc(j,tempfh);
705 j = '\r';
706 fputc(j,tempfh);
707 j = '\n';
708 fputc(j,tempfh);
709 j = 'a';
710 fputc(j,tempfh);
711 fclose(tempfh);
712 tempfh = fopen(tempf,"rt"); /* open in TEXT mode */
713 ok(fgets(buffer,256,tempfh) != 0,"fgets failed unexpected\n");
714 i=strlen(buffer);
715 j=strlen(mytext);
716 ok(i==j, "returned string length expected %d got %d\n", j, i);
717 j+=4; /* ftell should indicate the true end of file */
718 l=ftell(tempfh);
719 ok(l==j, "ftell expected %d got %d\n", j, l);
720 ok(feof(tempfh), "did not get EOF\n");
721 fclose(tempfh);
723 tempfh = fopen(tempf,"rb"); /* open in BINARY mode */
724 ok(fgets(buffer,256,tempfh) != 0,"fgets failed unexpected\n");
725 i=strlen(buffer);
726 j=strlen(mytext)+3; /* should get through newline */
727 ok(i==j, "returned string length expected %d got %d\n", j, i);
728 l=ftell(tempfh);
729 ok(l==j, "ftell expected %d got %d\n", j, l);
730 ok(fgets(buffer,256,tempfh) != 0,"fgets failed unexpected\n");
731 i=strlen(buffer);
732 ok(i==1, "returned string length expected %d got %d\n", 1, i);
733 ok(feof(tempfh), "did not get EOF\n");
734 fclose(tempfh);
735 unlink(tempf);
736 free(tempf);
739 static void test_file_put_get( void )
741 char* tempf;
742 FILE *tempfh;
743 static const char mytext[]= "This is a test_file_put_get\n";
744 static const char dostext[]= "This is a test_file_put_get\r\n";
745 char btext[LLEN];
746 WCHAR wtextW[LLEN+1];
747 WCHAR *mytextW = NULL, *aptr, *wptr;
748 BOOL diff_found = FALSE;
749 unsigned int i;
751 tempf=_tempnam(".","wne");
752 tempfh = fopen(tempf,"wt"); /* open in TEXT mode */
753 fputs(mytext,tempfh);
754 fclose(tempfh);
755 tempfh = fopen(tempf,"rb"); /* open in TEXT mode */
756 fgets(btext,LLEN,tempfh);
757 ok( strlen(mytext) + 1 == strlen(btext),"TEXT/BINARY mode not handled for write\n");
758 ok( btext[strlen(mytext)-1] == '\r', "CR not written\n");
759 fclose(tempfh);
760 tempfh = fopen(tempf,"wb"); /* open in BINARY mode */
761 fputs(dostext,tempfh);
762 fclose(tempfh);
763 tempfh = fopen(tempf,"rt"); /* open in TEXT mode */
764 fgets(btext,LLEN,tempfh);
765 ok(strcmp(btext, mytext) == 0,"_O_TEXT read doesn't strip CR\n");
766 fclose(tempfh);
767 tempfh = fopen(tempf,"rb"); /* open in TEXT mode */
768 fgets(btext,LLEN,tempfh);
769 ok(strcmp(btext, dostext) == 0,"_O_BINARY read doesn't preserve CR\n");
771 fclose(tempfh);
772 tempfh = fopen(tempf,"rt"); /* open in TEXT mode */
773 fgetws(wtextW,LLEN,tempfh);
774 mytextW = AtoW (mytext);
775 aptr = mytextW;
776 wptr = wtextW;
778 for (i=0; i<strlen(mytext); i++, aptr++, wptr++)
780 diff_found |= (*aptr != *wptr);
782 ok(!(diff_found), "fgetwc doesn't strip CR in TEXT mode\n");
783 free(mytextW);
784 fclose(tempfh);
785 unlink(tempf);
786 free(tempf);
789 static void test_file_write_read( void )
791 char* tempf;
792 int tempfd;
793 static const char mytext[]= "This is test_file_write_read\nsecond line\n";
794 static const char dostext[]= "This is test_file_write_read\r\nsecond line\r\n";
795 char btext[LLEN];
796 int ret, i;
798 tempf=_tempnam(".","wne");
799 tempfd = _open(tempf,_O_CREAT|_O_TRUNC|_O_BINARY|_O_RDWR,
800 _S_IREAD | _S_IWRITE);
801 ok( tempfd != -1,
802 "Can't open '%s': %d\n", tempf, errno); /* open in BINARY mode */
803 ok(_write(tempfd,dostext,strlen(dostext)) == lstrlenA(dostext),
804 "_write _O_BINARY bad return value\n");
805 _close(tempfd);
806 i = lstrlenA(mytext);
807 tempfd = _open(tempf,_O_RDONLY|_O_BINARY,0); /* open in BINARY mode */
808 ok(_read(tempfd,btext,i) == i,
809 "_read _O_BINARY got bad length\n");
810 ok( memcmp(dostext,btext,i) == 0,
811 "problems with _O_BINARY _write / _read\n");
812 _close(tempfd);
813 tempfd = _open(tempf,_O_RDONLY|_O_TEXT); /* open in TEXT mode */
814 ok(_read(tempfd,btext,i) == i-1,
815 "_read _O_TEXT got bad length\n");
816 ok( memcmp(mytext,btext,i-1) == 0,
817 "problems with _O_BINARY _write / _O_TEXT _read\n");
818 _close(tempfd);
819 tempfd = _open(tempf,_O_CREAT|_O_TRUNC|_O_TEXT|_O_RDWR,
820 _S_IREAD | _S_IWRITE);
821 ok( tempfd != -1,
822 "Can't open '%s': %d\n", tempf, errno); /* open in TEXT mode */
823 ok(_write(tempfd,mytext,strlen(mytext)) == lstrlenA(mytext),
824 "_write _O_TEXT bad return value\n");
825 _close(tempfd);
826 tempfd = _open(tempf,_O_RDONLY|_O_BINARY,0); /* open in BINARY mode */
827 ok(_read(tempfd,btext,LLEN) == lstrlenA(dostext),
828 "_read _O_BINARY got bad length\n");
829 ok( memcmp(dostext,btext,strlen(dostext)) == 0,
830 "problems with _O_TEXT _write / _O_BINARY _read\n");
831 ok( btext[strlen(dostext)-2] == '\r', "CR not written or read\n");
832 _close(tempfd);
833 tempfd = _open(tempf,_O_RDONLY|_O_TEXT); /* open in TEXT mode */
834 ok(_read(tempfd,btext,LLEN) == lstrlenA(mytext),
835 "_read _O_TEXT got bad length\n");
836 ok( memcmp(mytext,btext,strlen(mytext)) == 0,
837 "problems with _O_TEXT _write / _read\n");
838 _close(tempfd);
840 memset(btext, 0, LLEN);
841 tempfd = _open(tempf,_O_APPEND|_O_RDWR); /* open for APPEND in default mode */
842 ok(tell(tempfd) == 0, "bad position %u expecting 0\n", tell(tempfd));
843 ok(_read(tempfd,btext,LLEN) == lstrlenA(mytext), "_read _O_APPEND got bad length\n");
844 ok( memcmp(mytext,btext,strlen(mytext)) == 0, "problems with _O_APPEND _read\n");
845 _close(tempfd);
847 /* Test reading only \n or \r */
848 tempfd = _open(tempf,_O_RDONLY|_O_TEXT); /* open in TEXT mode */
849 _lseek(tempfd, -1, FILE_END);
850 ret = _read(tempfd,btext,LLEN);
851 ok(ret == 1 && *btext == '\n', "_read expected 1 got bad length: %d\n", ret);
852 _lseek(tempfd, -2, FILE_END);
853 ret = _read(tempfd,btext,LLEN);
854 ok(ret == 1 && *btext == '\n', "_read expected '\\n' got bad length: %d\n", ret);
855 _lseek(tempfd, -3, FILE_END);
856 ret = _read(tempfd,btext,1);
857 ok(ret == 1 && *btext == 'e', "_read expected 'e' got \"%.*s\" bad length: %d\n", ret, btext, ret);
858 ok(tell(tempfd) == 41, "bad position %u expecting 41\n", tell(tempfd));
859 _lseek(tempfd, -3, FILE_END);
860 ret = _read(tempfd,btext,2);
861 ok(ret == 1 && *btext == 'e', "_read expected 'e' got \"%.*s\" bad length: %d\n", ret, btext, ret);
862 ok(tell(tempfd) == 42, "bad position %u expecting 42\n", tell(tempfd));
863 _lseek(tempfd, -3, FILE_END);
864 ret = _read(tempfd,btext,3);
865 ok(ret == 2 && *btext == 'e', "_read expected 'e' got \"%.*s\" bad length: %d\n", ret, btext, ret);
866 ok(tell(tempfd) == 43, "bad position %u expecting 43\n", tell(tempfd));
867 _close(tempfd);
869 ret = unlink(tempf);
870 ok( ret == 0 ,"Can't unlink '%s': %d\n", tempf, errno);
871 free(tempf);
873 tempf=_tempnam(".","wne");
874 tempfd = _open(tempf,_O_CREAT|_O_TRUNC|_O_BINARY|_O_RDWR,0);
875 ok( tempfd != -1,
876 "Can't open '%s': %d\n", tempf, errno); /* open in BINARY mode */
877 ok(_write(tempfd,dostext,strlen(dostext)) == lstrlenA(dostext),
878 "_write _O_BINARY bad return value\n");
879 _close(tempfd);
880 tempfd = _open(tempf,_O_RDONLY|_O_BINARY,0); /* open in BINARY mode */
881 ok(_read(tempfd,btext,LLEN) == lstrlenA(dostext),
882 "_read _O_BINARY got bad length\n");
883 ok( memcmp(dostext,btext,strlen(dostext)) == 0,
884 "problems with _O_BINARY _write / _read\n");
885 ok( btext[strlen(dostext)-2] == '\r', "CR not written or read\n");
886 _close(tempfd);
887 tempfd = _open(tempf,_O_RDONLY|_O_TEXT); /* open in TEXT mode */
888 ok(_read(tempfd,btext,LLEN) == lstrlenA(mytext),
889 "_read _O_TEXT got bad length\n");
890 ok( memcmp(mytext,btext,strlen(mytext)) == 0,
891 "problems with _O_BINARY _write / _O_TEXT _read\n");
892 _close(tempfd);
894 /* test _read with single bytes. CR should be skipped and LF pulled in */
895 tempfd = _open(tempf,_O_RDONLY|_O_TEXT); /* open in TEXT mode */
896 for (i=0; i<strlen(mytext); i++) /* */
898 _read(tempfd,btext, 1);
899 ok(btext[0] == mytext[i],"_read failed at pos %d 0x%02x vs 0x%02x\n", i, btext[0], mytext[i]);
901 while (_read(tempfd,btext, 1));
902 _close(tempfd);
904 /* test _read in buffered mode. Last CR should be skipped but LF not pulled in */
905 tempfd = _open(tempf,_O_RDONLY|_O_TEXT); /* open in TEXT mode */
906 i = _read(tempfd,btext, strlen(mytext));
907 ok(i == strlen(mytext)-1, "_read_i %d\n", i);
908 _close(tempfd);
910 ret =_chmod (tempf, _S_IREAD | _S_IWRITE);
911 ok( ret == 0,
912 "Can't chmod '%s' to read-write: %d\n", tempf, errno);
913 ret = unlink(tempf);
914 ok( ret == 0 ,"Can't unlink '%s': %d\n", tempf, errno);
915 free(tempf);
918 static void test_file_inherit_child(const char* fd_s)
920 int fd = atoi(fd_s);
921 char buffer[32];
922 int ret;
924 ret =write(fd, "Success", 8);
925 ok( ret == 8, "Couldn't write in child process on %d (%s)\n", fd, strerror(errno));
926 lseek(fd, 0, SEEK_SET);
927 ok(read(fd, buffer, sizeof (buffer)) == 8, "Couldn't read back the data\n");
928 ok(memcmp(buffer, "Success", 8) == 0, "Couldn't read back the data\n");
931 static void test_file_inherit_child_no(const char* fd_s)
933 int fd = atoi(fd_s);
934 int ret;
936 ret = write(fd, "Success", 8);
937 ok( ret == -1 && errno == EBADF,
938 "Wrong write result in child process on %d (%s)\n", fd, strerror(errno));
941 static void create_io_inherit_block( STARTUPINFO *startup, unsigned int count, const HANDLE *handles )
943 static BYTE block[1024];
944 BYTE *wxflag_ptr;
945 HANDLE *handle_ptr;
946 unsigned int i;
948 startup->lpReserved2 = block;
949 startup->cbReserved2 = sizeof(unsigned) + (sizeof(char) + sizeof(HANDLE)) * count;
950 wxflag_ptr = block + sizeof(unsigned);
951 handle_ptr = (HANDLE *)(wxflag_ptr + count);
953 *(unsigned*)block = count;
954 for (i = 0; i < count; i++)
956 wxflag_ptr[i] = 0x81;
957 handle_ptr[i] = handles[i];
961 static const char *read_file( HANDLE file )
963 static char buffer[128];
964 DWORD ret;
965 SetFilePointer( file, 0, NULL, FILE_BEGIN );
966 if (!ReadFile( file, buffer, sizeof(buffer) - 1, &ret, NULL)) ret = 0;
967 buffer[ret] = 0;
968 return buffer;
971 static void test_stdout_handle( STARTUPINFO *startup, char *cmdline, HANDLE hstdout, BOOL expect_stdout,
972 const char *descr )
974 const char *data;
975 HANDLE hErrorFile;
976 SECURITY_ATTRIBUTES sa;
977 PROCESS_INFORMATION proc;
979 /* make file handle inheritable */
980 sa.nLength = sizeof(sa);
981 sa.lpSecurityDescriptor = NULL;
982 sa.bInheritHandle = TRUE;
984 hErrorFile = CreateFileA( "fdopen.err", GENERIC_READ|GENERIC_WRITE,
985 FILE_SHARE_READ | FILE_SHARE_WRITE, &sa, CREATE_ALWAYS, 0, NULL );
986 startup->dwFlags = STARTF_USESTDHANDLES;
987 startup->hStdInput = GetStdHandle( STD_INPUT_HANDLE );
988 startup->hStdOutput = hErrorFile;
989 startup->hStdError = GetStdHandle( STD_ERROR_HANDLE );
991 CreateProcessA( NULL, cmdline, NULL, NULL, TRUE,
992 CREATE_DEFAULT_ERROR_MODE | NORMAL_PRIORITY_CLASS, NULL, NULL, startup, &proc );
993 winetest_wait_child_process( proc.hProcess );
995 data = read_file( hErrorFile );
996 if (expect_stdout)
997 ok( strcmp( data, "Success" ), "%s: Error file shouldn't contain data\n", descr );
998 else
999 ok( !strcmp( data, "Success" ), "%s: Wrong error data (%s)\n", descr, data );
1001 if (hstdout)
1003 data = read_file( hstdout );
1004 if (expect_stdout)
1005 ok( !strcmp( data, "Success" ), "%s: Wrong stdout data (%s)\n", descr, data );
1006 else
1007 ok( strcmp( data, "Success" ), "%s: Stdout file shouldn't contain data\n", descr );
1010 CloseHandle( hErrorFile );
1011 DeleteFile( "fdopen.err" );
1014 static void test_file_inherit( const char* selfname )
1016 int fd;
1017 const char* arg_v[5];
1018 char buffer[16];
1019 char cmdline[MAX_PATH];
1020 STARTUPINFO startup;
1021 SECURITY_ATTRIBUTES sa;
1022 HANDLE handles[3];
1024 fd = open ("fdopen.tst", O_CREAT | O_RDWR | O_BINARY, _S_IREAD |_S_IWRITE);
1025 ok(fd != -1, "Couldn't create test file\n");
1026 arg_v[0] = selfname;
1027 arg_v[1] = "tests/file.c";
1028 arg_v[2] = "inherit";
1029 arg_v[3] = buffer; sprintf(buffer, "%d", fd);
1030 arg_v[4] = 0;
1031 _spawnvp(_P_WAIT, selfname, arg_v);
1032 ok(tell(fd) == 8, "bad position %u expecting 8\n", tell(fd));
1033 lseek(fd, 0, SEEK_SET);
1034 ok(read(fd, buffer, sizeof (buffer)) == 8 && memcmp(buffer, "Success", 8) == 0, "Couldn't read back the data\n");
1035 close (fd);
1036 ok(unlink("fdopen.tst") == 0, "Couldn't unlink\n");
1038 fd = open ("fdopen.tst", O_CREAT | O_RDWR | O_BINARY | O_NOINHERIT, _S_IREAD |_S_IWRITE);
1039 ok(fd != -1, "Couldn't create test file\n");
1040 arg_v[0] = selfname;
1041 arg_v[1] = "tests/file.c";
1042 arg_v[2] = "inherit_no";
1043 arg_v[3] = buffer; sprintf(buffer, "%d", fd);
1044 arg_v[4] = 0;
1045 _spawnvp(_P_WAIT, selfname, arg_v);
1046 ok(tell(fd) == 0, "bad position %u expecting 0\n", tell(fd));
1047 ok(read(fd, buffer, sizeof (buffer)) == 0, "Found unexpected data (%s)\n", buffer);
1048 close (fd);
1049 ok(unlink("fdopen.tst") == 0, "Couldn't unlink\n");
1051 /* make file handle inheritable */
1052 sa.nLength = sizeof(sa);
1053 sa.lpSecurityDescriptor = NULL;
1054 sa.bInheritHandle = TRUE;
1055 sprintf(cmdline, "%s file inherit 1", selfname);
1057 /* init an empty Reserved2, which should not be recognized as inherit-block */
1058 ZeroMemory(&startup, sizeof(STARTUPINFO));
1059 startup.cb = sizeof(startup);
1060 create_io_inherit_block( &startup, 0, NULL );
1061 test_stdout_handle( &startup, cmdline, 0, FALSE, "empty block" );
1063 /* test with valid inheritblock */
1064 handles[0] = GetStdHandle( STD_INPUT_HANDLE );
1065 handles[1] = CreateFileA( "fdopen.tst", GENERIC_READ|GENERIC_WRITE,
1066 FILE_SHARE_READ | FILE_SHARE_WRITE, &sa, CREATE_ALWAYS, 0, NULL );
1067 handles[2] = GetStdHandle( STD_ERROR_HANDLE );
1068 create_io_inherit_block( &startup, 3, handles );
1069 test_stdout_handle( &startup, cmdline, handles[1], TRUE, "valid block" );
1070 CloseHandle( handles[1] );
1071 DeleteFile("fdopen.tst");
1073 /* test inherit block starting with unsigned zero */
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 *(unsigned int *)startup.lpReserved2 = 0;
1078 test_stdout_handle( &startup, cmdline, handles[1], FALSE, "zero count block" );
1079 CloseHandle( handles[1] );
1080 DeleteFile("fdopen.tst");
1082 /* test inherit block with smaller size */
1083 handles[1] = CreateFileA( "fdopen.tst", GENERIC_READ|GENERIC_WRITE,
1084 FILE_SHARE_READ | FILE_SHARE_WRITE, &sa, CREATE_ALWAYS, 0, NULL );
1085 create_io_inherit_block( &startup, 3, handles );
1086 startup.cbReserved2 -= 3;
1087 test_stdout_handle( &startup, cmdline, handles[1], TRUE, "small size block" );
1088 CloseHandle( handles[1] );
1089 DeleteFile("fdopen.tst");
1091 /* test inherit block with even smaller size */
1092 handles[1] = CreateFileA( "fdopen.tst", GENERIC_READ|GENERIC_WRITE,
1093 FILE_SHARE_READ | FILE_SHARE_WRITE, &sa, CREATE_ALWAYS, 0, NULL );
1094 create_io_inherit_block( &startup, 3, handles );
1095 startup.cbReserved2 = sizeof(unsigned int) + sizeof(HANDLE) + sizeof(char);
1096 test_stdout_handle( &startup, cmdline, handles[1], FALSE, "smaller size block" );
1097 CloseHandle( handles[1] );
1098 DeleteFile("fdopen.tst");
1100 /* test inherit block with larger size */
1101 handles[1] = CreateFileA( "fdopen.tst", GENERIC_READ|GENERIC_WRITE,
1102 FILE_SHARE_READ | FILE_SHARE_WRITE, &sa, CREATE_ALWAYS, 0, NULL );
1103 create_io_inherit_block( &startup, 3, handles );
1104 startup.cbReserved2 += 7;
1105 test_stdout_handle( &startup, cmdline, handles[1], TRUE, "large size block" );
1106 CloseHandle( handles[1] );
1107 DeleteFile("fdopen.tst");
1110 static void test_tmpnam( void )
1112 char name[MAX_PATH] = "abc";
1113 char *res;
1115 res = tmpnam(NULL);
1116 ok(res != NULL, "tmpnam returned NULL\n");
1117 ok(res[0] == '\\', "first character is not a backslash\n");
1118 ok(strchr(res+1, '\\') == 0, "file not in the root directory\n");
1119 ok(res[strlen(res)-1] == '.', "first call - last character is not a dot\n");
1121 res = tmpnam(name);
1122 ok(res != NULL, "tmpnam returned NULL\n");
1123 ok(res == name, "supplied buffer was not used\n");
1124 ok(res[0] == '\\', "first character is not a backslash\n");
1125 ok(strchr(res+1, '\\') == 0, "file not in the root directory\n");
1126 ok(res[strlen(res)-1] != '.', "second call - last character is a dot\n");
1129 static void test_chsize( void )
1131 int fd;
1132 LONG cur, pos, count;
1133 char temptext[] = "012345678";
1134 char *tempfile = _tempnam( ".", "tst" );
1136 ok( tempfile != NULL, "Couldn't create test file: %s\n", tempfile );
1138 fd = _open( tempfile, _O_CREAT|_O_TRUNC|_O_RDWR, _S_IREAD|_S_IWRITE );
1139 ok( fd > 0, "Couldn't open test file\n" );
1141 count = _write( fd, temptext, sizeof(temptext) );
1142 ok( count > 0, "Couldn't write to test file\n" );
1144 /* get current file pointer */
1145 cur = _lseek( fd, 0, SEEK_CUR );
1147 /* make the file smaller */
1148 ok( _chsize( fd, sizeof(temptext) / 2 ) == 0, "_chsize() failed\n" );
1150 pos = _lseek( fd, 0, SEEK_CUR );
1151 ok( cur == pos, "File pointer changed from: %d to: %d\n", cur, pos );
1152 ok( _filelength( fd ) == sizeof(temptext) / 2, "Wrong file size\n" );
1154 /* enlarge the file */
1155 ok( _chsize( fd, sizeof(temptext) * 2 ) == 0, "_chsize() failed\n" );
1157 pos = _lseek( fd, 0, SEEK_CUR );
1158 ok( cur == pos, "File pointer changed from: %d to: %d\n", cur, pos );
1159 ok( _filelength( fd ) == sizeof(temptext) * 2, "Wrong file size\n" );
1161 _close( fd );
1162 _unlink( tempfile );
1163 free( tempfile );
1166 static void test_fopen_fclose_fcloseall( void )
1168 char fname1[] = "empty1";
1169 char fname2[] = "empty2";
1170 char fname3[] = "empty3";
1171 FILE *stream1, *stream2, *stream3, *stream4;
1172 int ret, numclosed;
1174 /* testing fopen() */
1175 stream1 = fopen(fname1, "w+");
1176 ok(stream1 != NULL, "The file '%s' was not opened\n", fname1);
1177 stream2 = fopen(fname2, "w ");
1178 ok(stream2 != NULL, "The file '%s' was not opened\n", fname2 );
1179 _unlink(fname3);
1180 stream3 = fopen(fname3, "r");
1181 ok(stream3 == NULL, "The file '%s' shouldn't exist before\n", fname3 );
1182 stream3 = fopen(fname3, "w+");
1183 ok(stream3 != NULL, "The file '%s' should be opened now\n", fname3 );
1184 errno = 0xfaceabad;
1185 stream4 = fopen("", "w+");
1186 ok(stream4 == NULL && (errno == EINVAL || errno == ENOENT),
1187 "filename is empty, errno = %d (expected 2 or 22)\n", errno);
1188 errno = 0xfaceabad;
1189 stream4 = fopen(NULL, "w+");
1190 ok(stream4 == NULL && (errno == EINVAL || errno == ENOENT),
1191 "filename is NULL, errno = %d (expected 2 or 22)\n", errno);
1193 /* testing fclose() */
1194 ret = fclose(stream2);
1195 ok(ret == 0, "The file '%s' was not closed\n", fname2);
1196 ret = fclose(stream3);
1197 ok(ret == 0, "The file '%s' was not closed\n", fname3);
1198 ret = fclose(stream2);
1199 ok(ret == EOF, "Closing file '%s' returned %d\n", fname2, ret);
1200 ret = fclose(stream3);
1201 ok(ret == EOF, "Closing file '%s' returned %d\n", fname3, ret);
1203 /* testing fcloseall() */
1204 numclosed = _fcloseall();
1205 /* fname1 should be closed here */
1206 ok(numclosed == 1, "Number of files closed by fcloseall(): %u\n", numclosed);
1207 numclosed = _fcloseall();
1208 ok(numclosed == 0, "Number of files closed by fcloseall(): %u\n", numclosed);
1210 ok(_unlink(fname1) == 0, "Couldn't unlink file named '%s'\n", fname1);
1211 ok(_unlink(fname2) == 0, "Couldn't unlink file named '%s'\n", fname2);
1212 ok(_unlink(fname3) == 0, "Couldn't unlink file named '%s'\n", fname3);
1215 static void test_fopen_s( void )
1217 const char name[] = "empty1";
1218 char buff[16];
1219 FILE *file;
1220 int ret;
1221 int len;
1223 if (!p_fopen_s)
1225 win_skip("Skipping fopen_s test\n");
1226 return;
1228 /* testing fopen_s */
1229 ret = p_fopen_s(&file, name, "w");
1230 ok(ret == 0, "fopen_s failed with %d\n", ret);
1231 ok(file != 0, "fopen_s failed to return value\n");
1232 fwrite(name, sizeof(name), 1, file);
1234 ret = fclose(file);
1235 ok(ret != EOF, "File failed to close\n");
1237 file = fopen(name, "r");
1238 ok(file != 0, "fopen failed\n");
1239 len = fread(buff, 1, sizeof(name), file);
1240 ok(len == sizeof(name), "File length is %d\n", len);
1241 buff[sizeof(name)] = '\0';
1242 ok(strcmp(name, buff) == 0, "File content mismatch! Got %s, expected %s\n", buff, name);
1244 ret = fclose(file);
1245 ok(ret != EOF, "File failed to close\n");
1247 ok(_unlink(name) == 0, "Couldn't unlink file named '%s'\n", name);
1250 static void test__wfopen_s( void )
1252 const char name[] = "empty1";
1253 const WCHAR wname[] = {
1254 'e','m','p','t','y','1',0
1256 const WCHAR wmode[] = {
1257 'w',0
1259 char buff[16];
1260 FILE *file;
1261 int ret;
1262 int len;
1264 if (!p__wfopen_s)
1266 win_skip("Skipping _wfopen_s test\n");
1267 return;
1269 /* testing _wfopen_s */
1270 ret = p__wfopen_s(&file, wname, wmode);
1271 ok(ret == 0, "_wfopen_s failed with %d\n", ret);
1272 ok(file != 0, "_wfopen_s failed to return value\n");
1273 fwrite(name, sizeof(name), 1, file);
1275 ret = fclose(file);
1276 ok(ret != EOF, "File failed to close\n");
1278 file = fopen(name, "r");
1279 ok(file != 0, "fopen failed\n");
1280 len = fread(buff, 1, sizeof(name), file);
1281 ok(len == sizeof(name), "File length is %d\n", len);
1282 buff[sizeof(name)] = '\0';
1283 ok(strcmp(name, buff) == 0, "File content mismatch! Got %s, expected %s\n", buff, name);
1285 ret = fclose(file);
1286 ok(ret != EOF, "File failed to close\n");
1288 ok(_unlink(name) == 0, "Couldn't unlink file named '%s'\n", name);
1291 static void test_get_osfhandle(void)
1293 int fd;
1294 char fname[] = "t_get_osfhanle";
1295 DWORD bytes_written;
1296 HANDLE handle;
1298 fd = _sopen(fname, _O_CREAT|_O_RDWR, _SH_DENYRW, _S_IREAD | _S_IWRITE);
1299 handle = (HANDLE)_get_osfhandle(fd);
1300 WriteFile(handle, "bar", 3, &bytes_written, NULL);
1301 _close(fd);
1302 fd = _open(fname, _O_RDONLY, 0);
1303 ok(fd != -1, "Coudn't open '%s' after _get_osfhanle()\n", fname);
1305 _close(fd);
1306 _unlink(fname);
1309 static void test_setmaxstdio(void)
1311 ok(2048 == _setmaxstdio(2048),"_setmaxstdio returned %d instead of 2048\n",_setmaxstdio(2048));
1312 ok(-1 == _setmaxstdio(2049),"_setmaxstdio returned %d instead of -1\n",_setmaxstdio(2049));
1315 static void test_stat(void)
1317 int fd;
1318 int pipes[2];
1319 int ret;
1320 struct stat buf;
1322 /* Tests for a file */
1323 fd = open("stat.tst", O_WRONLY | O_CREAT | O_BINARY, _S_IREAD |_S_IWRITE);
1324 if (fd >= 0)
1326 ret = fstat(fd, &buf);
1327 ok(!ret, "fstat failed: errno=%d\n", errno);
1328 ok((buf.st_mode & _S_IFMT) == _S_IFREG, "bad format = %06o\n", buf.st_mode);
1329 ok((buf.st_mode & 0777) == 0666, "bad st_mode = %06o\n", buf.st_mode);
1330 ok(buf.st_dev == 0, "st_dev is %d, expected 0\n", buf.st_dev);
1331 ok(buf.st_dev == buf.st_rdev, "st_dev (%d) and st_rdev (%d) differ\n", buf.st_dev, buf.st_rdev);
1332 ok(buf.st_nlink == 1, "st_nlink is %d, expected 1\n", buf.st_nlink);
1333 ok(buf.st_size == 0, "st_size is %d, expected 0\n", buf.st_size);
1335 ret = stat("stat.tst", &buf);
1336 ok(!ret, "stat failed: errno=%d\n", errno);
1337 ok((buf.st_mode & _S_IFMT) == _S_IFREG, "bad format = %06o\n", buf.st_mode);
1338 ok((buf.st_mode & 0777) == 0666, "bad st_mode = %06o\n", buf.st_mode);
1339 ok(buf.st_dev == buf.st_rdev, "st_dev (%d) and st_rdev (%d) differ\n", buf.st_dev, buf.st_rdev);
1340 ok(buf.st_nlink == 1, "st_nlink is %d, expected 1\n", buf.st_nlink);
1341 ok(buf.st_size == 0, "st_size is %d, expected 0\n", buf.st_size);
1343 close(fd);
1344 remove("stat.tst");
1346 else
1347 skip("open failed with errno %d\n", errno);
1349 /* Tests for a char device */
1350 if (_dup2(0, 10) == 0)
1352 ret = fstat(10, &buf);
1353 ok(!ret, "fstat(stdin) failed: errno=%d\n", errno);
1354 if ((buf.st_mode & _S_IFMT) == _S_IFCHR)
1356 ok(buf.st_mode == _S_IFCHR, "bad st_mode=%06o\n", buf.st_mode);
1357 ok(buf.st_dev == 10, "st_dev is %d, expected 10\n", buf.st_dev);
1358 ok(buf.st_rdev == 10, "st_rdev is %d, expected 10\n", buf.st_rdev);
1359 ok(buf.st_nlink == 1, "st_nlink is %d, expected 1\n", buf.st_nlink);
1361 else
1362 skip("stdin is not a char device? st_mode=%06o\n", buf.st_mode);
1363 close(10);
1365 else
1366 skip("_dup2 failed with errno %d\n", errno);
1368 /* Tests for pipes */
1369 if (_pipe(pipes, 1024, O_BINARY) == 0)
1371 ret = fstat(pipes[0], &buf);
1372 ok(!ret, "fstat(pipe) failed: errno=%d\n", errno);
1373 ok(buf.st_mode == _S_IFIFO, "bad st_mode=%06o\n", buf.st_mode);
1374 ok(buf.st_dev == pipes[0], "st_dev is %d, expected %d\n", buf.st_dev, pipes[0]);
1375 ok(buf.st_rdev == pipes[0], "st_rdev is %d, expected %d\n", buf.st_rdev, pipes[0]);
1376 ok(buf.st_nlink == 1, "st_nlink is %d, expected 1\n", buf.st_nlink);
1377 close(pipes[0]);
1378 close(pipes[1]);
1380 else
1381 skip("pipe failed with errno %d\n", errno);
1384 static const char* pipe_string="Hello world";
1386 /* How many messages to transfer over the pipe */
1387 #define N_TEST_MESSAGES 3
1389 static void test_pipes_child(int argc, char** args)
1391 int fd;
1392 int nwritten;
1393 int i;
1395 if (argc < 5)
1397 ok(0, "not enough parameters: %d\n", argc);
1398 return;
1401 fd=atoi(args[3]);
1402 i=close(fd);
1403 ok(!i, "unable to close %d: %d\n", fd, errno);
1405 fd=atoi(args[4]);
1407 for (i=0; i<N_TEST_MESSAGES; i++) {
1408 nwritten=write(fd, pipe_string, strlen(pipe_string));
1409 ok(nwritten == strlen(pipe_string), "i %d, expected to write '%s' wrote %d\n", i, pipe_string, nwritten);
1410 /* let other process wake up so they can show off their "keep reading until EOF" behavior */
1411 if (i < N_TEST_MESSAGES-1)
1412 Sleep(100);
1415 i=close(fd);
1416 ok(!i, "unable to close %d: %d\n", fd, errno);
1419 static void test_pipes(const char* selfname)
1421 int pipes[2];
1422 char str_fdr[12], str_fdw[12];
1423 FILE* file;
1424 const char* arg_v[6];
1425 char buf[4096];
1426 char expected[4096];
1427 int r;
1428 int i;
1430 /* Test reading from a pipe with read() */
1431 if (_pipe(pipes, 1024, O_BINARY) < 0)
1433 ok(0, "pipe failed with errno %d\n", errno);
1434 return;
1437 arg_v[0] = selfname;
1438 arg_v[1] = "tests/file.c";
1439 arg_v[2] = "pipes";
1440 arg_v[3] = str_fdr; sprintf(str_fdr, "%d", pipes[0]);
1441 arg_v[4] = str_fdw; sprintf(str_fdw, "%d", pipes[1]);
1442 arg_v[5] = NULL;
1443 proc_handles[0] = (HANDLE)_spawnvp(_P_NOWAIT, selfname, arg_v);
1444 i=close(pipes[1]);
1445 ok(!i, "unable to close %d: %d\n", pipes[1], errno);
1447 for (i=0; i<N_TEST_MESSAGES; i++) {
1448 r=read(pipes[0], buf, sizeof(buf)-1);
1449 ok(r == strlen(pipe_string), "i %d, got %d\n", i, r);
1450 if (r > 0)
1451 buf[r]='\0';
1452 ok(strcmp(buf, pipe_string) == 0, "expected to read '%s', got '%s'\n", pipe_string, buf);
1455 r=read(pipes[0], buf, sizeof(buf)-1);
1456 ok(r == 0, "expected to read 0 bytes, got %d\n", r);
1457 i=close(pipes[0]);
1458 ok(!i, "unable to close %d: %d\n", pipes[0], errno);
1460 /* Test reading from a pipe with fread() */
1461 if (_pipe(pipes, 1024, O_BINARY) < 0)
1463 ok(0, "pipe failed with errno %d\n", errno);
1464 return;
1467 arg_v[0] = selfname;
1468 arg_v[1] = "tests/file.c";
1469 arg_v[2] = "pipes";
1470 arg_v[3] = str_fdr; sprintf(str_fdr, "%d", pipes[0]);
1471 arg_v[4] = str_fdw; sprintf(str_fdw, "%d", pipes[1]);
1472 arg_v[5] = NULL;
1473 proc_handles[1] = (HANDLE)_spawnvp(_P_NOWAIT, selfname, arg_v);
1474 i=close(pipes[1]);
1475 ok(!i, "unable to close %d: %d\n", pipes[1], errno);
1476 file=fdopen(pipes[0], "r");
1478 /* In blocking mode, fread will keep calling read() until it gets
1479 * enough bytes, or EOF, even on Unix. (If this were a Unix terminal
1480 * in cooked mode instead of a pipe, it would also stop on EOL.)
1482 expected[0] = 0;
1483 for (i=0; i<N_TEST_MESSAGES; i++)
1484 strcat(expected, pipe_string);
1485 r=fread(buf, 1, sizeof(buf)-1, file);
1486 ok(r == strlen(expected), "fread() returned %d: ferror=%d\n", r, ferror(file));
1487 if (r > 0)
1488 buf[r]='\0';
1489 ok(strcmp(buf, expected) == 0, "got '%s' expected '%s'\n", buf, expected);
1491 /* Let child close the file before we read, so we can sense EOF reliably */
1492 Sleep(100);
1493 r=fread(buf, 1, sizeof(buf)-1, file);
1494 ok(r == 0, "fread() returned %d instead of 0\n", r);
1495 ok(ferror(file) == 0, "got ferror() = %d\n", ferror(file));
1496 ok(feof(file), "feof() is false!\n");
1498 i=fclose(file);
1499 ok(!i, "unable to close the pipe: %d\n", errno);
1502 static void test_unlink(void)
1504 FILE* file;
1505 ok(mkdir("test_unlink") == 0, "unable to create test dir\n");
1506 file = fopen("test_unlink\\empty", "w");
1507 ok(file != NULL, "unable to create test file\n");
1508 if(file)
1509 fclose(file);
1510 ok(_unlink("test_unlink") != 0, "unlinking a non-empty directory must fail\n");
1511 unlink("test_unlink\\empty");
1512 rmdir("test_unlink");
1515 static void test_dup2(void)
1517 ok(-1 == _dup2(0, -1), "expected _dup2 to fail when second arg is negative\n" );
1520 START_TEST(file)
1522 int arg_c;
1523 char** arg_v;
1525 init();
1527 arg_c = winetest_get_mainargs( &arg_v );
1529 /* testing low-level I/O */
1530 if (arg_c >= 3)
1532 if (strcmp(arg_v[2], "inherit") == 0)
1533 test_file_inherit_child(arg_v[3]);
1534 else if (strcmp(arg_v[2], "inherit_no") == 0)
1535 test_file_inherit_child_no(arg_v[3]);
1536 else if (strcmp(arg_v[2], "pipes") == 0)
1537 test_pipes_child(arg_c, arg_v);
1538 else
1539 ok(0, "invalid argument '%s'\n", arg_v[2]);
1540 return;
1542 test_dup2();
1543 test_file_inherit(arg_v[0]);
1544 test_file_write_read();
1545 test_chsize();
1546 test_stat();
1547 test_unlink();
1549 /* testing stream I/O */
1550 test_filbuf();
1551 test_fdopen();
1552 test_fopen_fclose_fcloseall();
1553 test_fopen_s();
1554 test__wfopen_s();
1555 test_fileops();
1556 test_asciimode();
1557 test_asciimode2();
1558 test_readmode(FALSE); /* binary mode */
1559 test_readmode(TRUE); /* ascii mode */
1560 test_readboundary();
1561 test_fgetc();
1562 test_fputc();
1563 test_flsbuf();
1564 test_fgetwc();
1565 test_ctrlz();
1566 test_file_put_get();
1567 test_tmpnam();
1568 test_get_osfhandle();
1569 test_setmaxstdio();
1570 test_pipes(arg_v[0]);
1572 /* Wait for the (_P_NOWAIT) spawned processes to finish to make sure the report
1573 * file contains lines in the correct order
1575 WaitForMultipleObjects(sizeof(proc_handles)/sizeof(proc_handles[0]), proc_handles, TRUE, 5000);