9e2beee27e086029f6ca629afecd9f39a8e99562
[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 #include <locale.h>
37
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;
47
48 static HANDLE proc_handles[2];
49
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*);
52
53 static const char* get_base_name(const char *path)
54 {
55 const char *ret = path+strlen(path)-1;
56
57 while(ret >= path) {
58 if(*ret=='\\' || *ret=='/')
59 break;
60 ret--;
61 }
62 return ret+1;
63 }
64
65 static void init(void)
66 {
67 HMODULE hmod = GetModuleHandleA("msvcrt.dll");
68
69 setlocale(LC_CTYPE, "C");
70
71 p_fopen_s = (void*)GetProcAddress(hmod, "fopen_s");
72 p__wfopen_s = (void*)GetProcAddress(hmod, "_wfopen_s");
73 __pioinfo = (void*)GetProcAddress(hmod, "__pioinfo");
74 }
75
76 static void test_filbuf( void )
77 {
78 FILE *fp;
79 int c;
80 fpos_t pos;
81
82 fp = fopen("filbuf.tst", "wb");
83 fwrite("\n\n\n\n", 1, 4, fp);
84 fclose(fp);
85
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.
99 */
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");
105 }
106
107 static void test_fdopen( void )
108 {
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;
113
114 fd = open ("fdopen.tst", O_WRONLY | O_CREAT | O_BINARY, _S_IREAD |_S_IWRITE);
115 write (fd, buffer, sizeof (buffer));
116 close (fd);
117
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");
125 }
126
127 static void test_fileops( void )
128 {
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};
137
138 fd = open ("fdopen.tst", O_WRONLY | O_CREAT | O_BINARY, _S_IREAD |_S_IWRITE);
139 write (fd, outbuffer, sizeof (outbuffer));
140 close (fd);
141
142 for (bufmode=0; bufmode < sizeof(bufmodes)/sizeof(bufmodes[0]); bufmode++)
143 {
144 fd = open ("fdopen.tst", O_RDONLY | O_BINARY);
145 file = fdopen (fd, "rb");
146 setvbuf(file,NULL,bufmodes[bufmode],2048);
147 if(bufmodes[bufmode] == _IOFBF)
148 ok(file->_bufsiz == 2048, "file->_bufsiz = %d\n", file->_bufsiz);
149 ok(file->_base != NULL, "file->_base = NULL\n");
150 ok(strlen(outbuffer) == (sizeof(outbuffer)-1),"strlen/sizeof error for bufmode=%x\n", bufmodes[bufmode]);
151 ok(fgets(buffer,sizeof(buffer),file) !=0,"fgets failed unexpected for bufmode=%x\n", bufmodes[bufmode]);
152 ok(fgets(buffer,sizeof(buffer),file) ==0,"fgets didn't signal EOF for bufmode=%x\n", bufmodes[bufmode]);
153 ok(feof(file) !=0,"feof doesn't signal EOF for bufmode=%x\n", bufmodes[bufmode]);
154 rewind(file);
155 ok(fgets(buffer,strlen(outbuffer),file) !=0,"fgets failed unexpected for bufmode=%x\n", bufmodes[bufmode]);
156 ok(lstrlenA(buffer) == lstrlenA(outbuffer) -1,"fgets didn't read right size for bufmode=%x\n", bufmodes[bufmode]);
157 ok(fgets(buffer,sizeof(outbuffer),file) !=0,"fgets failed unexpected for bufmode=%x\n", bufmodes[bufmode]);
158 ok(strlen(buffer) == 1,"fgets dropped chars for bufmode=%x\n", bufmodes[bufmode]);
159 ok(buffer[0] == outbuffer[strlen(outbuffer)-1],"fgets exchanged chars for bufmode=%x\n", bufmodes[bufmode]);
160
161 rewind(file);
162 for (i = 0; i < sizeof(outbuffer); i++)
163 {
164 ok(fgetc(file) == outbuffer[i], "fgetc returned wrong data for bufmode=%x\n", bufmodes[bufmode]);
165 }
166 ok((c = fgetc(file)) == EOF, "getc did not return EOF for bufmode=%x\n", bufmodes[bufmode]);
167 ok(feof(file), "feof did not return EOF for bufmode=%x\n", bufmodes[bufmode]);
168 ok(ungetc(c, file) == EOF, "ungetc(EOF) did not return EOF for bufmode=%x\n", bufmodes[bufmode]);
169 ok(feof(file), "feof after ungetc(EOF) did not return EOF for bufmode=%x\n", bufmodes[bufmode]);
170 ok(fgetc(file) == EOF, "getc did not return EOF for bufmode=%x\n", bufmodes[bufmode]);
171 c = outbuffer[sizeof(outbuffer) - 1];
172 ok(ungetc(c, file) == c, "ungetc did not return its input for bufmode=%x\n", bufmodes[bufmode]);
173 ok(!feof(file), "feof after ungetc returned EOF for bufmode=%x\n", bufmodes[bufmode]);
174 ok((c = fgetc(file)) != EOF, "getc after ungetc returned EOF for bufmode=%x\n", bufmodes[bufmode]);
175 ok(c == outbuffer[sizeof(outbuffer) - 1],
176 "getc did not return ungetc'd data for bufmode=%x\n", bufmodes[bufmode]);
177 ok(!feof(file), "feof after getc returned EOF prematurely for bufmode=%x\n", bufmodes[bufmode]);
178 ok(fgetc(file) == EOF, "getc did not return EOF for bufmode=%x\n", bufmodes[bufmode]);
179 ok(feof(file), "feof after getc did not return EOF for bufmode=%x\n", bufmodes[bufmode]);
180
181 rewind(file);
182 ok(fgetpos(file,&pos) == 0, "fgetpos failed unexpected for bufmode=%x\n", bufmodes[bufmode]);
183 ok(pos == 0, "Unexpected result of fgetpos %x%08x for bufmode=%x\n", (DWORD)(pos >> 32), (DWORD)pos, bufmodes[bufmode]);
184 pos = sizeof (outbuffer);
185 ok(fsetpos(file, &pos) == 0, "fsetpos failed unexpected for bufmode=%x\n", bufmodes[bufmode]);
186 ok(fgetpos(file,&pos) == 0, "fgetpos failed unexpected for bufmode=%x\n", bufmodes[bufmode]);
187 ok(pos == sizeof (outbuffer), "Unexpected result of fgetpos %x%08x for bufmode=%x\n", (DWORD)(pos >> 32), (DWORD)pos, bufmodes[bufmode]);
188
189 fclose (file);
190 }
191 fd = open ("fdopen.tst", O_RDONLY | O_TEXT);
192 file = fdopen (fd, "rt"); /* open in TEXT mode */
193 ok(fgetws(wbuffer,sizeof(wbuffer)/sizeof(wbuffer[0]),file) !=0,"fgetws failed unexpected\n");
194 ok(fgetws(wbuffer,sizeof(wbuffer)/sizeof(wbuffer[0]),file) ==0,"fgetws didn't signal EOF\n");
195 ok(feof(file) !=0,"feof doesn't signal EOF\n");
196 rewind(file);
197 ok(fgetws(wbuffer,strlen(outbuffer),file) !=0,"fgetws failed unexpected\n");
198 ok(lstrlenW(wbuffer) == (lstrlenA(outbuffer) -1),"fgetws didn't read right size\n");
199 ok(fgetws(wbuffer,sizeof(outbuffer)/sizeof(outbuffer[0]),file) !=0,"fgets failed unexpected\n");
200 ok(lstrlenW(wbuffer) == 1,"fgets dropped chars\n");
201 fclose (file);
202
203 file = fopen("fdopen.tst", "rb");
204 ok( file != NULL, "fopen failed\n");
205 /* sizeof(buffer) > content of file */
206 ok(fread(buffer, sizeof(buffer), 1, file) == 0, "fread test failed\n");
207 /* feof should be set now */
208 ok(feof(file), "feof after fread failed\n");
209 fclose (file);
210
211 unlink ("fdopen.tst");
212 }
213
214 #define IOMODE (ao?"ascii mode":"binary mode")
215 static void test_readmode( BOOL ascii_mode )
216 {
217 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";
218 static const char padbuffer[] = "ghjghjghjghj";
219 static const char nlbuffer[] = "\r\n";
220 char buffer[2*BUFSIZ+256];
221 const char *optr;
222 int fd;
223 FILE *file;
224 const int *ip;
225 int i, j, m, ao, pl;
226 unsigned int fp;
227 LONG l;
228
229 fd = open ("fdopen.tst", O_WRONLY | O_CREAT | O_BINARY, _S_IREAD |_S_IWRITE);
230 /* an internal buffer of BUFSIZ is maintained, so make a file big
231 * enough to test operations that cross the buffer boundary
232 */
233 j = (2*BUFSIZ-4)/strlen(padbuffer);
234 for (i=0; i<j; i++)
235 write (fd, padbuffer, strlen(padbuffer));
236 j = (2*BUFSIZ-4)%strlen(padbuffer);
237 for (i=0; i<j; i++)
238 write (fd, &padbuffer[i], 1);
239 write (fd, nlbuffer, strlen(nlbuffer));
240 write (fd, outbuffer, sizeof (outbuffer));
241 close (fd);
242
243 if (ascii_mode) {
244 /* Open file in ascii mode */
245 fd = open ("fdopen.tst", O_RDONLY);
246 file = fdopen (fd, "r");
247 ao = -1; /* on offset to account for carriage returns */
248 }
249 else {
250 fd = open ("fdopen.tst", O_RDONLY | O_BINARY);
251 file = fdopen (fd, "rb");
252 ao = 0;
253 }
254
255 /* first is a test of fgets, ftell, fseek */
256 ok(ftell(file) == 0,"Did not start at beginning of file in %s\n", IOMODE);
257 ok(fgets(buffer,2*BUFSIZ+256,file) !=0,"padding line fgets failed unexpected in %s\n", IOMODE);
258 l = ftell(file);
259 pl = 2*BUFSIZ-2;
260 ok(l == pl,"padding line ftell got %d should be %d in %s\n", l, pl, IOMODE);
261 ok(lstrlenA(buffer) == pl+ao,"padding line fgets got size %d should be %d in %s\n",
262 lstrlenA(buffer), pl+ao, IOMODE);
263 for (fp=0; fp<strlen(outbuffer); fp++)
264 if (outbuffer[fp] == '\n') break;
265 fp++;
266 ok(fgets(buffer,256,file) !=0,"line 1 fgets failed unexpected in %s\n", IOMODE);
267 l = ftell(file);
268 ok(l == pl+fp,"line 1 ftell got %d should be %d in %s\n", l, pl+fp, IOMODE);
269 ok(lstrlenA(buffer) == fp+ao,"line 1 fgets got size %d should be %d in %s\n",
270 lstrlenA(buffer), fp+ao, IOMODE);
271 /* test a seek back across the buffer boundary */
272 l = pl;
273 ok(fseek(file,l,SEEK_SET)==0,"seek failure in %s\n", IOMODE);
274 l = ftell(file);
275 ok(l == pl,"ftell after seek got %d should be %d in %s\n", l, pl, IOMODE);
276 ok(fgets(buffer,256,file) !=0,"second read of line 1 fgets failed unexpected in %s\n", IOMODE);
277 l = ftell(file);
278 ok(l == pl+fp,"second read of line 1 ftell got %d should be %d in %s\n", l, pl+fp, IOMODE);
279 ok(lstrlenA(buffer) == fp+ao,"second read of line 1 fgets got size %d should be %d in %s\n",
280 lstrlenA(buffer), fp+ao, IOMODE);
281 ok(fgets(buffer,256,file) !=0,"line 2 fgets failed unexpected in %s\n", IOMODE);
282 fp += 2;
283 l = ftell(file);
284 ok(l == pl+fp,"line 2 ftell got %d should be %d in %s\n", l, pl+fp, IOMODE);
285 ok(lstrlenA(buffer) == 2+ao,"line 2 fgets got size %d should be %d in %s\n",
286 lstrlenA(buffer), 2+ao, IOMODE);
287
288 /* test fread across buffer boundary */
289 rewind(file);
290 ok(ftell(file) == 0,"Did not start at beginning of file in %s\n", IOMODE);
291 ok(fgets(buffer,BUFSIZ-6,file) !=0,"padding line fgets failed unexpected in %s\n", IOMODE);
292 j=strlen(outbuffer);
293 i=fread(buffer,1,BUFSIZ+strlen(outbuffer),file);
294 ok(i==BUFSIZ+j,"fread failed, expected %d got %d in %s\n", BUFSIZ+j, i, IOMODE);
295 l = ftell(file);
296 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);
297 for (m=0; m<3; m++)
298 ok(buffer[m]==padbuffer[m+(BUFSIZ-4)%strlen(padbuffer)],"expected %c got %c\n", padbuffer[m], buffer[m]);
299 m+=BUFSIZ+2+ao;
300 optr = outbuffer;
301 for (; m<i; m++) {
302 ok(buffer[m]==*optr,"char %d expected %c got %c in %s\n", m, *optr, buffer[m], IOMODE);
303 optr++;
304 if (ao && (*optr == '\r'))
305 optr++;
306 }
307 /* fread should return the requested number of bytes if available */
308 rewind(file);
309 ok(ftell(file) == 0,"Did not start at beginning of file in %s\n", IOMODE);
310 ok(fgets(buffer,BUFSIZ-6,file) !=0,"padding line fgets failed unexpected in %s\n", IOMODE);
311 j = fp+10;
312 i=fread(buffer,1,j,file);
313 ok(i==j,"fread failed, expected %d got %d in %s\n", j, i, IOMODE);
314 /* test fread eof */
315 ok(fseek(file,0,SEEK_END)==0,"seek failure in %s\n", IOMODE);
316 ok(feof(file)==0,"feof failure in %s\n", IOMODE);
317 ok(fread(buffer,1,1,file)==0,"fread failure in %s\n", IOMODE);
318 ok(feof(file)!=0,"feof failure in %s\n", IOMODE);
319 ok(fseek(file,-3,SEEK_CUR)==0,"seek failure in %s\n", IOMODE);
320 ok(feof(file)==0,"feof failure in %s\n", IOMODE);
321 ok(fread(buffer,2,1,file)==1,"fread failed in %s\n", IOMODE);
322 ok(feof(file)==0,"feof failure in %s\n", IOMODE);
323 ok(fread(buffer,2,1,file)==0,"fread failure in %s\n",IOMODE);
324 ok(feof(file)!=0,"feof failure in %s\n", IOMODE);
325
326 /* test some additional functions */
327 rewind(file);
328 ok(ftell(file) == 0,"Did not start at beginning of file in %s\n", IOMODE);
329 ok(fgets(buffer,2*BUFSIZ+256,file) !=0,"padding line fgets failed unexpected in %s\n", IOMODE);
330 i = _getw(file);
331 ip = (const int *)outbuffer;
332 ok(i == *ip,"_getw failed, expected %08x got %08x in %s\n", *ip, i, IOMODE);
333 for (fp=0; fp<strlen(outbuffer); fp++)
334 if (outbuffer[fp] == '\n') break;
335 fp++;
336 /* this will cause the next _getw to cross carriage return characters */
337 ok(fgets(buffer,fp-6,file) !=0,"line 1 fgets failed unexpected in %s\n", IOMODE);
338 for (i=0, j=0; i<6; i++) {
339 if (ao==0 || outbuffer[fp-3+i] != '\r')
340 buffer[j++] = outbuffer[fp-3+i];
341 }
342 i = _getw(file);
343 ip = (int *)buffer;
344 ok(i == *ip,"_getw failed, expected %08x got %08x in %s\n", *ip, i, IOMODE);
345
346 fclose (file);
347 unlink ("fdopen.tst");
348 }
349
350 static void test_asciimode(void)
351 {
352 FILE *fp;
353 char buf[64];
354 int c, i, j;
355
356 /* Simple test of CR CR LF handling. Test both fgets and fread code paths, they're different! */
357 fp = fopen("ascii.tst", "wb");
358 fputs("\r\r\n", fp);
359 fclose(fp);
360 fp = fopen("ascii.tst", "rt");
361 ok(fgets(buf, sizeof(buf), fp) != NULL, "fgets\n");
362 ok(0 == strcmp(buf, "\r\n"), "CR CR LF not read as CR LF\n");
363 rewind(fp);
364 ok((fread(buf, 1, sizeof(buf), fp) == 2) && (0 == strcmp(buf, "\r\n")), "CR CR LF not read as CR LF\n");
365 fclose(fp);
366 unlink("ascii.tst");
367
368 /* Simple test of foo ^Z [more than one block] bar handling */
369 fp = fopen("ascii.tst", "wb");
370 fputs("foo\032", fp); /* foo, logical EOF, ... */
371 fseek(fp, 65536L, SEEK_SET); /* ... more than MSVCRT_BUFSIZ, ... */
372 fputs("bar", fp); /* ... bar */
373 fclose(fp);
374 fp = fopen("ascii.tst", "rt");
375 ok(fgets(buf, sizeof(buf), fp) != NULL, "fgets foo\n");
376 ok(0 == strcmp(buf, "foo"), "foo ^Z not read as foo by fgets\n");
377 ok(fgets(buf, sizeof(buf), fp) == NULL, "fgets after logical EOF\n");
378 rewind(fp);
379 ok((fread(buf, 1, sizeof(buf), fp) == 3) && (0 == strcmp(buf, "foo")), "foo ^Z not read as foo by fread\n");
380 ok((fread(buf, 1, sizeof(buf), fp) == 0), "fread after logical EOF\n");
381 fclose(fp);
382
383 /* Show ASCII mode handling*/
384 fp= fopen("ascii.tst","wb");
385 fputs("0\r\n1\r\n2\r\n3\r\n4\r\n5\r\n6\r\n7\r\n8\r\n9\r\n", fp);
386 fclose(fp);
387
388 fp = fopen("ascii.tst", "r");
389 c= fgetc(fp);
390 ok(c == '0', "fgetc failed, expected '0', got '%c'\n", c);
391 c= fgetc(fp);
392 ok(c == '\n', "fgetc failed, expected '\\n', got '%c'\n", c);
393 fseek(fp,0,SEEK_CUR);
394 for(i=1; i<10; i++) {
395 ok((j = ftell(fp)) == i*3, "ftell fails in TEXT mode\n");
396 fseek(fp,0,SEEK_CUR);
397 ok((c = fgetc(fp)) == '0'+ i, "fgetc after fseek failed in line %d\n", i);
398 c= fgetc(fp);
399 ok(c == '\n', "fgetc failed, expected '\\n', got '%c'\n", c);
400 }
401 /* Show that fseek doesn't skip \\r !*/
402 rewind(fp);
403 c= fgetc(fp);
404 ok(c == '0', "fgetc failed, expected '0', got '%c'\n", c);
405 fseek(fp, 2 ,SEEK_CUR);
406 for(i=1; i<10; i++) {
407 ok((c = fgetc(fp)) == '0'+ i, "fgetc after fseek with pos Offset failed in line %d\n", i);
408 fseek(fp, 2 ,SEEK_CUR);
409 }
410 fseek(fp, 9*3 ,SEEK_SET);
411 c = fgetc(fp);
412 ok(c == '9', "fgetc failed, expected '9', got '%c'\n", c);
413 fseek(fp, -4 ,SEEK_CUR);
414 for(i= 8; i>=0; i--) {
415 ok((c = fgetc(fp)) == '0'+ i, "fgetc after fseek with neg Offset failed in line %d\n", i);
416 fseek(fp, -4 ,SEEK_CUR);
417 }
418 /* Show what happens if fseek positions filepointer on \\r */
419 fclose(fp);
420 fp = fopen("ascii.tst", "r");
421 fseek(fp, 3 ,SEEK_SET);
422 ok((c = fgetc(fp)) == '1', "fgetc fails to read next char when positioned on \\r\n");
423 fclose(fp);
424
425 unlink("ascii.tst");
426 }
427
428 static void test_asciimode2(void)
429 {
430 /* Error sequence from one app was getchar followed by small fread
431 * with one \r removed had last byte of buffer filled with
432 * next byte of *unbuffered* data rather than next byte from buffer
433 * Test case is a short string of one byte followed by a newline
434 * followed by filler to fill out the sector, then a sector of
435 * some different byte.
436 */
437
438 FILE *fp;
439 char ibuf[4];
440 int i;
441 static const char obuf[] =
442 "00\n"
443 "000000000000000000000000000000000000000000000000000000000000000000000000000000\n"
444 "000000000000000000000000000000000000000000000000000000000000000000000000000000\n"
445 "000000000000000000000000000000000000000000000000000000000000000000000000000000\n"
446 "000000000000000000000000000000000000000000000000000000000000000000000000000000\n"
447 "000000000000000000000000000000000000000000000000000000000000000000000000000000\n"
448 "000000000000000000000000000000000000000000000000000000000000000000000000000000\n"
449 "000000000000000000\n"
450 "1111111111111111111";
451
452 fp = fopen("ascii2.tst", "wt");
453 fwrite(obuf, 1, sizeof(obuf), fp);
454 fclose(fp);
455
456 fp = fopen("ascii2.tst", "rt");
457 ok(getc(fp) == '0', "first char not 0\n");
458 memset(ibuf, 0, sizeof(ibuf));
459 i = fread(ibuf, 1, sizeof(ibuf), fp);
460 ok(i == sizeof(ibuf), "fread i %d != sizeof(ibuf)\n", i);
461 ok(0 == strncmp(ibuf, obuf+1, sizeof(ibuf)), "ibuf != obuf\n");
462 fclose(fp);
463 unlink("ascii2.tst");
464 }
465
466 static void test_filemodeT(void)
467 {
468 char DATA [] = {26, 't', 'e', 's' ,'t'};
469 char DATA2 [100];
470 char temppath[MAX_PATH];
471 char tempfile[MAX_PATH];
472 FILE* f;
473 size_t bytesWritten;
474 size_t bytesRead;
475 WIN32_FIND_DATAA findData;
476 HANDLE h;
477
478 GetTempPathA(MAX_PATH, temppath);
479 GetTempFileNameA(temppath, "", 0, tempfile);
480
481 f = fopen(tempfile, "w+bDT");
482 bytesWritten = fwrite(DATA, 1, sizeof(DATA), f);
483 rewind(f);
484 bytesRead = fread(DATA2, 1, sizeof(DATA2), f);
485 fclose(f);
486
487 ok (bytesRead == bytesWritten && bytesRead == sizeof(DATA),
488 "fopen file mode 'T' wrongly interpreted as 't'\n" );
489
490 h = FindFirstFileA(tempfile, &findData);
491
492 ok (h == INVALID_HANDLE_VALUE, "file wasn't deleted when closed.\n" );
493
494 if (h != INVALID_HANDLE_VALUE) FindClose(h);
495 }
496
497 static WCHAR* AtoW( const char* p )
498 {
499 WCHAR* buffer;
500 DWORD len = MultiByteToWideChar( CP_ACP, 0, p, -1, NULL, 0 );
501 buffer = malloc( len * sizeof(WCHAR) );
502 MultiByteToWideChar( CP_ACP, 0, p, -1, buffer, len );
503 return buffer;
504 }
505
506 /* Test reading in text mode when the 512'th character read is \r*/
507 static void test_readboundary(void)
508 {
509 FILE *fp;
510 char buf[513], rbuf[513];
511 int i, j;
512 for (i = 0; i < 511; i++)
513 {
514 j = (i%('~' - ' ')+ ' ');
515 buf[i] = j;
516 }
517 buf[511] = '\n';
518 buf[512] =0;
519 fp = fopen("boundary.tst", "wt");
520 fwrite(buf, 512,1,fp);
521 fclose(fp);
522 fp = fopen("boundary.tst", "rt");
523 for(i=0; i<512; i++)
524 {
525 fseek(fp,0 , SEEK_CUR);
526 rbuf[i] = fgetc(fp);
527 }
528 rbuf[512] =0;
529 fclose(fp);
530 unlink("boundary.tst");
531
532 ok(strcmp(buf, rbuf) == 0,"CRLF on buffer boundary failure\n");
533 }
534
535 static void test_fgetc( void )
536 {
537 char* tempf;
538 FILE *tempfh;
539 int ich=0xe0, ret;
540
541 tempf=_tempnam(".","wne");
542 tempfh = fopen(tempf,"w+");
543 fputc(ich, tempfh);
544 fputc(ich, tempfh);
545 rewind(tempfh);
546 ret = fgetc(tempfh);
547 ok(ich == ret, "First fgetc expected %x got %x\n", ich, ret);
548 ret = fgetc(tempfh);
549 ok(ich == ret, "Second fgetc expected %x got %x\n", ich, ret);
550 fclose(tempfh);
551 tempfh = fopen(tempf,"wt");
552 fputc('\n', tempfh);
553 fclose(tempfh);
554 tempfh = fopen(tempf,"wt");
555 setbuf(tempfh, NULL);
556 ret = fgetc(tempfh);
557 ok(ret == -1, "Unbuffered fgetc in text mode must failed on \\r\\n\n");
558 fclose(tempfh);
559 unlink(tempf);
560 free(tempf);
561 }
562
563 static void test_fputc( void )
564 {
565 char* tempf;
566 FILE *tempfh;
567 int ret;
568
569 tempf=_tempnam(".","wne");
570 tempfh = fopen(tempf,"wb");
571 ret = fputc(0,tempfh);
572 ok(0 == ret, "fputc(0,tempfh) expected %x got %x\n", 0, ret);
573 ret = fputc(0xff,tempfh);
574 ok(0xff == ret, "fputc(0xff,tempfh) expected %x got %x\n", 0xff, ret);
575 ret = fputc(0xffffffff,tempfh);
576 ok(0xff == ret, "fputc(0xffffffff,tempfh) expected %x got %x\n", 0xff, ret);
577 fclose(tempfh);
578
579 tempfh = fopen(tempf,"rb");
580 ret = fputc(0,tempfh);
581 ok(EOF == ret, "fputc(0,tempfh) on r/o file expected %x got %x\n", EOF, ret);
582 fclose(tempfh);
583
584 unlink(tempf);
585 free(tempf);
586 }
587
588 static void test_flsbuf( void )
589 {
590 char* tempf;
591 FILE *tempfh;
592 int c;
593 int ret;
594 int bufmode;
595 static const int bufmodes[] = {_IOFBF,_IONBF};
596
597 tempf=_tempnam(".","wne");
598 for (bufmode=0; bufmode < sizeof(bufmodes)/sizeof(bufmodes[0]); bufmode++)
599 {
600 tempfh = fopen(tempf,"wb");
601 setvbuf(tempfh,NULL,bufmodes[bufmode],2048);
602 ret = _flsbuf(0,tempfh);
603 ok(0 == ret, "_flsbuf(0,tempfh) with bufmode %x expected %x got %x\n",
604 bufmodes[bufmode], 0, ret);
605 ret = _flsbuf(0xff,tempfh);
606 ok(0xff == ret, "_flsbuf(0xff,tempfh) with bufmode %x expected %x got %x\n",
607 bufmodes[bufmode], 0xff, ret);
608 ret = _flsbuf(0xffffffff,tempfh);
609 ok(0xff == ret, "_flsbuf(0xffffffff,tempfh) with bufmode %x expected %x got %x\n",
610 bufmodes[bufmode], 0xff, ret);
611 if(tempfh->_base) {
612 fputc('x', tempfh);
613 tempfh->_cnt = -1;
614 tempfh->_base[1] = 'a';
615 ret = _flsbuf(0xab,tempfh);
616 ok(ret == 0xab, "_flsbuf(0xab,tempfh) with bufmode %x expected 0xab got %x\n",
617 bufmodes[bufmode], ret);
618 ok(tempfh->_base[1] == 'a', "tempfh->_base[1] should not be changed (%d)\n",
619 tempfh->_base[1]);
620 }
621
622 fclose(tempfh);
623 }
624
625 tempfh = fopen(tempf,"rb");
626 ret = _flsbuf(0,tempfh);
627 ok(EOF == ret, "_flsbuf(0,tempfh) on r/o file expected %x got %x\n", EOF, ret);
628 fclose(tempfh);
629
630 /* See bug 17123, exposed by WinAVR's make */
631 tempfh = fopen(tempf,"w");
632 ok(tempfh->_cnt == 0, "_cnt on freshly opened file was %d\n", tempfh->_cnt);
633 setbuf(tempfh, NULL);
634 ok(tempfh->_cnt == 0, "_cnt on unbuffered file was %d\n", tempfh->_cnt);
635 ok(tempfh->_bufsiz == 2, "_bufsiz = %d\n", tempfh->_bufsiz);
636 /* Inlined putchar sets _cnt to -1. Native seems to ignore the value... */
637 tempfh->_cnt = 1234;
638 ret = _flsbuf('Q',tempfh);
639 ok('Q' == ret, "_flsbuf('Q',tempfh) expected %x got %x\n", 'Q', ret);
640 /* ... and reset it to zero */
641 ok(tempfh->_cnt == 0, "after unbuf _flsbuf, _cnt was %d\n", tempfh->_cnt);
642 fclose(tempfh);
643 /* And just for grins, make sure the file is correct */
644 tempfh = fopen(tempf,"r");
645 c = fgetc(tempfh);
646 ok(c == 'Q', "first byte should be 'Q'\n");
647 c = fgetc(tempfh);
648 ok(c == EOF, "there should only be one byte\n");
649 fclose(tempfh);
650
651 unlink(tempf);
652 free(tempf);
653 }
654
655 static void test_fflush( void )
656 {
657 static const char obuf[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
658 char buf1[16], buf2[24];
659 char *tempf;
660 FILE *tempfh;
661 int ret;
662
663 tempf=_tempnam(".","wne");
664
665 /* Prepare the file. */
666 tempfh = fopen(tempf,"wb");
667 ok(tempfh != NULL, "Can't open test file.\n");
668 fwrite(obuf, 1, sizeof(obuf), tempfh);
669 fclose(tempfh);
670
671 /* Open the file for input. */
672 tempfh = fopen(tempf,"rb");
673 ok(tempfh != NULL, "Can't open test file.\n");
674 fread(buf1, 1, sizeof(buf1), tempfh);
675
676 /* Using fflush() on input stream is undefined in ANSI.
677 * But MSDN says that it clears input buffer. */
678 _lseek(_fileno(tempfh), 0, SEEK_SET);
679 ret = fflush(tempfh);
680 ok(ret == 0, "expected 0, got %d\n", ret);
681 memset(buf2, '?', sizeof(buf2));
682 fread(buf2, 1, sizeof(buf2), tempfh);
683 ok(memcmp(buf1, buf2, sizeof(buf1)) == 0, "Got unexpected data (%c)\n", buf2[0]);
684
685 /* fflush(NULL) doesn't clear input buffer. */
686 _lseek(_fileno(tempfh), 0, SEEK_SET);
687 ret = fflush(NULL);
688 ok(ret == 0, "expected 0, got %d\n", ret);
689 memset(buf2, '?', sizeof(buf2));
690 fread(buf2, 1, sizeof(buf2), tempfh);
691 ok(memcmp(buf1, buf2, sizeof(buf1)) != 0, "Got unexpected data (%c)\n", buf2[0]);
692
693 /* _flushall() clears input buffer. */
694 _lseek(_fileno(tempfh), 0, SEEK_SET);
695 ret = _flushall();
696 ok(ret >= 0, "unexpected ret %d\n", ret);
697 memset(buf2, '?', sizeof(buf2));
698 fread(buf2, 1, sizeof(buf2), tempfh);
699 ok(memcmp(buf1, buf2, sizeof(buf1)) == 0, "Got unexpected data (%c)\n", buf2[0]);
700
701 fclose(tempfh);
702
703 unlink(tempf);
704 free(tempf);
705 }
706
707 static void test_fgetwc( void )
708 {
709 #define LLEN 512
710
711 char* tempf;
712 FILE *tempfh;
713 static const char mytext[]= "This is test_fgetwc\r\n";
714 WCHAR wtextW[BUFSIZ+LLEN+1];
715 WCHAR *mytextW = NULL, *aptr, *wptr;
716 BOOL diff_found = FALSE;
717 int j;
718 unsigned int i;
719 LONG l;
720
721 tempf=_tempnam(".","wne");
722 tempfh = fopen(tempf,"wb");
723 j = 'a';
724 /* pad to almost the length of the internal buffer */
725 for (i=0; i<BUFSIZ-4; i++)
726 fputc(j,tempfh);
727 j = '\r';
728 fputc(j,tempfh);
729 j = '\n';
730 fputc(j,tempfh);
731 fputs(mytext,tempfh);
732 fclose(tempfh);
733 /* in text mode, getws/c expects multibyte characters */
734 /*currently Wine only supports plain ascii, and that is all that is tested here */
735 tempfh = fopen(tempf,"rt"); /* open in TEXT mode */
736 fgetws(wtextW,LLEN,tempfh);
737 l=ftell(tempfh);
738 ok(l==BUFSIZ-2, "ftell expected %d got %d\n", BUFSIZ-2, l);
739 fgetws(wtextW,LLEN,tempfh);
740 l=ftell(tempfh);
741 ok(l==BUFSIZ-2+strlen(mytext), "ftell expected %d got %d\n", BUFSIZ-2+lstrlenA(mytext), l);
742 mytextW = AtoW (mytext);
743 aptr = mytextW;
744 wptr = wtextW;
745 for (i=0; i<strlen(mytext)-2; i++, aptr++, wptr++)
746 {
747 diff_found |= (*aptr != *wptr);
748 }
749 ok(!(diff_found), "fgetwc difference found in TEXT mode\n");
750 ok(*wptr == '\n', "Carriage return was not skipped\n");
751 fclose(tempfh);
752 unlink(tempf);
753
754 tempfh = fopen(tempf,"wb");
755 j = 'a';
756 /* pad to almost the length of the internal buffer. Use an odd number of bytes
757 to test that we can read wchars that are split across the internal buffer
758 boundary */
759 for (i=0; i<BUFSIZ-3-strlen(mytext)*sizeof(WCHAR); i++)
760 fputc(j,tempfh);
761 j = '\r';
762 fputwc(j,tempfh);
763 j = '\n';
764 fputwc(j,tempfh);
765 fputws(wtextW,tempfh);
766 fputws(wtextW,tempfh);
767 fclose(tempfh);
768 /* in binary mode, getws/c expects wide characters */
769 tempfh = fopen(tempf,"rb"); /* open in BINARY mode */
770 j=(BUFSIZ-2)/sizeof(WCHAR)-strlen(mytext);
771 fgetws(wtextW,j,tempfh);
772 l=ftell(tempfh);
773 j=(j-1)*sizeof(WCHAR);
774 ok(l==j, "ftell expected %d got %d\n", j, l);
775 i=fgetc(tempfh);
776 ok(i=='a', "fgetc expected %d got %d\n", 0x61, i);
777 l=ftell(tempfh);
778 j++;
779 ok(l==j, "ftell expected %d got %d\n", j, l);
780 fgetws(wtextW,3,tempfh);
781 ok(wtextW[0]=='\r',"expected carriage return got %04hx\n", wtextW[0]);
782 ok(wtextW[1]=='\n',"expected newline got %04hx\n", wtextW[1]);
783 l=ftell(tempfh);
784 j += 4;
785 ok(l==j, "ftell expected %d got %d\n", j, l);
786 for(i=0; i<strlen(mytext); i++)
787 wtextW[i] = 0;
788 /* the first time we get the string, it should be entirely within the local buffer */
789 fgetws(wtextW,LLEN,tempfh);
790 l=ftell(tempfh);
791 j += (strlen(mytext)-1)*sizeof(WCHAR);
792 ok(l==j, "ftell expected %d got %d\n", j, l);
793 diff_found = FALSE;
794 aptr = mytextW;
795 wptr = wtextW;
796 for (i=0; i<strlen(mytext)-2; i++, aptr++, wptr++)
797 {
798 ok(*aptr == *wptr, "Char %d expected %04hx got %04hx\n", i, *aptr, *wptr);
799 diff_found |= (*aptr != *wptr);
800 }
801 ok(!(diff_found), "fgetwc difference found in BINARY mode\n");
802 ok(*wptr == '\n', "Should get newline\n");
803 for(i=0; i<strlen(mytext); i++)
804 wtextW[i] = 0;
805 /* the second time we get the string, it should cross the local buffer boundary.
806 One of the wchars should be split across the boundary */
807 fgetws(wtextW,LLEN,tempfh);
808 diff_found = FALSE;
809 aptr = mytextW;
810 wptr = wtextW;
811 for (i=0; i<strlen(mytext)-2; i++, aptr++, wptr++)
812 {
813 ok(*aptr == *wptr, "Char %d expected %04hx got %04hx\n", i, *aptr, *wptr);
814 diff_found |= (*aptr != *wptr);
815 }
816 ok(!(diff_found), "fgetwc difference found in BINARY mode\n");
817 ok(*wptr == '\n', "Should get newline\n");
818
819 free(mytextW);
820 fclose(tempfh);
821 unlink(tempf);
822 free(tempf);
823 }
824
825 static void test_fgetwc_locale(const char* text, const char* locale, int codepage)
826 {
827 char temppath[MAX_PATH], tempfile[MAX_PATH];
828 FILE *tempfh;
829 static const WCHAR wchar_text[] = { 0xfeff, 0xff1f, '!' };
830 WCHAR wtextW[BUFSIZ];
831 int ret = 0, i;
832 wint_t ch;
833
834 if (!setlocale(LC_CTYPE, locale))
835 {
836 win_skip("%s locale not available\n", locale);
837 return;
838 }
839
840 GetTempPathA(MAX_PATH, temppath);
841 GetTempFileNameA(temppath, "", 0, tempfile);
842
843 tempfh = fopen(tempfile, "wb");
844 ok(tempfh != NULL, "can't open tempfile\n");
845 fwrite(text, 1, strlen(text), tempfh);
846 fclose(tempfh);
847
848 if (codepage != 0)
849 {
850 /* mbstowcs rejects invalid multibyte sequence,
851 so we use MultiByteToWideChar here. */
852 ret = MultiByteToWideChar(codepage, 0, text, -1,
853 wtextW, sizeof(wtextW)/sizeof(wtextW[0]));
854 ok(ret > 0, "MultiByteToWideChar failed\n");
855 }
856 else
857 {
858 /* C locale */
859 const char *p;
860 for (p = text; *p != '\0'; p++)
861 wtextW[ret++] = (unsigned char)*p;
862 wtextW[ret++] = 0;
863 }
864
865 tempfh = fopen(tempfile, "rt");
866 ok(tempfh != NULL, "can't open tempfile\n");
867
868 for (i = 0; i < ret-1; i++)
869 {
870 ch = fgetwc(tempfh);
871 ok(ch == wtextW[i], "got %04hx, expected %04hx (cp%d[%d])\n", ch, wtextW[i], codepage, i);
872 }
873 ch = fgetwc(tempfh);
874 ok(ch == WEOF, "got %04hx, expected WEOF (cp%d)\n", ch, codepage);
875 fclose(tempfh);
876
877 tempfh = fopen(tempfile, "wb");
878 ok(tempfh != NULL, "can't open tempfile\n");
879 fwrite(wchar_text, 1, sizeof(wchar_text), tempfh);
880 fclose(tempfh);
881
882 tempfh = fopen(tempfile, "rb");
883 ok(tempfh != NULL, "can't open tempfile\n");
884 for (i = 0; i < sizeof(wchar_text)/sizeof(wchar_text[0]); i++)
885 {
886 ch = fgetwc(tempfh);
887 ok(ch == wchar_text[i], "got %04hx, expected %04x (cp%d[%d])\n", ch, wchar_text[i], codepage, i);
888 }
889 ch = fgetwc(tempfh);
890 ok(ch == WEOF, "got %04hx, expected WEOF (cp%d)\n", ch, codepage);
891 fclose(tempfh);
892 unlink(tempfile);
893 }
894
895 static void test_fgetwc_unicode(void)
896 {
897 char temppath[MAX_PATH], tempfile[MAX_PATH];
898 FILE *tempfh;
899 static const WCHAR wchar_text[] = { 0xfeff, 0xff1f, '!' };
900 char utf8_text[BUFSIZ];
901 int ret, i;
902 wint_t ch;
903
904 GetTempPathA(MAX_PATH, temppath);
905 GetTempFileNameA(temppath, "", 0, tempfile);
906
907 if (!p_fopen_s)
908 {
909 win_skip("fopen_s not available\n");
910 return;
911 }
912
913 tempfh = fopen(tempfile, "wb");
914 ok(tempfh != NULL, "can't open tempfile\n");
915 fwrite(wchar_text, 1, sizeof(wchar_text), tempfh);
916 fclose(tempfh);
917
918 tempfh = fopen(tempfile, "rt,ccs=unicode");
919 ok(tempfh != NULL, "can't open tempfile\n");
920 for (i = 1; i < sizeof(wchar_text)/sizeof(wchar_text[0]); i++)
921 {
922 ch = fgetwc(tempfh);
923 ok(ch == wchar_text[i],
924 "got %04hx, expected %04x (unicode[%d])\n", ch, wchar_text[i], i-1);
925 }
926 ch = fgetwc(tempfh);
927 ok(ch == WEOF, "got %04hx, expected WEOF (unicode)\n", ch);
928 fclose(tempfh);
929
930 tempfh = fopen(tempfile, "wb");
931 ok(tempfh != NULL, "can't open tempfile\n");
932 ret = WideCharToMultiByte(CP_UTF8, 0, wchar_text, sizeof(wchar_text)/sizeof(wchar_text[0]),
933 utf8_text, sizeof(utf8_text), NULL, NULL);
934 ok(ret > 0, "utf-8 conversion failed\n");
935 fwrite(utf8_text, sizeof(char), ret, tempfh);
936 fclose(tempfh);
937
938 tempfh = fopen(tempfile, "rt, ccs=UTF-8");
939 ok(tempfh != NULL, "can't open tempfile\n");
940 for (i = 1; i < sizeof(wchar_text)/sizeof(wchar_text[0]); i++)
941 {
942 ch = fgetwc(tempfh);
943 ok(ch == wchar_text[i],
944 "got %04hx, expected %04x (utf8[%d])\n", ch, wchar_text[i], i-1);
945 }
946 ch = fgetwc(tempfh);
947 ok(ch == WEOF, "got %04hx, expected WEOF (utf8)\n", ch);
948 fclose(tempfh);
949 unlink(temppath);
950 }
951
952 static void test_fputwc(void)
953 {
954 char temppath[MAX_PATH];
955 char tempfile[MAX_PATH];
956 FILE *f;
957 char buf[1024];
958 int ret;
959
960 GetTempPathA(MAX_PATH, temppath);
961 GetTempFileNameA(temppath, "", 0, tempfile);
962
963 f = fopen(tempfile, "w");
964 ret = fputwc('a', f);
965 ok(ret == 'a', "fputwc returned %x, expected 'a'\n", ret);
966 ret = fputwc('\n', f);
967 ok(ret == '\n', "fputwc returned %x, expected '\\n'\n", ret);
968 fclose(f);
969
970 f = fopen(tempfile, "rb");
971 ret = fread(buf, 1, sizeof(buf), f);
972 ok(ret == 3, "fread returned %d, expected 3\n", ret);
973 ok(!memcmp(buf, "a\r\n", 3), "incorrect file data\n");
974 fclose(f);
975
976 if(p_fopen_s) {
977 f = fopen(tempfile, "w,ccs=unicode");
978 ret = fputwc('a', f);
979 ok(ret == 'a', "fputwc returned %x, expected 'a'\n", ret);
980 ret = fputwc('\n', f);
981 ok(ret == '\n', "fputwc returned %x, expected '\\n'\n", ret);
982 fclose(f);
983
984 f = fopen(tempfile, "rb");
985 ret = fread(buf, 1, sizeof(buf), f);
986 ok(ret == 8, "fread returned %d, expected 8\n", ret);
987 ok(!memcmp(buf, "\xff\xfe\x61\x00\r\x00\n\x00", 8), "incorrect file data\n");
988 fclose(f);
989
990 f = fopen(tempfile, "w,ccs=utf-8");
991 ret = fputwc('a', f);
992 ok(ret == 'a', "fputwc returned %x, expected 'a'\n", ret);
993 ret = fputwc('\n', f);
994 ok(ret == '\n', "fputwc returned %x, expected '\\n'\n", ret);
995 fclose(f);
996
997 f = fopen(tempfile, "rb");
998 ret = fread(buf, 1, sizeof(buf), f);
999 ok(ret == 6, "fread returned %d, expected 6\n", ret);
1000 ok(!memcmp(buf, "\xef\xbb\xbf\x61\r\n", 6), "incorrect file data\n");
1001 fclose(f);
1002 }else {
1003 win_skip("fputwc tests on unicode files\n");
1004 }
1005
1006 _unlink(tempfile);
1007 }
1008
1009 static void test_ctrlz( void )
1010 {
1011 char* tempf;
1012 FILE *tempfh;
1013 static const char mytext[]= "This is test_ctrlz";
1014 char buffer[256];
1015 int i, j;
1016 LONG l;
1017
1018 tempf=_tempnam(".","wne");
1019 tempfh = fopen(tempf,"wb");
1020 fputs(mytext,tempfh);
1021 j = 0x1a; /* a ctrl-z character signals EOF in text mode */
1022 fputc(j,tempfh);
1023 j = '\r';
1024 fputc(j,tempfh);
1025 j = '\n';
1026 fputc(j,tempfh);
1027 j = 'a';
1028 fputc(j,tempfh);
1029 fclose(tempfh);
1030 tempfh = fopen(tempf,"rt"); /* open in TEXT mode */
1031 ok(fgets(buffer,256,tempfh) != 0,"fgets failed unexpected\n");
1032 i=strlen(buffer);
1033 j=strlen(mytext);
1034 ok(i==j, "returned string length expected %d got %d\n", j, i);
1035 j+=4; /* ftell should indicate the true end of file */
1036 l=ftell(tempfh);
1037 ok(l==j, "ftell expected %d got %d\n", j, l);
1038 ok(feof(tempfh), "did not get EOF\n");
1039 fclose(tempfh);
1040
1041 tempfh = fopen(tempf,"rb"); /* open in BINARY mode */
1042 ok(fgets(buffer,256,tempfh) != 0,"fgets failed unexpected\n");
1043 i=strlen(buffer);
1044 j=strlen(mytext)+3; /* should get through newline */
1045 ok(i==j, "returned string length expected %d got %d\n", j, i);
1046 l=ftell(tempfh);
1047 ok(l==j, "ftell expected %d got %d\n", j, l);
1048 ok(fgets(buffer,256,tempfh) != 0,"fgets failed unexpected\n");
1049 i=strlen(buffer);
1050 ok(i==1, "returned string length expected %d got %d\n", 1, i);
1051 ok(feof(tempfh), "did not get EOF\n");
1052 fclose(tempfh);
1053 unlink(tempf);
1054 free(tempf);
1055 }
1056
1057 static void test_file_put_get( void )
1058 {
1059 char* tempf;
1060 FILE *tempfh;
1061 static const char mytext[]= "This is a test_file_put_get\n";
1062 static const char dostext[]= "This is a test_file_put_get\r\n";
1063 char btext[LLEN];
1064 WCHAR wtextW[LLEN+1];
1065 WCHAR *mytextW = NULL, *aptr, *wptr;
1066 BOOL diff_found = FALSE;
1067 unsigned int i;
1068
1069 tempf=_tempnam(".","wne");
1070 tempfh = fopen(tempf,"wt"); /* open in TEXT mode */
1071 fputs(mytext,tempfh);
1072 fclose(tempfh);
1073 tempfh = fopen(tempf,"rb"); /* open in TEXT mode */
1074 fgets(btext,LLEN,tempfh);
1075 ok( strlen(mytext) + 1 == strlen(btext),"TEXT/BINARY mode not handled for write\n");
1076 ok( btext[strlen(mytext)-1] == '\r', "CR not written\n");
1077 fclose(tempfh);
1078 tempfh = fopen(tempf,"wb"); /* open in BINARY mode */
1079 fputs(dostext,tempfh);
1080 fclose(tempfh);
1081 tempfh = fopen(tempf,"rt"); /* open in TEXT mode */
1082 fgets(btext,LLEN,tempfh);
1083 ok(strcmp(btext, mytext) == 0,"_O_TEXT read doesn't strip CR\n");
1084 fclose(tempfh);
1085 tempfh = fopen(tempf,"rb"); /* open in TEXT mode */
1086 fgets(btext,LLEN,tempfh);
1087 ok(strcmp(btext, dostext) == 0,"_O_BINARY read doesn't preserve CR\n");
1088
1089 fclose(tempfh);
1090 tempfh = fopen(tempf,"rt"); /* open in TEXT mode */
1091 fgetws(wtextW,LLEN,tempfh);
1092 mytextW = AtoW (mytext);
1093 aptr = mytextW;
1094 wptr = wtextW;
1095
1096 for (i=0; i<strlen(mytext); i++, aptr++, wptr++)
1097 {
1098 diff_found |= (*aptr != *wptr);
1099 }
1100 ok(!(diff_found), "fgetwc doesn't strip CR in TEXT mode\n");
1101 free(mytextW);
1102 fclose(tempfh);
1103 unlink(tempf);
1104 free(tempf);
1105 }
1106
1107 static void test_file_write_read( void )
1108 {
1109 char* tempf;
1110 int tempfd;
1111 static const char mytext[]= "This is test_file_write_read\nsecond line\n";
1112 static const char dostext[]= "This is test_file_write_read\r\nsecond line\r\n";
1113 char btext[LLEN];
1114 int ret, i;
1115
1116 tempf=_tempnam(".","wne");
1117 tempfd = _open(tempf,_O_CREAT|_O_TRUNC|_O_BINARY|_O_RDWR,
1118 _S_IREAD | _S_IWRITE);
1119 ok( tempfd != -1,
1120 "Can't open '%s': %d\n", tempf, errno); /* open in BINARY mode */
1121 ok(_write(tempfd,dostext,strlen(dostext)) == lstrlenA(dostext),
1122 "_write _O_BINARY bad return value\n");
1123 _close(tempfd);
1124 i = lstrlenA(mytext);
1125 tempfd = _open(tempf,_O_RDONLY|_O_BINARY,0); /* open in BINARY mode */
1126 ok(_read(tempfd,btext,i) == i,
1127 "_read _O_BINARY got bad length\n");
1128 ok( memcmp(dostext,btext,i) == 0,
1129 "problems with _O_BINARY _write / _read\n");
1130 _close(tempfd);
1131 tempfd = _open(tempf,_O_RDONLY|_O_TEXT); /* open in TEXT mode */
1132 ok(_read(tempfd,btext,i) == i-1,
1133 "_read _O_TEXT got bad length\n");
1134 ok( memcmp(mytext,btext,i-1) == 0,
1135 "problems with _O_BINARY _write / _O_TEXT _read\n");
1136 _close(tempfd);
1137 tempfd = _open(tempf,_O_CREAT|_O_TRUNC|_O_TEXT|_O_RDWR,
1138 _S_IREAD | _S_IWRITE);
1139 ok( tempfd != -1,
1140 "Can't open '%s': %d\n", tempf, errno); /* open in TEXT mode */
1141 ok(_write(tempfd,mytext,strlen(mytext)) == lstrlenA(mytext),
1142 "_write _O_TEXT bad return value\n");
1143 _close(tempfd);
1144 tempfd = _open(tempf,_O_RDONLY|_O_BINARY,0); /* open in BINARY mode */
1145 ok(_read(tempfd,btext,LLEN) == lstrlenA(dostext),
1146 "_read _O_BINARY got bad length\n");
1147 ok( memcmp(dostext,btext,strlen(dostext)) == 0,
1148 "problems with _O_TEXT _write / _O_BINARY _read\n");
1149 ok( btext[strlen(dostext)-2] == '\r', "CR not written or read\n");
1150 _close(tempfd);
1151 tempfd = _open(tempf,_O_RDONLY|_O_TEXT); /* open in TEXT mode */
1152 ok(_read(tempfd,btext,LLEN) == lstrlenA(mytext),
1153 "_read _O_TEXT got bad length\n");
1154 ok( memcmp(mytext,btext,strlen(mytext)) == 0,
1155 "problems with _O_TEXT _write / _read\n");
1156 _close(tempfd);
1157
1158 memset(btext, 0, LLEN);
1159 tempfd = _open(tempf,_O_APPEND|_O_RDWR); /* open for APPEND in default mode */
1160 ok(tell(tempfd) == 0, "bad position %u expecting 0\n", tell(tempfd));
1161 ok(_read(tempfd,btext,LLEN) == lstrlenA(mytext), "_read _O_APPEND got bad length\n");
1162 ok( memcmp(mytext,btext,strlen(mytext)) == 0, "problems with _O_APPEND _read\n");
1163 _close(tempfd);
1164
1165 /* Test reading only \n or \r */
1166 tempfd = _open(tempf,_O_RDONLY|_O_TEXT); /* open in TEXT mode */
1167 _lseek(tempfd, -1, FILE_END);
1168 ret = _read(tempfd,btext,LLEN);
1169 ok(ret == 1 && *btext == '\n', "_read expected 1 got bad length: %d\n", ret);
1170 _lseek(tempfd, -2, FILE_END);
1171 ret = _read(tempfd,btext,LLEN);
1172 ok(ret == 1 && *btext == '\n', "_read expected '\\n' got bad length: %d\n", ret);
1173 _lseek(tempfd, -2, FILE_END);
1174 ret = _read(tempfd,btext,1);
1175 ok(ret == 1 && *btext == '\n', "_read returned %d, buf: %d\n", ret, *btext);
1176 ret = read(tempfd,btext,1);
1177 ok(ret == 0, "_read returned %d, expected 0\n", ret);
1178 _lseek(tempfd, -3, FILE_END);
1179 ret = _read(tempfd,btext,1);
1180 ok(ret == 1 && *btext == 'e', "_read expected 'e' got \"%.*s\" bad length: %d\n", ret, btext, ret);
1181 ok(tell(tempfd) == 41, "bad position %u expecting 41\n", tell(tempfd));
1182 _lseek(tempfd, -3, FILE_END);
1183 ret = _read(tempfd,btext,2);
1184 ok(ret == 1 && *btext == 'e', "_read expected 'e' got \"%.*s\" bad length: %d\n", ret, btext, ret);
1185 ok(tell(tempfd) == 42, "bad position %u expecting 42\n", tell(tempfd));
1186 _lseek(tempfd, -3, FILE_END);
1187 ret = _read(tempfd,btext,3);
1188 ok(ret == 2 && *btext == 'e', "_read expected 'e' got \"%.*s\" bad length: %d\n", ret, btext, ret);
1189 ok(tell(tempfd) == 43, "bad position %u expecting 43\n", tell(tempfd));
1190 _close(tempfd);
1191
1192 ret = unlink(tempf);
1193 ok( ret == 0 ,"Can't unlink '%s': %d\n", tempf, errno);
1194 free(tempf);
1195
1196 tempf=_tempnam(".","wne");
1197 tempfd = _open(tempf, _O_CREAT|_O_TRUNC|_O_BINARY|_O_RDWR, _S_IWRITE);
1198 ok( tempfd != -1,
1199 "Can't open '%s': %d\n", tempf, errno); /* open in BINARY mode */
1200 ok(_write(tempfd,dostext,strlen(dostext)) == lstrlenA(dostext),
1201 "_write _O_BINARY bad return value\n");
1202 _close(tempfd);
1203 tempfd = _open(tempf,_O_RDONLY|_O_BINARY,0); /* open in BINARY mode */
1204 ok(_read(tempfd,btext,LLEN) == lstrlenA(dostext),
1205 "_read _O_BINARY got bad length\n");
1206 ok( memcmp(dostext,btext,strlen(dostext)) == 0,
1207 "problems with _O_BINARY _write / _read\n");
1208 ok( btext[strlen(dostext)-2] == '\r', "CR not written or read\n");
1209 _close(tempfd);
1210 tempfd = _open(tempf,_O_RDONLY|_O_TEXT); /* open in TEXT mode */
1211 ok(_read(tempfd,btext,LLEN) == lstrlenA(mytext),
1212 "_read _O_TEXT got bad length\n");
1213 ok( memcmp(mytext,btext,strlen(mytext)) == 0,
1214 "problems with _O_BINARY _write / _O_TEXT _read\n");
1215 _close(tempfd);
1216
1217 /* test _read with single bytes. CR should be skipped and LF pulled in */
1218 tempfd = _open(tempf,_O_RDONLY|_O_TEXT); /* open in TEXT mode */
1219 for (i=0; i<strlen(mytext); i++) /* */
1220 {
1221 _read(tempfd,btext, 1);
1222 ok(btext[0] == mytext[i],"_read failed at pos %d 0x%02x vs 0x%02x\n", i, btext[0], mytext[i]);
1223 }
1224 while (_read(tempfd,btext, 1));
1225 _close(tempfd);
1226
1227 /* test _read in buffered mode. Last CR should be skipped but LF not pulled in */
1228 tempfd = _open(tempf,_O_RDONLY|_O_TEXT); /* open in TEXT mode */
1229 i = _read(tempfd,btext, strlen(mytext));
1230 ok(i == strlen(mytext)-1, "_read_i %d\n", i);
1231 _close(tempfd);
1232
1233 /* test read/write in unicode mode */
1234 if(p_fopen_s)
1235 {
1236 tempfd = _open(tempf, _O_CREAT|_O_TRUNC|_O_WRONLY|_O_WTEXT, _S_IWRITE);
1237 ok(tempfd != -1, "_open failed with error: %d\n", errno);
1238 ret = _write(tempfd, "a", 1);
1239 ok(ret == -1, "_write returned %d, expected -1\n", ret);
1240 ret = _write(tempfd, "a\x00\n\x00\xff\xff", 6);
1241 ok(ret == 6, "_write returned %d, expected 6\n", ret);
1242 _close(tempfd);
1243
1244 tempfd = _open(tempf, _O_RDONLY|_O_BINARY, 0);
1245 ok(tempfd != -1, "_open failed with error: %d\n", errno);
1246 ret = _read(tempfd, btext, sizeof(btext));
1247 ok(ret == 10, "_read returned %d, expected 10\n", ret);
1248 ok(!memcmp(btext, "\xff\xfe\x61\x00\r\x00\n\x00\xff\xff", 10), "btext is incorrect\n");
1249 _close(tempfd);
1250
1251 tempfd = _open(tempf, _O_RDONLY|_O_WTEXT, 0);
1252 ok(tempfd != -1, "_open failed with error: %d\n", errno);
1253 errno = 0xdeadbeef;
1254 ret = _read(tempfd, btext, 3);
1255 ok(ret == -1, "_read returned %d, expected -1\n", ret);
1256 ok(errno == 22, "errno = %d\n", errno);
1257 ret = _read(tempfd, btext, sizeof(btext));
1258 ok(ret == 6, "_read returned %d, expected 6\n", ret);
1259 ok(!memcmp(btext, "\x61\x00\n\x00\xff\xff", 6), "btext is incorrect\n");
1260 _close(tempfd);
1261
1262 tempfd = _open(tempf, _O_CREAT|_O_TRUNC|_O_WRONLY|_O_U8TEXT, _S_IWRITE);
1263 ok(tempfd != -1, "_open failed with error: %d\n", errno);
1264 errno = 0xdeadbeef;
1265 ret = _write(tempfd, "a", 1);
1266 ok(ret == -1, "_write returned %d, expected -1\n", ret);
1267 ok(errno == 22, "errno = %d\n", errno);
1268 ret = _write(tempfd, "a\x00\n\x00\x62\x00", 6);
1269 ok(ret == 6, "_write returned %d, expected 6\n", ret);
1270 _close(tempfd);
1271
1272 tempfd = _open(tempf, _O_RDONLY|_O_BINARY, 0);
1273 ok(tempfd != -1, "_open failed with error: %d\n", errno);
1274 ret = _read(tempfd, btext, sizeof(btext));
1275 ok(ret == 7, "_read returned %d, expected 7\n", ret);
1276 ok(!memcmp(btext, "\xef\xbb\xbf\x61\r\n\x62", 7), "btext is incorrect\n");
1277 _close(tempfd);
1278
1279 tempfd = _open(tempf, _O_RDONLY|_O_WTEXT, 0);
1280 ok(tempfd != -1, "_open failed with error: %d\n", errno);
1281 ret = _read(tempfd, btext, sizeof(btext));
1282 ok(ret == 6, "_read returned %d, expected 6\n", ret);
1283 ok(!memcmp(btext, "\x61\x00\n\x00\x62\x00", 6), "btext is incorrect\n");
1284
1285 /* when buffer is small read sometimes fails in native implementation */
1286 lseek(tempfd, 3 /* skip bom */, SEEK_SET);
1287 ret = _read(tempfd, btext, 4);
1288 todo_wine ok(ret == -1, "_read returned %d, expected -1\n", ret);
1289
1290 lseek(tempfd, 6, SEEK_SET);
1291 ret = _read(tempfd, btext, 2);
1292 ok(ret == 2, "_read returned %d, expected 2\n", ret);
1293 ok(!memcmp(btext, "\x62\x00", 2), "btext is incorrect\n");
1294 _close(tempfd);
1295
1296 tempfd = _open(tempf, _O_CREAT|_O_TRUNC|_O_WRONLY|_O_BINARY, _S_IWRITE);
1297 ok(tempfd != -1, "_open failed with error: %d\n", errno);
1298 ret = _write(tempfd, "\xef\xbb\xbf\x61\xc4\x85\x62\xc5\xbc\r\r\n", 12);
1299 ok(ret == 12, "_write returned %d, expected 9\n", ret);
1300 _close(tempfd);
1301
1302 tempfd = _open(tempf, _O_RDONLY|_O_WTEXT, 0);
1303 ok(tempfd != -1, "_open failed with error: %d\n", errno);
1304 ret = _read(tempfd, btext, sizeof(btext));
1305 ok(ret == 12, "_read returned %d, expected 12\n", ret);
1306 ok(!memcmp(btext, "\x61\x00\x05\x01\x62\x00\x7c\x01\x0d\x00\x0a\x00", 12), "btext is incorrect\n");
1307
1308 /* test invalid utf8 sequence */
1309 lseek(tempfd, 5, SEEK_SET);
1310 ret = _read(tempfd, btext, sizeof(btext));
1311 todo_wine ok(ret == 10, "_read returned %d, expected 10\n", ret);
1312 /* invalid char should be replaced by U+FFFD in MultiByteToWideChar */
1313 todo_wine ok(!memcmp(btext, "\xfd\xff", 2), "invalid UTF8 character was not replaced by U+FFFD\n");
1314 ok(!memcmp(btext+ret-8, "\x62\x00\x7c\x01\x0d\x00\x0a\x00", 8), "btext is incorrect\n");
1315 _close(tempfd);
1316 }
1317 else
1318 {
1319 win_skip("unicode mode tests on file\n");
1320 }
1321
1322 ret =_chmod (tempf, _S_IREAD | _S_IWRITE);
1323 ok( ret == 0,
1324 "Can't chmod '%s' to read-write: %d\n", tempf, errno);
1325 ret = unlink(tempf);
1326 ok( ret == 0 ,"Can't unlink '%s': %d\n", tempf, errno);
1327 free(tempf);
1328 }
1329
1330 static void test_file_inherit_child(const char* fd_s)
1331 {
1332 int fd = atoi(fd_s);
1333 char buffer[32];
1334 int ret;
1335
1336 ret =write(fd, "Success", 8);
1337 ok( ret == 8, "Couldn't write in child process on %d (%s)\n", fd, strerror(errno));
1338 lseek(fd, 0, SEEK_SET);
1339 ok(read(fd, buffer, sizeof (buffer)) == 8, "Couldn't read back the data\n");
1340 ok(memcmp(buffer, "Success", 8) == 0, "Couldn't read back the data\n");
1341 }
1342
1343 static void test_file_inherit_child_no(const char* fd_s)
1344 {
1345 int fd = atoi(fd_s);
1346 int ret;
1347
1348 ret = write(fd, "Success", 8);
1349 ok( ret == -1 && errno == EBADF,
1350 "Wrong write result in child process on %d (%s)\n", fd, strerror(errno));
1351 }
1352
1353 static void create_io_inherit_block( STARTUPINFOA *startup, unsigned int count, const HANDLE *handles )
1354 {
1355 static BYTE block[1024];
1356 BYTE *wxflag_ptr;
1357 HANDLE *handle_ptr;
1358 unsigned int i;
1359
1360 startup->lpReserved2 = block;
1361 startup->cbReserved2 = sizeof(unsigned) + (sizeof(char) + sizeof(HANDLE)) * count;
1362 wxflag_ptr = block + sizeof(unsigned);
1363 handle_ptr = (HANDLE *)(wxflag_ptr + count);
1364
1365 *(unsigned*)block = count;
1366 for (i = 0; i < count; i++)
1367 {
1368 wxflag_ptr[i] = 0x81;
1369 handle_ptr[i] = handles[i];
1370 }
1371 }
1372
1373 static const char *read_file( HANDLE file )
1374 {
1375 static char buffer[128];
1376 DWORD ret;
1377 SetFilePointer( file, 0, NULL, FILE_BEGIN );
1378 if (!ReadFile( file, buffer, sizeof(buffer) - 1, &ret, NULL)) ret = 0;
1379 buffer[ret] = 0;
1380 return buffer;
1381 }
1382
1383 static void test_stdout_handle( STARTUPINFOA *startup, char *cmdline, HANDLE hstdout, BOOL expect_stdout,
1384 const char *descr )
1385 {
1386 const char *data;
1387 HANDLE hErrorFile;
1388 SECURITY_ATTRIBUTES sa;
1389 PROCESS_INFORMATION proc;
1390
1391 /* make file handle inheritable */
1392 sa.nLength = sizeof(sa);
1393 sa.lpSecurityDescriptor = NULL;
1394 sa.bInheritHandle = TRUE;
1395
1396 hErrorFile = CreateFileA( "fdopen.err", GENERIC_READ|GENERIC_WRITE,
1397 FILE_SHARE_READ | FILE_SHARE_WRITE, &sa, CREATE_ALWAYS, 0, NULL );
1398 startup->dwFlags = STARTF_USESTDHANDLES;
1399 startup->hStdInput = GetStdHandle( STD_INPUT_HANDLE );
1400 startup->hStdOutput = hErrorFile;
1401 startup->hStdError = GetStdHandle( STD_ERROR_HANDLE );
1402
1403 CreateProcessA( NULL, cmdline, NULL, NULL, TRUE,
1404 CREATE_DEFAULT_ERROR_MODE | NORMAL_PRIORITY_CLASS, NULL, NULL, startup, &proc );
1405 winetest_wait_child_process( proc.hProcess );
1406
1407 data = read_file( hErrorFile );
1408 if (expect_stdout)
1409 ok( strcmp( data, "Success" ), "%s: Error file shouldn't contain data\n", descr );
1410 else
1411 ok( !strcmp( data, "Success" ), "%s: Wrong error data (%s)\n", descr, data );
1412
1413 if (hstdout)
1414 {
1415 data = read_file( hstdout );
1416 if (expect_stdout)
1417 ok( !strcmp( data, "Success" ), "%s: Wrong stdout data (%s)\n", descr, data );
1418 else
1419 ok( strcmp( data, "Success" ), "%s: Stdout file shouldn't contain data\n", descr );
1420 }
1421
1422 CloseHandle( hErrorFile );
1423 DeleteFileA( "fdopen.err" );
1424 }
1425
1426 static void test_file_inherit( const char* selfname )
1427 {
1428 int fd;
1429 const char* arg_v[5];
1430 char buffer[16];
1431 char cmdline[MAX_PATH];
1432 STARTUPINFOA startup;
1433 SECURITY_ATTRIBUTES sa;
1434 HANDLE handles[3];
1435
1436 fd = open ("fdopen.tst", O_CREAT | O_RDWR | O_BINARY, _S_IREAD |_S_IWRITE);
1437 ok(fd != -1, "Couldn't create test file\n");
1438 arg_v[0] = get_base_name(selfname);
1439 arg_v[1] = "tests/file.c";
1440 arg_v[2] = "inherit";
1441 arg_v[3] = buffer; sprintf(buffer, "%d", fd);
1442 arg_v[4] = 0;
1443 _spawnvp(_P_WAIT, selfname, arg_v);
1444 ok(tell(fd) == 8, "bad position %u expecting 8\n", tell(fd));
1445 lseek(fd, 0, SEEK_SET);
1446 ok(read(fd, buffer, sizeof (buffer)) == 8 && memcmp(buffer, "Success", 8) == 0, "Couldn't read back the data\n");
1447 close (fd);
1448 ok(unlink("fdopen.tst") == 0, "Couldn't unlink\n");
1449
1450 fd = open ("fdopen.tst", O_CREAT | O_RDWR | O_BINARY | O_NOINHERIT, _S_IREAD |_S_IWRITE);
1451 ok(fd != -1, "Couldn't create test file\n");
1452 arg_v[1] = "tests/file.c";
1453 arg_v[2] = "inherit_no";
1454 arg_v[3] = buffer; sprintf(buffer, "%d", fd);
1455 arg_v[4] = 0;
1456 _spawnvp(_P_WAIT, selfname, arg_v);
1457 ok(tell(fd) == 0, "bad position %u expecting 0\n", tell(fd));
1458 ok(read(fd, buffer, sizeof (buffer)) == 0, "Found unexpected data (%s)\n", buffer);
1459 close (fd);
1460 ok(unlink("fdopen.tst") == 0, "Couldn't unlink\n");
1461
1462 /* make file handle inheritable */
1463 sa.nLength = sizeof(sa);
1464 sa.lpSecurityDescriptor = NULL;
1465 sa.bInheritHandle = TRUE;
1466 sprintf(cmdline, "%s file inherit 1", selfname);
1467
1468 /* init an empty Reserved2, which should not be recognized as inherit-block */
1469 ZeroMemory(&startup, sizeof(startup));
1470 startup.cb = sizeof(startup);
1471 create_io_inherit_block( &startup, 0, NULL );
1472 test_stdout_handle( &startup, cmdline, 0, FALSE, "empty block" );
1473
1474 /* test with valid inheritblock */
1475 handles[0] = GetStdHandle( STD_INPUT_HANDLE );
1476 handles[1] = CreateFileA( "fdopen.tst", GENERIC_READ|GENERIC_WRITE,
1477 FILE_SHARE_READ | FILE_SHARE_WRITE, &sa, CREATE_ALWAYS, 0, NULL );
1478 handles[2] = GetStdHandle( STD_ERROR_HANDLE );
1479 create_io_inherit_block( &startup, 3, handles );
1480 test_stdout_handle( &startup, cmdline, handles[1], TRUE, "valid block" );
1481 CloseHandle( handles[1] );
1482 DeleteFileA("fdopen.tst");
1483
1484 /* test inherit block starting with unsigned zero */
1485 handles[1] = CreateFileA( "fdopen.tst", GENERIC_READ|GENERIC_WRITE,
1486 FILE_SHARE_READ | FILE_SHARE_WRITE, &sa, CREATE_ALWAYS, 0, NULL );
1487 create_io_inherit_block( &startup, 3, handles );
1488 *(unsigned int *)startup.lpReserved2 = 0;
1489 test_stdout_handle( &startup, cmdline, handles[1], FALSE, "zero count block" );
1490 CloseHandle( handles[1] );
1491 DeleteFileA("fdopen.tst");
1492
1493 /* test inherit block with smaller size */
1494 handles[1] = CreateFileA( "fdopen.tst", GENERIC_READ|GENERIC_WRITE,
1495 FILE_SHARE_READ | FILE_SHARE_WRITE, &sa, CREATE_ALWAYS, 0, NULL );
1496 create_io_inherit_block( &startup, 3, handles );
1497 startup.cbReserved2 -= 3;
1498 test_stdout_handle( &startup, cmdline, handles[1], TRUE, "small size block" );
1499 CloseHandle( handles[1] );
1500 DeleteFileA("fdopen.tst");
1501
1502 /* test inherit block with even smaller size */
1503 handles[1] = CreateFileA( "fdopen.tst", GENERIC_READ|GENERIC_WRITE,
1504 FILE_SHARE_READ | FILE_SHARE_WRITE, &sa, CREATE_ALWAYS, 0, NULL );
1505 create_io_inherit_block( &startup, 3, handles );
1506 startup.cbReserved2 = sizeof(unsigned int) + sizeof(HANDLE) + sizeof(char);
1507 test_stdout_handle( &startup, cmdline, handles[1], FALSE, "smaller size block" );
1508 CloseHandle( handles[1] );
1509 DeleteFileA("fdopen.tst");
1510
1511 /* test inherit block with larger size */
1512 handles[1] = CreateFileA( "fdopen.tst", GENERIC_READ|GENERIC_WRITE,
1513 FILE_SHARE_READ | FILE_SHARE_WRITE, &sa, CREATE_ALWAYS, 0, NULL );
1514 create_io_inherit_block( &startup, 3, handles );
1515 startup.cbReserved2 += 7;
1516 test_stdout_handle( &startup, cmdline, handles[1], TRUE, "large size block" );
1517 CloseHandle( handles[1] );
1518 DeleteFileA("fdopen.tst");
1519 }
1520
1521 static void test_tmpnam( void )
1522 {
1523 char name[MAX_PATH] = "abc";
1524 char *res;
1525
1526 res = tmpnam(NULL);
1527 ok(res != NULL, "tmpnam returned NULL\n");
1528 ok(res[0] == '\\', "first character is not a backslash\n");
1529 ok(strchr(res+1, '\\') == 0, "file not in the root directory\n");
1530 ok(res[strlen(res)-1] == '.', "first call - last character is not a dot\n");
1531
1532 res = tmpnam(name);
1533 ok(res != NULL, "tmpnam returned NULL\n");
1534 ok(res == name, "supplied buffer was not used\n");
1535 ok(res[0] == '\\', "first character is not a backslash\n");
1536 ok(strchr(res+1, '\\') == 0, "file not in the root directory\n");
1537 ok(res[strlen(res)-1] != '.', "second call - last character is a dot\n");
1538 }
1539
1540 static void test_chsize( void )
1541 {
1542 int fd;
1543 LONG cur, pos, count;
1544 char temptext[] = "012345678";
1545 char *tempfile = _tempnam( ".", "tst" );
1546
1547 ok( tempfile != NULL, "Couldn't create test file: %s\n", tempfile );
1548
1549 fd = _open( tempfile, _O_CREAT|_O_TRUNC|_O_RDWR, _S_IREAD|_S_IWRITE );
1550 ok( fd > 0, "Couldn't open test file\n" );
1551
1552 count = _write( fd, temptext, sizeof(temptext) );
1553 ok( count > 0, "Couldn't write to test file\n" );
1554
1555 /* get current file pointer */
1556 cur = _lseek( fd, 0, SEEK_CUR );
1557
1558 /* make the file smaller */
1559 ok( _chsize( fd, sizeof(temptext) / 2 ) == 0, "_chsize() failed\n" );
1560
1561 pos = _lseek( fd, 0, SEEK_CUR );
1562 ok( cur == pos, "File pointer changed from: %d to: %d\n", cur, pos );
1563 ok( _filelength( fd ) == sizeof(temptext) / 2, "Wrong file size\n" );
1564
1565 /* enlarge the file */
1566 ok( _chsize( fd, sizeof(temptext) * 2 ) == 0, "_chsize() failed\n" );
1567
1568 pos = _lseek( fd, 0, SEEK_CUR );
1569 ok( cur == pos, "File pointer changed from: %d to: %d\n", cur, pos );
1570 ok( _filelength( fd ) == sizeof(temptext) * 2, "Wrong file size\n" );
1571
1572 _close( fd );
1573 _unlink( tempfile );
1574 free( tempfile );
1575 }
1576
1577 static void test_fopen_fclose_fcloseall( void )
1578 {
1579 char fname1[] = "empty1";
1580 char fname2[] = "empty2";
1581 char fname3[] = "empty3";
1582 FILE *stream1, *stream2, *stream3, *stream4;
1583 int ret, numclosed;
1584
1585 /* testing fopen() */
1586 stream1 = fopen(fname1, "w+");
1587 ok(stream1 != NULL, "The file '%s' was not opened\n", fname1);
1588 stream2 = fopen(fname2, "w ");
1589 ok(stream2 != NULL, "The file '%s' was not opened\n", fname2 );
1590 _unlink(fname3);
1591 stream3 = fopen(fname3, "r");
1592 ok(stream3 == NULL, "The file '%s' shouldn't exist before\n", fname3 );
1593 stream3 = fopen(fname3, "w+");
1594 ok(stream3 != NULL, "The file '%s' should be opened now\n", fname3 );
1595 errno = 0xfaceabad;
1596 stream4 = fopen("", "w+");
1597 ok(stream4 == NULL && (errno == EINVAL || errno == ENOENT),
1598 "filename is empty, errno = %d (expected 2 or 22)\n", errno);
1599 errno = 0xfaceabad;
1600 stream4 = fopen(NULL, "w+");
1601 ok(stream4 == NULL && (errno == EINVAL || errno == ENOENT),
1602 "filename is NULL, errno = %d (expected 2 or 22)\n", errno);
1603
1604 /* testing fclose() */
1605 ret = fclose(stream2);
1606 ok(ret == 0, "The file '%s' was not closed\n", fname2);
1607 ret = fclose(stream3);
1608 ok(ret == 0, "The file '%s' was not closed\n", fname3);
1609 ret = fclose(stream2);
1610 ok(ret == EOF, "Closing file '%s' returned %d\n", fname2, ret);
1611 ret = fclose(stream3);
1612 ok(ret == EOF, "Closing file '%s' returned %d\n", fname3, ret);
1613
1614 /* testing fcloseall() */
1615 numclosed = _fcloseall();
1616 /* fname1 should be closed here */
1617 ok(numclosed == 1, "Number of files closed by fcloseall(): %u\n", numclosed);
1618 numclosed = _fcloseall();
1619 ok(numclosed == 0, "Number of files closed by fcloseall(): %u\n", numclosed);
1620
1621 ok(_unlink(fname1) == 0, "Couldn't unlink file named '%s'\n", fname1);
1622 ok(_unlink(fname2) == 0, "Couldn't unlink file named '%s'\n", fname2);
1623 ok(_unlink(fname3) == 0, "Couldn't unlink file named '%s'\n", fname3);
1624 }
1625
1626 static void test_fopen_s( void )
1627 {
1628 const char name[] = "empty1";
1629 char buff[16];
1630 unsigned char *ubuff = (unsigned char*)buff;
1631 FILE *file, *file2;
1632 int ret;
1633 int len;
1634
1635 if (!p_fopen_s)
1636 {
1637 win_skip("Skipping fopen_s test\n");
1638 return;
1639 }
1640 /* testing fopen_s */
1641 ret = p_fopen_s(&file, name, "w");
1642 ok(ret == 0, "fopen_s failed with %d\n", ret);
1643 ok(file != 0, "fopen_s failed to return value\n");
1644 fwrite(name, sizeof(name), 1, file);
1645
1646 ret = fclose(file);
1647 ok(ret != EOF, "File failed to close\n");
1648
1649 file = fopen(name, "r");
1650 ok(file != 0, "fopen failed\n");
1651 len = fread(buff, 1, sizeof(name), file);
1652 ok(len == sizeof(name), "File length is %d\n", len);
1653 buff[sizeof(name)] = '\0';
1654 ok(strcmp(name, buff) == 0, "File content mismatch! Got %s, expected %s\n", buff, name);
1655
1656 ret = fclose(file);
1657 ok(ret != EOF, "File failed to close\n");
1658
1659 ret = p_fopen_s(&file, name, "w, ccs=UNIcode");
1660 ok(ret == 0, "fopen_s failed with %d\n", ret);
1661 ret = fwrite("a", 1, 2, file);
1662 ok(ret == 2, "fwrite returned %d\n", ret);
1663 fclose(file);
1664
1665 ret = p_fopen_s(&file, name, "r");
1666 ok(ret == 0, "fopen_s failed with %d\n", ret);
1667 len = fread(buff, 1, 2, file);
1668 ok(len == 2, "len = %d\n", len);
1669 ok(ubuff[0]==0xff && ubuff[1]==0xfe, "buff[0]=%02x, buff[1]=%02x\n",
1670 ubuff[0], ubuff[1]);
1671 fclose(file);
1672
1673 ret = p_fopen_s(&file, name, "r,ccs=unicode");
1674 ok(ret == 0, "fopen_s failed with %d\n", ret);
1675 len = fread(buff, 1, 2, file);
1676 ok(len == 2, "len = %d\n", len);
1677 ok(ubuff[0]=='a' && ubuff[1]==0, "buff[0]=%02x, buff[1]=%02x\n",
1678 ubuff[0], ubuff[1]);
1679 fclose(file);
1680
1681 ret = p_fopen_s(&file, name, "r,ccs=utf-16le");
1682 ok(ret == 0, "fopen_s failed with %d\n", ret);
1683 len = fread(buff, 1, 2, file);
1684 ok(len == 2, "len = %d\n", len);
1685 ok(ubuff[0]=='a' && ubuff[1]==0, "buff[0]=%02x, buff[1]=%02x\n",
1686 ubuff[0], ubuff[1]);
1687 fclose(file);
1688
1689 ret = p_fopen_s(&file, name, "r,ccs=utf-8");
1690 ok(ret == 0, "fopen_s failed with %d\n", ret);
1691 len = fread(buff, 1, 2, file);
1692 ok(len == 2, "len = %d\n", len);
1693 ok(ubuff[0]=='a' && ubuff[1]==0, "buff[0]=%02x, buff[1]=%02x\n",
1694 ubuff[0], ubuff[1]);
1695 fclose(file);
1696
1697 ret = p_fopen_s(&file, name, "w,ccs=utf-16le");
1698 ok(ret == 0, "fopen_s failed with %d\n", ret);
1699 fclose(file);
1700
1701 ret = p_fopen_s(&file, name, "r");
1702 ok(ret == 0, "fopen_s failed with %d\n", ret);
1703 len = fread(buff, 1, 3, file);
1704 ok(len == 2, "len = %d\n", len);
1705 ok(ubuff[0]==0xff && ubuff[1]==0xfe, "buff[0]=%02x, buff[1]=%02x\n",
1706 ubuff[0], ubuff[1]);
1707 fclose(file);
1708
1709 ret = p_fopen_s(&file, name, "w,ccs=utf-8");
1710 ok(ret == 0, "fopen_s failed with %d\n", ret);
1711 fclose(file);
1712
1713 ret = p_fopen_s(&file, name, "r");
1714 ok(ret == 0, "fopen_s failed with %d\n", ret);
1715 len = fread(buff, 1, 4, file);
1716 ok(len == 3, "len = %d\n", len);
1717 ok(ubuff[0]==0xef && ubuff[1]==0xbb && ubuff[2]==0xbf,
1718 "buff[0]=%02x, buff[1]=%02x, buff[2]=%02x\n",
1719 ubuff[0], ubuff[1], ubuff[2]);
1720 fclose(file);
1721
1722 /* test initial FILE values */
1723 memset(file, 0xfe, sizeof(*file));
1724 file->_flag = 0;
1725 ret = p_fopen_s(&file2, name, "r");
1726 ok(!ret, "fopen_s failed with %d\n", ret);
1727 ok(file == file2, "file != file2 %p %p\n", file, file2);
1728 ok(!file->_ptr, "file->_ptr != NULL\n");
1729 ok(!file->_cnt, "file->_cnt != 0\n");
1730 ok(!file->_base, "file->_base != NULL\n");
1731 ok(file->_flag == 1, "file->_flag = %x\n", file->_flag);
1732 ok(file->_file, "file->_file == 0\n");
1733 ok(file->_charbuf == 0xfefefefe, "file->_charbuf = %x\n", file->_charbuf);
1734 ok(file->_bufsiz == 0xfefefefe, "file->_bufsiz = %x\n", file->_bufsiz);
1735 ok(!file->_tmpfname, "file->_tmpfname != NULL\n");
1736 fclose(file2);
1737
1738 ok(_unlink(name) == 0, "Couldn't unlink file named '%s'\n", name);
1739 }
1740
1741 static void test__wfopen_s( void )
1742 {
1743 const char name[] = "empty1";
1744 const WCHAR wname[] = {
1745 'e','m','p','t','y','1',0
1746 };
1747 const WCHAR wmode[] = {
1748 'w',0
1749 };
1750 char buff[16];
1751 FILE *file;
1752 int ret;
1753 int len;
1754
1755 if (!p__wfopen_s)
1756 {
1757 win_skip("Skipping _wfopen_s test\n");
1758 return;
1759 }
1760 /* testing _wfopen_s */
1761 ret = p__wfopen_s(&file, wname, wmode);
1762 ok(ret == 0, "_wfopen_s failed with %d\n", ret);
1763 ok(file != 0, "_wfopen_s failed to return value\n");
1764 fwrite(name, sizeof(name), 1, file);
1765
1766 ret = fclose(file);
1767 ok(ret != EOF, "File failed to close\n");
1768
1769 file = fopen(name, "r");
1770 ok(file != 0, "fopen failed\n");
1771 len = fread(buff, 1, sizeof(name), file);
1772 ok(len == sizeof(name), "File length is %d\n", len);
1773 buff[sizeof(name)] = '\0';
1774 ok(strcmp(name, buff) == 0, "File content mismatch! Got %s, expected %s\n", buff, name);
1775
1776 ret = fclose(file);
1777 ok(ret != EOF, "File failed to close\n");
1778
1779 ok(_unlink(name) == 0, "Couldn't unlink file named '%s'\n", name);
1780 }
1781
1782 static void test_setmode(void)
1783 {
1784 const char name[] = "empty1";
1785 int fd, ret;
1786
1787 if(!p_fopen_s) {
1788 win_skip("unicode file modes are not available, skipping setmode tests\n");
1789 return;
1790 }
1791
1792 errno = 0xdeadbeef;
1793 ret = _setmode(-2, 0);
1794 ok(ret == -1, "_setmode returned %x, expected -1\n", ret);
1795 ok(errno == EINVAL, "errno = %d\n", errno);
1796
1797 errno = 0xdeadbeef;
1798 ret = _setmode(-2, _O_TEXT);
1799 ok(ret == -1, "_setmode returned %x, expected -1\n", ret);
1800 ok(errno == EBADF, "errno = %d\n", errno);
1801
1802 fd = _open(name, _O_CREAT|_O_WRONLY, _S_IWRITE);
1803 ok(fd != -1, "failed to open file\n");
1804
1805 errno = 0xdeadbeef;
1806 ret = _setmode(fd, 0xffffffff);
1807 ok(ret == -1, "_setmode returned %x, expected -1\n", ret);
1808 ok(errno == EINVAL, "errno = %d\n", errno);
1809
1810 errno = 0xdeadbeef;
1811 ret = _setmode(fd, 0);
1812 ok(ret == -1, "_setmode returned %x, expected -1\n", ret);
1813 ok(errno == EINVAL, "errno = %d\n", errno);
1814
1815 errno = 0xdeadbeef;
1816 ret = _setmode(fd, _O_BINARY|_O_TEXT);
1817 ok(ret == -1, "_setmode returned %x, expected -1\n", ret);
1818 ok(errno == EINVAL, "errno = %d\n", errno);
1819
1820 errno = 0xdeadbeef;
1821 ret = _setmode(fd, _O_WTEXT|_O_U16TEXT);
1822 ok(ret == -1, "_setmode returned %x, expected -1\n", ret);
1823 ok(errno == EINVAL, "errno = %d\n", errno);
1824
1825 ret = _setmode(fd, _O_BINARY);
1826 ok(ret == _O_TEXT, "_setmode returned %x, expected _O_TEXT\n", ret);
1827
1828 ret = _setmode(fd, _O_WTEXT);
1829 ok(ret == _O_BINARY, "_setmode returned %x, expected _O_BINARY\n", ret);
1830
1831 ret = _setmode(fd, _O_TEXT);
1832 ok(ret == _O_WTEXT, "_setmode returned %x, expected _O_WTEXT\n", ret);
1833
1834 ret = _setmode(fd, _O_U16TEXT);
1835 ok(ret == _O_TEXT, "_setmode returned %x, expected _O_TEXT\n", ret);
1836
1837 ret = _setmode(fd, _O_U8TEXT);
1838 ok(ret == _O_WTEXT, "_setmode returned %x, expected _O_WTEXT\n", ret);
1839
1840 ret = _setmode(fd, _O_TEXT);
1841 ok(ret == _O_WTEXT, "_setmode returned %x, expected _O_WTEXT\n", ret);
1842
1843 _close(fd);
1844 _unlink(name);
1845 }
1846
1847 static void test_get_osfhandle(void)
1848 {
1849 int fd;
1850 char fname[] = "t_get_osfhanle";
1851 DWORD bytes_written;
1852 HANDLE handle;
1853
1854 fd = _sopen(fname, _O_CREAT|_O_RDWR, _SH_DENYRW, _S_IREAD | _S_IWRITE);
1855 handle = (HANDLE)_get_osfhandle(fd);
1856 WriteFile(handle, "bar", 3, &bytes_written, NULL);
1857 _close(fd);
1858 fd = _open(fname, _O_RDONLY, 0);
1859 ok(fd != -1, "Couldn't open '%s' after _get_osfhandle()\n", fname);
1860
1861 _close(fd);
1862 _unlink(fname);
1863
1864 errno = 0xdeadbeef;
1865 handle = (HANDLE)_get_osfhandle(fd);
1866 ok(handle == INVALID_HANDLE_VALUE, "_get_osfhandle returned %p\n", handle);
1867 ok(errno == EBADF, "errno = %d\n", errno);
1868 }
1869
1870 static void test_setmaxstdio(void)
1871 {
1872 ok(2048 == _setmaxstdio(2048),"_setmaxstdio returned %d instead of 2048\n",_setmaxstdio(2048));
1873 ok(-1 == _setmaxstdio(2049),"_setmaxstdio returned %d instead of -1\n",_setmaxstdio(2049));
1874 }
1875
1876 static void test_stat(void)
1877 {
1878 int fd;
1879 int pipes[2];
1880 int ret;
1881 struct stat buf;
1882
1883 /* Tests for a file */
1884 fd = open("stat.tst", O_WRONLY | O_CREAT | O_BINARY, _S_IREAD |_S_IWRITE);
1885 if (fd >= 0)
1886 {
1887 ret = fstat(fd, &buf);
1888 ok(!ret, "fstat failed: errno=%d\n", errno);
1889 ok((buf.st_mode & _S_IFMT) == _S_IFREG, "bad format = %06o\n", buf.st_mode);
1890 ok((buf.st_mode & 0777) == 0666, "bad st_mode = %06o\n", buf.st_mode);
1891 ok(buf.st_dev == 0, "st_dev is %d, expected 0\n", buf.st_dev);
1892 ok(buf.st_dev == buf.st_rdev, "st_dev (%d) and st_rdev (%d) differ\n", buf.st_dev, buf.st_rdev);
1893 ok(buf.st_nlink == 1, "st_nlink is %d, expected 1\n", buf.st_nlink);
1894 ok(buf.st_size == 0, "st_size is %d, expected 0\n", buf.st_size);
1895
1896 ret = stat("stat.tst", &buf);
1897 ok(!ret, "stat failed: errno=%d\n", errno);
1898 ok((buf.st_mode & _S_IFMT) == _S_IFREG, "bad format = %06o\n", buf.st_mode);
1899 ok((buf.st_mode & 0777) == 0666, "bad st_mode = %06o\n", buf.st_mode);
1900 ok(buf.st_dev == buf.st_rdev, "st_dev (%d) and st_rdev (%d) differ\n", buf.st_dev, buf.st_rdev);
1901 ok(buf.st_nlink == 1, "st_nlink is %d, expected 1\n", buf.st_nlink);
1902 ok(buf.st_size == 0, "st_size is %d, expected 0\n", buf.st_size);
1903
1904 errno = 0xdeadbeef;
1905 ret = stat("stat.tst\\", &buf);
1906 ok(ret == -1, "stat returned %d\n", ret);
1907 ok(errno == ENOENT, "errno = %d\n", errno);
1908
1909 close(fd);
1910 remove("stat.tst");
1911 }
1912 else
1913 skip("open failed with errno %d\n", errno);
1914
1915 /* Tests for a char device */
1916 if (_dup2(0, 10) == 0)
1917 {
1918 ret = fstat(10, &buf);
1919 ok(!ret, "fstat(stdin) failed: errno=%d\n", errno);
1920 if ((buf.st_mode & _S_IFMT) == _S_IFCHR)
1921 {
1922 ok(buf.st_mode == _S_IFCHR, "bad st_mode=%06o\n", buf.st_mode);
1923 ok(buf.st_dev == 10, "st_dev is %d, expected 10\n", buf.st_dev);
1924 ok(buf.st_rdev == 10, "st_rdev is %d, expected 10\n", buf.st_rdev);
1925 ok(buf.st_nlink == 1, "st_nlink is %d, expected 1\n", buf.st_nlink);
1926 }
1927 else
1928 skip("stdin is not a char device? st_mode=%06o\n", buf.st_mode);
1929 close(10);
1930 }
1931 else
1932 skip("_dup2 failed with errno %d\n", errno);
1933
1934 /* Tests for pipes */
1935 if (_pipe(pipes, 1024, O_BINARY) == 0)
1936 {
1937 ret = fstat(pipes[0], &buf);
1938 ok(!ret, "fstat(pipe) failed: errno=%d\n", errno);
1939 ok(buf.st_mode == _S_IFIFO, "bad st_mode=%06o\n", buf.st_mode);
1940 ok(buf.st_dev == pipes[0], "st_dev is %d, expected %d\n", buf.st_dev, pipes[0]);
1941 ok(buf.st_rdev == pipes[0], "st_rdev is %d, expected %d\n", buf.st_rdev, pipes[0]);
1942 ok(buf.st_nlink == 1, "st_nlink is %d, expected 1\n", buf.st_nlink);
1943 close(pipes[0]);
1944 close(pipes[1]);
1945 }
1946 else
1947 skip("pipe failed with errno %d\n", errno);
1948
1949 /* Tests for directory */
1950 if(mkdir("stat.tst") == 0)
1951 {
1952 ret = stat("stat.tst ", &buf);
1953 ok(!ret, "stat(directory) failed: errno=%d\n", errno);
1954 ok((buf.st_mode & _S_IFMT) == _S_IFDIR, "bad format = %06o\n", buf.st_mode);
1955 ok((buf.st_mode & 0777) == 0777, "bad st_mode = %06o\n", buf.st_mode);
1956 ok(buf.st_dev == buf.st_rdev, "st_dev (%d) and st_rdev (%d) differ\n", buf.st_dev, buf.st_rdev);
1957 ok(buf.st_nlink == 1, "st_nlink is %d, expected 1\n", buf.st_nlink);
1958
1959 errno = 0xdeadbeef;
1960 ret = stat("stat.tst\\ ", &buf);
1961 ok(ret == -1, "stat returned %d\n", ret);
1962 ok(errno == ENOENT, "errno = %d\n", errno);
1963 rmdir( "stat.tst" );
1964 }
1965 else
1966 skip("mkdir failed with errno %d\n", errno);
1967
1968 errno = 0xdeadbeef;
1969 ret = stat("c:", &buf);
1970 ok(ret == -1, "stat returned %d\n", ret);
1971 ok(errno == ENOENT, "errno = %d\n", errno);
1972
1973 ret = stat("c:/", &buf);
1974 ok(!ret, "stat returned %d\n", ret);
1975 ok(buf.st_dev == 2, "st_dev = %d\n", buf.st_dev);
1976 ok(buf.st_rdev == 2, "st_rdev = %d\n", buf.st_rdev);
1977 }
1978
1979 static const char* pipe_string="Hello world";
1980
1981 /* How many messages to transfer over the pipe */
1982 #define N_TEST_MESSAGES 3
1983
1984 static void test_pipes_child(int argc, char** args)
1985 {
1986 int fd;
1987 int nwritten;
1988 int i;
1989
1990 if (argc < 5)
1991 {
1992 ok(0, "not enough parameters: %d\n", argc);
1993 return;
1994 }
1995
1996 fd=atoi(args[3]);
1997 i=close(fd);
1998 ok(!i, "unable to close %d: %d\n", fd, errno);
1999
2000 fd=atoi(args[4]);
2001
2002 for (i=0; i<N_TEST_MESSAGES; i++) {
2003 nwritten=write(fd, pipe_string, strlen(pipe_string));
2004 ok(nwritten == strlen(pipe_string), "i %d, expected to write '%s' wrote %d\n", i, pipe_string, nwritten);
2005 /* let other process wake up so they can show off their "keep reading until EOF" behavior */
2006 if (i < N_TEST_MESSAGES-1)
2007 Sleep(100);
2008 }
2009
2010 i=close(fd);
2011 ok(!i, "unable to close %d: %d\n", fd, errno);
2012 }
2013
2014 static void test_pipes(const char* selfname)
2015 {
2016 int pipes[2];
2017 char str_fdr[12], str_fdw[12];
2018 FILE* file;
2019 const char* arg_v[6];
2020 char buf[4096];
2021 char expected[4096];
2022 int r;
2023 int i;
2024
2025 /* Test reading from a pipe with read() */
2026 if (_pipe(pipes, 1024, O_BINARY) < 0)
2027 {
2028 ok(0, "pipe failed with errno %d\n", errno);
2029 return;
2030 }
2031
2032 arg_v[0] = get_base_name(selfname);
2033 arg_v[1] = "tests/file.c";
2034 arg_v[2] = "pipes";
2035 arg_v[3] = str_fdr; sprintf(str_fdr, "%d", pipes[0]);
2036 arg_v[4] = str_fdw; sprintf(str_fdw, "%d", pipes[1]);
2037 arg_v[5] = NULL;
2038 proc_handles[0] = (HANDLE)_spawnvp(_P_NOWAIT, selfname, arg_v);
2039 i=close(pipes[1]);
2040 ok(!i, "unable to close %d: %d\n", pipes[1], errno);
2041
2042 for (i=0; i<N_TEST_MESSAGES; i++) {
2043 r=read(pipes[0], buf, sizeof(buf)-1);
2044 ok(r == strlen(pipe_string), "i %d, got %d\n", i, r);
2045 if (r > 0)
2046 buf[r]='\0';
2047 ok(strcmp(buf, pipe_string) == 0, "expected to read '%s', got '%s'\n", pipe_string, buf);
2048 }
2049
2050 r=read(pipes[0], buf, sizeof(buf)-1);
2051 ok(r == 0, "expected to read 0 bytes, got %d\n", r);
2052 i=close(pipes[0]);
2053 ok(!i, "unable to close %d: %d\n", pipes[0], errno);
2054
2055 /* Test reading from a pipe with fread() */
2056 if (_pipe(pipes, 1024, O_BINARY) < 0)
2057 {
2058 ok(0, "pipe failed with errno %d\n", errno);
2059 return;
2060 }
2061
2062 arg_v[1] = "tests/file.c";
2063 arg_v[2] = "pipes";
2064 arg_v[3] = str_fdr; sprintf(str_fdr, "%d", pipes[0]);
2065 arg_v[4] = str_fdw; sprintf(str_fdw, "%d", pipes[1]);
2066 arg_v[5] = NULL;
2067 proc_handles[1] = (HANDLE)_spawnvp(_P_NOWAIT, selfname, arg_v);
2068 i=close(pipes[1]);
2069 ok(!i, "unable to close %d: %d\n", pipes[1], errno);
2070 file=fdopen(pipes[0], "r");
2071
2072 /* In blocking mode, fread will keep calling read() until it gets
2073 * enough bytes, or EOF, even on Unix. (If this were a Unix terminal
2074 * in cooked mode instead of a pipe, it would also stop on EOL.)
2075 */
2076 expected[0] = 0;
2077 for (i=0; i<N_TEST_MESSAGES; i++)
2078 strcat(expected, pipe_string);
2079 r=fread(buf, 1, sizeof(buf)-1, file);
2080 ok(r == strlen(expected), "fread() returned %d: ferror=%d\n", r, ferror(file));
2081 if (r > 0)
2082 buf[r]='\0';
2083 ok(strcmp(buf, expected) == 0, "got '%s' expected '%s'\n", buf, expected);
2084
2085 /* Let child close the file before we read, so we can sense EOF reliably */
2086 Sleep(100);
2087 r=fread(buf, 1, sizeof(buf)-1, file);
2088 ok(r == 0, "fread() returned %d instead of 0\n", r);
2089 ok(ferror(file) == 0, "got ferror() = %d\n", ferror(file));
2090 ok(feof(file), "feof() is false!\n");
2091
2092 i=fclose(file);
2093 ok(!i, "unable to close the pipe: %d\n", errno);
2094
2095 /* test \r handling when it's the last character read */
2096 if (_pipe(pipes, 1024, O_BINARY) < 0)
2097 {
2098 ok(0, "pipe failed with errno %d\n", errno);
2099 return;
2100 }
2101 r = write(pipes[1], "\r\n\rab\r\n", 7);
2102 ok(r == 7, "write returned %d, errno = %d\n", r, errno);
2103 setmode(pipes[0], O_TEXT);
2104 r = read(pipes[0], buf, 1);
2105 ok(r == 1, "read returned %d, expected 1\n", r);
2106 ok(buf[0] == '\n', "buf[0] = %x, expected '\\n'\n", buf[0]);
2107 r = read(pipes[0], buf, 1);
2108 ok(r == 1, "read returned %d, expected 1\n", r);
2109 ok(buf[0] == '\r', "buf[0] = %x, expected '\\r'\n", buf[0]);
2110 r = read(pipes[0], buf, 1);
2111 ok(r == 1, "read returned %d, expected 1\n", r);
2112 ok(buf[0] == 'a', "buf[0] = %x, expected 'a'\n", buf[0]);
2113 r = read(pipes[0], buf, 2);
2114 ok(r == 2, "read returned %d, expected 1\n", r);
2115 ok(buf[0] == 'b', "buf[0] = %x, expected 'b'\n", buf[0]);
2116 ok(buf[1] == '\n', "buf[1] = %x, expected '\\n'\n", buf[1]);
2117
2118 if (p_fopen_s)
2119 {
2120 /* test utf16 read with insufficient data */
2121 r = write(pipes[1], "a\0b", 3);
2122 ok(r == 3, "write returned %d, errno = %d\n", r, errno);
2123 buf[2] = 'z';
2124 buf[3] = 'z';
2125 setmode(pipes[0], _O_WTEXT);
2126 r = read(pipes[0], buf, 4);
2127 ok(r == 2, "read returned %d, expected 2\n", r);
2128 ok(!memcmp(buf, "a\0bz", 4), "read returned incorrect data\n");
2129 r = write(pipes[1], "\0", 1);
2130 ok(r == 1, "write returned %d, errno = %d\n", r, errno);
2131 buf[0] = 'z';
2132 buf[1] = 'z';
2133 r = read(pipes[0], buf, 2);
2134 ok(r == 0, "read returned %d, expected 0\n", r);
2135 ok(!memcmp(buf, "\0z", 2), "read returned incorrect data\n");
2136 }
2137 else
2138 {
2139 win_skip("unicode mode tests on pipe\n");
2140 }
2141
2142 close(pipes[1]);
2143 close(pipes[0]);
2144 }
2145
2146 static void test_unlink(void)
2147 {
2148 FILE* file;
2149 ok(mkdir("test_unlink") == 0, "unable to create test dir\n");
2150 file = fopen("test_unlink\\empty", "w");
2151 ok(file != NULL, "unable to create test file\n");
2152 if(file)
2153 fclose(file);
2154 ok(_unlink("test_unlink") != 0, "unlinking a non-empty directory must fail\n");
2155 unlink("test_unlink\\empty");
2156 rmdir("test_unlink");
2157 }
2158
2159 static void test_dup2(void)
2160 {
2161 ok(-1 == _dup2(0, -1), "expected _dup2 to fail when second arg is negative\n" );
2162 }
2163
2164 static void test_stdin(void)
2165 {
2166 HANDLE stdinh = GetStdHandle(STD_INPUT_HANDLE);
2167 int stdin_dup, fd;
2168 HANDLE h;
2169 DWORD r;
2170
2171 stdin_dup = _dup(STDIN_FILENO);
2172 ok(stdin_dup != -1, "_dup(STDIN_FILENO) failed\n");
2173
2174 ok(stdinh == (HANDLE)_get_osfhandle(STDIN_FILENO),
2175 "GetStdHandle(STD_INPUT_HANDLE) != _get_osfhandle(STDIN_FILENO)\n");
2176
2177 r = SetStdHandle(STD_INPUT_HANDLE, INVALID_HANDLE_VALUE);
2178 ok(r == TRUE, "SetStdHandle returned %x, expected TRUE\n", r);
2179 h = GetStdHandle(STD_INPUT_HANDLE);
2180 ok(h == INVALID_HANDLE_VALUE, "h = %p\n", h);
2181
2182 close(STDIN_FILENO);
2183 h = GetStdHandle(STD_INPUT_HANDLE);
2184 ok(h == NULL, "h != NULL\n");
2185
2186 fd = open("stdin.tst", O_WRONLY | O_CREAT, _S_IREAD |_S_IWRITE);
2187 ok(fd != -1, "open failed\n");
2188 ok(fd == STDIN_FILENO, "fd = %d, expected STDIN_FILENO\n", fd);
2189 h = GetStdHandle(STD_INPUT_HANDLE);
2190 ok(h != NULL, "h == NULL\n");
2191 close(fd);
2192 unlink("stdin.tst");
2193
2194 r = _dup2(stdin_dup, STDIN_FILENO);
2195 ok(r != -1, "_dup2 failed\n");
2196 h = GetStdHandle(STD_INPUT_HANDLE);
2197 ok(h != NULL, "h == NULL\n");
2198 }
2199
2200 static void test_mktemp(void)
2201 {
2202 char buf[16];
2203
2204 strcpy(buf, "a");
2205 ok(!_mktemp(buf), "_mktemp(\"a\") != NULL\n");
2206
2207 strcpy(buf, "testXXXXX");
2208 ok(!_mktemp(buf), "_mktemp(\"testXXXXX\") != NULL\n");
2209
2210 strcpy(buf, "testXXXXXX");
2211 ok(_mktemp(buf) != NULL, "_mktemp(\"testXXXXXX\") == NULL\n");
2212
2213 strcpy(buf, "testXXXXXXa");
2214 ok(!_mktemp(buf), "_mktemp(\"testXXXXXXa\") != NULL\n");
2215
2216 strcpy(buf, "**XXXXXX");
2217 ok(_mktemp(buf) != NULL, "_mktemp(\"**XXXXXX\") == NULL\n");
2218 }
2219
2220 static void test__open_osfhandle(void)
2221 {
2222 ioinfo *info;
2223 HANDLE h, tmp;
2224 int fd;
2225
2226 errno = 0xdeadbeef;
2227 fd = _open_osfhandle((intptr_t)INVALID_HANDLE_VALUE, 0);
2228 ok(fd == -1, "_open_osfhandle returned %d\n", fd);
2229 ok(errno == EBADF, "errno = %d\n", errno);
2230
2231 h = CreateFileA("open_osfhandle.tst", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
2232 fd = _open_osfhandle((intptr_t)h, 0);
2233 ok(fd > 0, "_open_osfhandle returned %d (%d)\n", fd, errno);
2234 info = &__pioinfo[fd/MSVCRT_FD_BLOCK_SIZE][fd%MSVCRT_FD_BLOCK_SIZE];
2235 ok(info->handle == h, "info->handle = %p, expected %p\n", info->handle, h);
2236 ok(info->wxflag == 1, "info->wxflag = %x, expected 1\n", info->wxflag);
2237 close(fd);
2238 ok(info->handle == INVALID_HANDLE_VALUE, "info->handle = %p, expected INVALID_HANDLE_VALUE\n", info->handle);
2239 ok(info->wxflag == 0, "info->wxflag = %x, expected 0\n", info->wxflag);
2240 DeleteFileA("open_osfhandle.tst");
2241
2242 errno = 0xdeadbeef;
2243 fd = _open_osfhandle((intptr_t)h, 0);
2244 ok(fd == -1, "_open_osfhandle returned %d\n", fd);
2245 ok(errno == EBADF, "errno = %d\n", errno);
2246
2247 ok(CreatePipe(&h, &tmp, NULL, 0), "CreatePipe failed\n");
2248 fd = _open_osfhandle((intptr_t)h, 0);
2249 ok(fd > 0, "_open_osfhandle returned %d (%d)\n", fd, errno);
2250 info = &__pioinfo[fd/MSVCRT_FD_BLOCK_SIZE][fd%MSVCRT_FD_BLOCK_SIZE];
2251 ok(info->handle == h, "info->handle = %p, expected %p\n", info->handle, h);
2252 ok(info->wxflag == 9, "info->wxflag = %x, expected 9\n", info->wxflag);
2253 close(fd);
2254 CloseHandle(tmp);
2255 }
2256
2257 static void test_write_flush_size(FILE *file, int bufsize)
2258 {
2259 char *inbuffer;
2260 char *outbuffer;
2261 int size, fd;
2262 fpos_t pos, pos2;
2263
2264 fd = fileno(file);
2265 inbuffer = calloc(1, bufsize + 1);
2266 outbuffer = calloc(1, bufsize + 1);
2267 _snprintf(outbuffer, bufsize + 1, "0,1,2,3,4,5,6,7,8,9");
2268
2269 for (size = bufsize + 1; size >= bufsize - 1; size--) {
2270 rewind(file);
2271 ok(file->_cnt == 0, "_cnt should be 0 after rewind, but is %d\n", file->_cnt);
2272 fwrite(outbuffer, 1, size, file);
2273 /* lseek() below intentionally redirects the write in fflush() to detect
2274 * if fwrite() has already flushed the whole buffer or not.
2275 */
2276 lseek(fd, 1, SEEK_SET);
2277 fflush(file);
2278 ok(file->_cnt == 0, "_cnt should be 0 after fflush, but is %d\n", file->_cnt);
2279 fseek(file, 0, SEEK_SET);
2280 ok(fread(inbuffer, 1, bufsize, file) == bufsize, "read failed\n");
2281 if (size == bufsize)
2282 ok(memcmp(outbuffer, inbuffer, bufsize) == 0, "missing flush by %d byte write\n", size);
2283 else
2284 ok(memcmp(outbuffer, inbuffer, bufsize) != 0, "unexpected flush by %d byte write\n", size);
2285 }
2286 rewind(file);
2287 fwrite(outbuffer, 1, bufsize / 2, file);
2288 fwrite(outbuffer + bufsize / 2, 1, bufsize / 2, file);
2289 lseek(fd, 1, SEEK_SET);
2290 fflush(file);
2291 fseek(file, 0, SEEK_SET);
2292 ok(fread(inbuffer, 1, bufsize, file) == bufsize, "read failed\n");
2293 ok(memcmp(outbuffer, inbuffer, bufsize) != 0, "unexpected flush by %d/2 byte double write\n", bufsize);
2294
2295 ok(!fseek(file, -1, SEEK_END), "fseek failed\n");
2296 ok(!fgetpos(file, &pos), "fgetpos failed\n");
2297 ok(fread(inbuffer, 1, 1, file) == 1, "fread failed\n");
2298 ok(file->_flag & _IOREAD, "file->_flag = %x\n", file->_flag);
2299 ok(!file->_cnt, "file->_cnt = %d\n", file->_cnt);
2300 ok(file->_ptr != file->_base, "file->_ptr == file->_base\n");
2301 ok(fwrite(outbuffer, 1, bufsize, file), "fwrite failed\n");
2302 ok(file->_flag & _IOREAD, "file->_flag = %x\n", file->_flag);
2303 ok(!file->_cnt, "file->_cnt = %d\n", file->_cnt);
2304 ok(file->_ptr == file->_base, "file->_ptr == file->_base\n");
2305 ok(!fgetpos(file, &pos2), "fgetpos failed\n");
2306 ok(pos+bufsize+1 == pos2, "pos = %d (%d)\n", (int)pos, (int)pos2);
2307 free(inbuffer);
2308 free(outbuffer);
2309 }
2310
2311 static void test_write_flush(void)
2312 {
2313 char iobuf[1024];
2314 char *tempf;
2315 FILE *file;
2316
2317 tempf = _tempnam(".","wne");
2318 file = fopen(tempf, "wb+");
2319 ok(file != NULL, "unable to create test file\n");
2320 iobuf[0] = 0;
2321 ok(file->_bufsiz == 4096, "incorrect default buffer size: %d\n", file->_bufsiz);
2322 test_write_flush_size(file, file->_bufsiz);
2323 setvbuf(file, iobuf, _IOFBF, sizeof(iobuf));
2324 test_write_flush_size(file, sizeof(iobuf));
2325 fclose(file);
2326 unlink(tempf);
2327 free(tempf);
2328 }
2329
2330 static void test_close(void)
2331 {
2332 ioinfo *stdout_info, stdout_copy, *stderr_info, stderr_copy;
2333 int fd1, fd2, ret1, ret2, ret3, ret4;
2334 DWORD flags;
2335 HANDLE h;
2336
2337 /* test close on fds that use the same handle */
2338 h = CreateFileA("fdopen.tst", GENERIC_READ|GENERIC_WRITE,
2339 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, 0, NULL);
2340 ok(h != INVALID_HANDLE_VALUE, "error opening fdopen.tst file\n");
2341
2342 fd1 = _open_osfhandle((intptr_t)h, 0);
2343 ok(fd1 != -1, "_open_osfhandle failed (%d)\n", errno);
2344 fd2 = _open_osfhandle((intptr_t)h, 0);
2345 ok(fd2 != -1, "_open_osfhandle failed (%d)\n", errno);
2346 ok(fd1 != fd2, "fd1 == fd2\n");
2347
2348 ok((HANDLE)_get_osfhandle(fd1) == h, "handles mismatch (%p != %p)\n",
2349 (HANDLE)_get_osfhandle(fd1), h);
2350 ok((HANDLE)_get_osfhandle(fd2) == h, "handles mismatch (%p != %p)\n",
2351 (HANDLE)_get_osfhandle(fd2), h);
2352 ret1 = close(fd1);
2353 ok(!ret1, "close(fd1) failed (%d)\n", errno);
2354 ok(!GetHandleInformation(h, &flags), "GetHandleInformation succeeded\n");
2355 ok(close(fd2), "close(fd2) succeeded\n");
2356
2357 /* test close on stdout and stderr that use the same handle */
2358 h = CreateFileA("fdopen.tst", GENERIC_READ|GENERIC_WRITE,
2359 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, 0, NULL);
2360 ok(h != INVALID_HANDLE_VALUE, "error opening fdopen.tst file\n");
2361
2362 /* tests output will not be visible from now on */
2363 stdout_info = &__pioinfo[STDOUT_FILENO/MSVCRT_FD_BLOCK_SIZE][STDOUT_FILENO%MSVCRT_FD_BLOCK_SIZE];
2364 stderr_info = &__pioinfo[STDERR_FILENO/MSVCRT_FD_BLOCK_SIZE][STDERR_FILENO%MSVCRT_FD_BLOCK_SIZE];
2365 stdout_copy = *stdout_info;
2366 stderr_copy = *stderr_info;
2367 stdout_info->handle = h;
2368 stderr_info->handle = h;
2369
2370 ret1 = close(STDOUT_FILENO);
2371 ret2 = GetHandleInformation(h, &flags);
2372 ret3 = close(STDERR_FILENO);
2373 ret4 = GetHandleInformation(h, &flags);
2374
2375 *stdout_info = stdout_copy;
2376 *stderr_info = stderr_copy;
2377 SetStdHandle(STD_OUTPUT_HANDLE, stdout_info->handle);
2378 SetStdHandle(STD_ERROR_HANDLE, stderr_info->handle);
2379 /* stdout and stderr restored */
2380
2381 ok(!ret1, "close(STDOUT_FILENO) failed\n");
2382 ok(ret2, "GetHandleInformation failed\n");
2383 ok(!ret3, "close(STDERR_FILENO) failed\n");
2384 ok(!ret4, "GetHandleInformation succeeded\n");
2385
2386 DeleteFileA( "fdopen.tst" );
2387 }
2388
2389 START_TEST(file)
2390 {
2391 int arg_c;
2392 char** arg_v;
2393
2394 init();
2395
2396 arg_c = winetest_get_mainargs( &arg_v );
2397
2398 /* testing low-level I/O */
2399 if (arg_c >= 3)
2400 {
2401 if (strcmp(arg_v[2], "inherit") == 0)
2402 test_file_inherit_child(arg_v[3]);
2403 else if (strcmp(arg_v[2], "inherit_no") == 0)
2404 test_file_inherit_child_no(arg_v[3]);
2405 else if (strcmp(arg_v[2], "pipes") == 0)
2406 test_pipes_child(arg_c, arg_v);
2407 else
2408 ok(0, "invalid argument '%s'\n", arg_v[2]);
2409 return;
2410 }
2411 test_dup2();
2412 test_file_inherit(arg_v[0]);
2413 test_file_write_read();
2414 test_chsize();
2415 test_stat();
2416 test_unlink();
2417
2418 /* testing stream I/O */
2419 test_filbuf();
2420 test_fdopen();
2421 test_fopen_fclose_fcloseall();
2422 test_fopen_s();
2423 test__wfopen_s();
2424 test_setmode();
2425 test_fileops();
2426 test_asciimode();
2427 test_asciimode2();
2428 test_filemodeT();
2429 test_readmode(FALSE); /* binary mode */
2430 test_readmode(TRUE); /* ascii mode */
2431 test_readboundary();
2432 test_fgetc();
2433 test_fputc();
2434 test_flsbuf();
2435 test_fflush();
2436 test_fgetwc();
2437 /* \x83\xa9 is double byte character, \xe0\x7f is not (undefined). */
2438 test_fgetwc_locale("AB\x83\xa9\xe0\x7f", "Japanese_Japan.932", 932);
2439 /* \x83 is U+0192 */
2440 test_fgetwc_locale("AB\x83\xa9", "English", 1252);
2441 /* \x83 is U+0083 */
2442 test_fgetwc_locale("AB\x83\xa9", "C", 0);
2443 test_fgetwc_unicode();
2444 test_fputwc();
2445 test_ctrlz();
2446 test_file_put_get();
2447 test_tmpnam();
2448 test_get_osfhandle();
2449 test_setmaxstdio();
2450 test_pipes(arg_v[0]);
2451 test_stdin();
2452 test_mktemp();
2453 test__open_osfhandle();
2454 test_write_flush();
2455 test_close();
2456
2457 /* Wait for the (_P_NOWAIT) spawned processes to finish to make sure the report
2458 * file contains lines in the correct order
2459 */
2460 WaitForMultipleObjects(sizeof(proc_handles)/sizeof(proc_handles[0]), proc_handles, TRUE, 5000);
2461 }