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