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