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