sync msvcrt_winetest with wine 1.1.35
[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 free(tempf);
443 }
444
445 static void test_fputc( void )
446 {
447 char* tempf;
448 FILE *tempfh;
449 int ret;
450
451 tempf=_tempnam(".","wne");
452 tempfh = fopen(tempf,"wb");
453 ret = fputc(0,tempfh);
454 ok(0 == ret, "fputc(0,tempfh) expected %x got %x\n", 0, ret);
455 ret = fputc(0xff,tempfh);
456 ok(0xff == ret, "fputc(0xff,tempfh) expected %x got %x\n", 0xff, ret);
457 ret = fputc(0xffffffff,tempfh);
458 ok(0xff == ret, "fputc(0xffffffff,tempfh) expected %x got %x\n", 0xff, ret);
459 fclose(tempfh);
460
461 tempfh = fopen(tempf,"rb");
462 ret = fputc(0,tempfh);
463 ok(EOF == ret, "fputc(0,tempfh) on r/o file expected %x got %x\n", EOF, ret);
464 fclose(tempfh);
465
466 unlink(tempf);
467 free(tempf);
468 }
469
470 static void test_flsbuf( void )
471 {
472 char* tempf;
473 FILE *tempfh;
474 int c;
475 int ret;
476 int bufmode;
477 static const int bufmodes[] = {_IOFBF,_IONBF};
478
479 tempf=_tempnam(".","wne");
480 for (bufmode=0; bufmode < sizeof(bufmodes)/sizeof(bufmodes[0]); bufmode++)
481 {
482 tempfh = fopen(tempf,"wb");
483 setvbuf(tempfh,NULL,bufmodes[bufmode],2048);
484 ret = _flsbuf(0,tempfh);
485 ok(0 == ret, "_flsbuf(0,tempfh) with bufmode %x expected %x got %x\n",
486 bufmodes[bufmode], 0, ret);
487 ret = _flsbuf(0xff,tempfh);
488 ok(0xff == ret, "_flsbuf(0xff,tempfh) with bufmode %x expected %x got %x\n",
489 bufmodes[bufmode], 0, ret);
490 ret = _flsbuf(0xffffffff,tempfh);
491 ok(0xff == ret, "_flsbuf(0xffffffff,tempfh) with bufmode %x expected %x got %x\n",
492 bufmodes[bufmode], 0, ret);
493 fclose(tempfh);
494 }
495
496 tempfh = fopen(tempf,"rb");
497 ret = _flsbuf(0,tempfh);
498 ok(EOF == ret, "_flsbuf(0,tempfh) on r/o file expected %x got %x\n", EOF, ret);
499 fclose(tempfh);
500
501 /* See bug 17123, exposed by WinAVR's make */
502 tempfh = fopen(tempf,"w");
503 ok(tempfh->_cnt == 0, "_cnt on freshly opened file was %d\n", tempfh->_cnt);
504 setbuf(tempfh, NULL);
505 ok(tempfh->_cnt == 0, "_cnt on unbuffered file was %d\n", tempfh->_cnt);
506 /* Inlined putchar sets _cnt to -1. Native seems to ignore the value... */
507 tempfh->_cnt = 1234;
508 ret = _flsbuf('Q',tempfh);
509 ok('Q' == ret, "_flsbuf('Q',tempfh) expected %x got %x\n", 'Q', ret);
510 /* ... and reset it to zero */
511 ok(tempfh->_cnt == 0, "after unbuf _flsbuf, _cnt was %d\n", tempfh->_cnt);
512 fclose(tempfh);
513 /* And just for grins, make sure the file is correct */
514 tempfh = fopen(tempf,"r");
515 c = fgetc(tempfh);
516 ok(c == 'Q', "first byte should be 'Q'\n");
517 c = fgetc(tempfh);
518 ok(c == EOF, "there should only be one byte\n");
519 fclose(tempfh);
520
521 unlink(tempf);
522 free(tempf);
523 }
524
525 static void test_fgetwc( void )
526 {
527 #define LLEN 512
528
529 char* tempf;
530 FILE *tempfh;
531 static const char mytext[]= "This is test_fgetwc\r\n";
532 WCHAR wtextW[BUFSIZ+LLEN+1];
533 WCHAR *mytextW = NULL, *aptr, *wptr;
534 BOOL diff_found = FALSE;
535 int j;
536 unsigned int i;
537 LONG l;
538
539 tempf=_tempnam(".","wne");
540 tempfh = fopen(tempf,"wb");
541 j = 'a';
542 /* pad to almost the length of the internal buffer */
543 for (i=0; i<BUFSIZ-4; i++)
544 fputc(j,tempfh);
545 j = '\r';
546 fputc(j,tempfh);
547 j = '\n';
548 fputc(j,tempfh);
549 fputs(mytext,tempfh);
550 fclose(tempfh);
551 /* in text mode, getws/c expects multibyte characters */
552 /*currently Wine only supports plain ascii, and that is all that is tested here */
553 tempfh = fopen(tempf,"rt"); /* open in TEXT mode */
554 fgetws(wtextW,LLEN,tempfh);
555 l=ftell(tempfh);
556 ok(l==BUFSIZ-2, "ftell expected %d got %d\n", BUFSIZ-2, l);
557 fgetws(wtextW,LLEN,tempfh);
558 l=ftell(tempfh);
559 ok(l==BUFSIZ-2+strlen(mytext), "ftell expected %d got %d\n", BUFSIZ-2+lstrlen(mytext), l);
560 mytextW = AtoW (mytext);
561 aptr = mytextW;
562 wptr = wtextW;
563 for (i=0; i<strlen(mytext)-2; i++, aptr++, wptr++)
564 {
565 diff_found |= (*aptr != *wptr);
566 }
567 ok(!(diff_found), "fgetwc difference found in TEXT mode\n");
568 ok(*wptr == '\n', "Carriage return was not skipped\n");
569 fclose(tempfh);
570 unlink(tempf);
571
572 tempfh = fopen(tempf,"wb");
573 j = 'a';
574 /* pad to almost the length of the internal buffer. Use an odd number of bytes
575 to test that we can read wchars that are split across the internal buffer
576 boundary */
577 for (i=0; i<BUFSIZ-3-strlen(mytext)*sizeof(WCHAR); i++)
578 fputc(j,tempfh);
579 j = '\r';
580 fputwc(j,tempfh);
581 j = '\n';
582 fputwc(j,tempfh);
583 fputws(wtextW,tempfh);
584 fputws(wtextW,tempfh);
585 fclose(tempfh);
586 /* in binary mode, getws/c expects wide characters */
587 tempfh = fopen(tempf,"rb"); /* open in BINARY mode */
588 j=(BUFSIZ-2)/sizeof(WCHAR)-strlen(mytext);
589 fgetws(wtextW,j,tempfh);
590 l=ftell(tempfh);
591 j=(j-1)*sizeof(WCHAR);
592 ok(l==j, "ftell expected %d got %d\n", j, l);
593 i=fgetc(tempfh);
594 ok(i=='a', "fgetc expected %d got %d\n", 0x61, i);
595 l=ftell(tempfh);
596 j++;
597 ok(l==j, "ftell expected %d got %d\n", j, l);
598 fgetws(wtextW,3,tempfh);
599 ok(wtextW[0]=='\r',"expected carriage return got %04hx\n", wtextW[0]);
600 ok(wtextW[1]=='\n',"expected newline got %04hx\n", wtextW[1]);
601 l=ftell(tempfh);
602 j += 4;
603 ok(l==j, "ftell expected %d got %d\n", j, l);
604 for(i=0; i<strlen(mytext); i++)
605 wtextW[i] = 0;
606 /* the first time we get the string, it should be entirely within the local buffer */
607 fgetws(wtextW,LLEN,tempfh);
608 l=ftell(tempfh);
609 j += (strlen(mytext)-1)*sizeof(WCHAR);
610 ok(l==j, "ftell expected %d got %d\n", j, l);
611 diff_found = FALSE;
612 aptr = mytextW;
613 wptr = wtextW;
614 for (i=0; i<strlen(mytext)-2; i++, aptr++, wptr++)
615 {
616 ok(*aptr == *wptr, "Char %d expected %04hx got %04hx\n", i, *aptr, *wptr);
617 diff_found |= (*aptr != *wptr);
618 }
619 ok(!(diff_found), "fgetwc difference found in BINARY mode\n");
620 ok(*wptr == '\n', "Should get newline\n");
621 for(i=0; i<strlen(mytext); i++)
622 wtextW[i] = 0;
623 /* the second time we get the string, it should cross the local buffer boundary.
624 One of the wchars should be split across the boundary */
625 fgetws(wtextW,LLEN,tempfh);
626 diff_found = FALSE;
627 aptr = mytextW;
628 wptr = wtextW;
629 for (i=0; i<strlen(mytext)-2; i++, aptr++, wptr++)
630 {
631 ok(*aptr == *wptr, "Char %d expected %04hx got %04hx\n", i, *aptr, *wptr);
632 diff_found |= (*aptr != *wptr);
633 }
634 ok(!(diff_found), "fgetwc difference found in BINARY mode\n");
635 ok(*wptr == '\n', "Should get newline\n");
636
637 free(mytextW);
638 fclose(tempfh);
639 unlink(tempf);
640 free(tempf);
641 }
642
643 static void test_ctrlz( void )
644 {
645 char* tempf;
646 FILE *tempfh;
647 static const char mytext[]= "This is test_ctrlz";
648 char buffer[256];
649 int i, j;
650 LONG l;
651
652 tempf=_tempnam(".","wne");
653 tempfh = fopen(tempf,"wb");
654 fputs(mytext,tempfh);
655 j = 0x1a; /* a ctrl-z character signals EOF in text mode */
656 fputc(j,tempfh);
657 j = '\r';
658 fputc(j,tempfh);
659 j = '\n';
660 fputc(j,tempfh);
661 j = 'a';
662 fputc(j,tempfh);
663 fclose(tempfh);
664 tempfh = fopen(tempf,"rt"); /* open in TEXT mode */
665 ok(fgets(buffer,256,tempfh) != 0,"fgets failed unexpected\n");
666 i=strlen(buffer);
667 j=strlen(mytext);
668 ok(i==j, "returned string length expected %d got %d\n", j, i);
669 j+=4; /* ftell should indicate the true end of file */
670 l=ftell(tempfh);
671 ok(l==j, "ftell expected %d got %d\n", j, l);
672 ok(feof(tempfh), "did not get EOF\n");
673 fclose(tempfh);
674
675 tempfh = fopen(tempf,"rb"); /* open in BINARY mode */
676 ok(fgets(buffer,256,tempfh) != 0,"fgets failed unexpected\n");
677 i=strlen(buffer);
678 j=strlen(mytext)+3; /* should get through newline */
679 ok(i==j, "returned string length expected %d got %d\n", j, i);
680 l=ftell(tempfh);
681 ok(l==j, "ftell expected %d got %d\n", j, l);
682 ok(fgets(buffer,256,tempfh) != 0,"fgets failed unexpected\n");
683 i=strlen(buffer);
684 ok(i==1, "returned string length expected %d got %d\n", 1, i);
685 ok(feof(tempfh), "did not get EOF\n");
686 fclose(tempfh);
687 unlink(tempf);
688 free(tempf);
689 }
690
691 static void test_file_put_get( void )
692 {
693 char* tempf;
694 FILE *tempfh;
695 static const char mytext[]= "This is a test_file_put_get\n";
696 static const char dostext[]= "This is a test_file_put_get\r\n";
697 char btext[LLEN];
698 WCHAR wtextW[LLEN+1];
699 WCHAR *mytextW = NULL, *aptr, *wptr;
700 BOOL diff_found = FALSE;
701 unsigned int i;
702
703 tempf=_tempnam(".","wne");
704 tempfh = fopen(tempf,"wt"); /* open in TEXT mode */
705 fputs(mytext,tempfh);
706 fclose(tempfh);
707 tempfh = fopen(tempf,"rb"); /* open in TEXT mode */
708 fgets(btext,LLEN,tempfh);
709 ok( strlen(mytext) + 1 == strlen(btext),"TEXT/BINARY mode not handled for write\n");
710 ok( btext[strlen(mytext)-1] == '\r', "CR not written\n");
711 fclose(tempfh);
712 tempfh = fopen(tempf,"wb"); /* open in BINARY mode */
713 fputs(dostext,tempfh);
714 fclose(tempfh);
715 tempfh = fopen(tempf,"rt"); /* open in TEXT mode */
716 fgets(btext,LLEN,tempfh);
717 ok(strcmp(btext, mytext) == 0,"_O_TEXT read doesn't strip CR\n");
718 fclose(tempfh);
719 tempfh = fopen(tempf,"rb"); /* open in TEXT mode */
720 fgets(btext,LLEN,tempfh);
721 ok(strcmp(btext, dostext) == 0,"_O_BINARY read doesn't preserve CR\n");
722
723 fclose(tempfh);
724 tempfh = fopen(tempf,"rt"); /* open in TEXT mode */
725 fgetws(wtextW,LLEN,tempfh);
726 mytextW = AtoW (mytext);
727 aptr = mytextW;
728 wptr = wtextW;
729
730 for (i=0; i<strlen(mytext); i++, aptr++, wptr++)
731 {
732 diff_found |= (*aptr != *wptr);
733 }
734 ok(!(diff_found), "fgetwc doesn't strip CR in TEXT mode\n");
735 free(mytextW);
736 fclose(tempfh);
737 unlink(tempf);
738 free(tempf);
739 }
740
741 static void test_file_write_read( void )
742 {
743 char* tempf;
744 int tempfd;
745 static const char mytext[]= "This is test_file_write_read\nsecond line\n";
746 static const char dostext[]= "This is test_file_write_read\r\nsecond line\r\n";
747 char btext[LLEN];
748 int ret, i;
749
750 tempf=_tempnam(".","wne");
751 tempfd = _open(tempf,_O_CREAT|_O_TRUNC|_O_BINARY|_O_RDWR,
752 _S_IREAD | _S_IWRITE);
753 ok( tempfd != -1,
754 "Can't open '%s': %d\n", tempf, errno); /* open in BINARY mode */
755 ok(_write(tempfd,dostext,strlen(dostext)) == lstrlenA(dostext),
756 "_write _O_BINARY bad return value\n");
757 _close(tempfd);
758 i = lstrlenA(mytext);
759 tempfd = _open(tempf,_O_RDONLY|_O_BINARY,0); /* open in BINARY mode */
760 ok(_read(tempfd,btext,i) == i,
761 "_read _O_BINARY got bad length\n");
762 ok( memcmp(dostext,btext,i) == 0,
763 "problems with _O_BINARY _write / _read\n");
764 _close(tempfd);
765 tempfd = _open(tempf,_O_RDONLY|_O_TEXT); /* open in TEXT mode */
766 ok(_read(tempfd,btext,i) == i-1,
767 "_read _O_TEXT got bad length\n");
768 ok( memcmp(mytext,btext,i-1) == 0,
769 "problems with _O_BINARY _write / _O_TEXT _read\n");
770 _close(tempfd);
771 tempfd = _open(tempf,_O_CREAT|_O_TRUNC|_O_TEXT|_O_RDWR,
772 _S_IREAD | _S_IWRITE);
773 ok( tempfd != -1,
774 "Can't open '%s': %d\n", tempf, errno); /* open in TEXT mode */
775 ok(_write(tempfd,mytext,strlen(mytext)) == lstrlenA(mytext),
776 "_write _O_TEXT bad return value\n");
777 _close(tempfd);
778 tempfd = _open(tempf,_O_RDONLY|_O_BINARY,0); /* open in BINARY mode */
779 ok(_read(tempfd,btext,LLEN) == lstrlenA(dostext),
780 "_read _O_BINARY got bad length\n");
781 ok( memcmp(dostext,btext,strlen(dostext)) == 0,
782 "problems with _O_TEXT _write / _O_BINARY _read\n");
783 ok( btext[strlen(dostext)-2] == '\r', "CR not written or read\n");
784 _close(tempfd);
785 tempfd = _open(tempf,_O_RDONLY|_O_TEXT); /* open in TEXT mode */
786 ok(_read(tempfd,btext,LLEN) == lstrlenA(mytext),
787 "_read _O_TEXT got bad length\n");
788 ok( memcmp(mytext,btext,strlen(mytext)) == 0,
789 "problems with _O_TEXT _write / _read\n");
790 _close(tempfd);
791
792 memset(btext, 0, LLEN);
793 tempfd = _open(tempf,_O_APPEND|_O_RDWR); /* open for APPEND in default mode */
794 ok(tell(tempfd) == 0, "bad position %u expecting 0\n", tell(tempfd));
795 ok(_read(tempfd,btext,LLEN) == lstrlenA(mytext), "_read _O_APPEND got bad length\n");
796 ok( memcmp(mytext,btext,strlen(mytext)) == 0, "problems with _O_APPEND _read\n");
797 _close(tempfd);
798
799 /* Test reading only \n or \r */
800 tempfd = _open(tempf,_O_RDONLY|_O_TEXT); /* open in TEXT mode */
801 _lseek(tempfd, -1, FILE_END);
802 ret = _read(tempfd,btext,LLEN);
803 ok(ret == 1, "_read expected 1 got bad length: %d\n", ret);
804 _lseek(tempfd, -2, FILE_END);
805 ret = _read(tempfd,btext,LLEN);
806 ok(ret == 1 && *btext == '\n', "_read expected '\\n' got bad length: %d\n", ret);
807 _lseek(tempfd, -3, FILE_END);
808 ret = _read(tempfd,btext,2);
809 ok(ret == 1 && *btext == 'e', "_read expected 'e' got \"%.*s\" bad length: %d\n", ret, btext, ret);
810 ok(tell(tempfd) == 42, "bad position %u expecting 42\n", tell(tempfd));
811 _close(tempfd);
812
813 ret = unlink(tempf);
814 ok( ret == 0 ,"Can't unlink '%s': %d\n", tempf, errno);
815 free(tempf);
816
817 tempf=_tempnam(".","wne");
818 tempfd = _open(tempf,_O_CREAT|_O_TRUNC|_O_BINARY|_O_RDWR,0);
819 ok( tempfd != -1,
820 "Can't open '%s': %d\n", tempf, errno); /* open in BINARY mode */
821 ok(_write(tempfd,dostext,strlen(dostext)) == lstrlenA(dostext),
822 "_write _O_BINARY bad return value\n");
823 _close(tempfd);
824 tempfd = _open(tempf,_O_RDONLY|_O_BINARY,0); /* open in BINARY mode */
825 ok(_read(tempfd,btext,LLEN) == lstrlenA(dostext),
826 "_read _O_BINARY got bad length\n");
827 ok( memcmp(dostext,btext,strlen(dostext)) == 0,
828 "problems with _O_BINARY _write / _read\n");
829 ok( btext[strlen(dostext)-2] == '\r', "CR not written or read\n");
830 _close(tempfd);
831 tempfd = _open(tempf,_O_RDONLY|_O_TEXT); /* open in TEXT mode */
832 ok(_read(tempfd,btext,LLEN) == lstrlenA(mytext),
833 "_read _O_TEXT got bad length\n");
834 ok( memcmp(mytext,btext,strlen(mytext)) == 0,
835 "problems with _O_BINARY _write / _O_TEXT _read\n");
836 _close(tempfd);
837
838 ret =_chmod (tempf, _S_IREAD | _S_IWRITE);
839 ok( ret == 0,
840 "Can't chmod '%s' to read-write: %d\n", tempf, errno);
841 ret = unlink(tempf);
842 ok( ret == 0 ,"Can't unlink '%s': %d\n", tempf, errno);
843 free(tempf);
844 }
845
846 static void test_file_inherit_child(const char* fd_s)
847 {
848 int fd = atoi(fd_s);
849 char buffer[32];
850 int ret;
851
852 ret =write(fd, "Success", 8);
853 ok( ret == 8, "Couldn't write in child process on %d (%s)\n", fd, strerror(errno));
854 lseek(fd, 0, SEEK_SET);
855 ok(read(fd, buffer, sizeof (buffer)) == 8, "Couldn't read back the data\n");
856 ok(memcmp(buffer, "Success", 8) == 0, "Couldn't read back the data\n");
857 }
858
859 static void test_file_inherit_child_no(const char* fd_s)
860 {
861 int fd = atoi(fd_s);
862 int ret;
863
864 ret = write(fd, "Success", 8);
865 ok( ret == -1 && errno == EBADF,
866 "Wrong write result in child process on %d (%s)\n", fd, strerror(errno));
867 }
868
869 static void create_io_inherit_block( STARTUPINFO *startup, unsigned int count, const HANDLE *handles )
870 {
871 static BYTE block[1024];
872 BYTE *wxflag_ptr;
873 HANDLE *handle_ptr;
874 unsigned int i;
875
876 startup->lpReserved2 = block;
877 startup->cbReserved2 = sizeof(unsigned) + (sizeof(char) + sizeof(HANDLE)) * count;
878 wxflag_ptr = block + sizeof(unsigned);
879 handle_ptr = (HANDLE *)(wxflag_ptr + count);
880
881 *(unsigned*)block = count;
882 for (i = 0; i < count; i++)
883 {
884 wxflag_ptr[i] = 0x81;
885 handle_ptr[i] = handles[i];
886 }
887 }
888
889 static const char *read_file( HANDLE file )
890 {
891 static char buffer[128];
892 DWORD ret;
893 SetFilePointer( file, 0, NULL, FILE_BEGIN );
894 if (!ReadFile( file, buffer, sizeof(buffer) - 1, &ret, NULL)) ret = 0;
895 buffer[ret] = 0;
896 return buffer;
897 }
898
899 static void test_stdout_handle( STARTUPINFO *startup, char *cmdline, HANDLE hstdout, BOOL expect_stdout,
900 const char *descr )
901 {
902 const char *data;
903 HANDLE hErrorFile;
904 SECURITY_ATTRIBUTES sa;
905 PROCESS_INFORMATION proc;
906
907 /* make file handle inheritable */
908 sa.nLength = sizeof(sa);
909 sa.lpSecurityDescriptor = NULL;
910 sa.bInheritHandle = TRUE;
911
912 hErrorFile = CreateFileA( "fdopen.err", GENERIC_READ|GENERIC_WRITE,
913 FILE_SHARE_READ | FILE_SHARE_WRITE, &sa, CREATE_ALWAYS, 0, NULL );
914 startup->dwFlags = STARTF_USESTDHANDLES;
915 startup->hStdInput = GetStdHandle( STD_INPUT_HANDLE );
916 startup->hStdOutput = hErrorFile;
917 startup->hStdError = GetStdHandle( STD_ERROR_HANDLE );
918
919 CreateProcessA( NULL, cmdline, NULL, NULL, TRUE,
920 CREATE_DEFAULT_ERROR_MODE | NORMAL_PRIORITY_CLASS, NULL, NULL, startup, &proc );
921 winetest_wait_child_process( proc.hProcess );
922
923 data = read_file( hErrorFile );
924 if (expect_stdout)
925 ok( strcmp( data, "Success" ), "%s: Error file shouldn't contain data\n", descr );
926 else
927 ok( !strcmp( data, "Success" ), "%s: Wrong error data (%s)\n", descr, data );
928
929 if (hstdout)
930 {
931 data = read_file( hstdout );
932 if (expect_stdout)
933 ok( !strcmp( data, "Success" ), "%s: Wrong stdout data (%s)\n", descr, data );
934 else
935 ok( strcmp( data, "Success" ), "%s: Stdout file shouldn't contain data\n", descr );
936 }
937
938 CloseHandle( hErrorFile );
939 DeleteFile( "fdopen.err" );
940 }
941
942 static void test_file_inherit( const char* selfname )
943 {
944 int fd;
945 const char* arg_v[5];
946 char buffer[16];
947 char cmdline[MAX_PATH];
948 STARTUPINFO startup;
949 SECURITY_ATTRIBUTES sa;
950 HANDLE handles[3];
951
952 fd = open ("fdopen.tst", O_CREAT | O_RDWR | O_BINARY, _S_IREAD |_S_IWRITE);
953 ok(fd != -1, "Couldn't create test file\n");
954 arg_v[0] = selfname;
955 arg_v[1] = "tests/file.c";
956 arg_v[2] = "inherit";
957 arg_v[3] = buffer; sprintf(buffer, "%d", fd);
958 arg_v[4] = 0;
959 _spawnvp(_P_WAIT, selfname, arg_v);
960 ok(tell(fd) == 8, "bad position %u expecting 8\n", tell(fd));
961 lseek(fd, 0, SEEK_SET);
962 ok(read(fd, buffer, sizeof (buffer)) == 8 && memcmp(buffer, "Success", 8) == 0, "Couldn't read back the data\n");
963 close (fd);
964 ok(unlink("fdopen.tst") == 0, "Couldn't unlink\n");
965
966 fd = open ("fdopen.tst", O_CREAT | O_RDWR | O_BINARY | O_NOINHERIT, _S_IREAD |_S_IWRITE);
967 ok(fd != -1, "Couldn't create test file\n");
968 arg_v[0] = selfname;
969 arg_v[1] = "tests/file.c";
970 arg_v[2] = "inherit_no";
971 arg_v[3] = buffer; sprintf(buffer, "%d", fd);
972 arg_v[4] = 0;
973 _spawnvp(_P_WAIT, selfname, arg_v);
974 ok(tell(fd) == 0, "bad position %u expecting 0\n", tell(fd));
975 ok(read(fd, buffer, sizeof (buffer)) == 0, "Found unexpected data (%s)\n", buffer);
976 close (fd);
977 ok(unlink("fdopen.tst") == 0, "Couldn't unlink\n");
978
979 /* make file handle inheritable */
980 sa.nLength = sizeof(sa);
981 sa.lpSecurityDescriptor = NULL;
982 sa.bInheritHandle = TRUE;
983 sprintf(cmdline, "%s file inherit 1", selfname);
984
985 /* init an empty Reserved2, which should not be recognized as inherit-block */
986 ZeroMemory(&startup, sizeof(STARTUPINFO));
987 startup.cb = sizeof(startup);
988 create_io_inherit_block( &startup, 0, NULL );
989 test_stdout_handle( &startup, cmdline, 0, FALSE, "empty block" );
990
991 /* test with valid inheritblock */
992 handles[0] = GetStdHandle( STD_INPUT_HANDLE );
993 handles[1] = CreateFileA( "fdopen.tst", GENERIC_READ|GENERIC_WRITE,
994 FILE_SHARE_READ | FILE_SHARE_WRITE, &sa, CREATE_ALWAYS, 0, NULL );
995 handles[2] = GetStdHandle( STD_ERROR_HANDLE );
996 create_io_inherit_block( &startup, 3, handles );
997 test_stdout_handle( &startup, cmdline, handles[1], TRUE, "valid block" );
998 CloseHandle( handles[1] );
999 DeleteFile("fdopen.tst");
1000
1001 /* test inherit block starting with unsigned zero */
1002 handles[1] = CreateFileA( "fdopen.tst", GENERIC_READ|GENERIC_WRITE,
1003 FILE_SHARE_READ | FILE_SHARE_WRITE, &sa, CREATE_ALWAYS, 0, NULL );
1004 create_io_inherit_block( &startup, 3, handles );
1005 *(unsigned int *)startup.lpReserved2 = 0;
1006 test_stdout_handle( &startup, cmdline, handles[1], FALSE, "zero count block" );
1007 CloseHandle( handles[1] );
1008 DeleteFile("fdopen.tst");
1009
1010 /* test inherit block with smaller size */
1011 handles[1] = CreateFileA( "fdopen.tst", GENERIC_READ|GENERIC_WRITE,
1012 FILE_SHARE_READ | FILE_SHARE_WRITE, &sa, CREATE_ALWAYS, 0, NULL );
1013 create_io_inherit_block( &startup, 3, handles );
1014 startup.cbReserved2 -= 3;
1015 test_stdout_handle( &startup, cmdline, handles[1], TRUE, "small size block" );
1016 CloseHandle( handles[1] );
1017 DeleteFile("fdopen.tst");
1018
1019 /* test inherit block with even smaller size */
1020 handles[1] = CreateFileA( "fdopen.tst", GENERIC_READ|GENERIC_WRITE,
1021 FILE_SHARE_READ | FILE_SHARE_WRITE, &sa, CREATE_ALWAYS, 0, NULL );
1022 create_io_inherit_block( &startup, 3, handles );
1023 startup.cbReserved2 = sizeof(unsigned int) + sizeof(HANDLE) + sizeof(char);
1024 test_stdout_handle( &startup, cmdline, handles[1], FALSE, "smaller size block" );
1025 CloseHandle( handles[1] );
1026 DeleteFile("fdopen.tst");
1027
1028 /* test inherit block with larger size */
1029 handles[1] = CreateFileA( "fdopen.tst", GENERIC_READ|GENERIC_WRITE,
1030 FILE_SHARE_READ | FILE_SHARE_WRITE, &sa, CREATE_ALWAYS, 0, NULL );
1031 create_io_inherit_block( &startup, 3, handles );
1032 startup.cbReserved2 += 7;
1033 test_stdout_handle( &startup, cmdline, handles[1], TRUE, "large size block" );
1034 CloseHandle( handles[1] );
1035 DeleteFile("fdopen.tst");
1036 }
1037
1038 static void test_tmpnam( void )
1039 {
1040 char name[MAX_PATH] = "abc";
1041 char *res;
1042
1043 res = tmpnam(NULL);
1044 ok(res != NULL, "tmpnam returned NULL\n");
1045 ok(res[0] == '\\', "first character is not a backslash\n");
1046 ok(strchr(res+1, '\\') == 0, "file not in the root directory\n");
1047 ok(res[strlen(res)-1] == '.', "first call - last character is not a dot\n");
1048
1049 res = tmpnam(name);
1050 ok(res != NULL, "tmpnam returned NULL\n");
1051 ok(res == name, "supplied buffer was not used\n");
1052 ok(res[0] == '\\', "first character is not a backslash\n");
1053 ok(strchr(res+1, '\\') == 0, "file not in the root directory\n");
1054 ok(res[strlen(res)-1] != '.', "second call - last character is a dot\n");
1055 }
1056
1057 static void test_chsize( void )
1058 {
1059 int fd;
1060 LONG cur, pos, count;
1061 char temptext[] = "012345678";
1062 char *tempfile = _tempnam( ".", "tst" );
1063
1064 ok( tempfile != NULL, "Couldn't create test file: %s\n", tempfile );
1065
1066 fd = _open( tempfile, _O_CREAT|_O_TRUNC|_O_RDWR, _S_IREAD|_S_IWRITE );
1067 ok( fd > 0, "Couldn't open test file\n" );
1068
1069 count = _write( fd, temptext, sizeof(temptext) );
1070 ok( count > 0, "Couldn't write to test file\n" );
1071
1072 /* get current file pointer */
1073 cur = _lseek( fd, 0, SEEK_CUR );
1074
1075 /* make the file smaller */
1076 ok( _chsize( fd, sizeof(temptext) / 2 ) == 0, "_chsize() failed\n" );
1077
1078 pos = _lseek( fd, 0, SEEK_CUR );
1079 ok( cur == pos, "File pointer changed from: %d to: %d\n", cur, pos );
1080 ok( _filelength( fd ) == sizeof(temptext) / 2, "Wrong file size\n" );
1081
1082 /* enlarge the file */
1083 ok( _chsize( fd, sizeof(temptext) * 2 ) == 0, "_chsize() failed\n" );
1084
1085 pos = _lseek( fd, 0, SEEK_CUR );
1086 ok( cur == pos, "File pointer changed from: %d to: %d\n", cur, pos );
1087 ok( _filelength( fd ) == sizeof(temptext) * 2, "Wrong file size\n" );
1088
1089 _close( fd );
1090 _unlink( tempfile );
1091 free( tempfile );
1092 }
1093
1094 static void test_fopen_fclose_fcloseall( void )
1095 {
1096 char fname1[] = "empty1";
1097 char fname2[] = "empty2";
1098 char fname3[] = "empty3";
1099 FILE *stream1, *stream2, *stream3, *stream4;
1100 int ret, numclosed;
1101
1102 /* testing fopen() */
1103 stream1 = fopen(fname1, "w+");
1104 ok(stream1 != NULL, "The file '%s' was not opened\n", fname1);
1105 stream2 = fopen(fname2, "w ");
1106 ok(stream2 != NULL, "The file '%s' was not opened\n", fname2 );
1107 _unlink(fname3);
1108 stream3 = fopen(fname3, "r");
1109 ok(stream3 == NULL, "The file '%s' shouldn't exist before\n", fname3 );
1110 stream3 = fopen(fname3, "w+");
1111 ok(stream3 != NULL, "The file '%s' should be opened now\n", fname3 );
1112 errno = 0xfaceabad;
1113 stream4 = fopen("", "w+");
1114 ok(stream4 == NULL && (errno == EINVAL || errno == ENOENT),
1115 "filename is empty, errno = %d (expected 2 or 22)\n", errno);
1116 errno = 0xfaceabad;
1117 stream4 = fopen(NULL, "w+");
1118 ok(stream4 == NULL && (errno == EINVAL || errno == ENOENT),
1119 "filename is NULL, errno = %d (expected 2 or 22)\n", errno);
1120
1121 /* testing fclose() */
1122 ret = fclose(stream2);
1123 ok(ret == 0, "The file '%s' was not closed\n", fname2);
1124 ret = fclose(stream3);
1125 ok(ret == 0, "The file '%s' was not closed\n", fname3);
1126 ret = fclose(stream2);
1127 ok(ret == EOF, "Closing file '%s' returned %d\n", fname2, ret);
1128 ret = fclose(stream3);
1129 ok(ret == EOF, "Closing file '%s' returned %d\n", fname3, ret);
1130
1131 /* testing fcloseall() */
1132 numclosed = _fcloseall();
1133 /* fname1 should be closed here */
1134 ok(numclosed == 1, "Number of files closed by fcloseall(): %u\n", numclosed);
1135 numclosed = _fcloseall();
1136 ok(numclosed == 0, "Number of files closed by fcloseall(): %u\n", numclosed);
1137
1138 ok(_unlink(fname1) == 0, "Couldn't unlink file named '%s'\n", fname1);
1139 ok(_unlink(fname2) == 0, "Couldn't unlink file named '%s'\n", fname2);
1140 ok(_unlink(fname3) == 0, "Couldn't unlink file named '%s'\n", fname3);
1141 }
1142
1143 static void test_get_osfhandle(void)
1144 {
1145 int fd;
1146 char fname[] = "t_get_osfhanle";
1147 DWORD bytes_written;
1148 HANDLE handle;
1149
1150 fd = _sopen(fname, _O_CREAT|_O_RDWR, _SH_DENYRW, _S_IREAD | _S_IWRITE);
1151 handle = (HANDLE)_get_osfhandle(fd);
1152 WriteFile(handle, "bar", 3, &bytes_written, NULL);
1153 _close(fd);
1154 fd = _open(fname, _O_RDONLY, 0);
1155 ok(fd != -1, "Coudn't open '%s' after _get_osfhanle()\n", fname);
1156
1157 _close(fd);
1158 _unlink(fname);
1159 }
1160
1161 static void test_setmaxstdio(void)
1162 {
1163 ok(2048 == _setmaxstdio(2048),"_setmaxstdio returned %d instead of 2048\n",_setmaxstdio(2048));
1164 ok(-1 == _setmaxstdio(2049),"_setmaxstdio returned %d instead of -1\n",_setmaxstdio(2049));
1165 }
1166
1167 static void test_stat(void)
1168 {
1169 int fd;
1170 int pipes[2];
1171 struct stat buf;
1172
1173 /* Tests for a file */
1174 fd = open("stat.tst", O_WRONLY | O_CREAT | O_BINARY, _S_IREAD |_S_IWRITE);
1175 if (fd >= 0)
1176 {
1177 ok(fstat(fd, &buf) == 0, "fstat failed: errno=%d\n", errno);
1178 ok((buf.st_mode & _S_IFMT) == _S_IFREG, "bad format = %06o\n", buf.st_mode);
1179 ok((buf.st_mode & 0777) == 0666, "bad st_mode = %06o\n", buf.st_mode);
1180 ok(buf.st_dev == 0, "st_dev is %d, expected 0\n", buf.st_dev);
1181 ok(buf.st_dev == buf.st_rdev, "st_dev (%d) and st_rdev (%d) differ\n", buf.st_dev, buf.st_rdev);
1182 ok(buf.st_nlink == 1, "st_nlink is %d, expected 1\n", buf.st_nlink);
1183 ok(buf.st_size == 0, "st_size is %d, expected 0\n", buf.st_size);
1184
1185 ok(stat("stat.tst", &buf) == 0, "stat failed: errno=%d\n", errno);
1186 ok((buf.st_mode & _S_IFMT) == _S_IFREG, "bad format = %06o\n", buf.st_mode);
1187 ok((buf.st_mode & 0777) == 0666, "bad st_mode = %06o\n", buf.st_mode);
1188 ok(buf.st_dev == buf.st_rdev, "st_dev (%d) and st_rdev (%d) differ\n", buf.st_dev, buf.st_rdev);
1189 ok(buf.st_nlink == 1, "st_nlink is %d, expected 1\n", buf.st_nlink);
1190 ok(buf.st_size == 0, "st_size is %d, expected 0\n", buf.st_size);
1191
1192 close(fd);
1193 remove("stat.tst");
1194 }
1195 else
1196 skip("open failed with errno %d\n", errno);
1197
1198 /* Tests for a char device */
1199 if (_dup2(0, 10) == 0)
1200 {
1201 ok(fstat(10, &buf) == 0, "fstat(stdin) failed: errno=%d\n", errno);
1202 if ((buf.st_mode & _S_IFMT) == _S_IFCHR)
1203 {
1204 ok(buf.st_mode == _S_IFCHR, "bad st_mode=%06o\n", buf.st_mode);
1205 ok(buf.st_dev == 10, "st_dev is %d, expected 10\n", buf.st_dev);
1206 ok(buf.st_rdev == 10, "st_rdev is %d, expected 10\n", buf.st_rdev);
1207 ok(buf.st_nlink == 1, "st_nlink is %d, expected 1\n", buf.st_nlink);
1208 }
1209 else
1210 skip("stdin is not a char device? st_mode=%06o\n", buf.st_mode);
1211 close(10);
1212 }
1213 else
1214 skip("_dup2 failed with errno %d\n", errno);
1215
1216 /* Tests for pipes */
1217 if (_pipe(pipes, 1024, O_BINARY) == 0)
1218 {
1219 ok(fstat(pipes[0], &buf) == 0, "fstat(pipe) failed: errno=%d\n", errno);
1220 ok(buf.st_mode == _S_IFIFO, "bad st_mode=%06o\n", buf.st_mode);
1221 ok(buf.st_dev == pipes[0], "st_dev is %d, expected %d\n", buf.st_dev, pipes[0]);
1222 ok(buf.st_rdev == pipes[0], "st_rdev is %d, expected %d\n", buf.st_rdev, pipes[0]);
1223 ok(buf.st_nlink == 1, "st_nlink is %d, expected 1\n", buf.st_nlink);
1224 close(pipes[0]);
1225 close(pipes[1]);
1226 }
1227 else
1228 skip("pipe failed with errno %d\n", errno);
1229 }
1230
1231 static const char* pipe_string="Hello world";
1232
1233 /* How many messages to transfer over the pipe */
1234 #define N_TEST_MESSAGES 3
1235
1236 static void test_pipes_child(int argc, char** args)
1237 {
1238 int fd;
1239 int nwritten;
1240 int i;
1241
1242 if (argc < 5)
1243 {
1244 ok(0, "not enough parameters: %d\n", argc);
1245 return;
1246 }
1247
1248 fd=atoi(args[3]);
1249 ok(close(fd) == 0, "unable to close %d: %d\n", fd, errno);
1250
1251 fd=atoi(args[4]);
1252
1253 for (i=0; i<N_TEST_MESSAGES; i++) {
1254 nwritten=write(fd, pipe_string, strlen(pipe_string));
1255 ok(nwritten == strlen(pipe_string), "i %d, expected to write '%s' wrote %d\n", i, pipe_string, nwritten);
1256 /* let other process wake up so they can show off their "keep reading until EOF" behavior */
1257 if (i < N_TEST_MESSAGES-1)
1258 Sleep(100);
1259 }
1260
1261 ok(close(fd) == 0, "unable to close %d: %d\n", fd, errno);
1262 }
1263
1264 static void test_pipes(const char* selfname)
1265 {
1266 int pipes[2];
1267 char str_fdr[12], str_fdw[12];
1268 FILE* file;
1269 const char* arg_v[6];
1270 char buf[4096];
1271 char expected[4096];
1272 int r;
1273 int i;
1274
1275 /* Test reading from a pipe with read() */
1276 if (_pipe(pipes, 1024, O_BINARY) < 0)
1277 {
1278 ok(0, "pipe failed with errno %d\n", errno);
1279 return;
1280 }
1281
1282 arg_v[0] = selfname;
1283 arg_v[1] = "tests/file.c";
1284 arg_v[2] = "pipes";
1285 arg_v[3] = str_fdr; sprintf(str_fdr, "%d", pipes[0]);
1286 arg_v[4] = str_fdw; sprintf(str_fdw, "%d", pipes[1]);
1287 arg_v[5] = NULL;
1288 proc_handles[0] = (HANDLE)_spawnvp(_P_NOWAIT, selfname, arg_v);
1289 ok(close(pipes[1]) == 0, "unable to close %d: %d\n", pipes[1], errno);
1290
1291 for (i=0; i<N_TEST_MESSAGES; i++) {
1292 r=read(pipes[0], buf, sizeof(buf)-1);
1293 ok(r == strlen(pipe_string), "i %d, got %d\n", i, r);
1294 if (r > 0)
1295 buf[r]='\0';
1296 ok(strcmp(buf, pipe_string) == 0, "expected to read '%s', got '%s'\n", pipe_string, buf);
1297 }
1298
1299 r=read(pipes[0], buf, sizeof(buf)-1);
1300 ok(r == 0, "expected to read 0 bytes, got %d\n", r);
1301 ok(close(pipes[0]) == 0, "unable to close %d: %d\n", pipes[0], errno);
1302
1303 /* Test reading from a pipe with fread() */
1304 if (_pipe(pipes, 1024, O_BINARY) < 0)
1305 {
1306 ok(0, "pipe failed with errno %d\n", errno);
1307 return;
1308 }
1309
1310 arg_v[0] = selfname;
1311 arg_v[1] = "tests/file.c";
1312 arg_v[2] = "pipes";
1313 arg_v[3] = str_fdr; sprintf(str_fdr, "%d", pipes[0]);
1314 arg_v[4] = str_fdw; sprintf(str_fdw, "%d", pipes[1]);
1315 arg_v[5] = NULL;
1316 proc_handles[1] = (HANDLE)_spawnvp(_P_NOWAIT, selfname, arg_v);
1317 ok(close(pipes[1]) == 0, "unable to close %d: %d\n", pipes[1], errno);
1318 file=fdopen(pipes[0], "r");
1319
1320 /* In blocking mode, fread will keep calling read() until it gets
1321 * enough bytes, or EOF, even on Unix. (If this were a Unix terminal
1322 * in cooked mode instead of a pipe, it would also stop on EOL.)
1323 */
1324 expected[0] = 0;
1325 for (i=0; i<N_TEST_MESSAGES; i++)
1326 strcat(expected, pipe_string);
1327 r=fread(buf, 1, sizeof(buf)-1, file);
1328 ok(r == strlen(expected), "fread() returned %d: ferror=%d\n", r, ferror(file));
1329 if (r > 0)
1330 buf[r]='\0';
1331 ok(strcmp(buf, expected) == 0, "got '%s' expected '%s'\n", buf, expected);
1332
1333 /* Let child close the file before we read, so we can sense EOF reliably */
1334 Sleep(100);
1335 r=fread(buf, 1, sizeof(buf)-1, file);
1336 ok(r == 0, "fread() returned %d instead of 0\n", r);
1337 ok(ferror(file) == 0, "got ferror() = %d\n", ferror(file));
1338 ok(feof(file), "feof() is false!\n");
1339
1340 ok(fclose(file) == 0, "unable to close the pipe: %d\n", errno);
1341 }
1342
1343 static void test_unlink(void)
1344 {
1345 FILE* file;
1346 ok(mkdir("test_unlink") == 0, "unable to create test dir\n");
1347 file = fopen("test_unlink\\empty", "w");
1348 ok(file != NULL, "unable to create test file\n");
1349 if(file)
1350 fclose(file);
1351 ok(_unlink("test_unlink") != 0, "unlinking a non-empty directory must fail\n");
1352 unlink("test_unlink\\empty");
1353 rmdir("test_unlink");
1354 }
1355
1356 START_TEST(file)
1357 {
1358 int arg_c;
1359 char** arg_v;
1360
1361 arg_c = winetest_get_mainargs( &arg_v );
1362
1363 /* testing low-level I/O */
1364 if (arg_c >= 3)
1365 {
1366 if (strcmp(arg_v[2], "inherit") == 0)
1367 test_file_inherit_child(arg_v[3]);
1368 else if (strcmp(arg_v[2], "inherit_no") == 0)
1369 test_file_inherit_child_no(arg_v[3]);
1370 else if (strcmp(arg_v[2], "pipes") == 0)
1371 test_pipes_child(arg_c, arg_v);
1372 else
1373 ok(0, "invalid argument '%s'\n", arg_v[2]);
1374 return;
1375 }
1376 test_file_inherit(arg_v[0]);
1377 test_file_write_read();
1378 test_chsize();
1379 test_stat();
1380 test_unlink();
1381
1382 /* testing stream I/O */
1383 test_filbuf();
1384 test_fdopen();
1385 test_fopen_fclose_fcloseall();
1386 test_fileops();
1387 test_asciimode();
1388 test_asciimode2();
1389 test_readmode(FALSE); /* binary mode */
1390 test_readmode(TRUE); /* ascii mode */
1391 test_fgetc();
1392 test_fputc();
1393 test_flsbuf();
1394 test_fgetwc();
1395 test_ctrlz();
1396 test_file_put_get();
1397 test_tmpnam();
1398 test_get_osfhandle();
1399 test_setmaxstdio();
1400 test_pipes(arg_v[0]);
1401
1402 /* Wait for the (_P_NOWAIT) spawned processes to finish to make sure the report
1403 * file contains lines in the correct order
1404 */
1405 WaitForMultipleObjects(sizeof(proc_handles)/sizeof(proc_handles[0]), proc_handles, TRUE, 5000);
1406 }