[ADVAPI32_WINETEST] Sync with Wine Staging 1.7.55. CORE-10536
[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 fd = _open(name, _O_CREAT|_O_WRONLY, _S_IWRITE);
1793 ok(fd != -1, "failed to open file\n");
1794
1795 errno = 0xdeadbeef;
1796 ret = _setmode(fd, 0xffffffff);
1797 ok(ret == -1, "_setmode returned %x, expected -1\n", ret);
1798 ok(errno == EINVAL, "errno = %d\n", errno);
1799
1800 errno = 0xdeadbeef;
1801 ret = _setmode(fd, 0);
1802 ok(ret == -1, "_setmode returned %x, expected -1\n", ret);
1803 ok(errno == EINVAL, "errno = %d\n", errno);
1804
1805 errno = 0xdeadbeef;
1806 ret = _setmode(fd, _O_BINARY|_O_TEXT);
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, _O_WTEXT|_O_U16TEXT);
1812 ok(ret == -1, "_setmode returned %x, expected -1\n", ret);
1813 ok(errno == EINVAL, "errno = %d\n", errno);
1814
1815 ret = _setmode(fd, _O_BINARY);
1816 ok(ret == _O_TEXT, "_setmode returned %x, expected _O_TEXT\n", ret);
1817
1818 ret = _setmode(fd, _O_WTEXT);
1819 ok(ret == _O_BINARY, "_setmode returned %x, expected _O_BINARY\n", ret);
1820
1821 ret = _setmode(fd, _O_TEXT);
1822 ok(ret == _O_WTEXT, "_setmode returned %x, expected _O_WTEXT\n", ret);
1823
1824 ret = _setmode(fd, _O_U16TEXT);
1825 ok(ret == _O_TEXT, "_setmode returned %x, expected _O_TEXT\n", ret);
1826
1827 ret = _setmode(fd, _O_U8TEXT);
1828 ok(ret == _O_WTEXT, "_setmode returned %x, expected _O_WTEXT\n", ret);
1829
1830 ret = _setmode(fd, _O_TEXT);
1831 ok(ret == _O_WTEXT, "_setmode returned %x, expected _O_WTEXT\n", ret);
1832
1833 _close(fd);
1834 _unlink(name);
1835 }
1836
1837 static void test_get_osfhandle(void)
1838 {
1839 int fd;
1840 char fname[] = "t_get_osfhanle";
1841 DWORD bytes_written;
1842 HANDLE handle;
1843
1844 fd = _sopen(fname, _O_CREAT|_O_RDWR, _SH_DENYRW, _S_IREAD | _S_IWRITE);
1845 handle = (HANDLE)_get_osfhandle(fd);
1846 WriteFile(handle, "bar", 3, &bytes_written, NULL);
1847 _close(fd);
1848 fd = _open(fname, _O_RDONLY, 0);
1849 ok(fd != -1, "Couldn't open '%s' after _get_osfhandle()\n", fname);
1850
1851 _close(fd);
1852 _unlink(fname);
1853 }
1854
1855 static void test_setmaxstdio(void)
1856 {
1857 ok(2048 == _setmaxstdio(2048),"_setmaxstdio returned %d instead of 2048\n",_setmaxstdio(2048));
1858 ok(-1 == _setmaxstdio(2049),"_setmaxstdio returned %d instead of -1\n",_setmaxstdio(2049));
1859 }
1860
1861 static void test_stat(void)
1862 {
1863 int fd;
1864 int pipes[2];
1865 int ret;
1866 struct stat buf;
1867
1868 /* Tests for a file */
1869 fd = open("stat.tst", O_WRONLY | O_CREAT | O_BINARY, _S_IREAD |_S_IWRITE);
1870 if (fd >= 0)
1871 {
1872 ret = fstat(fd, &buf);
1873 ok(!ret, "fstat failed: errno=%d\n", errno);
1874 ok((buf.st_mode & _S_IFMT) == _S_IFREG, "bad format = %06o\n", buf.st_mode);
1875 ok((buf.st_mode & 0777) == 0666, "bad st_mode = %06o\n", buf.st_mode);
1876 ok(buf.st_dev == 0, "st_dev is %d, expected 0\n", buf.st_dev);
1877 ok(buf.st_dev == buf.st_rdev, "st_dev (%d) and st_rdev (%d) differ\n", buf.st_dev, buf.st_rdev);
1878 ok(buf.st_nlink == 1, "st_nlink is %d, expected 1\n", buf.st_nlink);
1879 ok(buf.st_size == 0, "st_size is %d, expected 0\n", buf.st_size);
1880
1881 ret = stat("stat.tst", &buf);
1882 ok(!ret, "stat failed: errno=%d\n", errno);
1883 ok((buf.st_mode & _S_IFMT) == _S_IFREG, "bad format = %06o\n", buf.st_mode);
1884 ok((buf.st_mode & 0777) == 0666, "bad st_mode = %06o\n", buf.st_mode);
1885 ok(buf.st_dev == buf.st_rdev, "st_dev (%d) and st_rdev (%d) differ\n", buf.st_dev, buf.st_rdev);
1886 ok(buf.st_nlink == 1, "st_nlink is %d, expected 1\n", buf.st_nlink);
1887 ok(buf.st_size == 0, "st_size is %d, expected 0\n", buf.st_size);
1888
1889 errno = 0xdeadbeef;
1890 ret = stat("stat.tst\\", &buf);
1891 ok(ret == -1, "stat returned %d\n", ret);
1892 ok(errno == ENOENT, "errno = %d\n", errno);
1893
1894 close(fd);
1895 remove("stat.tst");
1896 }
1897 else
1898 skip("open failed with errno %d\n", errno);
1899
1900 /* Tests for a char device */
1901 if (_dup2(0, 10) == 0)
1902 {
1903 ret = fstat(10, &buf);
1904 ok(!ret, "fstat(stdin) failed: errno=%d\n", errno);
1905 if ((buf.st_mode & _S_IFMT) == _S_IFCHR)
1906 {
1907 ok(buf.st_mode == _S_IFCHR, "bad st_mode=%06o\n", buf.st_mode);
1908 ok(buf.st_dev == 10, "st_dev is %d, expected 10\n", buf.st_dev);
1909 ok(buf.st_rdev == 10, "st_rdev is %d, expected 10\n", buf.st_rdev);
1910 ok(buf.st_nlink == 1, "st_nlink is %d, expected 1\n", buf.st_nlink);
1911 }
1912 else
1913 skip("stdin is not a char device? st_mode=%06o\n", buf.st_mode);
1914 close(10);
1915 }
1916 else
1917 skip("_dup2 failed with errno %d\n", errno);
1918
1919 /* Tests for pipes */
1920 if (_pipe(pipes, 1024, O_BINARY) == 0)
1921 {
1922 ret = fstat(pipes[0], &buf);
1923 ok(!ret, "fstat(pipe) failed: errno=%d\n", errno);
1924 ok(buf.st_mode == _S_IFIFO, "bad st_mode=%06o\n", buf.st_mode);
1925 ok(buf.st_dev == pipes[0], "st_dev is %d, expected %d\n", buf.st_dev, pipes[0]);
1926 ok(buf.st_rdev == pipes[0], "st_rdev is %d, expected %d\n", buf.st_rdev, pipes[0]);
1927 ok(buf.st_nlink == 1, "st_nlink is %d, expected 1\n", buf.st_nlink);
1928 close(pipes[0]);
1929 close(pipes[1]);
1930 }
1931 else
1932 skip("pipe failed with errno %d\n", errno);
1933
1934 /* Tests for directory */
1935 if(mkdir("stat.tst") == 0)
1936 {
1937 ret = stat("stat.tst ", &buf);
1938 ok(!ret, "stat(directory) failed: errno=%d\n", errno);
1939 ok((buf.st_mode & _S_IFMT) == _S_IFDIR, "bad format = %06o\n", buf.st_mode);
1940 ok((buf.st_mode & 0777) == 0777, "bad st_mode = %06o\n", buf.st_mode);
1941 ok(buf.st_dev == buf.st_rdev, "st_dev (%d) and st_rdev (%d) differ\n", buf.st_dev, buf.st_rdev);
1942 ok(buf.st_nlink == 1, "st_nlink is %d, expected 1\n", buf.st_nlink);
1943
1944 errno = 0xdeadbeef;
1945 ret = stat("stat.tst\\ ", &buf);
1946 ok(ret == -1, "stat returned %d\n", ret);
1947 ok(errno == ENOENT, "errno = %d\n", errno);
1948 rmdir( "stat.tst" );
1949 }
1950 else
1951 skip("mkdir failed with errno %d\n", errno);
1952
1953 errno = 0xdeadbeef;
1954 ret = stat("c:", &buf);
1955 ok(ret == -1, "stat returned %d\n", ret);
1956 ok(errno == ENOENT, "errno = %d\n", errno);
1957
1958 ret = stat("c:/", &buf);
1959 ok(!ret, "stat returned %d\n", ret);
1960 ok(buf.st_dev == 2, "st_dev = %d\n", buf.st_dev);
1961 ok(buf.st_rdev == 2, "st_rdev = %d\n", buf.st_rdev);
1962 }
1963
1964 static const char* pipe_string="Hello world";
1965
1966 /* How many messages to transfer over the pipe */
1967 #define N_TEST_MESSAGES 3
1968
1969 static void test_pipes_child(int argc, char** args)
1970 {
1971 int fd;
1972 int nwritten;
1973 int i;
1974
1975 if (argc < 5)
1976 {
1977 ok(0, "not enough parameters: %d\n", argc);
1978 return;
1979 }
1980
1981 fd=atoi(args[3]);
1982 i=close(fd);
1983 ok(!i, "unable to close %d: %d\n", fd, errno);
1984
1985 fd=atoi(args[4]);
1986
1987 for (i=0; i<N_TEST_MESSAGES; i++) {
1988 nwritten=write(fd, pipe_string, strlen(pipe_string));
1989 ok(nwritten == strlen(pipe_string), "i %d, expected to write '%s' wrote %d\n", i, pipe_string, nwritten);
1990 /* let other process wake up so they can show off their "keep reading until EOF" behavior */
1991 if (i < N_TEST_MESSAGES-1)
1992 Sleep(100);
1993 }
1994
1995 i=close(fd);
1996 ok(!i, "unable to close %d: %d\n", fd, errno);
1997 }
1998
1999 static void test_pipes(const char* selfname)
2000 {
2001 int pipes[2];
2002 char str_fdr[12], str_fdw[12];
2003 FILE* file;
2004 const char* arg_v[6];
2005 char buf[4096];
2006 char expected[4096];
2007 int r;
2008 int i;
2009
2010 /* Test reading from a pipe with read() */
2011 if (_pipe(pipes, 1024, O_BINARY) < 0)
2012 {
2013 ok(0, "pipe failed with errno %d\n", errno);
2014 return;
2015 }
2016
2017 arg_v[0] = get_base_name(selfname);
2018 arg_v[1] = "tests/file.c";
2019 arg_v[2] = "pipes";
2020 arg_v[3] = str_fdr; sprintf(str_fdr, "%d", pipes[0]);
2021 arg_v[4] = str_fdw; sprintf(str_fdw, "%d", pipes[1]);
2022 arg_v[5] = NULL;
2023 proc_handles[0] = (HANDLE)_spawnvp(_P_NOWAIT, selfname, arg_v);
2024 i=close(pipes[1]);
2025 ok(!i, "unable to close %d: %d\n", pipes[1], errno);
2026
2027 for (i=0; i<N_TEST_MESSAGES; i++) {
2028 r=read(pipes[0], buf, sizeof(buf)-1);
2029 ok(r == strlen(pipe_string), "i %d, got %d\n", i, r);
2030 if (r > 0)
2031 buf[r]='\0';
2032 ok(strcmp(buf, pipe_string) == 0, "expected to read '%s', got '%s'\n", pipe_string, buf);
2033 }
2034
2035 r=read(pipes[0], buf, sizeof(buf)-1);
2036 ok(r == 0, "expected to read 0 bytes, got %d\n", r);
2037 i=close(pipes[0]);
2038 ok(!i, "unable to close %d: %d\n", pipes[0], errno);
2039
2040 /* Test reading from a pipe with fread() */
2041 if (_pipe(pipes, 1024, O_BINARY) < 0)
2042 {
2043 ok(0, "pipe failed with errno %d\n", errno);
2044 return;
2045 }
2046
2047 arg_v[1] = "tests/file.c";
2048 arg_v[2] = "pipes";
2049 arg_v[3] = str_fdr; sprintf(str_fdr, "%d", pipes[0]);
2050 arg_v[4] = str_fdw; sprintf(str_fdw, "%d", pipes[1]);
2051 arg_v[5] = NULL;
2052 proc_handles[1] = (HANDLE)_spawnvp(_P_NOWAIT, selfname, arg_v);
2053 i=close(pipes[1]);
2054 ok(!i, "unable to close %d: %d\n", pipes[1], errno);
2055 file=fdopen(pipes[0], "r");
2056
2057 /* In blocking mode, fread will keep calling read() until it gets
2058 * enough bytes, or EOF, even on Unix. (If this were a Unix terminal
2059 * in cooked mode instead of a pipe, it would also stop on EOL.)
2060 */
2061 expected[0] = 0;
2062 for (i=0; i<N_TEST_MESSAGES; i++)
2063 strcat(expected, pipe_string);
2064 r=fread(buf, 1, sizeof(buf)-1, file);
2065 ok(r == strlen(expected), "fread() returned %d: ferror=%d\n", r, ferror(file));
2066 if (r > 0)
2067 buf[r]='\0';
2068 ok(strcmp(buf, expected) == 0, "got '%s' expected '%s'\n", buf, expected);
2069
2070 /* Let child close the file before we read, so we can sense EOF reliably */
2071 Sleep(100);
2072 r=fread(buf, 1, sizeof(buf)-1, file);
2073 ok(r == 0, "fread() returned %d instead of 0\n", r);
2074 ok(ferror(file) == 0, "got ferror() = %d\n", ferror(file));
2075 ok(feof(file), "feof() is false!\n");
2076
2077 i=fclose(file);
2078 ok(!i, "unable to close the pipe: %d\n", errno);
2079
2080 /* test \r handling when it's the last character read */
2081 if (_pipe(pipes, 1024, O_BINARY) < 0)
2082 {
2083 ok(0, "pipe failed with errno %d\n", errno);
2084 return;
2085 }
2086 r = write(pipes[1], "\r\n\rab\r\n", 7);
2087 ok(r == 7, "write returned %d, errno = %d\n", r, errno);
2088 setmode(pipes[0], O_TEXT);
2089 r = read(pipes[0], buf, 1);
2090 ok(r == 1, "read returned %d, expected 1\n", r);
2091 ok(buf[0] == '\n', "buf[0] = %x, expected '\\n'\n", buf[0]);
2092 r = read(pipes[0], buf, 1);
2093 ok(r == 1, "read returned %d, expected 1\n", r);
2094 ok(buf[0] == '\r', "buf[0] = %x, expected '\\r'\n", buf[0]);
2095 r = read(pipes[0], buf, 1);
2096 ok(r == 1, "read returned %d, expected 1\n", r);
2097 ok(buf[0] == 'a', "buf[0] = %x, expected 'a'\n", buf[0]);
2098 r = read(pipes[0], buf, 2);
2099 ok(r == 2, "read returned %d, expected 1\n", r);
2100 ok(buf[0] == 'b', "buf[0] = %x, expected 'b'\n", buf[0]);
2101 ok(buf[1] == '\n', "buf[1] = %x, expected '\\n'\n", buf[1]);
2102
2103 if (p_fopen_s)
2104 {
2105 /* test utf16 read with insufficient data */
2106 r = write(pipes[1], "a\0b", 3);
2107 ok(r == 3, "write returned %d, errno = %d\n", r, errno);
2108 buf[2] = 'z';
2109 buf[3] = 'z';
2110 setmode(pipes[0], _O_WTEXT);
2111 r = read(pipes[0], buf, 4);
2112 ok(r == 2, "read returned %d, expected 2\n", r);
2113 ok(!memcmp(buf, "a\0bz", 4), "read returned incorrect data\n");
2114 r = write(pipes[1], "\0", 1);
2115 ok(r == 1, "write returned %d, errno = %d\n", r, errno);
2116 buf[0] = 'z';
2117 buf[1] = 'z';
2118 r = read(pipes[0], buf, 2);
2119 ok(r == 0, "read returned %d, expected 0\n", r);
2120 ok(!memcmp(buf, "\0z", 2), "read returned incorrect data\n");
2121 }
2122 else
2123 {
2124 win_skip("unicode mode tests on pipe\n");
2125 }
2126
2127 close(pipes[1]);
2128 close(pipes[0]);
2129 }
2130
2131 static void test_unlink(void)
2132 {
2133 FILE* file;
2134 ok(mkdir("test_unlink") == 0, "unable to create test dir\n");
2135 file = fopen("test_unlink\\empty", "w");
2136 ok(file != NULL, "unable to create test file\n");
2137 if(file)
2138 fclose(file);
2139 ok(_unlink("test_unlink") != 0, "unlinking a non-empty directory must fail\n");
2140 unlink("test_unlink\\empty");
2141 rmdir("test_unlink");
2142 }
2143
2144 static void test_dup2(void)
2145 {
2146 ok(-1 == _dup2(0, -1), "expected _dup2 to fail when second arg is negative\n" );
2147 }
2148
2149 static void test_stdin(void)
2150 {
2151 HANDLE stdinh = GetStdHandle(STD_INPUT_HANDLE);
2152 int stdin_dup, fd;
2153 HANDLE h;
2154 DWORD r;
2155
2156 stdin_dup = _dup(STDIN_FILENO);
2157 ok(stdin_dup != -1, "_dup(STDIN_FILENO) failed\n");
2158
2159 ok(stdinh == (HANDLE)_get_osfhandle(STDIN_FILENO),
2160 "GetStdHandle(STD_INPUT_HANDLE) != _get_osfhandle(STDIN_FILENO)\n");
2161
2162 r = SetStdHandle(STD_INPUT_HANDLE, INVALID_HANDLE_VALUE);
2163 ok(r == TRUE, "SetStdHandle returned %x, expected TRUE\n", r);
2164 h = GetStdHandle(STD_INPUT_HANDLE);
2165 ok(h == INVALID_HANDLE_VALUE, "h = %p\n", h);
2166
2167 close(STDIN_FILENO);
2168 h = GetStdHandle(STD_INPUT_HANDLE);
2169 ok(h == NULL, "h != NULL\n");
2170
2171 fd = open("stdin.tst", O_WRONLY | O_CREAT, _S_IREAD |_S_IWRITE);
2172 ok(fd != -1, "open failed\n");
2173 ok(fd == STDIN_FILENO, "fd = %d, expected STDIN_FILENO\n", fd);
2174 h = GetStdHandle(STD_INPUT_HANDLE);
2175 ok(h != NULL, "h == NULL\n");
2176 close(fd);
2177 unlink("stdin.tst");
2178
2179 r = _dup2(stdin_dup, STDIN_FILENO);
2180 ok(r != -1, "_dup2 failed\n");
2181 h = GetStdHandle(STD_INPUT_HANDLE);
2182 ok(h != NULL, "h == NULL\n");
2183 }
2184
2185 static void test_mktemp(void)
2186 {
2187 char buf[16];
2188
2189 strcpy(buf, "a");
2190 ok(!_mktemp(buf), "_mktemp(\"a\") != NULL\n");
2191
2192 strcpy(buf, "testXXXXX");
2193 ok(!_mktemp(buf), "_mktemp(\"testXXXXX\") != NULL\n");
2194
2195 strcpy(buf, "testXXXXXX");
2196 ok(_mktemp(buf) != NULL, "_mktemp(\"testXXXXXX\") == NULL\n");
2197
2198 strcpy(buf, "testXXXXXXa");
2199 ok(!_mktemp(buf), "_mktemp(\"testXXXXXXa\") != NULL\n");
2200
2201 strcpy(buf, "**XXXXXX");
2202 ok(_mktemp(buf) != NULL, "_mktemp(\"**XXXXXX\") == NULL\n");
2203 }
2204
2205 static void test__open_osfhandle(void)
2206 {
2207 ioinfo *info;
2208 HANDLE h, tmp;
2209 int fd;
2210
2211 errno = 0xdeadbeef;
2212 fd = _open_osfhandle((intptr_t)INVALID_HANDLE_VALUE, 0);
2213 ok(fd == -1, "_open_osfhandle returned %d\n", fd);
2214 ok(errno == EBADF, "errno = %d\n", errno);
2215
2216 h = CreateFileA("open_osfhandle.tst", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
2217 fd = _open_osfhandle((intptr_t)h, 0);
2218 ok(fd > 0, "_open_osfhandle returned %d (%d)\n", fd, errno);
2219 info = &__pioinfo[fd/MSVCRT_FD_BLOCK_SIZE][fd%MSVCRT_FD_BLOCK_SIZE];
2220 ok(info->handle == h, "info->handle = %p, expected %p\n", info->handle, h);
2221 ok(info->wxflag == 1, "info->wxflag = %x, expected 1\n", info->wxflag);
2222 close(fd);
2223 ok(info->handle == INVALID_HANDLE_VALUE, "info->handle = %p, expected INVALID_HANDLE_VALUE\n", info->handle);
2224 ok(info->wxflag == 0, "info->wxflag = %x, expected 0\n", info->wxflag);
2225 DeleteFileA("open_osfhandle.tst");
2226
2227 errno = 0xdeadbeef;
2228 fd = _open_osfhandle((intptr_t)h, 0);
2229 ok(fd == -1, "_open_osfhandle returned %d\n", fd);
2230 ok(errno == EBADF, "errno = %d\n", errno);
2231
2232 ok(CreatePipe(&h, &tmp, NULL, 0), "CreatePipe failed\n");
2233 fd = _open_osfhandle((intptr_t)h, 0);
2234 ok(fd > 0, "_open_osfhandle returned %d (%d)\n", fd, errno);
2235 info = &__pioinfo[fd/MSVCRT_FD_BLOCK_SIZE][fd%MSVCRT_FD_BLOCK_SIZE];
2236 ok(info->handle == h, "info->handle = %p, expected %p\n", info->handle, h);
2237 ok(info->wxflag == 9, "info->wxflag = %x, expected 9\n", info->wxflag);
2238 close(fd);
2239 CloseHandle(tmp);
2240 }
2241
2242 static void test_write_flush_size(FILE *file, int bufsize)
2243 {
2244 char *inbuffer;
2245 char *outbuffer;
2246 int size, fd;
2247 fpos_t pos, pos2;
2248
2249 fd = fileno(file);
2250 inbuffer = calloc(bufsize + 1, 1);
2251 outbuffer = calloc(bufsize + 1, 1);
2252 _snprintf(outbuffer, bufsize + 1, "0,1,2,3,4,5,6,7,8,9");
2253
2254 for (size = bufsize + 1; size >= bufsize - 1; size--) {
2255 rewind(file);
2256 ok(file->_cnt == 0, "_cnt should be 0 after rewind, but is %d\n", file->_cnt);
2257 fwrite(outbuffer, 1, size, file);
2258 /* lseek() below intentionally redirects the write in fflush() to detect
2259 * if fwrite() has already flushed the whole buffer or not.
2260 */
2261 lseek(fd, 1, SEEK_SET);
2262 fflush(file);
2263 ok(file->_cnt == 0, "_cnt should be 0 after fflush, but is %d\n", file->_cnt);
2264 fseek(file, 0, SEEK_SET);
2265 ok(fread(inbuffer, 1, bufsize, file) == bufsize, "read failed\n");
2266 if (size == bufsize)
2267 ok(memcmp(outbuffer, inbuffer, bufsize) == 0, "missing flush by %d byte write\n", size);
2268 else
2269 ok(memcmp(outbuffer, inbuffer, bufsize) != 0, "unexpected flush by %d byte write\n", size);
2270 }
2271 rewind(file);
2272 fwrite(outbuffer, 1, bufsize / 2, file);
2273 fwrite(outbuffer + bufsize / 2, 1, bufsize / 2, file);
2274 lseek(fd, 1, SEEK_SET);
2275 fflush(file);
2276 fseek(file, 0, SEEK_SET);
2277 ok(fread(inbuffer, 1, bufsize, file) == bufsize, "read failed\n");
2278 ok(memcmp(outbuffer, inbuffer, bufsize) != 0, "unexpected flush by %d/2 byte double write\n", bufsize);
2279
2280 ok(!fseek(file, -1, SEEK_END), "fseek failed\n");
2281 ok(!fgetpos(file, &pos), "fgetpos failed\n");
2282 ok(fread(inbuffer, 1, 1, file) == 1, "fread failed\n");
2283 ok(file->_flag & _IOREAD, "file->_flag = %x\n", file->_flag);
2284 ok(!file->_cnt, "file->_cnt = %d\n", file->_cnt);
2285 ok(file->_ptr != file->_base, "file->_ptr == file->_base\n");
2286 ok(fwrite(outbuffer, 1, bufsize, file), "fwrite failed\n");
2287 ok(file->_flag & _IOREAD, "file->_flag = %x\n", file->_flag);
2288 ok(!file->_cnt, "file->_cnt = %d\n", file->_cnt);
2289 ok(file->_ptr == file->_base, "file->_ptr == file->_base\n");
2290 ok(!fgetpos(file, &pos2), "fgetpos failed\n");
2291 ok(pos+bufsize+1 == pos2, "pos = %d (%d)\n", (int)pos, (int)pos2);
2292 free(inbuffer);
2293 free(outbuffer);
2294 }
2295
2296 static void test_write_flush(void)
2297 {
2298 char iobuf[1024];
2299 char *tempf;
2300 FILE *file;
2301
2302 tempf = _tempnam(".","wne");
2303 file = fopen(tempf, "wb+");
2304 ok(file != NULL, "unable to create test file\n");
2305 iobuf[0] = 0;
2306 ok(file->_bufsiz == 4096, "incorrect default buffer size: %d\n", file->_bufsiz);
2307 test_write_flush_size(file, file->_bufsiz);
2308 setvbuf(file, iobuf, _IOFBF, sizeof(iobuf));
2309 test_write_flush_size(file, sizeof(iobuf));
2310 fclose(file);
2311 unlink(tempf);
2312 free(tempf);
2313 }
2314
2315 START_TEST(file)
2316 {
2317 int arg_c;
2318 char** arg_v;
2319
2320 init();
2321
2322 arg_c = winetest_get_mainargs( &arg_v );
2323
2324 /* testing low-level I/O */
2325 if (arg_c >= 3)
2326 {
2327 if (strcmp(arg_v[2], "inherit") == 0)
2328 test_file_inherit_child(arg_v[3]);
2329 else if (strcmp(arg_v[2], "inherit_no") == 0)
2330 test_file_inherit_child_no(arg_v[3]);
2331 else if (strcmp(arg_v[2], "pipes") == 0)
2332 test_pipes_child(arg_c, arg_v);
2333 else
2334 ok(0, "invalid argument '%s'\n", arg_v[2]);
2335 return;
2336 }
2337 test_dup2();
2338 test_file_inherit(arg_v[0]);
2339 test_file_write_read();
2340 test_chsize();
2341 test_stat();
2342 test_unlink();
2343
2344 /* testing stream I/O */
2345 test_filbuf();
2346 test_fdopen();
2347 test_fopen_fclose_fcloseall();
2348 test_fopen_s();
2349 test__wfopen_s();
2350 test_setmode();
2351 test_fileops();
2352 test_asciimode();
2353 test_asciimode2();
2354 test_filemodeT();
2355 test_readmode(FALSE); /* binary mode */
2356 test_readmode(TRUE); /* ascii mode */
2357 test_readboundary();
2358 test_fgetc();
2359 test_fputc();
2360 test_flsbuf();
2361 test_fflush();
2362 test_fgetwc();
2363 /* \x83\xa9 is double byte character, \xe0\x7f is not (undefined). */
2364 test_fgetwc_locale("AB\x83\xa9\xe0\x7f", "Japanese_Japan.932", 932);
2365 /* \x83 is U+0192 */
2366 test_fgetwc_locale("AB\x83\xa9", "English", 1252);
2367 /* \x83 is U+0083 */
2368 test_fgetwc_locale("AB\x83\xa9", "C", 0);
2369 test_fgetwc_unicode();
2370 test_fputwc();
2371 test_ctrlz();
2372 test_file_put_get();
2373 test_tmpnam();
2374 test_get_osfhandle();
2375 test_setmaxstdio();
2376 test_pipes(arg_v[0]);
2377 test_stdin();
2378 test_mktemp();
2379 test__open_osfhandle();
2380 test_write_flush();
2381
2382 /* Wait for the (_P_NOWAIT) spawned processes to finish to make sure the report
2383 * file contains lines in the correct order
2384 */
2385 WaitForMultipleObjects(sizeof(proc_handles)/sizeof(proc_handles[0]), proc_handles, TRUE, 5000);
2386 }