msvcrt: Add small blocks heap tests.
[wine.git] / dlls / msvcrt / tests / file.c
blob73965f34ce6a623babc9a0fb45f0ea1046f4b0b9
1 /*
2 * Unit test suite for file functions
4 * Copyright 2002 Bill Currie
5 * Copyright 2005 Paul Rupe
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.
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.
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
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 #include <locale.h>
38 #define MSVCRT_FD_BLOCK_SIZE 32
39 typedef struct {
40 HANDLE handle;
41 unsigned char wxflag;
42 char lookahead[3];
43 int exflag;
44 CRITICAL_SECTION crit;
45 } ioinfo;
46 static ioinfo **__pioinfo;
48 static HANDLE proc_handles[2];
50 static int (__cdecl *p_fopen_s)(FILE**, const char*, const char*);
51 static int (__cdecl *p__wfopen_s)(FILE**, const wchar_t*, const wchar_t*);
53 static const char* get_base_name(const char *path)
55 const char *ret = path+strlen(path)-1;
57 while(ret >= path) {
58 if(*ret=='\\' || *ret=='/')
59 break;
60 ret--;
62 return ret+1;
65 static void init(void)
67 HMODULE hmod = GetModuleHandleA("msvcrt.dll");
69 setlocale(LC_CTYPE, "C");
71 p_fopen_s = (void*)GetProcAddress(hmod, "fopen_s");
72 p__wfopen_s = (void*)GetProcAddress(hmod, "_wfopen_s");
73 __pioinfo = (void*)GetProcAddress(hmod, "__pioinfo");
76 static void test_filbuf( void )
78 FILE *fp;
79 int c;
80 fpos_t pos;
82 fp = fopen("filbuf.tst", "wb");
83 fwrite("\n\n\n\n", 1, 4, fp);
84 fclose(fp);
86 fp = fopen("filbuf.tst", "rt");
87 c = _filbuf(fp);
88 ok(c == '\n', "read wrong byte\n");
89 /* See bug 16970 for why we care about _filbuf.
90 * ftell returns screwy values on files with lots
91 * of bare LFs in ascii mode because it assumes
92 * that ascii files contain only CRLFs, removes
93 * the CR's early in _filbuf, and adjusts the return
94 * value of ftell to compensate.
95 * native _filbuf will read the whole file, then consume and return
96 * the first one. That leaves fp->_fd at offset 4, and fp->_ptr
97 * pointing to a buffer of three bare LFs, so
98 * ftell will return 4 - 3 - 3 = -2.
100 ok(ftell(fp) == -2, "ascii crlf removal does not match native\n");
101 ok(fgetpos(fp, &pos) == 0, "fgetpos fail\n");
102 ok(pos == -2, "ftell does not match fgetpos\n");
103 fclose(fp);
104 unlink("filbuf.tst");
107 static void test_fdopen( void )
109 static const char buffer[] = {0,1,2,3,4,5,6,7,8,9};
110 char ibuf[10];
111 int fd;
112 FILE *file;
114 fd = open ("fdopen.tst", O_WRONLY | O_CREAT | O_BINARY, _S_IREAD |_S_IWRITE);
115 write (fd, buffer, sizeof (buffer));
116 close (fd);
118 fd = open ("fdopen.tst", O_RDONLY | O_BINARY);
119 lseek (fd, 5, SEEK_SET);
120 file = fdopen (fd, "rb");
121 ok (fread (ibuf, 1, sizeof (buffer), file) == 5, "read wrong byte count\n");
122 ok (memcmp (ibuf, buffer + 5, 5) == 0, "read wrong bytes\n");
123 fclose (file);
124 unlink ("fdopen.tst");
127 static void test_fileops( void )
129 static const char outbuffer[] = "0,1,2,3,4,5,6,7,8,9";
130 char buffer[256];
131 WCHAR wbuffer[256];
132 int fd;
133 FILE *file;
134 fpos_t pos;
135 int i, c, bufmode;
136 static const int bufmodes[] = {_IOFBF,_IONBF};
138 fd = open ("fdopen.tst", O_WRONLY | O_CREAT | O_BINARY, _S_IREAD |_S_IWRITE);
139 write (fd, outbuffer, sizeof (outbuffer));
140 close (fd);
142 for (bufmode=0; bufmode < sizeof(bufmodes)/sizeof(bufmodes[0]); bufmode++)
144 fd = open ("fdopen.tst", O_RDONLY | O_BINARY);
145 file = fdopen (fd, "rb");
146 setvbuf(file,NULL,bufmodes[bufmode],2048);
147 ok(strlen(outbuffer) == (sizeof(outbuffer)-1),"strlen/sizeof error for bufmode=%x\n", bufmodes[bufmode]);
148 ok(fgets(buffer,sizeof(buffer),file) !=0,"fgets failed unexpected for bufmode=%x\n", bufmodes[bufmode]);
149 ok(fgets(buffer,sizeof(buffer),file) ==0,"fgets didn't signal EOF for bufmode=%x\n", bufmodes[bufmode]);
150 ok(feof(file) !=0,"feof doesn't signal EOF for bufmode=%x\n", bufmodes[bufmode]);
151 rewind(file);
152 ok(fgets(buffer,strlen(outbuffer),file) !=0,"fgets failed unexpected for bufmode=%x\n", bufmodes[bufmode]);
153 ok(lstrlenA(buffer) == lstrlenA(outbuffer) -1,"fgets didn't read right size for bufmode=%x\n", bufmodes[bufmode]);
154 ok(fgets(buffer,sizeof(outbuffer),file) !=0,"fgets failed unexpected for bufmode=%x\n", bufmodes[bufmode]);
155 ok(strlen(buffer) == 1,"fgets dropped chars for bufmode=%x\n", bufmodes[bufmode]);
156 ok(buffer[0] == outbuffer[strlen(outbuffer)-1],"fgets exchanged chars for bufmode=%x\n", bufmodes[bufmode]);
158 rewind(file);
159 for (i = 0; i < sizeof(outbuffer); i++)
161 ok(fgetc(file) == outbuffer[i], "fgetc returned wrong data for bufmode=%x\n", bufmodes[bufmode]);
163 ok((c = fgetc(file)) == EOF, "getc did not return EOF for bufmode=%x\n", bufmodes[bufmode]);
164 ok(feof(file), "feof did not return EOF for bufmode=%x\n", bufmodes[bufmode]);
165 ok(ungetc(c, file) == EOF, "ungetc(EOF) did not return EOF for bufmode=%x\n", bufmodes[bufmode]);
166 ok(feof(file), "feof after ungetc(EOF) did not return EOF for bufmode=%x\n", bufmodes[bufmode]);
167 ok(fgetc(file) == EOF, "getc did not return EOF for bufmode=%x\n", bufmodes[bufmode]);
168 c = outbuffer[sizeof(outbuffer) - 1];
169 ok(ungetc(c, file) == c, "ungetc did not return its input for bufmode=%x\n", bufmodes[bufmode]);
170 ok(!feof(file), "feof after ungetc returned EOF for bufmode=%x\n", bufmodes[bufmode]);
171 ok((c = fgetc(file)) != EOF, "getc after ungetc returned EOF for bufmode=%x\n", bufmodes[bufmode]);
172 ok(c == outbuffer[sizeof(outbuffer) - 1],
173 "getc did not return ungetc'd data for bufmode=%x\n", bufmodes[bufmode]);
174 ok(!feof(file), "feof after getc returned EOF prematurely for bufmode=%x\n", bufmodes[bufmode]);
175 ok(fgetc(file) == EOF, "getc did not return EOF for bufmode=%x\n", bufmodes[bufmode]);
176 ok(feof(file), "feof after getc did not return EOF for bufmode=%x\n", bufmodes[bufmode]);
178 rewind(file);
179 ok(fgetpos(file,&pos) == 0, "fgetpos failed unexpected for bufmode=%x\n", bufmodes[bufmode]);
180 ok(pos == 0, "Unexpected result of fgetpos %x%08x for bufmode=%x\n", (DWORD)(pos >> 32), (DWORD)pos, bufmodes[bufmode]);
181 pos = sizeof (outbuffer);
182 ok(fsetpos(file, &pos) == 0, "fsetpos failed unexpected for bufmode=%x\n", bufmodes[bufmode]);
183 ok(fgetpos(file,&pos) == 0, "fgetpos failed unexpected for bufmode=%x\n", bufmodes[bufmode]);
184 ok(pos == sizeof (outbuffer), "Unexpected result of fgetpos %x%08x for bufmode=%x\n", (DWORD)(pos >> 32), (DWORD)pos, bufmodes[bufmode]);
186 fclose (file);
188 fd = open ("fdopen.tst", O_RDONLY | O_TEXT);
189 file = fdopen (fd, "rt"); /* open in TEXT mode */
190 ok(fgetws(wbuffer,sizeof(wbuffer)/sizeof(wbuffer[0]),file) !=0,"fgetws failed unexpected\n");
191 ok(fgetws(wbuffer,sizeof(wbuffer)/sizeof(wbuffer[0]),file) ==0,"fgetws didn't signal EOF\n");
192 ok(feof(file) !=0,"feof doesn't signal EOF\n");
193 rewind(file);
194 ok(fgetws(wbuffer,strlen(outbuffer),file) !=0,"fgetws failed unexpected\n");
195 ok(lstrlenW(wbuffer) == (lstrlenA(outbuffer) -1),"fgetws didn't read right size\n");
196 ok(fgetws(wbuffer,sizeof(outbuffer)/sizeof(outbuffer[0]),file) !=0,"fgets failed unexpected\n");
197 ok(lstrlenW(wbuffer) == 1,"fgets dropped chars\n");
198 fclose (file);
200 file = fopen("fdopen.tst", "rb");
201 ok( file != NULL, "fopen failed\n");
202 /* sizeof(buffer) > content of file */
203 ok(fread(buffer, sizeof(buffer), 1, file) == 0, "fread test failed\n");
204 /* feof should be set now */
205 ok(feof(file), "feof after fread failed\n");
206 fclose (file);
208 unlink ("fdopen.tst");
211 #define IOMODE (ao?"ascii mode":"binary mode")
212 static void test_readmode( BOOL ascii_mode )
214 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";
215 static const char padbuffer[] = "ghjghjghjghj";
216 static const char nlbuffer[] = "\r\n";
217 char buffer[2*BUFSIZ+256];
218 const char *optr;
219 int fd;
220 FILE *file;
221 const int *ip;
222 int i, j, m, ao, pl;
223 unsigned int fp;
224 LONG l;
226 fd = open ("fdopen.tst", O_WRONLY | O_CREAT | O_BINARY, _S_IREAD |_S_IWRITE);
227 /* an internal buffer of BUFSIZ is maintained, so make a file big
228 * enough to test operations that cross the buffer boundary
230 j = (2*BUFSIZ-4)/strlen(padbuffer);
231 for (i=0; i<j; i++)
232 write (fd, padbuffer, strlen(padbuffer));
233 j = (2*BUFSIZ-4)%strlen(padbuffer);
234 for (i=0; i<j; i++)
235 write (fd, &padbuffer[i], 1);
236 write (fd, nlbuffer, strlen(nlbuffer));
237 write (fd, outbuffer, sizeof (outbuffer));
238 close (fd);
240 if (ascii_mode) {
241 /* Open file in ascii mode */
242 fd = open ("fdopen.tst", O_RDONLY);
243 file = fdopen (fd, "r");
244 ao = -1; /* on offset to account for carriage returns */
246 else {
247 fd = open ("fdopen.tst", O_RDONLY | O_BINARY);
248 file = fdopen (fd, "rb");
249 ao = 0;
252 /* first is a test of fgets, ftell, fseek */
253 ok(ftell(file) == 0,"Did not start at beginning of file in %s\n", IOMODE);
254 ok(fgets(buffer,2*BUFSIZ+256,file) !=0,"padding line fgets failed unexpected in %s\n", IOMODE);
255 l = ftell(file);
256 pl = 2*BUFSIZ-2;
257 ok(l == pl,"padding line ftell got %d should be %d in %s\n", l, pl, IOMODE);
258 ok(lstrlenA(buffer) == pl+ao,"padding line fgets got size %d should be %d in %s\n",
259 lstrlenA(buffer), pl+ao, IOMODE);
260 for (fp=0; fp<strlen(outbuffer); fp++)
261 if (outbuffer[fp] == '\n') break;
262 fp++;
263 ok(fgets(buffer,256,file) !=0,"line 1 fgets failed unexpected in %s\n", IOMODE);
264 l = ftell(file);
265 ok(l == pl+fp,"line 1 ftell got %d should be %d in %s\n", l, pl+fp, IOMODE);
266 ok(lstrlenA(buffer) == fp+ao,"line 1 fgets got size %d should be %d in %s\n",
267 lstrlenA(buffer), fp+ao, IOMODE);
268 /* test a seek back across the buffer boundary */
269 l = pl;
270 ok(fseek(file,l,SEEK_SET)==0,"seek failure in %s\n", IOMODE);
271 l = ftell(file);
272 ok(l == pl,"ftell after seek got %d should be %d in %s\n", l, pl, IOMODE);
273 ok(fgets(buffer,256,file) !=0,"second read of line 1 fgets failed unexpected in %s\n", IOMODE);
274 l = ftell(file);
275 ok(l == pl+fp,"second read of line 1 ftell got %d should be %d in %s\n", l, pl+fp, IOMODE);
276 ok(lstrlenA(buffer) == fp+ao,"second read of line 1 fgets got size %d should be %d in %s\n",
277 lstrlenA(buffer), fp+ao, IOMODE);
278 ok(fgets(buffer,256,file) !=0,"line 2 fgets failed unexpected in %s\n", IOMODE);
279 fp += 2;
280 l = ftell(file);
281 ok(l == pl+fp,"line 2 ftell got %d should be %d in %s\n", l, pl+fp, IOMODE);
282 ok(lstrlenA(buffer) == 2+ao,"line 2 fgets got size %d should be %d in %s\n",
283 lstrlenA(buffer), 2+ao, IOMODE);
285 /* test fread across buffer boundary */
286 rewind(file);
287 ok(ftell(file) == 0,"Did not start at beginning of file in %s\n", IOMODE);
288 ok(fgets(buffer,BUFSIZ-6,file) !=0,"padding line fgets failed unexpected in %s\n", IOMODE);
289 j=strlen(outbuffer);
290 i=fread(buffer,1,BUFSIZ+strlen(outbuffer),file);
291 ok(i==BUFSIZ+j,"fread failed, expected %d got %d in %s\n", BUFSIZ+j, i, IOMODE);
292 l = ftell(file);
293 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);
294 for (m=0; m<3; m++)
295 ok(buffer[m]==padbuffer[m+(BUFSIZ-4)%strlen(padbuffer)],"expected %c got %c\n", padbuffer[m], buffer[m]);
296 m+=BUFSIZ+2+ao;
297 optr = outbuffer;
298 for (; m<i; m++) {
299 ok(buffer[m]==*optr,"char %d expected %c got %c in %s\n", m, *optr, buffer[m], IOMODE);
300 optr++;
301 if (ao && (*optr == '\r'))
302 optr++;
304 /* fread should return the requested number of bytes if available */
305 rewind(file);
306 ok(ftell(file) == 0,"Did not start at beginning of file in %s\n", IOMODE);
307 ok(fgets(buffer,BUFSIZ-6,file) !=0,"padding line fgets failed unexpected in %s\n", IOMODE);
308 j = fp+10;
309 i=fread(buffer,1,j,file);
310 ok(i==j,"fread failed, expected %d got %d in %s\n", j, i, IOMODE);
311 /* test fread eof */
312 ok(fseek(file,0,SEEK_END)==0,"seek failure in %s\n", IOMODE);
313 ok(feof(file)==0,"feof failure in %s\n", IOMODE);
314 ok(fread(buffer,1,1,file)==0,"fread failure in %s\n", IOMODE);
315 ok(feof(file)!=0,"feof failure in %s\n", IOMODE);
316 ok(fseek(file,-3,SEEK_CUR)==0,"seek failure in %s\n", IOMODE);
317 ok(feof(file)==0,"feof failure in %s\n", IOMODE);
318 ok(fread(buffer,2,1,file)==1,"fread failed in %s\n", IOMODE);
319 ok(feof(file)==0,"feof failure in %s\n", IOMODE);
320 ok(fread(buffer,2,1,file)==0,"fread failure in %s\n",IOMODE);
321 ok(feof(file)!=0,"feof failure in %s\n", IOMODE);
323 /* test some additional functions */
324 rewind(file);
325 ok(ftell(file) == 0,"Did not start at beginning of file in %s\n", IOMODE);
326 ok(fgets(buffer,2*BUFSIZ+256,file) !=0,"padding line fgets failed unexpected in %s\n", IOMODE);
327 i = _getw(file);
328 ip = (const int *)outbuffer;
329 ok(i == *ip,"_getw failed, expected %08x got %08x in %s\n", *ip, i, IOMODE);
330 for (fp=0; fp<strlen(outbuffer); fp++)
331 if (outbuffer[fp] == '\n') break;
332 fp++;
333 /* this will cause the next _getw to cross carriage return characters */
334 ok(fgets(buffer,fp-6,file) !=0,"line 1 fgets failed unexpected in %s\n", IOMODE);
335 for (i=0, j=0; i<6; i++) {
336 if (ao==0 || outbuffer[fp-3+i] != '\r')
337 buffer[j++] = outbuffer[fp-3+i];
339 i = _getw(file);
340 ip = (int *)buffer;
341 ok(i == *ip,"_getw failed, expected %08x got %08x in %s\n", *ip, i, IOMODE);
343 fclose (file);
344 unlink ("fdopen.tst");
347 static void test_asciimode(void)
349 FILE *fp;
350 char buf[64];
351 int c, i, j;
353 /* Simple test of CR CR LF handling. Test both fgets and fread code paths, they're different! */
354 fp = fopen("ascii.tst", "wb");
355 fputs("\r\r\n", fp);
356 fclose(fp);
357 fp = fopen("ascii.tst", "rt");
358 ok(fgets(buf, sizeof(buf), fp) != NULL, "fgets\n");
359 ok(0 == strcmp(buf, "\r\n"), "CR CR LF not read as CR LF\n");
360 rewind(fp);
361 ok((fread(buf, 1, sizeof(buf), fp) == 2) && (0 == strcmp(buf, "\r\n")), "CR CR LF not read as CR LF\n");
362 fclose(fp);
363 unlink("ascii.tst");
365 /* Simple test of foo ^Z [more than one block] bar handling */
366 fp = fopen("ascii.tst", "wb");
367 fputs("foo\032", fp); /* foo, logical EOF, ... */
368 fseek(fp, 65536L, SEEK_SET); /* ... more than MSVCRT_BUFSIZ, ... */
369 fputs("bar", fp); /* ... bar */
370 fclose(fp);
371 fp = fopen("ascii.tst", "rt");
372 ok(fgets(buf, sizeof(buf), fp) != NULL, "fgets foo\n");
373 ok(0 == strcmp(buf, "foo"), "foo ^Z not read as foo by fgets\n");
374 ok(fgets(buf, sizeof(buf), fp) == NULL, "fgets after logical EOF\n");
375 rewind(fp);
376 ok((fread(buf, 1, sizeof(buf), fp) == 3) && (0 == strcmp(buf, "foo")), "foo ^Z not read as foo by fread\n");
377 ok((fread(buf, 1, sizeof(buf), fp) == 0), "fread after logical EOF\n");
378 fclose(fp);
380 /* Show ASCII mode handling*/
381 fp= fopen("ascii.tst","wb");
382 fputs("0\r\n1\r\n2\r\n3\r\n4\r\n5\r\n6\r\n7\r\n8\r\n9\r\n", fp);
383 fclose(fp);
385 fp = fopen("ascii.tst", "r");
386 c= fgetc(fp);
387 ok(c == '0', "fgetc failed, expected '0', got '%c'\n", c);
388 c= fgetc(fp);
389 ok(c == '\n', "fgetc failed, expected '\\n', got '%c'\n", c);
390 fseek(fp,0,SEEK_CUR);
391 for(i=1; i<10; i++) {
392 ok((j = ftell(fp)) == i*3, "ftell fails in TEXT mode\n");
393 fseek(fp,0,SEEK_CUR);
394 ok((c = fgetc(fp)) == '0'+ i, "fgetc after fseek failed in line %d\n", i);
395 c= fgetc(fp);
396 ok(c == '\n', "fgetc failed, expected '\\n', got '%c'\n", c);
398 /* Show that fseek doesn't skip \\r !*/
399 rewind(fp);
400 c= fgetc(fp);
401 ok(c == '0', "fgetc failed, expected '0', got '%c'\n", c);
402 fseek(fp, 2 ,SEEK_CUR);
403 for(i=1; i<10; i++) {
404 ok((c = fgetc(fp)) == '0'+ i, "fgetc after fseek with pos Offset failed in line %d\n", i);
405 fseek(fp, 2 ,SEEK_CUR);
407 fseek(fp, 9*3 ,SEEK_SET);
408 c = fgetc(fp);
409 ok(c == '9', "fgetc failed, expected '9', got '%c'\n", c);
410 fseek(fp, -4 ,SEEK_CUR);
411 for(i= 8; i>=0; i--) {
412 ok((c = fgetc(fp)) == '0'+ i, "fgetc after fseek with neg Offset failed in line %d\n", i);
413 fseek(fp, -4 ,SEEK_CUR);
415 /* Show what happens if fseek positions filepointer on \\r */
416 fclose(fp);
417 fp = fopen("ascii.tst", "r");
418 fseek(fp, 3 ,SEEK_SET);
419 ok((c = fgetc(fp)) == '1', "fgetc fails to read next char when positioned on \\r\n");
420 fclose(fp);
422 unlink("ascii.tst");
425 static void test_asciimode2(void)
427 /* Error sequence from one app was getchar followed by small fread
428 * with one \r removed had last byte of buffer filled with
429 * next byte of *unbuffered* data rather than next byte from buffer
430 * Test case is a short string of one byte followed by a newline
431 * followed by filler to fill out the sector, then a sector of
432 * some different byte.
435 FILE *fp;
436 char ibuf[4];
437 int i;
438 static const char obuf[] =
439 "00\n"
440 "000000000000000000000000000000000000000000000000000000000000000000000000000000\n"
441 "000000000000000000000000000000000000000000000000000000000000000000000000000000\n"
442 "000000000000000000000000000000000000000000000000000000000000000000000000000000\n"
443 "000000000000000000000000000000000000000000000000000000000000000000000000000000\n"
444 "000000000000000000000000000000000000000000000000000000000000000000000000000000\n"
445 "000000000000000000000000000000000000000000000000000000000000000000000000000000\n"
446 "000000000000000000\n"
447 "1111111111111111111";
449 fp = fopen("ascii2.tst", "wt");
450 fwrite(obuf, 1, sizeof(obuf), fp);
451 fclose(fp);
453 fp = fopen("ascii2.tst", "rt");
454 ok(getc(fp) == '0', "first char not 0\n");
455 memset(ibuf, 0, sizeof(ibuf));
456 i = fread(ibuf, 1, sizeof(ibuf), fp);
457 ok(i == sizeof(ibuf), "fread i %d != sizeof(ibuf)\n", i);
458 ok(0 == strncmp(ibuf, obuf+1, sizeof(ibuf)), "ibuf != obuf\n");
459 fclose(fp);
460 unlink("ascii2.tst");
463 static void test_filemodeT(void)
465 char DATA [] = {26, 't', 'e', 's' ,'t'};
466 char DATA2 [100];
467 char temppath[MAX_PATH];
468 char tempfile[MAX_PATH];
469 FILE* f;
470 size_t bytesWritten;
471 size_t bytesRead;
472 WIN32_FIND_DATAA findData;
473 HANDLE h;
475 GetTempPathA(MAX_PATH, temppath);
476 GetTempFileNameA(temppath, "", 0, tempfile);
478 f = fopen(tempfile, "w+bDT");
479 bytesWritten = fwrite(DATA, 1, sizeof(DATA), f);
480 rewind(f);
481 bytesRead = fread(DATA2, 1, sizeof(DATA2), f);
482 fclose(f);
484 ok (bytesRead == bytesWritten && bytesRead == sizeof(DATA),
485 "fopen file mode 'T' wrongly interpreted as 't'\n" );
487 h = FindFirstFileA(tempfile, &findData);
489 ok (h == INVALID_HANDLE_VALUE, "file wasn't deleted when closed.\n" );
491 if (h != INVALID_HANDLE_VALUE) FindClose(h);
494 static WCHAR* AtoW( const char* p )
496 WCHAR* buffer;
497 DWORD len = MultiByteToWideChar( CP_ACP, 0, p, -1, NULL, 0 );
498 buffer = malloc( len * sizeof(WCHAR) );
499 MultiByteToWideChar( CP_ACP, 0, p, -1, buffer, len );
500 return buffer;
503 /* Test reading in text mode when the 512'th character read is \r*/
504 static void test_readboundary(void)
506 FILE *fp;
507 char buf[513], rbuf[513];
508 int i, j;
509 for (i = 0; i < 511; i++)
511 j = (i%('~' - ' ')+ ' ');
512 buf[i] = j;
514 buf[511] = '\n';
515 buf[512] =0;
516 fp = fopen("boundary.tst", "wt");
517 fwrite(buf, 512,1,fp);
518 fclose(fp);
519 fp = fopen("boundary.tst", "rt");
520 for(i=0; i<512; i++)
522 fseek(fp,0 , SEEK_CUR);
523 rbuf[i] = fgetc(fp);
525 rbuf[512] =0;
526 fclose(fp);
527 unlink("boundary.tst");
529 ok(strcmp(buf, rbuf) == 0,"CRLF on buffer boundary failure\n");
532 static void test_fgetc( void )
534 char* tempf;
535 FILE *tempfh;
536 int ich=0xe0, ret;
538 tempf=_tempnam(".","wne");
539 tempfh = fopen(tempf,"w+");
540 fputc(ich, tempfh);
541 fputc(ich, tempfh);
542 rewind(tempfh);
543 ret = fgetc(tempfh);
544 ok(ich == ret, "First fgetc expected %x got %x\n", ich, ret);
545 ret = fgetc(tempfh);
546 ok(ich == ret, "Second fgetc expected %x got %x\n", ich, ret);
547 fclose(tempfh);
548 tempfh = fopen(tempf,"wt");
549 fputc('\n', tempfh);
550 fclose(tempfh);
551 tempfh = fopen(tempf,"wt");
552 setbuf(tempfh, NULL);
553 ret = fgetc(tempfh);
554 ok(ret == -1, "Unbuffered fgetc in text mode must failed on \\r\\n\n");
555 fclose(tempfh);
556 unlink(tempf);
557 free(tempf);
560 static void test_fputc( void )
562 char* tempf;
563 FILE *tempfh;
564 int ret;
566 tempf=_tempnam(".","wne");
567 tempfh = fopen(tempf,"wb");
568 ret = fputc(0,tempfh);
569 ok(0 == ret, "fputc(0,tempfh) expected %x got %x\n", 0, ret);
570 ret = fputc(0xff,tempfh);
571 ok(0xff == ret, "fputc(0xff,tempfh) expected %x got %x\n", 0xff, ret);
572 ret = fputc(0xffffffff,tempfh);
573 ok(0xff == ret, "fputc(0xffffffff,tempfh) expected %x got %x\n", 0xff, ret);
574 fclose(tempfh);
576 tempfh = fopen(tempf,"rb");
577 ret = fputc(0,tempfh);
578 ok(EOF == ret, "fputc(0,tempfh) on r/o file expected %x got %x\n", EOF, ret);
579 fclose(tempfh);
581 unlink(tempf);
582 free(tempf);
585 static void test_flsbuf( void )
587 char* tempf;
588 FILE *tempfh;
589 int c;
590 int ret;
591 int bufmode;
592 static const int bufmodes[] = {_IOFBF,_IONBF};
594 tempf=_tempnam(".","wne");
595 for (bufmode=0; bufmode < sizeof(bufmodes)/sizeof(bufmodes[0]); bufmode++)
597 tempfh = fopen(tempf,"wb");
598 setvbuf(tempfh,NULL,bufmodes[bufmode],2048);
599 ret = _flsbuf(0,tempfh);
600 ok(0 == ret, "_flsbuf(0,tempfh) with bufmode %x expected %x got %x\n",
601 bufmodes[bufmode], 0, ret);
602 ret = _flsbuf(0xff,tempfh);
603 ok(0xff == ret, "_flsbuf(0xff,tempfh) with bufmode %x expected %x got %x\n",
604 bufmodes[bufmode], 0xff, ret);
605 ret = _flsbuf(0xffffffff,tempfh);
606 ok(0xff == ret, "_flsbuf(0xffffffff,tempfh) with bufmode %x expected %x got %x\n",
607 bufmodes[bufmode], 0xff, ret);
608 if(tempfh->_base) {
609 fputc('x', tempfh);
610 tempfh->_cnt = -1;
611 tempfh->_base[1] = 'a';
612 ret = _flsbuf(0xab,tempfh);
613 ok(ret == 0xab, "_flsbuf(0xab,tempfh) with bufmode %x expected 0xab got %x\n",
614 bufmodes[bufmode], ret);
615 ok(tempfh->_base[1] == 'a', "tempfh->_base[1] should not be changed (%d)\n",
616 tempfh->_base[1]);
619 fclose(tempfh);
622 tempfh = fopen(tempf,"rb");
623 ret = _flsbuf(0,tempfh);
624 ok(EOF == ret, "_flsbuf(0,tempfh) on r/o file expected %x got %x\n", EOF, ret);
625 fclose(tempfh);
627 /* See bug 17123, exposed by WinAVR's make */
628 tempfh = fopen(tempf,"w");
629 ok(tempfh->_cnt == 0, "_cnt on freshly opened file was %d\n", tempfh->_cnt);
630 setbuf(tempfh, NULL);
631 ok(tempfh->_cnt == 0, "_cnt on unbuffered file was %d\n", tempfh->_cnt);
632 /* Inlined putchar sets _cnt to -1. Native seems to ignore the value... */
633 tempfh->_cnt = 1234;
634 ret = _flsbuf('Q',tempfh);
635 ok('Q' == ret, "_flsbuf('Q',tempfh) expected %x got %x\n", 'Q', ret);
636 /* ... and reset it to zero */
637 ok(tempfh->_cnt == 0, "after unbuf _flsbuf, _cnt was %d\n", tempfh->_cnt);
638 fclose(tempfh);
639 /* And just for grins, make sure the file is correct */
640 tempfh = fopen(tempf,"r");
641 c = fgetc(tempfh);
642 ok(c == 'Q', "first byte should be 'Q'\n");
643 c = fgetc(tempfh);
644 ok(c == EOF, "there should only be one byte\n");
645 fclose(tempfh);
647 unlink(tempf);
648 free(tempf);
651 static void test_fflush( void )
653 static const char obuf[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
654 char buf1[16], buf2[24];
655 char *tempf;
656 FILE *tempfh;
657 int ret;
659 tempf=_tempnam(".","wne");
661 /* Prepare the file. */
662 tempfh = fopen(tempf,"wb");
663 ok(tempfh != NULL, "Can't open test file.\n");
664 fwrite(obuf, 1, sizeof(obuf), tempfh);
665 fclose(tempfh);
667 /* Open the file for input. */
668 tempfh = fopen(tempf,"rb");
669 ok(tempfh != NULL, "Can't open test file.\n");
670 fread(buf1, 1, sizeof(buf1), tempfh);
672 /* Using fflush() on input stream is undefined in ANSI.
673 * But MSDN says that it clears input buffer. */
674 _lseek(_fileno(tempfh), 0, SEEK_SET);
675 ret = fflush(tempfh);
676 ok(ret == 0, "expected 0, got %d\n", ret);
677 memset(buf2, '?', sizeof(buf2));
678 fread(buf2, 1, sizeof(buf2), tempfh);
679 ok(memcmp(buf1, buf2, sizeof(buf1)) == 0, "Got unexpected data (%c)\n", buf2[0]);
681 /* fflush(NULL) doesn't clear input buffer. */
682 _lseek(_fileno(tempfh), 0, SEEK_SET);
683 ret = fflush(NULL);
684 ok(ret == 0, "expected 0, got %d\n", ret);
685 memset(buf2, '?', sizeof(buf2));
686 fread(buf2, 1, sizeof(buf2), tempfh);
687 ok(memcmp(buf1, buf2, sizeof(buf1)) != 0, "Got unexpected data (%c)\n", buf2[0]);
689 /* _flushall() clears input buffer. */
690 _lseek(_fileno(tempfh), 0, SEEK_SET);
691 ret = _flushall();
692 ok(ret >= 0, "unexpected ret %d\n", ret);
693 memset(buf2, '?', sizeof(buf2));
694 fread(buf2, 1, sizeof(buf2), tempfh);
695 ok(memcmp(buf1, buf2, sizeof(buf1)) == 0, "Got unexpected data (%c)\n", buf2[0]);
697 fclose(tempfh);
699 unlink(tempf);
700 free(tempf);
703 static void test_fgetwc( void )
705 #define LLEN 512
707 char* tempf;
708 FILE *tempfh;
709 static const char mytext[]= "This is test_fgetwc\r\n";
710 WCHAR wtextW[BUFSIZ+LLEN+1];
711 WCHAR *mytextW = NULL, *aptr, *wptr;
712 BOOL diff_found = FALSE;
713 int j;
714 unsigned int i;
715 LONG l;
717 tempf=_tempnam(".","wne");
718 tempfh = fopen(tempf,"wb");
719 j = 'a';
720 /* pad to almost the length of the internal buffer */
721 for (i=0; i<BUFSIZ-4; i++)
722 fputc(j,tempfh);
723 j = '\r';
724 fputc(j,tempfh);
725 j = '\n';
726 fputc(j,tempfh);
727 fputs(mytext,tempfh);
728 fclose(tempfh);
729 /* in text mode, getws/c expects multibyte characters */
730 /*currently Wine only supports plain ascii, and that is all that is tested here */
731 tempfh = fopen(tempf,"rt"); /* open in TEXT mode */
732 fgetws(wtextW,LLEN,tempfh);
733 l=ftell(tempfh);
734 ok(l==BUFSIZ-2, "ftell expected %d got %d\n", BUFSIZ-2, l);
735 fgetws(wtextW,LLEN,tempfh);
736 l=ftell(tempfh);
737 ok(l==BUFSIZ-2+strlen(mytext), "ftell expected %d got %d\n", BUFSIZ-2+lstrlenA(mytext), l);
738 mytextW = AtoW (mytext);
739 aptr = mytextW;
740 wptr = wtextW;
741 for (i=0; i<strlen(mytext)-2; i++, aptr++, wptr++)
743 diff_found |= (*aptr != *wptr);
745 ok(!(diff_found), "fgetwc difference found in TEXT mode\n");
746 ok(*wptr == '\n', "Carriage return was not skipped\n");
747 fclose(tempfh);
748 unlink(tempf);
750 tempfh = fopen(tempf,"wb");
751 j = 'a';
752 /* pad to almost the length of the internal buffer. Use an odd number of bytes
753 to test that we can read wchars that are split across the internal buffer
754 boundary */
755 for (i=0; i<BUFSIZ-3-strlen(mytext)*sizeof(WCHAR); i++)
756 fputc(j,tempfh);
757 j = '\r';
758 fputwc(j,tempfh);
759 j = '\n';
760 fputwc(j,tempfh);
761 fputws(wtextW,tempfh);
762 fputws(wtextW,tempfh);
763 fclose(tempfh);
764 /* in binary mode, getws/c expects wide characters */
765 tempfh = fopen(tempf,"rb"); /* open in BINARY mode */
766 j=(BUFSIZ-2)/sizeof(WCHAR)-strlen(mytext);
767 fgetws(wtextW,j,tempfh);
768 l=ftell(tempfh);
769 j=(j-1)*sizeof(WCHAR);
770 ok(l==j, "ftell expected %d got %d\n", j, l);
771 i=fgetc(tempfh);
772 ok(i=='a', "fgetc expected %d got %d\n", 0x61, i);
773 l=ftell(tempfh);
774 j++;
775 ok(l==j, "ftell expected %d got %d\n", j, l);
776 fgetws(wtextW,3,tempfh);
777 ok(wtextW[0]=='\r',"expected carriage return got %04hx\n", wtextW[0]);
778 ok(wtextW[1]=='\n',"expected newline got %04hx\n", wtextW[1]);
779 l=ftell(tempfh);
780 j += 4;
781 ok(l==j, "ftell expected %d got %d\n", j, l);
782 for(i=0; i<strlen(mytext); i++)
783 wtextW[i] = 0;
784 /* the first time we get the string, it should be entirely within the local buffer */
785 fgetws(wtextW,LLEN,tempfh);
786 l=ftell(tempfh);
787 j += (strlen(mytext)-1)*sizeof(WCHAR);
788 ok(l==j, "ftell expected %d got %d\n", j, l);
789 diff_found = FALSE;
790 aptr = mytextW;
791 wptr = wtextW;
792 for (i=0; i<strlen(mytext)-2; i++, aptr++, wptr++)
794 ok(*aptr == *wptr, "Char %d expected %04hx got %04hx\n", i, *aptr, *wptr);
795 diff_found |= (*aptr != *wptr);
797 ok(!(diff_found), "fgetwc difference found in BINARY mode\n");
798 ok(*wptr == '\n', "Should get newline\n");
799 for(i=0; i<strlen(mytext); i++)
800 wtextW[i] = 0;
801 /* the second time we get the string, it should cross the local buffer boundary.
802 One of the wchars should be split across the boundary */
803 fgetws(wtextW,LLEN,tempfh);
804 diff_found = FALSE;
805 aptr = mytextW;
806 wptr = wtextW;
807 for (i=0; i<strlen(mytext)-2; i++, aptr++, wptr++)
809 ok(*aptr == *wptr, "Char %d expected %04hx got %04hx\n", i, *aptr, *wptr);
810 diff_found |= (*aptr != *wptr);
812 ok(!(diff_found), "fgetwc difference found in BINARY mode\n");
813 ok(*wptr == '\n', "Should get newline\n");
815 free(mytextW);
816 fclose(tempfh);
817 unlink(tempf);
818 free(tempf);
821 static void test_fgetwc_locale(const char* text, const char* locale, int codepage)
823 char temppath[MAX_PATH], tempfile[MAX_PATH];
824 FILE *tempfh;
825 static const WCHAR wchar_text[] = { 0xfeff, 0xff1f, '!' };
826 WCHAR wtextW[BUFSIZ];
827 int ret = 0, i;
828 wint_t ch;
830 if (!setlocale(LC_CTYPE, locale))
832 win_skip("%s locale not available\n", locale);
833 return;
836 GetTempPathA(MAX_PATH, temppath);
837 GetTempFileNameA(temppath, "", 0, tempfile);
839 tempfh = fopen(tempfile, "wb");
840 ok(tempfh != NULL, "can't open tempfile\n");
841 fwrite(text, 1, strlen(text), tempfh);
842 fclose(tempfh);
844 if (codepage != 0)
846 /* mbstowcs rejects invalid multibyte sequence,
847 so we use MultiByteToWideChar here. */
848 ret = MultiByteToWideChar(codepage, 0, text, -1,
849 wtextW, sizeof(wtextW)/sizeof(wtextW[0]));
850 ok(ret > 0, "MultiByteToWideChar failed\n");
852 else
854 /* C locale */
855 const char *p;
856 for (p = text; *p != '\0'; p++)
857 wtextW[ret++] = (unsigned char)*p;
858 wtextW[ret++] = 0;
861 tempfh = fopen(tempfile, "rt");
862 ok(tempfh != NULL, "can't open tempfile\n");
864 for (i = 0; i < ret-1; i++)
866 ch = fgetwc(tempfh);
867 ok(ch == wtextW[i], "got %04hx, expected %04hx (cp%d[%d])\n", ch, wtextW[i], codepage, i);
869 ch = fgetwc(tempfh);
870 ok(ch == WEOF, "got %04hx, expected WEOF (cp%d)\n", ch, codepage);
871 fclose(tempfh);
873 tempfh = fopen(tempfile, "wb");
874 ok(tempfh != NULL, "can't open tempfile\n");
875 fwrite(wchar_text, 1, sizeof(wchar_text), tempfh);
876 fclose(tempfh);
878 tempfh = fopen(tempfile, "rb");
879 ok(tempfh != NULL, "can't open tempfile\n");
880 for (i = 0; i < sizeof(wchar_text)/sizeof(wchar_text[0]); i++)
882 ch = fgetwc(tempfh);
883 ok(ch == wchar_text[i], "got %04hx, expected %04x (cp%d[%d])\n", ch, wchar_text[i], codepage, i);
885 ch = fgetwc(tempfh);
886 ok(ch == WEOF, "got %04hx, expected WEOF (cp%d)\n", ch, codepage);
887 fclose(tempfh);
888 unlink(tempfile);
891 static void test_fgetwc_unicode(void)
893 char temppath[MAX_PATH], tempfile[MAX_PATH];
894 FILE *tempfh;
895 static const WCHAR wchar_text[] = { 0xfeff, 0xff1f, '!' };
896 char utf8_text[BUFSIZ];
897 int ret, i;
898 wint_t ch;
900 GetTempPathA(MAX_PATH, temppath);
901 GetTempFileNameA(temppath, "", 0, tempfile);
903 if (!p_fopen_s)
905 win_skip("fopen_s not available\n");
906 return;
909 tempfh = fopen(tempfile, "wb");
910 ok(tempfh != NULL, "can't open tempfile\n");
911 fwrite(wchar_text, 1, sizeof(wchar_text), tempfh);
912 fclose(tempfh);
914 tempfh = fopen(tempfile, "rt,ccs=unicode");
915 ok(tempfh != NULL, "can't open tempfile\n");
916 for (i = 1; i < sizeof(wchar_text)/sizeof(wchar_text[0]); i++)
918 ch = fgetwc(tempfh);
919 ok(ch == wchar_text[i],
920 "got %04hx, expected %04x (unicode[%d])\n", ch, wchar_text[i], i-1);
922 ch = fgetwc(tempfh);
923 ok(ch == WEOF, "got %04hx, expected WEOF (unicode)\n", ch);
924 fclose(tempfh);
926 tempfh = fopen(tempfile, "wb");
927 ok(tempfh != NULL, "can't open tempfile\n");
928 ret = WideCharToMultiByte(CP_UTF8, 0, wchar_text, sizeof(wchar_text)/sizeof(wchar_text[0]),
929 utf8_text, sizeof(utf8_text), NULL, NULL);
930 ok(ret > 0, "utf-8 conversion failed\n");
931 fwrite(utf8_text, sizeof(char), ret, tempfh);
932 fclose(tempfh);
934 tempfh = fopen(tempfile, "rt, ccs=UTF-8");
935 ok(tempfh != NULL, "can't open tempfile\n");
936 for (i = 1; i < sizeof(wchar_text)/sizeof(wchar_text[0]); i++)
938 ch = fgetwc(tempfh);
939 ok(ch == wchar_text[i],
940 "got %04hx, expected %04x (utf8[%d])\n", ch, wchar_text[i], i-1);
942 ch = fgetwc(tempfh);
943 ok(ch == WEOF, "got %04hx, expected WEOF (utf8)\n", ch);
944 fclose(tempfh);
945 unlink(temppath);
948 static void test_fputwc(void)
950 char temppath[MAX_PATH];
951 char tempfile[MAX_PATH];
952 FILE *f;
953 char buf[1024];
954 int ret;
956 GetTempPathA(MAX_PATH, temppath);
957 GetTempFileNameA(temppath, "", 0, tempfile);
959 f = fopen(tempfile, "w");
960 ret = fputwc('a', f);
961 ok(ret == 'a', "fputwc returned %x, expected 'a'\n", ret);
962 ret = fputwc('\n', f);
963 ok(ret == '\n', "fputwc returned %x, expected '\\n'\n", ret);
964 fclose(f);
966 f = fopen(tempfile, "rb");
967 ret = fread(buf, 1, sizeof(buf), f);
968 ok(ret == 3, "fread returned %d, expected 3\n", ret);
969 ok(!memcmp(buf, "a\r\n", 3), "incorrect file data\n");
970 fclose(f);
972 if(p_fopen_s) {
973 f = fopen(tempfile, "w,ccs=unicode");
974 ret = fputwc('a', f);
975 ok(ret == 'a', "fputwc returned %x, expected 'a'\n", ret);
976 ret = fputwc('\n', f);
977 ok(ret == '\n', "fputwc returned %x, expected '\\n'\n", ret);
978 fclose(f);
980 f = fopen(tempfile, "rb");
981 ret = fread(buf, 1, sizeof(buf), f);
982 ok(ret == 8, "fread returned %d, expected 8\n", ret);
983 ok(!memcmp(buf, "\xff\xfe\x61\x00\r\x00\n\x00", 8), "incorrect file data\n");
984 fclose(f);
986 f = fopen(tempfile, "w,ccs=utf-8");
987 ret = fputwc('a', f);
988 ok(ret == 'a', "fputwc returned %x, expected 'a'\n", ret);
989 ret = fputwc('\n', f);
990 ok(ret == '\n', "fputwc returned %x, expected '\\n'\n", ret);
991 fclose(f);
993 f = fopen(tempfile, "rb");
994 ret = fread(buf, 1, sizeof(buf), f);
995 ok(ret == 6, "fread returned %d, expected 6\n", ret);
996 ok(!memcmp(buf, "\xef\xbb\xbf\x61\r\n", 6), "incorrect file data\n");
997 fclose(f);
998 }else {
999 win_skip("fputwc tests on unicode files\n");
1002 _unlink(tempfile);
1005 static void test_ctrlz( void )
1007 char* tempf;
1008 FILE *tempfh;
1009 static const char mytext[]= "This is test_ctrlz";
1010 char buffer[256];
1011 int i, j;
1012 LONG l;
1014 tempf=_tempnam(".","wne");
1015 tempfh = fopen(tempf,"wb");
1016 fputs(mytext,tempfh);
1017 j = 0x1a; /* a ctrl-z character signals EOF in text mode */
1018 fputc(j,tempfh);
1019 j = '\r';
1020 fputc(j,tempfh);
1021 j = '\n';
1022 fputc(j,tempfh);
1023 j = 'a';
1024 fputc(j,tempfh);
1025 fclose(tempfh);
1026 tempfh = fopen(tempf,"rt"); /* open in TEXT mode */
1027 ok(fgets(buffer,256,tempfh) != 0,"fgets failed unexpected\n");
1028 i=strlen(buffer);
1029 j=strlen(mytext);
1030 ok(i==j, "returned string length expected %d got %d\n", j, i);
1031 j+=4; /* ftell should indicate the true end of file */
1032 l=ftell(tempfh);
1033 ok(l==j, "ftell expected %d got %d\n", j, l);
1034 ok(feof(tempfh), "did not get EOF\n");
1035 fclose(tempfh);
1037 tempfh = fopen(tempf,"rb"); /* open in BINARY mode */
1038 ok(fgets(buffer,256,tempfh) != 0,"fgets failed unexpected\n");
1039 i=strlen(buffer);
1040 j=strlen(mytext)+3; /* should get through newline */
1041 ok(i==j, "returned string length expected %d got %d\n", j, i);
1042 l=ftell(tempfh);
1043 ok(l==j, "ftell expected %d got %d\n", j, l);
1044 ok(fgets(buffer,256,tempfh) != 0,"fgets failed unexpected\n");
1045 i=strlen(buffer);
1046 ok(i==1, "returned string length expected %d got %d\n", 1, i);
1047 ok(feof(tempfh), "did not get EOF\n");
1048 fclose(tempfh);
1049 unlink(tempf);
1050 free(tempf);
1053 static void test_file_put_get( void )
1055 char* tempf;
1056 FILE *tempfh;
1057 static const char mytext[]= "This is a test_file_put_get\n";
1058 static const char dostext[]= "This is a test_file_put_get\r\n";
1059 char btext[LLEN];
1060 WCHAR wtextW[LLEN+1];
1061 WCHAR *mytextW = NULL, *aptr, *wptr;
1062 BOOL diff_found = FALSE;
1063 unsigned int i;
1065 tempf=_tempnam(".","wne");
1066 tempfh = fopen(tempf,"wt"); /* open in TEXT mode */
1067 fputs(mytext,tempfh);
1068 fclose(tempfh);
1069 tempfh = fopen(tempf,"rb"); /* open in TEXT mode */
1070 fgets(btext,LLEN,tempfh);
1071 ok( strlen(mytext) + 1 == strlen(btext),"TEXT/BINARY mode not handled for write\n");
1072 ok( btext[strlen(mytext)-1] == '\r', "CR not written\n");
1073 fclose(tempfh);
1074 tempfh = fopen(tempf,"wb"); /* open in BINARY mode */
1075 fputs(dostext,tempfh);
1076 fclose(tempfh);
1077 tempfh = fopen(tempf,"rt"); /* open in TEXT mode */
1078 fgets(btext,LLEN,tempfh);
1079 ok(strcmp(btext, mytext) == 0,"_O_TEXT read doesn't strip CR\n");
1080 fclose(tempfh);
1081 tempfh = fopen(tempf,"rb"); /* open in TEXT mode */
1082 fgets(btext,LLEN,tempfh);
1083 ok(strcmp(btext, dostext) == 0,"_O_BINARY read doesn't preserve CR\n");
1085 fclose(tempfh);
1086 tempfh = fopen(tempf,"rt"); /* open in TEXT mode */
1087 fgetws(wtextW,LLEN,tempfh);
1088 mytextW = AtoW (mytext);
1089 aptr = mytextW;
1090 wptr = wtextW;
1092 for (i=0; i<strlen(mytext); i++, aptr++, wptr++)
1094 diff_found |= (*aptr != *wptr);
1096 ok(!(diff_found), "fgetwc doesn't strip CR in TEXT mode\n");
1097 free(mytextW);
1098 fclose(tempfh);
1099 unlink(tempf);
1100 free(tempf);
1103 static void test_file_write_read( void )
1105 char* tempf;
1106 int tempfd;
1107 static const char mytext[]= "This is test_file_write_read\nsecond line\n";
1108 static const char dostext[]= "This is test_file_write_read\r\nsecond line\r\n";
1109 char btext[LLEN];
1110 int ret, i;
1112 tempf=_tempnam(".","wne");
1113 tempfd = _open(tempf,_O_CREAT|_O_TRUNC|_O_BINARY|_O_RDWR,
1114 _S_IREAD | _S_IWRITE);
1115 ok( tempfd != -1,
1116 "Can't open '%s': %d\n", tempf, errno); /* open in BINARY mode */
1117 ok(_write(tempfd,dostext,strlen(dostext)) == lstrlenA(dostext),
1118 "_write _O_BINARY bad return value\n");
1119 _close(tempfd);
1120 i = lstrlenA(mytext);
1121 tempfd = _open(tempf,_O_RDONLY|_O_BINARY,0); /* open in BINARY mode */
1122 ok(_read(tempfd,btext,i) == i,
1123 "_read _O_BINARY got bad length\n");
1124 ok( memcmp(dostext,btext,i) == 0,
1125 "problems with _O_BINARY _write / _read\n");
1126 _close(tempfd);
1127 tempfd = _open(tempf,_O_RDONLY|_O_TEXT); /* open in TEXT mode */
1128 ok(_read(tempfd,btext,i) == i-1,
1129 "_read _O_TEXT got bad length\n");
1130 ok( memcmp(mytext,btext,i-1) == 0,
1131 "problems with _O_BINARY _write / _O_TEXT _read\n");
1132 _close(tempfd);
1133 tempfd = _open(tempf,_O_CREAT|_O_TRUNC|_O_TEXT|_O_RDWR,
1134 _S_IREAD | _S_IWRITE);
1135 ok( tempfd != -1,
1136 "Can't open '%s': %d\n", tempf, errno); /* open in TEXT mode */
1137 ok(_write(tempfd,mytext,strlen(mytext)) == lstrlenA(mytext),
1138 "_write _O_TEXT bad return value\n");
1139 _close(tempfd);
1140 tempfd = _open(tempf,_O_RDONLY|_O_BINARY,0); /* open in BINARY mode */
1141 ok(_read(tempfd,btext,LLEN) == lstrlenA(dostext),
1142 "_read _O_BINARY got bad length\n");
1143 ok( memcmp(dostext,btext,strlen(dostext)) == 0,
1144 "problems with _O_TEXT _write / _O_BINARY _read\n");
1145 ok( btext[strlen(dostext)-2] == '\r', "CR not written or read\n");
1146 _close(tempfd);
1147 tempfd = _open(tempf,_O_RDONLY|_O_TEXT); /* open in TEXT mode */
1148 ok(_read(tempfd,btext,LLEN) == lstrlenA(mytext),
1149 "_read _O_TEXT got bad length\n");
1150 ok( memcmp(mytext,btext,strlen(mytext)) == 0,
1151 "problems with _O_TEXT _write / _read\n");
1152 _close(tempfd);
1154 memset(btext, 0, LLEN);
1155 tempfd = _open(tempf,_O_APPEND|_O_RDWR); /* open for APPEND in default mode */
1156 ok(tell(tempfd) == 0, "bad position %u expecting 0\n", tell(tempfd));
1157 ok(_read(tempfd,btext,LLEN) == lstrlenA(mytext), "_read _O_APPEND got bad length\n");
1158 ok( memcmp(mytext,btext,strlen(mytext)) == 0, "problems with _O_APPEND _read\n");
1159 _close(tempfd);
1161 /* Test reading only \n or \r */
1162 tempfd = _open(tempf,_O_RDONLY|_O_TEXT); /* open in TEXT mode */
1163 _lseek(tempfd, -1, FILE_END);
1164 ret = _read(tempfd,btext,LLEN);
1165 ok(ret == 1 && *btext == '\n', "_read expected 1 got bad length: %d\n", ret);
1166 _lseek(tempfd, -2, FILE_END);
1167 ret = _read(tempfd,btext,LLEN);
1168 ok(ret == 1 && *btext == '\n', "_read expected '\\n' got bad length: %d\n", ret);
1169 _lseek(tempfd, -2, FILE_END);
1170 ret = _read(tempfd,btext,1);
1171 ok(ret == 1 && *btext == '\n', "_read returned %d, buf: %d\n", ret, *btext);
1172 ret = read(tempfd,btext,1);
1173 ok(ret == 0, "_read returned %d, expected 0\n", ret);
1174 _lseek(tempfd, -3, FILE_END);
1175 ret = _read(tempfd,btext,1);
1176 ok(ret == 1 && *btext == 'e', "_read expected 'e' got \"%.*s\" bad length: %d\n", ret, btext, ret);
1177 ok(tell(tempfd) == 41, "bad position %u expecting 41\n", tell(tempfd));
1178 _lseek(tempfd, -3, FILE_END);
1179 ret = _read(tempfd,btext,2);
1180 ok(ret == 1 && *btext == 'e', "_read expected 'e' got \"%.*s\" bad length: %d\n", ret, btext, ret);
1181 ok(tell(tempfd) == 42, "bad position %u expecting 42\n", tell(tempfd));
1182 _lseek(tempfd, -3, FILE_END);
1183 ret = _read(tempfd,btext,3);
1184 ok(ret == 2 && *btext == 'e', "_read expected 'e' got \"%.*s\" bad length: %d\n", ret, btext, ret);
1185 ok(tell(tempfd) == 43, "bad position %u expecting 43\n", tell(tempfd));
1186 _close(tempfd);
1188 ret = unlink(tempf);
1189 ok( ret == 0 ,"Can't unlink '%s': %d\n", tempf, errno);
1190 free(tempf);
1192 tempf=_tempnam(".","wne");
1193 tempfd = _open(tempf, _O_CREAT|_O_TRUNC|_O_BINARY|_O_RDWR, _S_IWRITE);
1194 ok( tempfd != -1,
1195 "Can't open '%s': %d\n", tempf, errno); /* open in BINARY mode */
1196 ok(_write(tempfd,dostext,strlen(dostext)) == lstrlenA(dostext),
1197 "_write _O_BINARY bad return value\n");
1198 _close(tempfd);
1199 tempfd = _open(tempf,_O_RDONLY|_O_BINARY,0); /* open in BINARY mode */
1200 ok(_read(tempfd,btext,LLEN) == lstrlenA(dostext),
1201 "_read _O_BINARY got bad length\n");
1202 ok( memcmp(dostext,btext,strlen(dostext)) == 0,
1203 "problems with _O_BINARY _write / _read\n");
1204 ok( btext[strlen(dostext)-2] == '\r', "CR not written or read\n");
1205 _close(tempfd);
1206 tempfd = _open(tempf,_O_RDONLY|_O_TEXT); /* open in TEXT mode */
1207 ok(_read(tempfd,btext,LLEN) == lstrlenA(mytext),
1208 "_read _O_TEXT got bad length\n");
1209 ok( memcmp(mytext,btext,strlen(mytext)) == 0,
1210 "problems with _O_BINARY _write / _O_TEXT _read\n");
1211 _close(tempfd);
1213 /* test _read with single bytes. CR should be skipped and LF pulled in */
1214 tempfd = _open(tempf,_O_RDONLY|_O_TEXT); /* open in TEXT mode */
1215 for (i=0; i<strlen(mytext); i++) /* */
1217 _read(tempfd,btext, 1);
1218 ok(btext[0] == mytext[i],"_read failed at pos %d 0x%02x vs 0x%02x\n", i, btext[0], mytext[i]);
1220 while (_read(tempfd,btext, 1));
1221 _close(tempfd);
1223 /* test _read in buffered mode. Last CR should be skipped but LF not pulled in */
1224 tempfd = _open(tempf,_O_RDONLY|_O_TEXT); /* open in TEXT mode */
1225 i = _read(tempfd,btext, strlen(mytext));
1226 ok(i == strlen(mytext)-1, "_read_i %d\n", i);
1227 _close(tempfd);
1229 /* test read/write in unicode mode */
1230 if(p_fopen_s)
1232 tempfd = _open(tempf, _O_CREAT|_O_TRUNC|_O_WRONLY|_O_WTEXT, _S_IWRITE);
1233 ok(tempfd != -1, "_open failed with error: %d\n", errno);
1234 ret = _write(tempfd, "a", 1);
1235 ok(ret == -1, "_write returned %d, expected -1\n", ret);
1236 ret = _write(tempfd, "a\x00\n\x00\xff\xff", 6);
1237 ok(ret == 6, "_write returned %d, expected 6\n", ret);
1238 _close(tempfd);
1240 tempfd = _open(tempf, _O_RDONLY|_O_BINARY, 0);
1241 ok(tempfd != -1, "_open failed with error: %d\n", errno);
1242 ret = _read(tempfd, btext, sizeof(btext));
1243 ok(ret == 10, "_read returned %d, expected 10\n", ret);
1244 ok(!memcmp(btext, "\xff\xfe\x61\x00\r\x00\n\x00\xff\xff", 10), "btext is incorrect\n");
1245 _close(tempfd);
1247 tempfd = _open(tempf, _O_RDONLY|_O_WTEXT, 0);
1248 ok(tempfd != -1, "_open failed with error: %d\n", errno);
1249 errno = 0xdeadbeef;
1250 ret = _read(tempfd, btext, 3);
1251 ok(ret == -1, "_read returned %d, expected -1\n", ret);
1252 ok(errno == 22, "errno = %d\n", errno);
1253 ret = _read(tempfd, btext, sizeof(btext));
1254 ok(ret == 6, "_read returned %d, expected 6\n", ret);
1255 ok(!memcmp(btext, "\x61\x00\n\x00\xff\xff", 6), "btext is incorrect\n");
1256 _close(tempfd);
1258 tempfd = _open(tempf, _O_CREAT|_O_TRUNC|_O_WRONLY|_O_U8TEXT, _S_IWRITE);
1259 ok(tempfd != -1, "_open failed with error: %d\n", errno);
1260 errno = 0xdeadbeef;
1261 ret = _write(tempfd, "a", 1);
1262 ok(ret == -1, "_write returned %d, expected -1\n", ret);
1263 ok(errno == 22, "errno = %d\n", errno);
1264 ret = _write(tempfd, "a\x00\n\x00\x62\x00", 6);
1265 ok(ret == 6, "_write returned %d, expected 6\n", ret);
1266 _close(tempfd);
1268 tempfd = _open(tempf, _O_RDONLY|_O_BINARY, 0);
1269 ok(tempfd != -1, "_open failed with error: %d\n", errno);
1270 ret = _read(tempfd, btext, sizeof(btext));
1271 ok(ret == 7, "_read returned %d, expected 7\n", ret);
1272 ok(!memcmp(btext, "\xef\xbb\xbf\x61\r\n\x62", 7), "btext is incorrect\n");
1273 _close(tempfd);
1275 tempfd = _open(tempf, _O_RDONLY|_O_WTEXT, 0);
1276 ok(tempfd != -1, "_open failed with error: %d\n", errno);
1277 ret = _read(tempfd, btext, sizeof(btext));
1278 ok(ret == 6, "_read returned %d, expected 6\n", ret);
1279 ok(!memcmp(btext, "\x61\x00\n\x00\x62\x00", 6), "btext is incorrect\n");
1281 /* when buffer is small read sometimes fails in native implementation */
1282 lseek(tempfd, 3 /* skip bom */, SEEK_SET);
1283 ret = _read(tempfd, btext, 4);
1284 todo_wine ok(ret == -1, "_read returned %d, expected -1\n", ret);
1286 lseek(tempfd, 6, SEEK_SET);
1287 ret = _read(tempfd, btext, 2);
1288 ok(ret == 2, "_read returned %d, expected 2\n", ret);
1289 ok(!memcmp(btext, "\x62\x00", 2), "btext is incorrect\n");
1290 _close(tempfd);
1292 tempfd = _open(tempf, _O_CREAT|_O_TRUNC|_O_WRONLY|_O_BINARY, _S_IWRITE);
1293 ok(tempfd != -1, "_open failed with error: %d\n", errno);
1294 ret = _write(tempfd, "\xef\xbb\xbf\x61\xc4\x85\x62\xc5\xbc\r\r\n", 12);
1295 ok(ret == 12, "_write returned %d, expected 9\n", ret);
1296 _close(tempfd);
1298 tempfd = _open(tempf, _O_RDONLY|_O_WTEXT, 0);
1299 ok(tempfd != -1, "_open failed with error: %d\n", errno);
1300 ret = _read(tempfd, btext, sizeof(btext));
1301 ok(ret == 12, "_read returned %d, expected 12\n", ret);
1302 ok(!memcmp(btext, "\x61\x00\x05\x01\x62\x00\x7c\x01\x0d\x00\x0a\x00", 12), "btext is incorrect\n");
1304 /* test invalid utf8 sequence */
1305 lseek(tempfd, 5, SEEK_SET);
1306 ret = _read(tempfd, btext, sizeof(btext));
1307 todo_wine ok(ret == 10, "_read returned %d, expected 10\n", ret);
1308 /* invalid char should be replaced by U+FFFD in MultiByteToWideChar */
1309 todo_wine ok(!memcmp(btext, "\xfd\xff", 2), "invalid UTF8 character was not replaced by U+FFFD\n");
1310 ok(!memcmp(btext+ret-8, "\x62\x00\x7c\x01\x0d\x00\x0a\x00", 8), "btext is incorrect\n");
1311 _close(tempfd);
1313 else
1315 win_skip("unicode mode tests on file\n");
1318 ret =_chmod (tempf, _S_IREAD | _S_IWRITE);
1319 ok( ret == 0,
1320 "Can't chmod '%s' to read-write: %d\n", tempf, errno);
1321 ret = unlink(tempf);
1322 ok( ret == 0 ,"Can't unlink '%s': %d\n", tempf, errno);
1323 free(tempf);
1326 static void test_file_inherit_child(const char* fd_s)
1328 int fd = atoi(fd_s);
1329 char buffer[32];
1330 int ret;
1332 ret =write(fd, "Success", 8);
1333 ok( ret == 8, "Couldn't write in child process on %d (%s)\n", fd, strerror(errno));
1334 lseek(fd, 0, SEEK_SET);
1335 ok(read(fd, buffer, sizeof (buffer)) == 8, "Couldn't read back the data\n");
1336 ok(memcmp(buffer, "Success", 8) == 0, "Couldn't read back the data\n");
1339 static void test_file_inherit_child_no(const char* fd_s)
1341 int fd = atoi(fd_s);
1342 int ret;
1344 ret = write(fd, "Success", 8);
1345 ok( ret == -1 && errno == EBADF,
1346 "Wrong write result in child process on %d (%s)\n", fd, strerror(errno));
1349 static void create_io_inherit_block( STARTUPINFOA *startup, unsigned int count, const HANDLE *handles )
1351 static BYTE block[1024];
1352 BYTE *wxflag_ptr;
1353 HANDLE *handle_ptr;
1354 unsigned int i;
1356 startup->lpReserved2 = block;
1357 startup->cbReserved2 = sizeof(unsigned) + (sizeof(char) + sizeof(HANDLE)) * count;
1358 wxflag_ptr = block + sizeof(unsigned);
1359 handle_ptr = (HANDLE *)(wxflag_ptr + count);
1361 *(unsigned*)block = count;
1362 for (i = 0; i < count; i++)
1364 wxflag_ptr[i] = 0x81;
1365 handle_ptr[i] = handles[i];
1369 static const char *read_file( HANDLE file )
1371 static char buffer[128];
1372 DWORD ret;
1373 SetFilePointer( file, 0, NULL, FILE_BEGIN );
1374 if (!ReadFile( file, buffer, sizeof(buffer) - 1, &ret, NULL)) ret = 0;
1375 buffer[ret] = 0;
1376 return buffer;
1379 static void test_stdout_handle( STARTUPINFOA *startup, char *cmdline, HANDLE hstdout, BOOL expect_stdout,
1380 const char *descr )
1382 const char *data;
1383 HANDLE hErrorFile;
1384 SECURITY_ATTRIBUTES sa;
1385 PROCESS_INFORMATION proc;
1387 /* make file handle inheritable */
1388 sa.nLength = sizeof(sa);
1389 sa.lpSecurityDescriptor = NULL;
1390 sa.bInheritHandle = TRUE;
1392 hErrorFile = CreateFileA( "fdopen.err", GENERIC_READ|GENERIC_WRITE,
1393 FILE_SHARE_READ | FILE_SHARE_WRITE, &sa, CREATE_ALWAYS, 0, NULL );
1394 startup->dwFlags = STARTF_USESTDHANDLES;
1395 startup->hStdInput = GetStdHandle( STD_INPUT_HANDLE );
1396 startup->hStdOutput = hErrorFile;
1397 startup->hStdError = GetStdHandle( STD_ERROR_HANDLE );
1399 CreateProcessA( NULL, cmdline, NULL, NULL, TRUE,
1400 CREATE_DEFAULT_ERROR_MODE | NORMAL_PRIORITY_CLASS, NULL, NULL, startup, &proc );
1401 winetest_wait_child_process( proc.hProcess );
1403 data = read_file( hErrorFile );
1404 if (expect_stdout)
1405 ok( strcmp( data, "Success" ), "%s: Error file shouldn't contain data\n", descr );
1406 else
1407 ok( !strcmp( data, "Success" ), "%s: Wrong error data (%s)\n", descr, data );
1409 if (hstdout)
1411 data = read_file( hstdout );
1412 if (expect_stdout)
1413 ok( !strcmp( data, "Success" ), "%s: Wrong stdout data (%s)\n", descr, data );
1414 else
1415 ok( strcmp( data, "Success" ), "%s: Stdout file shouldn't contain data\n", descr );
1418 CloseHandle( hErrorFile );
1419 DeleteFileA( "fdopen.err" );
1422 static void test_file_inherit( const char* selfname )
1424 int fd;
1425 const char* arg_v[5];
1426 char buffer[16];
1427 char cmdline[MAX_PATH];
1428 STARTUPINFOA startup;
1429 SECURITY_ATTRIBUTES sa;
1430 HANDLE handles[3];
1432 fd = open ("fdopen.tst", O_CREAT | O_RDWR | O_BINARY, _S_IREAD |_S_IWRITE);
1433 ok(fd != -1, "Couldn't create test file\n");
1434 arg_v[0] = get_base_name(selfname);
1435 arg_v[1] = "tests/file.c";
1436 arg_v[2] = "inherit";
1437 arg_v[3] = buffer; sprintf(buffer, "%d", fd);
1438 arg_v[4] = 0;
1439 _spawnvp(_P_WAIT, selfname, arg_v);
1440 ok(tell(fd) == 8, "bad position %u expecting 8\n", tell(fd));
1441 lseek(fd, 0, SEEK_SET);
1442 ok(read(fd, buffer, sizeof (buffer)) == 8 && memcmp(buffer, "Success", 8) == 0, "Couldn't read back the data\n");
1443 close (fd);
1444 ok(unlink("fdopen.tst") == 0, "Couldn't unlink\n");
1446 fd = open ("fdopen.tst", O_CREAT | O_RDWR | O_BINARY | O_NOINHERIT, _S_IREAD |_S_IWRITE);
1447 ok(fd != -1, "Couldn't create test file\n");
1448 arg_v[1] = "tests/file.c";
1449 arg_v[2] = "inherit_no";
1450 arg_v[3] = buffer; sprintf(buffer, "%d", fd);
1451 arg_v[4] = 0;
1452 _spawnvp(_P_WAIT, selfname, arg_v);
1453 ok(tell(fd) == 0, "bad position %u expecting 0\n", tell(fd));
1454 ok(read(fd, buffer, sizeof (buffer)) == 0, "Found unexpected data (%s)\n", buffer);
1455 close (fd);
1456 ok(unlink("fdopen.tst") == 0, "Couldn't unlink\n");
1458 /* make file handle inheritable */
1459 sa.nLength = sizeof(sa);
1460 sa.lpSecurityDescriptor = NULL;
1461 sa.bInheritHandle = TRUE;
1462 sprintf(cmdline, "%s file inherit 1", selfname);
1464 /* init an empty Reserved2, which should not be recognized as inherit-block */
1465 ZeroMemory(&startup, sizeof(startup));
1466 startup.cb = sizeof(startup);
1467 create_io_inherit_block( &startup, 0, NULL );
1468 test_stdout_handle( &startup, cmdline, 0, FALSE, "empty block" );
1470 /* test with valid inheritblock */
1471 handles[0] = GetStdHandle( STD_INPUT_HANDLE );
1472 handles[1] = CreateFileA( "fdopen.tst", GENERIC_READ|GENERIC_WRITE,
1473 FILE_SHARE_READ | FILE_SHARE_WRITE, &sa, CREATE_ALWAYS, 0, NULL );
1474 handles[2] = GetStdHandle( STD_ERROR_HANDLE );
1475 create_io_inherit_block( &startup, 3, handles );
1476 test_stdout_handle( &startup, cmdline, handles[1], TRUE, "valid block" );
1477 CloseHandle( handles[1] );
1478 DeleteFileA("fdopen.tst");
1480 /* test inherit block starting with unsigned zero */
1481 handles[1] = CreateFileA( "fdopen.tst", GENERIC_READ|GENERIC_WRITE,
1482 FILE_SHARE_READ | FILE_SHARE_WRITE, &sa, CREATE_ALWAYS, 0, NULL );
1483 create_io_inherit_block( &startup, 3, handles );
1484 *(unsigned int *)startup.lpReserved2 = 0;
1485 test_stdout_handle( &startup, cmdline, handles[1], FALSE, "zero count block" );
1486 CloseHandle( handles[1] );
1487 DeleteFileA("fdopen.tst");
1489 /* test inherit block with smaller size */
1490 handles[1] = CreateFileA( "fdopen.tst", GENERIC_READ|GENERIC_WRITE,
1491 FILE_SHARE_READ | FILE_SHARE_WRITE, &sa, CREATE_ALWAYS, 0, NULL );
1492 create_io_inherit_block( &startup, 3, handles );
1493 startup.cbReserved2 -= 3;
1494 test_stdout_handle( &startup, cmdline, handles[1], TRUE, "small size block" );
1495 CloseHandle( handles[1] );
1496 DeleteFileA("fdopen.tst");
1498 /* test inherit block with even smaller size */
1499 handles[1] = CreateFileA( "fdopen.tst", GENERIC_READ|GENERIC_WRITE,
1500 FILE_SHARE_READ | FILE_SHARE_WRITE, &sa, CREATE_ALWAYS, 0, NULL );
1501 create_io_inherit_block( &startup, 3, handles );
1502 startup.cbReserved2 = sizeof(unsigned int) + sizeof(HANDLE) + sizeof(char);
1503 test_stdout_handle( &startup, cmdline, handles[1], FALSE, "smaller size block" );
1504 CloseHandle( handles[1] );
1505 DeleteFileA("fdopen.tst");
1507 /* test inherit block with larger size */
1508 handles[1] = CreateFileA( "fdopen.tst", GENERIC_READ|GENERIC_WRITE,
1509 FILE_SHARE_READ | FILE_SHARE_WRITE, &sa, CREATE_ALWAYS, 0, NULL );
1510 create_io_inherit_block( &startup, 3, handles );
1511 startup.cbReserved2 += 7;
1512 test_stdout_handle( &startup, cmdline, handles[1], TRUE, "large size block" );
1513 CloseHandle( handles[1] );
1514 DeleteFileA("fdopen.tst");
1517 static void test_tmpnam( void )
1519 char name[MAX_PATH] = "abc";
1520 char *res;
1522 res = tmpnam(NULL);
1523 ok(res != NULL, "tmpnam returned NULL\n");
1524 ok(res[0] == '\\', "first character is not a backslash\n");
1525 ok(strchr(res+1, '\\') == 0, "file not in the root directory\n");
1526 ok(res[strlen(res)-1] == '.', "first call - last character is not a dot\n");
1528 res = tmpnam(name);
1529 ok(res != NULL, "tmpnam returned NULL\n");
1530 ok(res == name, "supplied buffer was not used\n");
1531 ok(res[0] == '\\', "first character is not a backslash\n");
1532 ok(strchr(res+1, '\\') == 0, "file not in the root directory\n");
1533 ok(res[strlen(res)-1] != '.', "second call - last character is a dot\n");
1536 static void test_chsize( void )
1538 int fd;
1539 LONG cur, pos, count;
1540 char temptext[] = "012345678";
1541 char *tempfile = _tempnam( ".", "tst" );
1543 ok( tempfile != NULL, "Couldn't create test file: %s\n", tempfile );
1545 fd = _open( tempfile, _O_CREAT|_O_TRUNC|_O_RDWR, _S_IREAD|_S_IWRITE );
1546 ok( fd > 0, "Couldn't open test file\n" );
1548 count = _write( fd, temptext, sizeof(temptext) );
1549 ok( count > 0, "Couldn't write to test file\n" );
1551 /* get current file pointer */
1552 cur = _lseek( fd, 0, SEEK_CUR );
1554 /* make the file smaller */
1555 ok( _chsize( fd, sizeof(temptext) / 2 ) == 0, "_chsize() failed\n" );
1557 pos = _lseek( fd, 0, SEEK_CUR );
1558 ok( cur == pos, "File pointer changed from: %d to: %d\n", cur, pos );
1559 ok( _filelength( fd ) == sizeof(temptext) / 2, "Wrong file size\n" );
1561 /* enlarge the file */
1562 ok( _chsize( fd, sizeof(temptext) * 2 ) == 0, "_chsize() failed\n" );
1564 pos = _lseek( fd, 0, SEEK_CUR );
1565 ok( cur == pos, "File pointer changed from: %d to: %d\n", cur, pos );
1566 ok( _filelength( fd ) == sizeof(temptext) * 2, "Wrong file size\n" );
1568 _close( fd );
1569 _unlink( tempfile );
1570 free( tempfile );
1573 static void test_fopen_fclose_fcloseall( void )
1575 char fname1[] = "empty1";
1576 char fname2[] = "empty2";
1577 char fname3[] = "empty3";
1578 FILE *stream1, *stream2, *stream3, *stream4;
1579 int ret, numclosed;
1581 /* testing fopen() */
1582 stream1 = fopen(fname1, "w+");
1583 ok(stream1 != NULL, "The file '%s' was not opened\n", fname1);
1584 stream2 = fopen(fname2, "w ");
1585 ok(stream2 != NULL, "The file '%s' was not opened\n", fname2 );
1586 _unlink(fname3);
1587 stream3 = fopen(fname3, "r");
1588 ok(stream3 == NULL, "The file '%s' shouldn't exist before\n", fname3 );
1589 stream3 = fopen(fname3, "w+");
1590 ok(stream3 != NULL, "The file '%s' should be opened now\n", fname3 );
1591 errno = 0xfaceabad;
1592 stream4 = fopen("", "w+");
1593 ok(stream4 == NULL && (errno == EINVAL || errno == ENOENT),
1594 "filename is empty, errno = %d (expected 2 or 22)\n", errno);
1595 errno = 0xfaceabad;
1596 stream4 = fopen(NULL, "w+");
1597 ok(stream4 == NULL && (errno == EINVAL || errno == ENOENT),
1598 "filename is NULL, errno = %d (expected 2 or 22)\n", errno);
1600 /* testing fclose() */
1601 ret = fclose(stream2);
1602 ok(ret == 0, "The file '%s' was not closed\n", fname2);
1603 ret = fclose(stream3);
1604 ok(ret == 0, "The file '%s' was not closed\n", fname3);
1605 ret = fclose(stream2);
1606 ok(ret == EOF, "Closing file '%s' returned %d\n", fname2, ret);
1607 ret = fclose(stream3);
1608 ok(ret == EOF, "Closing file '%s' returned %d\n", fname3, ret);
1610 /* testing fcloseall() */
1611 numclosed = _fcloseall();
1612 /* fname1 should be closed here */
1613 ok(numclosed == 1, "Number of files closed by fcloseall(): %u\n", numclosed);
1614 numclosed = _fcloseall();
1615 ok(numclosed == 0, "Number of files closed by fcloseall(): %u\n", numclosed);
1617 ok(_unlink(fname1) == 0, "Couldn't unlink file named '%s'\n", fname1);
1618 ok(_unlink(fname2) == 0, "Couldn't unlink file named '%s'\n", fname2);
1619 ok(_unlink(fname3) == 0, "Couldn't unlink file named '%s'\n", fname3);
1622 static void test_fopen_s( void )
1624 const char name[] = "empty1";
1625 char buff[16];
1626 unsigned char *ubuff = (unsigned char*)buff;
1627 FILE *file;
1628 int ret;
1629 int len;
1631 if (!p_fopen_s)
1633 win_skip("Skipping fopen_s test\n");
1634 return;
1636 /* testing fopen_s */
1637 ret = p_fopen_s(&file, name, "w");
1638 ok(ret == 0, "fopen_s failed with %d\n", ret);
1639 ok(file != 0, "fopen_s failed to return value\n");
1640 fwrite(name, sizeof(name), 1, file);
1642 ret = fclose(file);
1643 ok(ret != EOF, "File failed to close\n");
1645 file = fopen(name, "r");
1646 ok(file != 0, "fopen failed\n");
1647 len = fread(buff, 1, sizeof(name), file);
1648 ok(len == sizeof(name), "File length is %d\n", len);
1649 buff[sizeof(name)] = '\0';
1650 ok(strcmp(name, buff) == 0, "File content mismatch! Got %s, expected %s\n", buff, name);
1652 ret = fclose(file);
1653 ok(ret != EOF, "File failed to close\n");
1655 ret = p_fopen_s(&file, name, "w, ccs=UNIcode");
1656 ok(ret == 0, "fopen_s failed with %d\n", ret);
1657 ret = fwrite("a", 1, 2, file);
1658 ok(ret == 2, "fwrite returned %d\n", ret);
1659 fclose(file);
1661 ret = p_fopen_s(&file, name, "r");
1662 ok(ret == 0, "fopen_s failed with %d\n", ret);
1663 len = fread(buff, 1, 2, file);
1664 ok(len == 2, "len = %d\n", len);
1665 ok(ubuff[0]==0xff && ubuff[1]==0xfe, "buff[0]=%02x, buff[1]=%02x\n",
1666 ubuff[0], ubuff[1]);
1667 fclose(file);
1669 ret = p_fopen_s(&file, name, "r,ccs=unicode");
1670 ok(ret == 0, "fopen_s failed with %d\n", ret);
1671 len = fread(buff, 1, 2, file);
1672 ok(len == 2, "len = %d\n", len);
1673 ok(ubuff[0]=='a' && ubuff[1]==0, "buff[0]=%02x, buff[1]=%02x\n",
1674 ubuff[0], ubuff[1]);
1675 fclose(file);
1677 ret = p_fopen_s(&file, name, "r,ccs=utf-16le");
1678 ok(ret == 0, "fopen_s failed with %d\n", ret);
1679 len = fread(buff, 1, 2, file);
1680 ok(len == 2, "len = %d\n", len);
1681 ok(ubuff[0]=='a' && ubuff[1]==0, "buff[0]=%02x, buff[1]=%02x\n",
1682 ubuff[0], ubuff[1]);
1683 fclose(file);
1685 ret = p_fopen_s(&file, name, "r,ccs=utf-8");
1686 ok(ret == 0, "fopen_s failed with %d\n", ret);
1687 len = fread(buff, 1, 2, file);
1688 ok(len == 2, "len = %d\n", len);
1689 ok(ubuff[0]=='a' && ubuff[1]==0, "buff[0]=%02x, buff[1]=%02x\n",
1690 ubuff[0], ubuff[1]);
1691 fclose(file);
1693 ret = p_fopen_s(&file, name, "w,ccs=utf-16le");
1694 ok(ret == 0, "fopen_s failed with %d\n", ret);
1695 fclose(file);
1697 ret = p_fopen_s(&file, name, "r");
1698 ok(ret == 0, "fopen_s failed with %d\n", ret);
1699 len = fread(buff, 1, 3, file);
1700 ok(len == 2, "len = %d\n", len);
1701 ok(ubuff[0]==0xff && ubuff[1]==0xfe, "buff[0]=%02x, buff[1]=%02x\n",
1702 ubuff[0], ubuff[1]);
1703 fclose(file);
1705 ret = p_fopen_s(&file, name, "w,ccs=utf-8");
1706 ok(ret == 0, "fopen_s failed with %d\n", ret);
1707 fclose(file);
1709 ret = p_fopen_s(&file, name, "r");
1710 ok(ret == 0, "fopen_s failed with %d\n", ret);
1711 len = fread(buff, 1, 4, file);
1712 ok(len == 3, "len = %d\n", len);
1713 ok(ubuff[0]==0xef && ubuff[1]==0xbb && ubuff[2]==0xbf,
1714 "buff[0]=%02x, buff[1]=%02x, buff[2]=%02x\n",
1715 ubuff[0], ubuff[1], ubuff[2]);
1716 fclose(file);
1718 ok(_unlink(name) == 0, "Couldn't unlink file named '%s'\n", name);
1721 static void test__wfopen_s( void )
1723 const char name[] = "empty1";
1724 const WCHAR wname[] = {
1725 'e','m','p','t','y','1',0
1727 const WCHAR wmode[] = {
1728 'w',0
1730 char buff[16];
1731 FILE *file;
1732 int ret;
1733 int len;
1735 if (!p__wfopen_s)
1737 win_skip("Skipping _wfopen_s test\n");
1738 return;
1740 /* testing _wfopen_s */
1741 ret = p__wfopen_s(&file, wname, wmode);
1742 ok(ret == 0, "_wfopen_s failed with %d\n", ret);
1743 ok(file != 0, "_wfopen_s failed to return value\n");
1744 fwrite(name, sizeof(name), 1, file);
1746 ret = fclose(file);
1747 ok(ret != EOF, "File failed to close\n");
1749 file = fopen(name, "r");
1750 ok(file != 0, "fopen failed\n");
1751 len = fread(buff, 1, sizeof(name), file);
1752 ok(len == sizeof(name), "File length is %d\n", len);
1753 buff[sizeof(name)] = '\0';
1754 ok(strcmp(name, buff) == 0, "File content mismatch! Got %s, expected %s\n", buff, name);
1756 ret = fclose(file);
1757 ok(ret != EOF, "File failed to close\n");
1759 ok(_unlink(name) == 0, "Couldn't unlink file named '%s'\n", name);
1762 static void test_setmode(void)
1764 const char name[] = "empty1";
1765 int fd, ret;
1767 if(!p_fopen_s) {
1768 win_skip("unicode file modes are not available, skipping setmode tests\n");
1769 return;
1772 fd = _open(name, _O_CREAT|_O_WRONLY, _S_IWRITE);
1773 ok(fd != -1, "failed to open file\n");
1775 errno = 0xdeadbeef;
1776 ret = _setmode(fd, 0xffffffff);
1777 ok(ret == -1, "_setmode returned %x, expected -1\n", ret);
1778 ok(errno == EINVAL, "errno = %d\n", errno);
1780 errno = 0xdeadbeef;
1781 ret = _setmode(fd, 0);
1782 ok(ret == -1, "_setmode returned %x, expected -1\n", ret);
1783 ok(errno == EINVAL, "errno = %d\n", errno);
1785 errno = 0xdeadbeef;
1786 ret = _setmode(fd, _O_BINARY|_O_TEXT);
1787 ok(ret == -1, "_setmode returned %x, expected -1\n", ret);
1788 ok(errno == EINVAL, "errno = %d\n", errno);
1790 errno = 0xdeadbeef;
1791 ret = _setmode(fd, _O_WTEXT|_O_U16TEXT);
1792 ok(ret == -1, "_setmode returned %x, expected -1\n", ret);
1793 ok(errno == EINVAL, "errno = %d\n", errno);
1795 ret = _setmode(fd, _O_BINARY);
1796 ok(ret == _O_TEXT, "_setmode returned %x, expected _O_TEXT\n", ret);
1798 ret = _setmode(fd, _O_WTEXT);
1799 ok(ret == _O_BINARY, "_setmode returned %x, expected _O_BINARY\n", ret);
1801 ret = _setmode(fd, _O_TEXT);
1802 ok(ret == _O_WTEXT, "_setmode returned %x, expected _O_WTEXT\n", ret);
1804 ret = _setmode(fd, _O_U16TEXT);
1805 ok(ret == _O_TEXT, "_setmode returned %x, expected _O_TEXT\n", ret);
1807 ret = _setmode(fd, _O_U8TEXT);
1808 ok(ret == _O_WTEXT, "_setmode returned %x, expected _O_WTEXT\n", ret);
1810 ret = _setmode(fd, _O_TEXT);
1811 ok(ret == _O_WTEXT, "_setmode returned %x, expected _O_WTEXT\n", ret);
1813 _close(fd);
1814 _unlink(name);
1817 static void test_get_osfhandle(void)
1819 int fd;
1820 char fname[] = "t_get_osfhanle";
1821 DWORD bytes_written;
1822 HANDLE handle;
1824 fd = _sopen(fname, _O_CREAT|_O_RDWR, _SH_DENYRW, _S_IREAD | _S_IWRITE);
1825 handle = (HANDLE)_get_osfhandle(fd);
1826 WriteFile(handle, "bar", 3, &bytes_written, NULL);
1827 _close(fd);
1828 fd = _open(fname, _O_RDONLY, 0);
1829 ok(fd != -1, "Couldn't open '%s' after _get_osfhandle()\n", fname);
1831 _close(fd);
1832 _unlink(fname);
1835 static void test_setmaxstdio(void)
1837 ok(2048 == _setmaxstdio(2048),"_setmaxstdio returned %d instead of 2048\n",_setmaxstdio(2048));
1838 ok(-1 == _setmaxstdio(2049),"_setmaxstdio returned %d instead of -1\n",_setmaxstdio(2049));
1841 static void test_stat(void)
1843 int fd;
1844 int pipes[2];
1845 int ret;
1846 struct stat buf;
1848 /* Tests for a file */
1849 fd = open("stat.tst", O_WRONLY | O_CREAT | O_BINARY, _S_IREAD |_S_IWRITE);
1850 if (fd >= 0)
1852 ret = fstat(fd, &buf);
1853 ok(!ret, "fstat failed: errno=%d\n", errno);
1854 ok((buf.st_mode & _S_IFMT) == _S_IFREG, "bad format = %06o\n", buf.st_mode);
1855 ok((buf.st_mode & 0777) == 0666, "bad st_mode = %06o\n", buf.st_mode);
1856 ok(buf.st_dev == 0, "st_dev is %d, expected 0\n", buf.st_dev);
1857 ok(buf.st_dev == buf.st_rdev, "st_dev (%d) and st_rdev (%d) differ\n", buf.st_dev, buf.st_rdev);
1858 ok(buf.st_nlink == 1, "st_nlink is %d, expected 1\n", buf.st_nlink);
1859 ok(buf.st_size == 0, "st_size is %d, expected 0\n", buf.st_size);
1861 ret = stat("stat.tst", &buf);
1862 ok(!ret, "stat failed: errno=%d\n", errno);
1863 ok((buf.st_mode & _S_IFMT) == _S_IFREG, "bad format = %06o\n", buf.st_mode);
1864 ok((buf.st_mode & 0777) == 0666, "bad st_mode = %06o\n", buf.st_mode);
1865 ok(buf.st_dev == buf.st_rdev, "st_dev (%d) and st_rdev (%d) differ\n", buf.st_dev, buf.st_rdev);
1866 ok(buf.st_nlink == 1, "st_nlink is %d, expected 1\n", buf.st_nlink);
1867 ok(buf.st_size == 0, "st_size is %d, expected 0\n", buf.st_size);
1869 errno = 0xdeadbeef;
1870 ret = stat("stat.tst\\", &buf);
1871 ok(ret == -1, "stat returned %d\n", ret);
1872 ok(errno == ENOENT, "errno = %d\n", errno);
1874 close(fd);
1875 remove("stat.tst");
1877 else
1878 skip("open failed with errno %d\n", errno);
1880 /* Tests for a char device */
1881 if (_dup2(0, 10) == 0)
1883 ret = fstat(10, &buf);
1884 ok(!ret, "fstat(stdin) failed: errno=%d\n", errno);
1885 if ((buf.st_mode & _S_IFMT) == _S_IFCHR)
1887 ok(buf.st_mode == _S_IFCHR, "bad st_mode=%06o\n", buf.st_mode);
1888 ok(buf.st_dev == 10, "st_dev is %d, expected 10\n", buf.st_dev);
1889 ok(buf.st_rdev == 10, "st_rdev is %d, expected 10\n", buf.st_rdev);
1890 ok(buf.st_nlink == 1, "st_nlink is %d, expected 1\n", buf.st_nlink);
1892 else
1893 skip("stdin is not a char device? st_mode=%06o\n", buf.st_mode);
1894 close(10);
1896 else
1897 skip("_dup2 failed with errno %d\n", errno);
1899 /* Tests for pipes */
1900 if (_pipe(pipes, 1024, O_BINARY) == 0)
1902 ret = fstat(pipes[0], &buf);
1903 ok(!ret, "fstat(pipe) failed: errno=%d\n", errno);
1904 ok(buf.st_mode == _S_IFIFO, "bad st_mode=%06o\n", buf.st_mode);
1905 ok(buf.st_dev == pipes[0], "st_dev is %d, expected %d\n", buf.st_dev, pipes[0]);
1906 ok(buf.st_rdev == pipes[0], "st_rdev is %d, expected %d\n", buf.st_rdev, pipes[0]);
1907 ok(buf.st_nlink == 1, "st_nlink is %d, expected 1\n", buf.st_nlink);
1908 close(pipes[0]);
1909 close(pipes[1]);
1911 else
1912 skip("pipe failed with errno %d\n", errno);
1914 /* Tests for directory */
1915 if(mkdir("stat.tst") == 0)
1917 ret = stat("stat.tst ", &buf);
1918 ok(!ret, "stat(directory) failed: errno=%d\n", errno);
1919 ok((buf.st_mode & _S_IFMT) == _S_IFDIR, "bad format = %06o\n", buf.st_mode);
1920 ok((buf.st_mode & 0777) == 0777, "bad st_mode = %06o\n", buf.st_mode);
1921 ok(buf.st_dev == buf.st_rdev, "st_dev (%d) and st_rdev (%d) differ\n", buf.st_dev, buf.st_rdev);
1922 ok(buf.st_nlink == 1, "st_nlink is %d, expected 1\n", buf.st_nlink);
1924 errno = 0xdeadbeef;
1925 ret = stat("stat.tst\\ ", &buf);
1926 ok(ret == -1, "stat returned %d\n", ret);
1927 ok(errno == ENOENT, "errno = %d\n", errno);
1928 rmdir( "stat.tst" );
1930 else
1931 skip("mkdir failed with errno %d\n", errno);
1933 errno = 0xdeadbeef;
1934 ret = stat("c:", &buf);
1935 ok(ret == -1, "stat returned %d\n", ret);
1936 ok(errno == ENOENT, "errno = %d\n", errno);
1938 ret = stat("c:/", &buf);
1939 ok(!ret, "stat returned %d\n", ret);
1940 ok(buf.st_dev == 2, "st_dev = %d\n", buf.st_dev);
1941 ok(buf.st_rdev == 2, "st_rdev = %d\n", buf.st_rdev);
1944 static const char* pipe_string="Hello world";
1946 /* How many messages to transfer over the pipe */
1947 #define N_TEST_MESSAGES 3
1949 static void test_pipes_child(int argc, char** args)
1951 int fd;
1952 int nwritten;
1953 int i;
1955 if (argc < 5)
1957 ok(0, "not enough parameters: %d\n", argc);
1958 return;
1961 fd=atoi(args[3]);
1962 i=close(fd);
1963 ok(!i, "unable to close %d: %d\n", fd, errno);
1965 fd=atoi(args[4]);
1967 for (i=0; i<N_TEST_MESSAGES; i++) {
1968 nwritten=write(fd, pipe_string, strlen(pipe_string));
1969 ok(nwritten == strlen(pipe_string), "i %d, expected to write '%s' wrote %d\n", i, pipe_string, nwritten);
1970 /* let other process wake up so they can show off their "keep reading until EOF" behavior */
1971 if (i < N_TEST_MESSAGES-1)
1972 Sleep(100);
1975 i=close(fd);
1976 ok(!i, "unable to close %d: %d\n", fd, errno);
1979 static void test_pipes(const char* selfname)
1981 int pipes[2];
1982 char str_fdr[12], str_fdw[12];
1983 FILE* file;
1984 const char* arg_v[6];
1985 char buf[4096];
1986 char expected[4096];
1987 int r;
1988 int i;
1990 /* Test reading from a pipe with read() */
1991 if (_pipe(pipes, 1024, O_BINARY) < 0)
1993 ok(0, "pipe failed with errno %d\n", errno);
1994 return;
1997 arg_v[0] = get_base_name(selfname);
1998 arg_v[1] = "tests/file.c";
1999 arg_v[2] = "pipes";
2000 arg_v[3] = str_fdr; sprintf(str_fdr, "%d", pipes[0]);
2001 arg_v[4] = str_fdw; sprintf(str_fdw, "%d", pipes[1]);
2002 arg_v[5] = NULL;
2003 proc_handles[0] = (HANDLE)_spawnvp(_P_NOWAIT, selfname, arg_v);
2004 i=close(pipes[1]);
2005 ok(!i, "unable to close %d: %d\n", pipes[1], errno);
2007 for (i=0; i<N_TEST_MESSAGES; i++) {
2008 r=read(pipes[0], buf, sizeof(buf)-1);
2009 ok(r == strlen(pipe_string), "i %d, got %d\n", i, r);
2010 if (r > 0)
2011 buf[r]='\0';
2012 ok(strcmp(buf, pipe_string) == 0, "expected to read '%s', got '%s'\n", pipe_string, buf);
2015 r=read(pipes[0], buf, sizeof(buf)-1);
2016 ok(r == 0, "expected to read 0 bytes, got %d\n", r);
2017 i=close(pipes[0]);
2018 ok(!i, "unable to close %d: %d\n", pipes[0], errno);
2020 /* Test reading from a pipe with fread() */
2021 if (_pipe(pipes, 1024, O_BINARY) < 0)
2023 ok(0, "pipe failed with errno %d\n", errno);
2024 return;
2027 arg_v[1] = "tests/file.c";
2028 arg_v[2] = "pipes";
2029 arg_v[3] = str_fdr; sprintf(str_fdr, "%d", pipes[0]);
2030 arg_v[4] = str_fdw; sprintf(str_fdw, "%d", pipes[1]);
2031 arg_v[5] = NULL;
2032 proc_handles[1] = (HANDLE)_spawnvp(_P_NOWAIT, selfname, arg_v);
2033 i=close(pipes[1]);
2034 ok(!i, "unable to close %d: %d\n", pipes[1], errno);
2035 file=fdopen(pipes[0], "r");
2037 /* In blocking mode, fread will keep calling read() until it gets
2038 * enough bytes, or EOF, even on Unix. (If this were a Unix terminal
2039 * in cooked mode instead of a pipe, it would also stop on EOL.)
2041 expected[0] = 0;
2042 for (i=0; i<N_TEST_MESSAGES; i++)
2043 strcat(expected, pipe_string);
2044 r=fread(buf, 1, sizeof(buf)-1, file);
2045 ok(r == strlen(expected), "fread() returned %d: ferror=%d\n", r, ferror(file));
2046 if (r > 0)
2047 buf[r]='\0';
2048 ok(strcmp(buf, expected) == 0, "got '%s' expected '%s'\n", buf, expected);
2050 /* Let child close the file before we read, so we can sense EOF reliably */
2051 Sleep(100);
2052 r=fread(buf, 1, sizeof(buf)-1, file);
2053 ok(r == 0, "fread() returned %d instead of 0\n", r);
2054 ok(ferror(file) == 0, "got ferror() = %d\n", ferror(file));
2055 ok(feof(file), "feof() is false!\n");
2057 i=fclose(file);
2058 ok(!i, "unable to close the pipe: %d\n", errno);
2060 /* test \r handling when it's the last character read */
2061 if (_pipe(pipes, 1024, O_BINARY) < 0)
2063 ok(0, "pipe failed with errno %d\n", errno);
2064 return;
2066 r = write(pipes[1], "\r\n\rab\r\n", 7);
2067 ok(r == 7, "write returned %d, errno = %d\n", r, errno);
2068 setmode(pipes[0], O_TEXT);
2069 r = read(pipes[0], buf, 1);
2070 ok(r == 1, "read returned %d, expected 1\n", r);
2071 ok(buf[0] == '\n', "buf[0] = %x, expected '\\n'\n", buf[0]);
2072 r = read(pipes[0], buf, 1);
2073 ok(r == 1, "read returned %d, expected 1\n", r);
2074 ok(buf[0] == '\r', "buf[0] = %x, expected '\\r'\n", buf[0]);
2075 r = read(pipes[0], buf, 1);
2076 ok(r == 1, "read returned %d, expected 1\n", r);
2077 ok(buf[0] == 'a', "buf[0] = %x, expected 'a'\n", buf[0]);
2078 r = read(pipes[0], buf, 2);
2079 ok(r == 2, "read returned %d, expected 1\n", r);
2080 ok(buf[0] == 'b', "buf[0] = %x, expected 'b'\n", buf[0]);
2081 ok(buf[1] == '\n', "buf[1] = %x, expected '\\n'\n", buf[1]);
2083 if (p_fopen_s)
2085 /* test utf16 read with insufficient data */
2086 r = write(pipes[1], "a\0b", 3);
2087 ok(r == 3, "write returned %d, errno = %d\n", r, errno);
2088 buf[2] = 'z';
2089 buf[3] = 'z';
2090 setmode(pipes[0], _O_WTEXT);
2091 r = read(pipes[0], buf, 4);
2092 ok(r == 2, "read returned %d, expected 2\n", r);
2093 ok(!memcmp(buf, "a\0bz", 4), "read returned incorrect data\n");
2094 r = write(pipes[1], "\0", 1);
2095 ok(r == 1, "write returned %d, errno = %d\n", r, errno);
2096 buf[0] = 'z';
2097 buf[1] = 'z';
2098 r = read(pipes[0], buf, 2);
2099 ok(r == 0, "read returned %d, expected 0\n", r);
2100 ok(!memcmp(buf, "\0z", 2), "read returned incorrect data\n");
2102 else
2104 win_skip("unicode mode tests on pipe\n");
2107 close(pipes[1]);
2108 close(pipes[0]);
2111 static void test_unlink(void)
2113 FILE* file;
2114 ok(mkdir("test_unlink") == 0, "unable to create test dir\n");
2115 file = fopen("test_unlink\\empty", "w");
2116 ok(file != NULL, "unable to create test file\n");
2117 if(file)
2118 fclose(file);
2119 ok(_unlink("test_unlink") != 0, "unlinking a non-empty directory must fail\n");
2120 unlink("test_unlink\\empty");
2121 rmdir("test_unlink");
2124 static void test_dup2(void)
2126 ok(-1 == _dup2(0, -1), "expected _dup2 to fail when second arg is negative\n" );
2129 static void test_stdin(void)
2131 HANDLE stdinh = GetStdHandle(STD_INPUT_HANDLE);
2132 int stdin_dup, fd;
2133 HANDLE h;
2134 DWORD r;
2136 stdin_dup = _dup(STDIN_FILENO);
2137 ok(stdin_dup != -1, "_dup(STDIN_FILENO) failed\n");
2139 ok(stdinh == (HANDLE)_get_osfhandle(STDIN_FILENO),
2140 "GetStdHandle(STD_INPUT_HANDLE) != _get_osfhandle(STDIN_FILENO)\n");
2142 r = SetStdHandle(STD_INPUT_HANDLE, INVALID_HANDLE_VALUE);
2143 ok(r == TRUE, "SetStdHandle returned %x, expected TRUE\n", r);
2144 h = GetStdHandle(STD_INPUT_HANDLE);
2145 ok(h == INVALID_HANDLE_VALUE, "h = %p\n", h);
2147 close(STDIN_FILENO);
2148 h = GetStdHandle(STD_INPUT_HANDLE);
2149 ok(h == NULL, "h != NULL\n");
2151 fd = open("stdin.tst", O_WRONLY | O_CREAT, _S_IREAD |_S_IWRITE);
2152 ok(fd != -1, "open failed\n");
2153 ok(fd == STDIN_FILENO, "fd = %d, expected STDIN_FILENO\n", fd);
2154 h = GetStdHandle(STD_INPUT_HANDLE);
2155 ok(h != NULL, "h == NULL\n");
2156 close(fd);
2157 unlink("stdin.tst");
2159 r = _dup2(stdin_dup, STDIN_FILENO);
2160 ok(r != -1, "_dup2 failed\n");
2161 h = GetStdHandle(STD_INPUT_HANDLE);
2162 ok(h != NULL, "h == NULL\n");
2165 static void test_mktemp(void)
2167 char buf[16];
2169 strcpy(buf, "a");
2170 ok(!_mktemp(buf), "_mktemp(\"a\") != NULL\n");
2172 strcpy(buf, "testXXXXX");
2173 ok(!_mktemp(buf), "_mktemp(\"testXXXXX\") != NULL\n");
2175 strcpy(buf, "testXXXXXX");
2176 ok(_mktemp(buf) != NULL, "_mktemp(\"testXXXXXX\") == NULL\n");
2178 strcpy(buf, "testXXXXXXa");
2179 ok(!_mktemp(buf), "_mktemp(\"testXXXXXXa\") != NULL\n");
2181 strcpy(buf, "**XXXXXX");
2182 ok(_mktemp(buf) != NULL, "_mktemp(\"**XXXXXX\") == NULL\n");
2185 static void test__open_osfhandle(void)
2187 ioinfo *info;
2188 HANDLE h, tmp;
2189 int fd;
2191 errno = 0xdeadbeef;
2192 fd = _open_osfhandle((intptr_t)INVALID_HANDLE_VALUE, 0);
2193 ok(fd == -1, "_open_osfhandle returned %d\n", fd);
2194 ok(errno == EBADF, "errno = %d\n", errno);
2196 h = CreateFileA("open_osfhandle.tst", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
2197 fd = _open_osfhandle((intptr_t)h, 0);
2198 ok(fd > 0, "_open_osfhandle returned %d (%d)\n", fd, errno);
2199 info = &__pioinfo[fd/MSVCRT_FD_BLOCK_SIZE][fd%MSVCRT_FD_BLOCK_SIZE];
2200 ok(info->handle == h, "info->handle = %p, expected %p\n", info->handle, h);
2201 ok(info->wxflag == 1, "info->wxflag = %x, expected 1\n", info->wxflag);
2202 close(fd);
2203 ok(info->handle == INVALID_HANDLE_VALUE, "info->handle = %p, expected INVALID_HANDLE_VALUE\n", info->handle);
2204 ok(info->wxflag == 0, "info->wxflag = %x, expected 0\n", info->wxflag);
2205 DeleteFileA("open_osfhandle.tst");
2207 errno = 0xdeadbeef;
2208 fd = _open_osfhandle((intptr_t)h, 0);
2209 ok(fd == -1, "_open_osfhandle returned %d\n", fd);
2210 ok(errno == EBADF, "errno = %d\n", errno);
2212 ok(CreatePipe(&h, &tmp, NULL, 0), "CreatePipe failed\n");
2213 fd = _open_osfhandle((intptr_t)h, 0);
2214 ok(fd > 0, "_open_osfhandle returned %d (%d)\n", fd, errno);
2215 info = &__pioinfo[fd/MSVCRT_FD_BLOCK_SIZE][fd%MSVCRT_FD_BLOCK_SIZE];
2216 ok(info->handle == h, "info->handle = %p, expected %p\n", info->handle, h);
2217 ok(info->wxflag == 9, "info->wxflag = %x, expected 9\n", info->wxflag);
2218 close(fd);
2219 CloseHandle(tmp);
2222 static void test_write_flush_size(FILE *file, int bufsize)
2224 char *inbuffer;
2225 char *outbuffer;
2226 int size, fd;
2228 fd = fileno(file);
2229 inbuffer = calloc(bufsize + 1, 1);
2230 outbuffer = calloc(bufsize + 1, 1);
2231 _snprintf(outbuffer, bufsize + 1, "0,1,2,3,4,5,6,7,8,9");
2233 for (size = bufsize + 1; size >= bufsize - 1; size--) {
2234 rewind(file);
2235 fwrite(outbuffer, 1, size, file);
2236 /* lseek() below intentionally redirects the write in fflush() to detect
2237 * if fwrite() has already flushed the whole buffer or not.
2239 lseek(fd, 1, SEEK_SET);
2240 fflush(file);
2241 fseek(file, 0, SEEK_SET);
2242 ok(fread(inbuffer, 1, bufsize, file) == bufsize, "read failed\n");
2243 if (size == bufsize)
2244 todo_wine ok(memcmp(outbuffer, inbuffer, bufsize) == 0, "missing flush by %d byte write\n", size);
2245 else
2246 ok(memcmp(outbuffer, inbuffer, bufsize) != 0, "unexpected flush by %d byte write\n", size);
2248 rewind(file);
2249 fwrite(outbuffer, 1, bufsize / 2, file);
2250 fwrite(outbuffer + bufsize / 2, 1, bufsize / 2, file);
2251 lseek(fd, 1, SEEK_SET);
2252 fflush(file);
2253 fseek(file, 0, SEEK_SET);
2254 ok(fread(inbuffer, 1, bufsize, file) == bufsize, "read failed\n");
2255 ok(memcmp(outbuffer, inbuffer, bufsize) != 0, "unexpected flush by %d/2 byte double write\n", bufsize);
2256 free(inbuffer);
2257 free(outbuffer);
2260 static void test_write_flush(void)
2262 char iobuf[1024];
2263 char *tempf;
2264 FILE *file;
2266 tempf = _tempnam(".","wne");
2267 file = fopen(tempf, "wb+");
2268 ok(file != NULL, "unable to create test file\n");
2269 iobuf[0] = 0;
2270 fwrite(iobuf, 1, 1, file); /* needed for wine to init _bufsiz */
2271 ok(file->_bufsiz == 4096, "incorrect default buffer size: %d", file->_bufsiz);
2272 test_write_flush_size(file, file->_bufsiz);
2273 setvbuf(file, iobuf, _IOFBF, sizeof(iobuf));
2274 test_write_flush_size(file, sizeof(iobuf));
2275 fclose(file);
2276 unlink(tempf);
2277 free(tempf);
2280 START_TEST(file)
2282 int arg_c;
2283 char** arg_v;
2285 init();
2287 arg_c = winetest_get_mainargs( &arg_v );
2289 /* testing low-level I/O */
2290 if (arg_c >= 3)
2292 if (strcmp(arg_v[2], "inherit") == 0)
2293 test_file_inherit_child(arg_v[3]);
2294 else if (strcmp(arg_v[2], "inherit_no") == 0)
2295 test_file_inherit_child_no(arg_v[3]);
2296 else if (strcmp(arg_v[2], "pipes") == 0)
2297 test_pipes_child(arg_c, arg_v);
2298 else
2299 ok(0, "invalid argument '%s'\n", arg_v[2]);
2300 return;
2302 test_dup2();
2303 test_file_inherit(arg_v[0]);
2304 test_file_write_read();
2305 test_chsize();
2306 test_stat();
2307 test_unlink();
2309 /* testing stream I/O */
2310 test_filbuf();
2311 test_fdopen();
2312 test_fopen_fclose_fcloseall();
2313 test_fopen_s();
2314 test__wfopen_s();
2315 test_setmode();
2316 test_fileops();
2317 test_asciimode();
2318 test_asciimode2();
2319 test_filemodeT();
2320 test_readmode(FALSE); /* binary mode */
2321 test_readmode(TRUE); /* ascii mode */
2322 test_readboundary();
2323 test_fgetc();
2324 test_fputc();
2325 test_flsbuf();
2326 test_fflush();
2327 test_fgetwc();
2328 /* \x83\xa9 is double byte character, \xe0\x7f is not (undefined). */
2329 test_fgetwc_locale("AB\x83\xa9\xe0\x7f", "Japanese_Japan.932", 932);
2330 /* \x83 is U+0192 */
2331 test_fgetwc_locale("AB\x83\xa9", "English", 1252);
2332 /* \x83 is U+0083 */
2333 test_fgetwc_locale("AB\x83\xa9", "C", 0);
2334 test_fgetwc_unicode();
2335 test_fputwc();
2336 test_ctrlz();
2337 test_file_put_get();
2338 test_tmpnam();
2339 test_get_osfhandle();
2340 test_setmaxstdio();
2341 test_pipes(arg_v[0]);
2342 test_stdin();
2343 test_mktemp();
2344 test__open_osfhandle();
2345 test_write_flush();
2347 /* Wait for the (_P_NOWAIT) spawned processes to finish to make sure the report
2348 * file contains lines in the correct order
2350 WaitForMultipleObjects(sizeof(proc_handles)/sizeof(proc_handles[0]), proc_handles, TRUE, 5000);