e652985ef8fd9c61c4e24a6c88e7adb861fde2b1
[reactos.git] / rostests / winetests / msvcrt / file.c
1 /*
2 * Unit test suite for file functions
3 *
4 * Copyright 2002 Bill Currie
5 * Copyright 2005 Paul Rupe
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 */
21
22 #include "wine/test.h"
23 #include <stdarg.h>
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <fcntl.h>
27 #include <share.h>
28 #include <sys/stat.h>
29 #include <io.h>
30 #include <direct.h>
31 #include <windef.h>
32 #include <winbase.h>
33 #include <winnls.h>
34 #include <process.h>
35 #include <errno.h>
36
37 static HANDLE proc_handles[2];
38
39 static void test_filbuf( void )
40 {
41 FILE *fp;
42 int c;
43 fpos_t pos;
44
45 fp = fopen("filbuf.tst", "wb");
46 fwrite("\n\n\n\n", 1, 4, fp);
47 fclose(fp);
48
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.
62 */
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");
68 }
69
70 static void test_fdopen( void )
71 {
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;
76
77 fd = open ("fdopen.tst", O_WRONLY | O_CREAT | O_BINARY, _S_IREAD |_S_IWRITE);
78 write (fd, buffer, sizeof (buffer));
79 close (fd);
80
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");
88 }
89
90 static void test_fileops( void )
91 {
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;
99
100 fd = open ("fdopen.tst", O_WRONLY | O_CREAT | O_BINARY, _S_IREAD |_S_IWRITE);
101 write (fd, outbuffer, sizeof (outbuffer));
102 close (fd);
103
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");
116
117 rewind(file);
118 for (i = 0, c = EOF; i < sizeof(outbuffer); i++)
119 {
120 ok((c = fgetc(file)) == outbuffer[i], "fgetc returned wrong data\n");
121 }
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");
136
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);
144
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);
157
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);
165
166 unlink ("fdopen.tst");
167 }
168
169 #define IOMODE (ao?"ascii mode":"binary mode")
170 static void test_readmode( BOOL ascii_mode )
171 {
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;
183
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
187 */
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);
197
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 */
203 }
204 else {
205 fd = open ("fdopen.tst", O_RDONLY | O_BINARY);
206 file = fdopen (fd, "rb");
207 ao = 0;
208 }
209
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 %d should be %d in %s\n", l, pl, IOMODE);
216 ok(lstrlenA(buffer) == pl+ao,"padding line fgets got size %d should be %d in %s\n",
217 lstrlenA(buffer), pl+ao, IOMODE);
218 for (fp=0; fp<strlen(outbuffer); fp++)
219 if (outbuffer[fp] == '\n') break;
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 %d should be %d in %s\n", l, pl+fp, IOMODE);
224 ok(lstrlenA(buffer) == fp+ao,"line 1 fgets got size %d should be %d in %s\n",
225 lstrlenA(buffer), fp+ao, IOMODE);
226 /* test a seek back across the buffer boundary */
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 %d should be %d in %s\n", l, pl, IOMODE);
231 ok(fgets(buffer,256,file) !=0,"second read of line 1 fgets failed unexpected in %s\n", IOMODE);
232 l = ftell(file);
233 ok(l == pl+fp,"second read of line 1 ftell got %d should be %d in %s\n", l, pl+fp, IOMODE);
234 ok(lstrlenA(buffer) == fp+ao,"second read of line 1 fgets got size %d should be %d in %s\n",
235 lstrlenA(buffer), fp+ao, IOMODE);
236 ok(fgets(buffer,256,file) !=0,"line 2 fgets failed unexpected in %s\n", IOMODE);
237 fp += 2;
238 l = ftell(file);
239 ok(l == pl+fp,"line 2 ftell got %d should be %d in %s\n", l, pl+fp, IOMODE);
240 ok(lstrlenA(buffer) == 2+ao,"line 2 fgets got size %d should be %d in %s\n",
241 lstrlenA(buffer), 2+ao, IOMODE);
242
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 %d 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++;
261 }
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);
280
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];
296 }
297 i = _getw(file);
298 ip = (int *)buffer;
299 ok(i == *ip,"_getw failed, expected %08x got %08x in %s\n", *ip, i, IOMODE);
300
301 fclose (file);
302 unlink ("fdopen.tst");
303 }
304
305 static void test_asciimode(void)
306 {
307 FILE *fp;
308 char buf[64];
309 int c, i, j;
310
311 /* Simple test of CR CR LF handling. Test both fgets and fread code paths, they're different! */
312 fp = fopen("ascii.tst", "wb");
313 fputs("\r\r\n", fp);
314 fclose(fp);
315 fp = fopen("ascii.tst", "rt");
316 ok(fgets(buf, sizeof(buf), fp) != NULL, "fgets\n");
317 ok(0 == strcmp(buf, "\r\n"), "CR CR LF not read as CR LF\n");
318 rewind(fp);
319 ok((fread(buf, 1, sizeof(buf), fp) == 2) && (0 == strcmp(buf, "\r\n")), "CR CR LF not read as CR LF\n");
320 fclose(fp);
321 unlink("ascii.tst");
322
323 /* Simple test of foo ^Z [more than one block] bar handling */
324 fp = fopen("ascii.tst", "wb");
325 fputs("foo\032", fp); /* foo, logical EOF, ... */
326 fseek(fp, 65536L, SEEK_SET); /* ... more than MSVCRT_BUFSIZ, ... */
327 fputs("bar", fp); /* ... bar */
328 fclose(fp);
329 fp = fopen("ascii.tst", "rt");
330 ok(fgets(buf, sizeof(buf), fp) != NULL, "fgets foo\n");
331 ok(0 == strcmp(buf, "foo"), "foo ^Z not read as foo by fgets\n");
332 ok(fgets(buf, sizeof(buf), fp) == NULL, "fgets after logical EOF\n");
333 rewind(fp);
334 ok((fread(buf, 1, sizeof(buf), fp) == 3) && (0 == strcmp(buf, "foo")), "foo ^Z not read as foo by fread\n");
335 ok((fread(buf, 1, sizeof(buf), fp) == 0), "fread after logical EOF\n");
336 fclose(fp);
337
338 /* Show ASCII mode handling*/
339 fp= fopen("ascii.tst","wb");
340 fputs("0\r\n1\r\n2\r\n3\r\n4\r\n5\r\n6\r\n7\r\n8\r\n9\r\n", fp);
341 fclose(fp);
342
343 fp = fopen("ascii.tst", "r");
344 c= fgetc(fp);
345 c= fgetc(fp);
346 fseek(fp,0,SEEK_CUR);
347 for(i=1; i<10; i++) {
348 ok((j = ftell(fp)) == i*3, "ftell fails in TEXT mode\n");
349 fseek(fp,0,SEEK_CUR);
350 ok((c = fgetc(fp)) == '0'+ i, "fgetc after fseek failed in line %d\n", i);
351 c= fgetc(fp);
352 }
353 /* Show that fseek doesn't skip \\r !*/
354 rewind(fp);
355 c= fgetc(fp);
356 fseek(fp, 2 ,SEEK_CUR);
357 for(i=1; i<10; i++) {
358 ok((c = fgetc(fp)) == '0'+ i, "fgetc after fseek with pos Offset failed in line %d\n", i);
359 fseek(fp, 2 ,SEEK_CUR);
360 }
361 fseek(fp, 9*3 ,SEEK_SET);
362 c = fgetc(fp);
363 fseek(fp, -4 ,SEEK_CUR);
364 for(i= 8; i>=0; i--) {
365 ok((c = fgetc(fp)) == '0'+ i, "fgetc after fseek with neg Offset failed in line %d\n", i);
366 fseek(fp, -4 ,SEEK_CUR);
367 }
368 /* Show what happens if fseek positions filepointer on \\r */
369 fclose(fp);
370 fp = fopen("ascii.tst", "r");
371 fseek(fp, 3 ,SEEK_SET);
372 ok((c = fgetc(fp)) == '1', "fgetc fails to read next char when positioned on \\r\n");
373 fclose(fp);
374
375 unlink("ascii.tst");
376 }
377
378 static void test_asciimode2(void)
379 {
380 /* Error sequence from one app was getchar followed by small fread
381 * with one \r removed had last byte of buffer filled with
382 * next byte of *unbuffered* data rather than next byte from buffer
383 * Test case is a short string of one byte followed by a newline
384 * followed by filler to fill out the sector, then a sector of
385 * some different byte.
386 */
387
388 FILE *fp;
389 char ibuf[4];
390 int i;
391 static const char obuf[] =
392 "00\n"
393 "000000000000000000000000000000000000000000000000000000000000000000000000000000\n"
394 "000000000000000000000000000000000000000000000000000000000000000000000000000000\n"
395 "000000000000000000000000000000000000000000000000000000000000000000000000000000\n"
396 "000000000000000000000000000000000000000000000000000000000000000000000000000000\n"
397 "000000000000000000000000000000000000000000000000000000000000000000000000000000\n"
398 "000000000000000000000000000000000000000000000000000000000000000000000000000000\n"
399 "000000000000000000\n"
400 "1111111111111111111";
401
402 fp = fopen("ascii2.tst", "wt");
403 fwrite(obuf, 1, sizeof(obuf), fp);
404 fclose(fp);
405
406 fp = fopen("ascii2.tst", "rt");
407 ok(getc(fp) == '0', "first char not 0\n");
408 memset(ibuf, 0, sizeof(ibuf));
409 i = fread(ibuf, 1, sizeof(ibuf), fp);
410 ok(i == sizeof(ibuf), "fread i %d != sizeof(ibuf)\n", i);
411 ok(0 == strncmp(ibuf, obuf+1, sizeof(ibuf)), "ibuf != obuf\n");
412 fclose(fp);
413 unlink("ascii2.tst");
414 }
415
416 static WCHAR* AtoW( const char* p )
417 {
418 WCHAR* buffer;
419 DWORD len = MultiByteToWideChar( CP_ACP, 0, p, -1, NULL, 0 );
420 buffer = malloc( len * sizeof(WCHAR) );
421 MultiByteToWideChar( CP_ACP, 0, p, -1, buffer, len );
422 return buffer;
423 }
424
425 static void test_fgetc( void )
426 {
427 char* tempf;
428 FILE *tempfh;
429 int ich=0xe0, ret;
430
431 tempf=_tempnam(".","wne");
432 tempfh = fopen(tempf,"w+");
433 fputc(ich, tempfh);
434 fputc(ich, tempfh);
435 rewind(tempfh);
436 ret = fgetc(tempfh);
437 ok(ich == ret, "First fgetc expected %x got %x\n", ich, ret);
438 ret = fgetc(tempfh);
439 ok(ich == ret, "Second fgetc expected %x got %x\n", ich, ret);
440 fclose(tempfh);
441 unlink(tempf);
442 }
443
444 static void test_fputc( void )
445 {
446 char* tempf;
447 FILE *tempfh;
448 int ret;
449
450 tempf=_tempnam(".","wne");
451 tempfh = fopen(tempf,"wb");
452 ret = fputc(0,tempfh);
453 ok(0 == ret, "fputc(0,tempfh) expected %x got %x\n", 0, ret);
454 ret = fputc(0xff,tempfh);
455 ok(0xff == ret, "fputc(0xff,tempfh) expected %x got %x\n", 0xff, ret);
456 ret = fputc(0xffffffff,tempfh);
457 ok(0xff == ret, "fputc(0xffffffff,tempfh) expected %x got %x\n", 0xff, ret);
458 fclose(tempfh);
459
460 tempfh = fopen(tempf,"rb");
461 ret = fputc(0,tempfh);
462 ok(EOF == ret, "fputc(0,tempfh) on r/o file expected %x got %x\n", EOF, ret);
463 fclose(tempfh);
464
465 unlink(tempf);
466 }
467
468 static void test_flsbuf( void )
469 {
470 char* tempf;
471 FILE *tempfh;
472 int c;
473 int ret;
474 int bufmode;
475 static const int bufmodes[] = {_IOFBF,_IONBF};
476
477 tempf=_tempnam(".","wne");
478 for (bufmode=0; bufmode < sizeof(bufmodes)/sizeof(bufmodes[0]); bufmode++)
479 {
480 tempfh = fopen(tempf,"wb");
481 setvbuf(tempfh,NULL,bufmodes[bufmode],2048);
482 ret = _flsbuf(0,tempfh);
483 ok(0 == ret, "_flsbuf(0,tempfh) with bufmode %x expected %x got %x\n",
484 bufmodes[bufmode], 0, ret);
485 ret = _flsbuf(0xff,tempfh);
486 ok(0xff == ret, "_flsbuf(0xff,tempfh) with bufmode %x expected %x got %x\n",
487 bufmodes[bufmode], 0, ret);
488 ret = _flsbuf(0xffffffff,tempfh);
489 ok(0xff == ret, "_flsbuf(0xffffffff,tempfh) with bufmode %x expected %x got %x\n",
490 bufmodes[bufmode], 0, ret);
491 fclose(tempfh);
492 }
493
494 tempfh = fopen(tempf,"rb");
495 ret = _flsbuf(0,tempfh);
496 ok(EOF == ret, "_flsbuf(0,tempfh) on r/o file expected %x got %x\n", EOF, ret);
497 fclose(tempfh);
498
499 /* See bug 17123, exposed by WinAVR's make */
500 tempfh = fopen(tempf,"w");
501 ok(tempfh->_cnt == 0, "_cnt on freshly opened file was %d\n", tempfh->_cnt);
502 setbuf(tempfh, NULL);
503 ok(tempfh->_cnt == 0, "_cnt on unbuffered file was %d\n", tempfh->_cnt);
504 /* Inlined putchar sets _cnt to -1. Native seems to ignore the value... */
505 tempfh->_cnt = 1234;
506 ret = _flsbuf('Q',tempfh);
507 ok('Q' == ret, "_flsbuf('Q',tempfh) expected %x got %x\n", 'Q', ret);
508 /* ... and reset it to zero */
509 ok(tempfh->_cnt == 0, "after unbuf _flsbuf, _cnt was %d\n", tempfh->_cnt);
510 fclose(tempfh);
511 /* And just for grins, make sure the file is correct */
512 tempfh = fopen(tempf,"r");
513 c = fgetc(tempfh);
514 ok(c == 'Q', "first byte should be 'Q'\n");
515 c = fgetc(tempfh);
516 ok(c == EOF, "there should only be one byte\n");
517 fclose(tempfh);
518
519 unlink(tempf);
520 }
521
522 static void test_fgetwc( void )
523 {
524 #define LLEN 512
525
526 char* tempf;
527 FILE *tempfh;
528 static const char mytext[]= "This is test_fgetwc\r\n";
529 WCHAR wtextW[BUFSIZ+LLEN+1];
530 WCHAR *mytextW = NULL, *aptr, *wptr;
531 BOOL diff_found = FALSE;
532 int j;
533 unsigned int i;
534 LONG l;
535
536 tempf=_tempnam(".","wne");
537 tempfh = fopen(tempf,"wb");
538 j = 'a';
539 /* pad to almost the length of the internal buffer */
540 for (i=0; i<BUFSIZ-4; i++)
541 fputc(j,tempfh);
542 j = '\r';
543 fputc(j,tempfh);
544 j = '\n';
545 fputc(j,tempfh);
546 fputs(mytext,tempfh);
547 fclose(tempfh);
548 /* in text mode, getws/c expects multibyte characters */
549 /*currently Wine only supports plain ascii, and that is all that is tested here */
550 tempfh = fopen(tempf,"rt"); /* open in TEXT mode */
551 fgetws(wtextW,LLEN,tempfh);
552 l=ftell(tempfh);
553 ok(l==BUFSIZ-2, "ftell expected %d got %d\n", BUFSIZ-2, l);
554 fgetws(wtextW,LLEN,tempfh);
555 l=ftell(tempfh);
556 ok(l==BUFSIZ-2+strlen(mytext), "ftell expected %d got %d\n", BUFSIZ-2+lstrlen(mytext), l);
557 mytextW = AtoW (mytext);
558 aptr = mytextW;
559 wptr = wtextW;
560 for (i=0; i<strlen(mytext)-2; i++, aptr++, wptr++)
561 {
562 diff_found |= (*aptr != *wptr);
563 }
564 ok(!(diff_found), "fgetwc difference found in TEXT mode\n");
565 ok(*wptr == '\n', "Carriage return was not skipped\n");
566 fclose(tempfh);
567 unlink(tempf);
568
569 tempfh = fopen(tempf,"wb");
570 j = 'a';
571 /* pad to almost the length of the internal buffer. Use an odd number of bytes
572 to test that we can read wchars that are split across the internal buffer
573 boundary */
574 for (i=0; i<BUFSIZ-3-strlen(mytext)*sizeof(WCHAR); i++)
575 fputc(j,tempfh);
576 j = '\r';
577 fputwc(j,tempfh);
578 j = '\n';
579 fputwc(j,tempfh);
580 fputws(wtextW,tempfh);
581 fputws(wtextW,tempfh);
582 fclose(tempfh);
583 /* in binary mode, getws/c expects wide characters */
584 tempfh = fopen(tempf,"rb"); /* open in BINARY mode */
585 j=(BUFSIZ-2)/sizeof(WCHAR)-strlen(mytext);
586 fgetws(wtextW,j,tempfh);
587 l=ftell(tempfh);
588 j=(j-1)*sizeof(WCHAR);
589 ok(l==j, "ftell expected %d got %d\n", j, l);
590 i=fgetc(tempfh);
591 ok(i=='a', "fgetc expected %d got %d\n", 0x61, i);
592 l=ftell(tempfh);
593 j++;
594 ok(l==j, "ftell expected %d got %d\n", j, l);
595 fgetws(wtextW,3,tempfh);
596 ok(wtextW[0]=='\r',"expected carriage return got %04hx\n", wtextW[0]);
597 ok(wtextW[1]=='\n',"expected newline got %04hx\n", wtextW[1]);
598 l=ftell(tempfh);
599 j += 4;
600 ok(l==j, "ftell expected %d got %d\n", j, l);
601 for(i=0; i<strlen(mytext); i++)
602 wtextW[i] = 0;
603 /* the first time we get the string, it should be entirely within the local buffer */
604 fgetws(wtextW,LLEN,tempfh);
605 l=ftell(tempfh);
606 j += (strlen(mytext)-1)*sizeof(WCHAR);
607 ok(l==j, "ftell expected %d got %d\n", j, l);
608 diff_found = FALSE;
609 aptr = mytextW;
610 wptr = wtextW;
611 for (i=0; i<strlen(mytext)-2; i++, aptr++, wptr++)
612 {
613 ok(*aptr == *wptr, "Char %d expected %04hx got %04hx\n", i, *aptr, *wptr);
614 diff_found |= (*aptr != *wptr);
615 }
616 ok(!(diff_found), "fgetwc difference found in BINARY mode\n");
617 ok(*wptr == '\n', "Should get newline\n");
618 for(i=0; i<strlen(mytext); i++)
619 wtextW[i] = 0;
620 /* the second time we get the string, it should cross the local buffer boundary.
621 One of the wchars should be split across the boundary */
622 fgetws(wtextW,LLEN,tempfh);
623 diff_found = FALSE;
624 aptr = mytextW;
625 wptr = wtextW;
626 for (i=0; i<strlen(mytext)-2; i++, aptr++, wptr++)
627 {
628 ok(*aptr == *wptr, "Char %d expected %04hx got %04hx\n", i, *aptr, *wptr);
629 diff_found |= (*aptr != *wptr);
630 }
631 ok(!(diff_found), "fgetwc difference found in BINARY mode\n");
632 ok(*wptr == '\n', "Should get newline\n");
633
634 free(mytextW);
635 fclose(tempfh);
636 unlink(tempf);
637 }
638
639 static void test_ctrlz( void )
640 {
641 char* tempf;
642 FILE *tempfh;
643 static const char mytext[]= "This is test_ctrlz";
644 char buffer[256];
645 int i, j;
646 LONG l;
647
648 tempf=_tempnam(".","wne");
649 tempfh = fopen(tempf,"wb");
650 fputs(mytext,tempfh);
651 j = 0x1a; /* a ctrl-z character signals EOF in text mode */
652 fputc(j,tempfh);
653 j = '\r';
654 fputc(j,tempfh);
655 j = '\n';
656 fputc(j,tempfh);
657 j = 'a';
658 fputc(j,tempfh);
659 fclose(tempfh);
660 tempfh = fopen(tempf,"rt"); /* open in TEXT mode */
661 ok(fgets(buffer,256,tempfh) != 0,"fgets failed unexpected\n");
662 i=strlen(buffer);
663 j=strlen(mytext);
664 ok(i==j, "returned string length expected %d got %d\n", j, i);
665 j+=4; /* ftell should indicate the true end of file */
666 l=ftell(tempfh);
667 ok(l==j, "ftell expected %d got %d\n", j, l);
668 ok(feof(tempfh), "did not get EOF\n");
669 fclose(tempfh);
670
671 tempfh = fopen(tempf,"rb"); /* open in BINARY mode */
672 ok(fgets(buffer,256,tempfh) != 0,"fgets failed unexpected\n");
673 i=strlen(buffer);
674 j=strlen(mytext)+3; /* should get through newline */
675 ok(i==j, "returned string length expected %d got %d\n", j, i);
676 l=ftell(tempfh);
677 ok(l==j, "ftell expected %d got %d\n", j, l);
678 ok(fgets(buffer,256,tempfh) != 0,"fgets failed unexpected\n");
679 i=strlen(buffer);
680 ok(i==1, "returned string length expected %d got %d\n", 1, i);
681 ok(feof(tempfh), "did not get EOF\n");
682 fclose(tempfh);
683 unlink(tempf);
684 }
685
686 static void test_file_put_get( void )
687 {
688 char* tempf;
689 FILE *tempfh;
690 static const char mytext[]= "This is a test_file_put_get\n";
691 static const char dostext[]= "This is a test_file_put_get\r\n";
692 char btext[LLEN];
693 WCHAR wtextW[LLEN+1];
694 WCHAR *mytextW = NULL, *aptr, *wptr;
695 BOOL diff_found = FALSE;
696 unsigned int i;
697
698 tempf=_tempnam(".","wne");
699 tempfh = fopen(tempf,"wt"); /* open in TEXT mode */
700 fputs(mytext,tempfh);
701 fclose(tempfh);
702 tempfh = fopen(tempf,"rb"); /* open in TEXT mode */
703 fgets(btext,LLEN,tempfh);
704 ok( strlen(mytext) + 1 == strlen(btext),"TEXT/BINARY mode not handled for write\n");
705 ok( btext[strlen(mytext)-1] == '\r', "CR not written\n");
706 fclose(tempfh);
707 tempfh = fopen(tempf,"wb"); /* open in BINARY mode */
708 fputs(dostext,tempfh);
709 fclose(tempfh);
710 tempfh = fopen(tempf,"rt"); /* open in TEXT mode */
711 fgets(btext,LLEN,tempfh);
712 ok(strcmp(btext, mytext) == 0,"_O_TEXT read doesn't strip CR\n");
713 fclose(tempfh);
714 tempfh = fopen(tempf,"rb"); /* open in TEXT mode */
715 fgets(btext,LLEN,tempfh);
716 ok(strcmp(btext, dostext) == 0,"_O_BINARY read doesn't preserve CR\n");
717
718 fclose(tempfh);
719 tempfh = fopen(tempf,"rt"); /* open in TEXT mode */
720 fgetws(wtextW,LLEN,tempfh);
721 mytextW = AtoW (mytext);
722 aptr = mytextW;
723 wptr = wtextW;
724
725 for (i=0; i<strlen(mytext); i++, aptr++, wptr++)
726 {
727 diff_found |= (*aptr != *wptr);
728 }
729 ok(!(diff_found), "fgetwc doesn't strip CR in TEXT mode\n");
730 free(mytextW);
731 fclose(tempfh);
732 unlink(tempf);
733 }
734
735 static void test_file_write_read( void )
736 {
737 char* tempf;
738 int tempfd;
739 static const char mytext[]= "This is test_file_write_read\nsecond line\n";
740 static const char dostext[]= "This is test_file_write_read\r\nsecond line\r\n";
741 char btext[LLEN];
742 int ret, i;
743
744 tempf=_tempnam(".","wne");
745 tempfd = _open(tempf,_O_CREAT|_O_TRUNC|_O_BINARY|_O_RDWR,
746 _S_IREAD | _S_IWRITE);
747 ok( tempfd != -1,
748 "Can't open '%s': %d\n", tempf, errno); /* open in BINARY mode */
749 ok(_write(tempfd,dostext,strlen(dostext)) == lstrlenA(dostext),
750 "_write _O_BINARY bad return value\n");
751 _close(tempfd);
752 i = lstrlenA(mytext);
753 tempfd = _open(tempf,_O_RDONLY|_O_BINARY,0); /* open in BINARY mode */
754 ok(_read(tempfd,btext,i) == i,
755 "_read _O_BINARY got bad length\n");
756 ok( memcmp(dostext,btext,i) == 0,
757 "problems with _O_BINARY _write / _read\n");
758 _close(tempfd);
759 tempfd = _open(tempf,_O_RDONLY|_O_TEXT); /* open in TEXT mode */
760 ok(_read(tempfd,btext,i) == i-1,
761 "_read _O_TEXT got bad length\n");
762 ok( memcmp(mytext,btext,i-1) == 0,
763 "problems with _O_BINARY _write / _O_TEXT _read\n");
764 _close(tempfd);
765 tempfd = _open(tempf,_O_CREAT|_O_TRUNC|_O_TEXT|_O_RDWR,
766 _S_IREAD | _S_IWRITE);
767 ok( tempfd != -1,
768 "Can't open '%s': %d\n", tempf, errno); /* open in TEXT mode */
769 ok(_write(tempfd,mytext,strlen(mytext)) == lstrlenA(mytext),
770 "_write _O_TEXT bad return value\n");
771 _close(tempfd);
772 tempfd = _open(tempf,_O_RDONLY|_O_BINARY,0); /* open in BINARY mode */
773 ok(_read(tempfd,btext,LLEN) == lstrlenA(dostext),
774 "_read _O_BINARY got bad length\n");
775 ok( memcmp(dostext,btext,strlen(dostext)) == 0,
776 "problems with _O_TEXT _write / _O_BINARY _read\n");
777 ok( btext[strlen(dostext)-2] == '\r', "CR not written or read\n");
778 _close(tempfd);
779 tempfd = _open(tempf,_O_RDONLY|_O_TEXT); /* open in TEXT mode */
780 ok(_read(tempfd,btext,LLEN) == lstrlenA(mytext),
781 "_read _O_TEXT got bad length\n");
782 ok( memcmp(mytext,btext,strlen(mytext)) == 0,
783 "problems with _O_TEXT _write / _read\n");
784 _close(tempfd);
785
786 memset(btext, 0, LLEN);
787 tempfd = _open(tempf,_O_APPEND|_O_RDWR); /* open for APPEND in default mode */
788 ok(tell(tempfd) == 0, "bad position %u expecting 0\n", tell(tempfd));
789 ok(_read(tempfd,btext,LLEN) == lstrlenA(mytext), "_read _O_APPEND got bad length\n");
790 ok( memcmp(mytext,btext,strlen(mytext)) == 0, "problems with _O_APPEND _read\n");
791 _close(tempfd);
792
793 /* Test reading only \n or \r */
794 tempfd = _open(tempf,_O_RDONLY|_O_TEXT); /* open in TEXT mode */
795 _lseek(tempfd, -1, FILE_END);
796 ret = _read(tempfd,btext,LLEN);
797 ok(ret == 1, "_read expected 1 got bad length: %d\n", ret);
798 _lseek(tempfd, -2, FILE_END);
799 ret = _read(tempfd,btext,LLEN);
800 ok(ret == 1 && *btext == '\n', "_read expected '\\n' got bad length: %d\n", ret);
801 _lseek(tempfd, -3, FILE_END);
802 ret = _read(tempfd,btext,2);
803 ok(ret == 1 && *btext == 'e', "_read expected 'e' got \"%.*s\" bad length: %d\n", ret, btext, ret);
804 ok(tell(tempfd) == 42, "bad position %u expecting 42\n", tell(tempfd));
805 _close(tempfd);
806
807 ret = unlink(tempf);
808 ok( ret == 0 ,"Can't unlink '%s': %d\n", tempf, errno);
809
810 tempf=_tempnam(".","wne");
811 tempfd = _open(tempf,_O_CREAT|_O_TRUNC|_O_BINARY|_O_RDWR,0);
812 ok( tempfd != -1,
813 "Can't open '%s': %d\n", tempf, errno); /* open in BINARY mode */
814 ok(_write(tempfd,dostext,strlen(dostext)) == lstrlenA(dostext),
815 "_write _O_BINARY bad return value\n");
816 _close(tempfd);
817 tempfd = _open(tempf,_O_RDONLY|_O_BINARY,0); /* open in BINARY mode */
818 ok(_read(tempfd,btext,LLEN) == lstrlenA(dostext),
819 "_read _O_BINARY got bad length\n");
820 ok( memcmp(dostext,btext,strlen(dostext)) == 0,
821 "problems with _O_BINARY _write / _read\n");
822 ok( btext[strlen(dostext)-2] == '\r', "CR not written or read\n");
823 _close(tempfd);
824 tempfd = _open(tempf,_O_RDONLY|_O_TEXT); /* open in TEXT mode */
825 ok(_read(tempfd,btext,LLEN) == lstrlenA(mytext),
826 "_read _O_TEXT got bad length\n");
827 ok( memcmp(mytext,btext,strlen(mytext)) == 0,
828 "problems with _O_BINARY _write / _O_TEXT _read\n");
829 _close(tempfd);
830
831 ret =_chmod (tempf, _S_IREAD | _S_IWRITE);
832 ok( ret == 0,
833 "Can't chmod '%s' to read-write: %d\n", tempf, errno);
834 ret = unlink(tempf);
835 ok( ret == 0 ,"Can't unlink '%s': %d\n", tempf, errno);
836 }
837
838 static void test_file_inherit_child(const char* fd_s)
839 {
840 int fd = atoi(fd_s);
841 char buffer[32];
842 int ret;
843
844 ret =write(fd, "Success", 8);
845 ok( ret == 8, "Couldn't write in child process on %d (%s)\n", fd, strerror(errno));
846 lseek(fd, 0, SEEK_SET);
847 ok(read(fd, buffer, sizeof (buffer)) == 8, "Couldn't read back the data\n");
848 ok(memcmp(buffer, "Success", 8) == 0, "Couldn't read back the data\n");
849 }
850
851 static void test_file_inherit_child_no(const char* fd_s)
852 {
853 int fd = atoi(fd_s);
854 int ret;
855
856 ret = write(fd, "Success", 8);
857 ok( ret == -1 && errno == EBADF,
858 "Wrong write result in child process on %d (%s)\n", fd, strerror(errno));
859 }
860
861 static void create_io_inherit_block( STARTUPINFO *startup, unsigned int count, const HANDLE *handles )
862 {
863 static BYTE block[1024];
864 BYTE *wxflag_ptr;
865 HANDLE *handle_ptr;
866 unsigned int i;
867
868 startup->lpReserved2 = block;
869 startup->cbReserved2 = sizeof(unsigned) + (sizeof(char) + sizeof(HANDLE)) * count;
870 wxflag_ptr = block + sizeof(unsigned);
871 handle_ptr = (HANDLE *)(wxflag_ptr + count);
872
873 *(unsigned*)block = count;
874 for (i = 0; i < count; i++)
875 {
876 wxflag_ptr[i] = 0x81;
877 handle_ptr[i] = handles[i];
878 }
879 }
880
881 static const char *read_file( HANDLE file )
882 {
883 static char buffer[128];
884 DWORD ret;
885 SetFilePointer( file, 0, NULL, FILE_BEGIN );
886 if (!ReadFile( file, buffer, sizeof(buffer) - 1, &ret, NULL)) ret = 0;
887 buffer[ret] = 0;
888 return buffer;
889 }
890
891 static void test_stdout_handle( STARTUPINFO *startup, char *cmdline, HANDLE hstdout, BOOL expect_stdout,
892 const char *descr )
893 {
894 const char *data;
895 HANDLE hErrorFile;
896 SECURITY_ATTRIBUTES sa;
897 PROCESS_INFORMATION proc;
898
899 /* make file handle inheritable */
900 sa.nLength = sizeof(sa);
901 sa.lpSecurityDescriptor = NULL;
902 sa.bInheritHandle = TRUE;
903
904 hErrorFile = CreateFileA( "fdopen.err", GENERIC_READ|GENERIC_WRITE,
905 FILE_SHARE_READ | FILE_SHARE_WRITE, &sa, CREATE_ALWAYS, 0, NULL );
906 startup->dwFlags = STARTF_USESTDHANDLES;
907 startup->hStdInput = GetStdHandle( STD_INPUT_HANDLE );
908 startup->hStdOutput = hErrorFile;
909 startup->hStdError = GetStdHandle( STD_ERROR_HANDLE );
910
911 CreateProcessA( NULL, cmdline, NULL, NULL, TRUE,
912 CREATE_DEFAULT_ERROR_MODE | NORMAL_PRIORITY_CLASS, NULL, NULL, startup, &proc );
913 winetest_wait_child_process( proc.hProcess );
914
915 data = read_file( hErrorFile );
916 if (expect_stdout)
917 ok( strcmp( data, "Success" ), "%s: Error file shouldn't contain data\n", descr );
918 else
919 ok( !strcmp( data, "Success" ), "%s: Wrong error data (%s)\n", descr, data );
920
921 if (hstdout)
922 {
923 data = read_file( hstdout );
924 if (expect_stdout)
925 ok( !strcmp( data, "Success" ), "%s: Wrong stdout data (%s)\n", descr, data );
926 else
927 ok( strcmp( data, "Success" ), "%s: Stdout file shouldn't contain data\n", descr );
928 }
929
930 CloseHandle( hErrorFile );
931 DeleteFile( "fdopen.err" );
932 }
933
934 static void test_file_inherit( const char* selfname )
935 {
936 int fd;
937 const char* arg_v[5];
938 char buffer[16];
939 char cmdline[MAX_PATH];
940 STARTUPINFO startup;
941 SECURITY_ATTRIBUTES sa;
942 HANDLE handles[3];
943
944 fd = open ("fdopen.tst", O_CREAT | O_RDWR | O_BINARY, _S_IREAD |_S_IWRITE);
945 ok(fd != -1, "Couldn't create test file\n");
946 arg_v[0] = selfname;
947 arg_v[1] = "tests/file.c";
948 arg_v[2] = "inherit";
949 arg_v[3] = buffer; sprintf(buffer, "%d", fd);
950 arg_v[4] = 0;
951 _spawnvp(_P_WAIT, selfname, arg_v);
952 ok(tell(fd) == 8, "bad position %u expecting 8\n", tell(fd));
953 lseek(fd, 0, SEEK_SET);
954 ok(read(fd, buffer, sizeof (buffer)) == 8 && memcmp(buffer, "Success", 8) == 0, "Couldn't read back the data\n");
955 close (fd);
956 ok(unlink("fdopen.tst") == 0, "Couldn't unlink\n");
957
958 fd = open ("fdopen.tst", O_CREAT | O_RDWR | O_BINARY | O_NOINHERIT, _S_IREAD |_S_IWRITE);
959 ok(fd != -1, "Couldn't create test file\n");
960 arg_v[0] = selfname;
961 arg_v[1] = "tests/file.c";
962 arg_v[2] = "inherit_no";
963 arg_v[3] = buffer; sprintf(buffer, "%d", fd);
964 arg_v[4] = 0;
965 _spawnvp(_P_WAIT, selfname, arg_v);
966 ok(tell(fd) == 0, "bad position %u expecting 0\n", tell(fd));
967 ok(read(fd, buffer, sizeof (buffer)) == 0, "Found unexpected data (%s)\n", buffer);
968 close (fd);
969 ok(unlink("fdopen.tst") == 0, "Couldn't unlink\n");
970
971 /* make file handle inheritable */
972 sa.nLength = sizeof(sa);
973 sa.lpSecurityDescriptor = NULL;
974 sa.bInheritHandle = TRUE;
975 sprintf(cmdline, "%s file inherit 1", selfname);
976
977 /* init an empty Reserved2, which should not be recognized as inherit-block */
978 ZeroMemory(&startup, sizeof(STARTUPINFO));
979 startup.cb = sizeof(startup);
980 create_io_inherit_block( &startup, 0, NULL );
981 test_stdout_handle( &startup, cmdline, 0, FALSE, "empty block" );
982
983 /* test with valid inheritblock */
984 handles[0] = GetStdHandle( STD_INPUT_HANDLE );
985 handles[1] = CreateFileA( "fdopen.tst", GENERIC_READ|GENERIC_WRITE,
986 FILE_SHARE_READ | FILE_SHARE_WRITE, &sa, CREATE_ALWAYS, 0, NULL );
987 handles[2] = GetStdHandle( STD_ERROR_HANDLE );
988 create_io_inherit_block( &startup, 3, handles );
989 test_stdout_handle( &startup, cmdline, handles[1], TRUE, "valid block" );
990 CloseHandle( handles[1] );
991 DeleteFile("fdopen.tst");
992
993 /* test inherit block starting with unsigned zero */
994 handles[1] = CreateFileA( "fdopen.tst", GENERIC_READ|GENERIC_WRITE,
995 FILE_SHARE_READ | FILE_SHARE_WRITE, &sa, CREATE_ALWAYS, 0, NULL );
996 create_io_inherit_block( &startup, 3, handles );
997 *(unsigned int *)startup.lpReserved2 = 0;
998 test_stdout_handle( &startup, cmdline, handles[1], FALSE, "zero count block" );
999 CloseHandle( handles[1] );
1000 DeleteFile("fdopen.tst");
1001
1002 /* test inherit block with smaller size */
1003 handles[1] = CreateFileA( "fdopen.tst", GENERIC_READ|GENERIC_WRITE,
1004 FILE_SHARE_READ | FILE_SHARE_WRITE, &sa, CREATE_ALWAYS, 0, NULL );
1005 create_io_inherit_block( &startup, 3, handles );
1006 startup.cbReserved2 -= 3;
1007 test_stdout_handle( &startup, cmdline, handles[1], TRUE, "small size block" );
1008 CloseHandle( handles[1] );
1009 DeleteFile("fdopen.tst");
1010
1011 /* test inherit block with even smaller size */
1012 handles[1] = CreateFileA( "fdopen.tst", GENERIC_READ|GENERIC_WRITE,
1013 FILE_SHARE_READ | FILE_SHARE_WRITE, &sa, CREATE_ALWAYS, 0, NULL );
1014 create_io_inherit_block( &startup, 3, handles );
1015 startup.cbReserved2 = sizeof(unsigned int) + sizeof(HANDLE) + sizeof(char);
1016 test_stdout_handle( &startup, cmdline, handles[1], FALSE, "smaller size block" );
1017 CloseHandle( handles[1] );
1018 DeleteFile("fdopen.tst");
1019
1020 /* test inherit block with larger size */
1021 handles[1] = CreateFileA( "fdopen.tst", GENERIC_READ|GENERIC_WRITE,
1022 FILE_SHARE_READ | FILE_SHARE_WRITE, &sa, CREATE_ALWAYS, 0, NULL );
1023 create_io_inherit_block( &startup, 3, handles );
1024 startup.cbReserved2 += 7;
1025 test_stdout_handle( &startup, cmdline, handles[1], TRUE, "large size block" );
1026 CloseHandle( handles[1] );
1027 DeleteFile("fdopen.tst");
1028 }
1029
1030 static void test_tmpnam( void )
1031 {
1032 char name[MAX_PATH] = "abc";
1033 char *res;
1034
1035 res = tmpnam(NULL);
1036 ok(res != NULL, "tmpnam returned NULL\n");
1037 ok(res[0] == '\\', "first character is not a backslash\n");
1038 ok(strchr(res+1, '\\') == 0, "file not in the root directory\n");
1039 ok(res[strlen(res)-1] == '.', "first call - last character is not a dot\n");
1040
1041 res = tmpnam(name);
1042 ok(res != NULL, "tmpnam returned NULL\n");
1043 ok(res == name, "supplied buffer was not used\n");
1044 ok(res[0] == '\\', "first character is not a backslash\n");
1045 ok(strchr(res+1, '\\') == 0, "file not in the root directory\n");
1046 ok(res[strlen(res)-1] != '.', "second call - last character is a dot\n");
1047 }
1048
1049 static void test_chsize( void )
1050 {
1051 int fd;
1052 LONG cur, pos, count;
1053 char temptext[] = "012345678";
1054 char *tempfile = _tempnam( ".", "tst" );
1055
1056 ok( tempfile != NULL, "Couldn't create test file: %s\n", tempfile );
1057
1058 fd = _open( tempfile, _O_CREAT|_O_TRUNC|_O_RDWR, _S_IREAD|_S_IWRITE );
1059 ok( fd > 0, "Couldn't open test file\n" );
1060
1061 count = _write( fd, temptext, sizeof(temptext) );
1062 ok( count > 0, "Couldn't write to test file\n" );
1063
1064 /* get current file pointer */
1065 cur = _lseek( fd, 0, SEEK_CUR );
1066
1067 /* make the file smaller */
1068 ok( _chsize( fd, sizeof(temptext) / 2 ) == 0, "_chsize() failed\n" );
1069
1070 pos = _lseek( fd, 0, SEEK_CUR );
1071 ok( cur == pos, "File pointer changed from: %d to: %d\n", cur, pos );
1072 ok( _filelength( fd ) == sizeof(temptext) / 2, "Wrong file size\n" );
1073
1074 /* enlarge the file */
1075 ok( _chsize( fd, sizeof(temptext) * 2 ) == 0, "_chsize() failed\n" );
1076
1077 pos = _lseek( fd, 0, SEEK_CUR );
1078 ok( cur == pos, "File pointer changed from: %d to: %d\n", cur, pos );
1079 ok( _filelength( fd ) == sizeof(temptext) * 2, "Wrong file size\n" );
1080
1081 _close( fd );
1082 _unlink( tempfile );
1083 }
1084
1085 static void test_fopen_fclose_fcloseall( void )
1086 {
1087 char fname1[] = "empty1";
1088 char fname2[] = "empty2";
1089 char fname3[] = "empty3";
1090 FILE *stream1, *stream2, *stream3, *stream4;
1091 int ret, numclosed;
1092
1093 /* testing fopen() */
1094 stream1 = fopen(fname1, "w+");
1095 ok(stream1 != NULL, "The file '%s' was not opened\n", fname1);
1096 stream2 = fopen(fname2, "w ");
1097 ok(stream2 != NULL, "The file '%s' was not opened\n", fname2 );
1098 _unlink(fname3);
1099 stream3 = fopen(fname3, "r");
1100 ok(stream3 == NULL, "The file '%s' shouldn't exist before\n", fname3 );
1101 stream3 = fopen(fname3, "w+");
1102 ok(stream3 != NULL, "The file '%s' should be opened now\n", fname3 );
1103 errno = 0xfaceabad;
1104 stream4 = fopen("", "w+");
1105 ok(stream4 == NULL && (errno == EINVAL || errno == ENOENT),
1106 "filename is empty, errno = %d (expected 2 or 22)\n", errno);
1107 errno = 0xfaceabad;
1108 stream4 = fopen(NULL, "w+");
1109 ok(stream4 == NULL && (errno == EINVAL || errno == ENOENT),
1110 "filename is NULL, errno = %d (expected 2 or 22)\n", errno);
1111
1112 /* testing fclose() */
1113 ret = fclose(stream2);
1114 ok(ret == 0, "The file '%s' was not closed\n", fname2);
1115 ret = fclose(stream3);
1116 ok(ret == 0, "The file '%s' was not closed\n", fname3);
1117 ret = fclose(stream2);
1118 ok(ret == EOF, "Closing file '%s' returned %d\n", fname2, ret);
1119 ret = fclose(stream3);
1120 ok(ret == EOF, "Closing file '%s' returned %d\n", fname3, ret);
1121
1122 /* testing fcloseall() */
1123 numclosed = _fcloseall();
1124 /* fname1 should be closed here */
1125 ok(numclosed == 1, "Number of files closed by fcloseall(): %u\n", numclosed);
1126 numclosed = _fcloseall();
1127 ok(numclosed == 0, "Number of files closed by fcloseall(): %u\n", numclosed);
1128
1129 ok(_unlink(fname1) == 0, "Couldn't unlink file named '%s'\n", fname1);
1130 ok(_unlink(fname2) == 0, "Couldn't unlink file named '%s'\n", fname2);
1131 ok(_unlink(fname3) == 0, "Couldn't unlink file named '%s'\n", fname3);
1132 }
1133
1134 static void test_get_osfhandle(void)
1135 {
1136 int fd;
1137 char fname[] = "t_get_osfhanle";
1138 DWORD bytes_written;
1139 HANDLE handle;
1140
1141 fd = _sopen(fname, _O_CREAT|_O_RDWR, _SH_DENYRW, _S_IREAD | _S_IWRITE);
1142 handle = (HANDLE)_get_osfhandle(fd);
1143 WriteFile(handle, "bar", 3, &bytes_written, NULL);
1144 _close(fd);
1145 fd = _open(fname, _O_RDONLY, 0);
1146 ok(fd != -1, "Coudn't open '%s' after _get_osfhanle()\n", fname);
1147
1148 _close(fd);
1149 _unlink(fname);
1150 }
1151
1152 static void test_setmaxstdio(void)
1153 {
1154 ok(2048 == _setmaxstdio(2048),"_setmaxstdio returned %d instead of 2048\n",_setmaxstdio(2048));
1155 ok(-1 == _setmaxstdio(2049),"_setmaxstdio returned %d instead of -1\n",_setmaxstdio(2049));
1156 }
1157
1158 static void test_stat(void)
1159 {
1160 int fd;
1161 int pipes[2];
1162 struct stat buf;
1163
1164 /* Tests for a file */
1165 fd = open("stat.tst", O_WRONLY | O_CREAT | O_BINARY, _S_IREAD |_S_IWRITE);
1166 if (fd >= 0)
1167 {
1168 ok(fstat(fd, &buf) == 0, "fstat failed: errno=%d\n", errno);
1169 ok((buf.st_mode & _S_IFMT) == _S_IFREG, "bad format = %06o\n", buf.st_mode);
1170 ok((buf.st_mode & 0777) == 0666, "bad st_mode = %06o\n", buf.st_mode);
1171 ok(buf.st_dev == 0, "st_dev is %d, expected 0\n", buf.st_dev);
1172 ok(buf.st_dev == buf.st_rdev, "st_dev (%d) and st_rdev (%d) differ\n", buf.st_dev, buf.st_rdev);
1173 ok(buf.st_nlink == 1, "st_nlink is %d, expected 1\n", buf.st_nlink);
1174 ok(buf.st_size == 0, "st_size is %d, expected 0\n", buf.st_size);
1175
1176 ok(stat("stat.tst", &buf) == 0, "stat failed: errno=%d\n", errno);
1177 ok((buf.st_mode & _S_IFMT) == _S_IFREG, "bad format = %06o\n", buf.st_mode);
1178 ok((buf.st_mode & 0777) == 0666, "bad st_mode = %06o\n", buf.st_mode);
1179 ok(buf.st_dev == buf.st_rdev, "st_dev (%d) and st_rdev (%d) differ\n", buf.st_dev, buf.st_rdev);
1180 ok(buf.st_nlink == 1, "st_nlink is %d, expected 1\n", buf.st_nlink);
1181 ok(buf.st_size == 0, "st_size is %d, expected 0\n", buf.st_size);
1182
1183 close(fd);
1184 remove("stat.tst");
1185 }
1186 else
1187 skip("open failed with errno %d\n", errno);
1188
1189 /* Tests for a char device */
1190 if (_dup2(0, 10) == 0)
1191 {
1192 ok(fstat(10, &buf) == 0, "fstat(stdin) failed: errno=%d\n", errno);
1193 if ((buf.st_mode & _S_IFMT) == _S_IFCHR)
1194 {
1195 ok(buf.st_mode == _S_IFCHR, "bad st_mode=%06o\n", buf.st_mode);
1196 ok(buf.st_dev == 10, "st_dev is %d, expected 10\n", buf.st_dev);
1197 ok(buf.st_rdev == 10, "st_rdev is %d, expected 10\n", buf.st_rdev);
1198 ok(buf.st_nlink == 1, "st_nlink is %d, expected 1\n", buf.st_nlink);
1199 }
1200 else
1201 skip("stdin is not a char device? st_mode=%06o\n", buf.st_mode);
1202 close(10);
1203 }
1204 else
1205 skip("_dup2 failed with errno %d\n", errno);
1206
1207 /* Tests for pipes */
1208 if (_pipe(pipes, 1024, O_BINARY) == 0)
1209 {
1210 ok(fstat(pipes[0], &buf) == 0, "fstat(pipe) failed: errno=%d\n", errno);
1211 ok(buf.st_mode == _S_IFIFO, "bad st_mode=%06o\n", buf.st_mode);
1212 ok(buf.st_dev == pipes[0], "st_dev is %d, expected %d\n", buf.st_dev, pipes[0]);
1213 ok(buf.st_rdev == pipes[0], "st_rdev is %d, expected %d\n", buf.st_rdev, pipes[0]);
1214 ok(buf.st_nlink == 1, "st_nlink is %d, expected 1\n", buf.st_nlink);
1215 close(pipes[0]);
1216 close(pipes[1]);
1217 }
1218 else
1219 skip("pipe failed with errno %d\n", errno);
1220 }
1221
1222 static const char* pipe_string="Hello world";
1223
1224 /* How many messages to transfer over the pipe */
1225 #define N_TEST_MESSAGES 3
1226
1227 static void test_pipes_child(int argc, char** args)
1228 {
1229 int fd;
1230 int nwritten;
1231 int i;
1232
1233 if (argc < 5)
1234 {
1235 ok(0, "not enough parameters: %d\n", argc);
1236 return;
1237 }
1238
1239 fd=atoi(args[3]);
1240 ok(close(fd) == 0, "unable to close %d: %d\n", fd, errno);
1241
1242 fd=atoi(args[4]);
1243
1244 for (i=0; i<N_TEST_MESSAGES; i++) {
1245 nwritten=write(fd, pipe_string, strlen(pipe_string));
1246 ok(nwritten == strlen(pipe_string), "i %d, expected to write '%s' wrote %d\n", i, pipe_string, nwritten);
1247 /* let other process wake up so they can show off their "keep reading until EOF" behavior */
1248 if (i < N_TEST_MESSAGES-1)
1249 Sleep(100);
1250 }
1251
1252 ok(close(fd) == 0, "unable to close %d: %d\n", fd, errno);
1253 }
1254
1255 static void test_pipes(const char* selfname)
1256 {
1257 int pipes[2];
1258 char str_fdr[12], str_fdw[12];
1259 FILE* file;
1260 const char* arg_v[6];
1261 char buf[4096];
1262 char expected[4096];
1263 int r;
1264 int i;
1265
1266 /* Test reading from a pipe with read() */
1267 if (_pipe(pipes, 1024, O_BINARY) < 0)
1268 {
1269 ok(0, "pipe failed with errno %d\n", errno);
1270 return;
1271 }
1272
1273 arg_v[0] = selfname;
1274 arg_v[1] = "tests/file.c";
1275 arg_v[2] = "pipes";
1276 arg_v[3] = str_fdr; sprintf(str_fdr, "%d", pipes[0]);
1277 arg_v[4] = str_fdw; sprintf(str_fdw, "%d", pipes[1]);
1278 arg_v[5] = NULL;
1279 proc_handles[0] = (HANDLE)_spawnvp(_P_NOWAIT, selfname, arg_v);
1280 ok(close(pipes[1]) == 0, "unable to close %d: %d\n", pipes[1], errno);
1281
1282 for (i=0; i<N_TEST_MESSAGES; i++) {
1283 r=read(pipes[0], buf, sizeof(buf)-1);
1284 ok(r == strlen(pipe_string), "i %d, got %d\n", i, r);
1285 if (r > 0)
1286 buf[r]='\0';
1287 ok(strcmp(buf, pipe_string) == 0, "expected to read '%s', got '%s'\n", pipe_string, buf);
1288 }
1289
1290 r=read(pipes[0], buf, sizeof(buf)-1);
1291 ok(r == 0, "expected to read 0 bytes, got %d\n", r);
1292 ok(close(pipes[0]) == 0, "unable to close %d: %d\n", pipes[0], errno);
1293
1294 /* Test reading from a pipe with fread() */
1295 if (_pipe(pipes, 1024, O_BINARY) < 0)
1296 {
1297 ok(0, "pipe failed with errno %d\n", errno);
1298 return;
1299 }
1300
1301 arg_v[0] = selfname;
1302 arg_v[1] = "tests/file.c";
1303 arg_v[2] = "pipes";
1304 arg_v[3] = str_fdr; sprintf(str_fdr, "%d", pipes[0]);
1305 arg_v[4] = str_fdw; sprintf(str_fdw, "%d", pipes[1]);
1306 arg_v[5] = NULL;
1307 proc_handles[1] = (HANDLE)_spawnvp(_P_NOWAIT, selfname, arg_v);
1308 ok(close(pipes[1]) == 0, "unable to close %d: %d\n", pipes[1], errno);
1309 file=fdopen(pipes[0], "r");
1310
1311 /* In blocking mode, fread will keep calling read() until it gets
1312 * enough bytes, or EOF, even on Unix. (If this were a Unix terminal
1313 * in cooked mode instead of a pipe, it would also stop on EOL.)
1314 */
1315 expected[0] = 0;
1316 for (i=0; i<N_TEST_MESSAGES; i++)
1317 strcat(expected, pipe_string);
1318 r=fread(buf, 1, sizeof(buf)-1, file);
1319 ok(r == strlen(expected), "fread() returned %d: ferror=%d\n", r, ferror(file));
1320 if (r > 0)
1321 buf[r]='\0';
1322 ok(strcmp(buf, expected) == 0, "got '%s' expected '%s'\n", buf, expected);
1323
1324 /* Let child close the file before we read, so we can sense EOF reliably */
1325 Sleep(100);
1326 r=fread(buf, 1, sizeof(buf)-1, file);
1327 ok(r == 0, "fread() returned %d instead of 0\n", r);
1328 ok(ferror(file) == 0, "got ferror() = %d\n", ferror(file));
1329 ok(feof(file), "feof() is false!\n");
1330
1331 ok(fclose(file) == 0, "unable to close the pipe: %d\n", errno);
1332 }
1333
1334 static void test_unlink(void)
1335 {
1336 FILE* file;
1337 ok(mkdir("test_unlink") == 0, "unable to create test dir\n");
1338 file = fopen("test_unlink\\empty", "w");
1339 ok(file != NULL, "unable to create test file\n");
1340 if(file)
1341 fclose(file);
1342 ok(_unlink("test_unlink") != 0, "unlinking a non-empty directory must fail\n");
1343 unlink("test_unlink\\empty");
1344 rmdir("test_unlink");
1345 }
1346
1347 START_TEST(file)
1348 {
1349 int arg_c;
1350 char** arg_v;
1351
1352 arg_c = winetest_get_mainargs( &arg_v );
1353
1354 /* testing low-level I/O */
1355 if (arg_c >= 3)
1356 {
1357 if (strcmp(arg_v[2], "inherit") == 0)
1358 test_file_inherit_child(arg_v[3]);
1359 else if (strcmp(arg_v[2], "inherit_no") == 0)
1360 test_file_inherit_child_no(arg_v[3]);
1361 else if (strcmp(arg_v[2], "pipes") == 0)
1362 test_pipes_child(arg_c, arg_v);
1363 else
1364 ok(0, "invalid argument '%s'\n", arg_v[2]);
1365 return;
1366 }
1367 test_file_inherit(arg_v[0]);
1368 test_file_write_read();
1369 test_chsize();
1370 test_stat();
1371 test_unlink();
1372
1373 /* testing stream I/O */
1374 test_filbuf();
1375 test_fdopen();
1376 test_fopen_fclose_fcloseall();
1377 test_fileops();
1378 test_asciimode();
1379 test_asciimode2();
1380 test_readmode(FALSE); /* binary mode */
1381 test_readmode(TRUE); /* ascii mode */
1382 test_fgetc();
1383 test_fputc();
1384 test_flsbuf();
1385 test_fgetwc();
1386 test_ctrlz();
1387 test_file_put_get();
1388 test_tmpnam();
1389 test_get_osfhandle();
1390 test_setmaxstdio();
1391 test_pipes(arg_v[0]);
1392
1393 /* Wait for the (_P_NOWAIT) spawned processes to finish to make sure the report
1394 * file contains lines in the correct order
1395 */
1396 WaitForMultipleObjects(sizeof(proc_handles)/sizeof(proc_handles[0]), proc_handles, TRUE, 5000);
1397 }