new 818051de2c8769029049ce3d36c6b856f47496c9
[wine/hacks.git] / dlls / msvcrt / tests / file.c
blob46ccad6b3bff4b6ed5dde9e8a09310b337d28e55
1 /*
2 * Unit test suite for file functions
4 * Copyright 2002 Bill Currie
5 * Copyright 2005 Paul Rupe
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include "wine/test.h"
23 #include <stdarg.h>
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <fcntl.h>
27 #include <share.h>
28 #include <sys/stat.h>
29 #include <io.h>
30 #include <direct.h>
31 #include <windef.h>
32 #include <winbase.h>
33 #include <winnls.h>
34 #include <process.h>
35 #include <errno.h>
37 static void test_fdopen( void )
39 static const char buffer[] = {0,1,2,3,4,5,6,7,8,9};
40 char ibuf[10];
41 int fd;
42 FILE *file;
44 fd = open ("fdopen.tst", O_WRONLY | O_CREAT | O_BINARY, _S_IREAD |_S_IWRITE);
45 write (fd, buffer, sizeof (buffer));
46 close (fd);
48 fd = open ("fdopen.tst", O_RDONLY | O_BINARY);
49 lseek (fd, 5, SEEK_SET);
50 file = fdopen (fd, "rb");
51 ok (fread (ibuf, 1, sizeof (buffer), file) == 5, "read wrong byte count\n");
52 ok (memcmp (ibuf, buffer + 5, 5) == 0, "read wrong bytes\n");
53 fclose (file);
54 unlink ("fdopen.tst");
57 static void test_fileops( void )
59 static const char outbuffer[] = "0,1,2,3,4,5,6,7,8,9";
60 char buffer[256];
61 WCHAR wbuffer[256];
62 int fd;
63 FILE *file;
64 fpos_t pos;
65 int i, c;
67 fd = open ("fdopen.tst", O_WRONLY | O_CREAT | O_BINARY, _S_IREAD |_S_IWRITE);
68 write (fd, outbuffer, sizeof (outbuffer));
69 close (fd);
71 fd = open ("fdopen.tst", O_RDONLY | O_BINARY);
72 file = fdopen (fd, "rb");
73 ok(strlen(outbuffer) == (sizeof(outbuffer)-1),"strlen/sizeof error\n");
74 ok(fgets(buffer,sizeof(buffer),file) !=0,"fgets failed unexpected\n");
75 ok(fgets(buffer,sizeof(buffer),file) ==0,"fgets didn't signal EOF\n");
76 ok(feof(file) !=0,"feof doesn't signal EOF\n");
77 rewind(file);
78 ok(fgets(buffer,strlen(outbuffer),file) !=0,"fgets failed unexpected\n");
79 ok(lstrlenA(buffer) == lstrlenA(outbuffer) -1,"fgets didn't read right size\n");
80 ok(fgets(buffer,sizeof(outbuffer),file) !=0,"fgets failed unexpected\n");
81 ok(strlen(buffer) == 1,"fgets dropped chars\n");
82 ok(buffer[0] == outbuffer[strlen(outbuffer)-1],"fgets exchanged chars\n");
84 rewind(file);
85 for (i = 0, c = EOF; i < sizeof(outbuffer); i++)
87 ok((c = fgetc(file)) == outbuffer[i], "fgetc returned wrong data\n");
89 ok((c = fgetc(file)) == EOF, "getc did not return EOF\n");
90 ok(feof(file), "feof did not return EOF\n");
91 ok(ungetc(c, file) == EOF, "ungetc(EOF) did not return EOF\n");
92 ok(feof(file), "feof after ungetc(EOF) did not return EOF\n");
93 ok((c = fgetc(file)) == EOF, "getc did not return EOF\n");
94 c = outbuffer[sizeof(outbuffer) - 1];
95 ok(ungetc(c, file) == c, "ungetc did not return its input\n");
96 ok(!feof(file), "feof after ungetc returned EOF\n");
97 ok((c = fgetc(file)) != EOF, "getc after ungetc returned EOF\n");
98 ok(c == outbuffer[sizeof(outbuffer) - 1],
99 "getc did not return ungetc'd data\n");
100 ok(!feof(file), "feof after getc returned EOF prematurely\n");
101 ok((c = fgetc(file)) == EOF, "getc did not return EOF\n");
102 ok(feof(file), "feof after getc did not return EOF\n");
104 rewind(file);
105 ok(fgetpos(file,&pos) == 0, "fgetpos failed unexpected\n");
106 ok(pos == 0, "Unexpected result of fgetpos 0x%Lx\n", pos);
107 pos = (ULONGLONG)sizeof (outbuffer);
108 ok(fsetpos(file, &pos) == 0, "fsetpos failed unexpected\n");
109 ok(fgetpos(file,&pos) == 0, "fgetpos failed unexpected\n");
110 ok(pos == (ULONGLONG)sizeof (outbuffer), "Unexpected result of fgetpos 0x%Lx\n", pos);
112 fclose (file);
113 fd = open ("fdopen.tst", O_RDONLY | O_TEXT);
114 file = fdopen (fd, "rt"); /* open in TEXT mode */
115 ok(fgetws(wbuffer,sizeof(wbuffer),file) !=0,"fgetws failed unexpected\n");
116 ok(fgetws(wbuffer,sizeof(wbuffer),file) ==0,"fgetws didn't signal EOF\n");
117 ok(feof(file) !=0,"feof doesn't signal EOF\n");
118 rewind(file);
119 ok(fgetws(wbuffer,strlen(outbuffer),file) !=0,"fgetws failed unexpected\n");
120 ok(lstrlenW(wbuffer) == (lstrlenA(outbuffer) -1),"fgetws didn't read right size\n");
121 ok(fgetws(wbuffer,sizeof(outbuffer),file) !=0,"fgets failed unexpected\n");
122 ok(lstrlenW(wbuffer) == 1,"fgets dropped chars\n");
123 fclose (file);
125 file = fopen("fdopen.tst", "rb");
126 ok( file != NULL, "fopen failed\n");
127 /* sizeof(buffer) > content of file */
128 ok(fread(buffer, sizeof(buffer), 1, file) == 0, "fread test failed\n");
129 /* feof should be set now */
130 ok(feof(file), "feof after fread failed\n");
131 fclose (file);
133 unlink ("fdopen.tst");
136 #define IOMODE (ao?"ascii mode":"binary mode")
137 static void test_readmode( BOOL ascii_mode )
139 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";
140 static const char padbuffer[] = "ghjghjghjghj";
141 static const char nlbuffer[] = "\r\n";
142 char buffer[2*BUFSIZ+256];
143 const char *optr;
144 int fd;
145 FILE *file;
146 const int *ip;
147 int i, j, m, ao, pl;
148 unsigned int fp;
149 long l;
151 fd = open ("fdopen.tst", O_WRONLY | O_CREAT | O_BINARY, _S_IREAD |_S_IWRITE);
152 /* an internal buffer of BUFSIZ is maintained, so make a file big
153 * enough to test operations that cross the buffer boundary
155 j = (2*BUFSIZ-4)/strlen(padbuffer);
156 for (i=0; i<j; i++)
157 write (fd, padbuffer, strlen(padbuffer));
158 j = (2*BUFSIZ-4)%strlen(padbuffer);
159 for (i=0; i<j; i++)
160 write (fd, &padbuffer[i], 1);
161 write (fd, nlbuffer, strlen(nlbuffer));
162 write (fd, outbuffer, sizeof (outbuffer));
163 close (fd);
165 if (ascii_mode) {
166 /* Open file in ascii mode */
167 fd = open ("fdopen.tst", O_RDONLY);
168 file = fdopen (fd, "r");
169 ao = -1; /* on offset to account for carriage returns */
171 else {
172 fd = open ("fdopen.tst", O_RDONLY | O_BINARY);
173 file = fdopen (fd, "rb");
174 ao = 0;
177 /* first is a test of fgets, ftell, fseek */
178 ok(ftell(file) == 0,"Did not start at beginning of file in %s\n", IOMODE);
179 ok(fgets(buffer,2*BUFSIZ+256,file) !=0,"padding line fgets failed unexpected in %s\n", IOMODE);
180 l = ftell(file);
181 pl = 2*BUFSIZ-2;
182 ok(l == pl,"padding line ftell got %ld should be %d in %s\n", l, pl, IOMODE);
183 ok(lstrlenA(buffer) == pl+ao,"padding line fgets got size %d should be %d in %s\n",
184 lstrlenA(buffer), pl+ao, IOMODE);
185 for (fp=0; fp<strlen(outbuffer); fp++)
186 if (outbuffer[fp] == '\n') break;
187 fp++;
188 ok(fgets(buffer,256,file) !=0,"line 1 fgets failed unexpected in %s\n", IOMODE);
189 l = ftell(file);
190 ok(l == pl+fp,"line 1 ftell got %ld should be %d in %s\n", l, pl+fp, IOMODE);
191 ok(lstrlenA(buffer) == fp+ao,"line 1 fgets got size %d should be %d in %s\n",
192 lstrlenA(buffer), fp+ao, IOMODE);
193 /* test a seek back across the buffer boundary */
194 l = pl;
195 ok(fseek(file,l,SEEK_SET)==0,"seek failure in %s\n", IOMODE);
196 l = ftell(file);
197 ok(l == pl,"ftell after seek got %ld should be %d in %s\n", l, pl, IOMODE);
198 ok(fgets(buffer,256,file) !=0,"second read of line 1 fgets failed unexpected in %s\n", IOMODE);
199 l = ftell(file);
200 ok(l == pl+fp,"second read of line 1 ftell got %ld should be %d in %s\n", l, pl+fp, IOMODE);
201 ok(lstrlenA(buffer) == fp+ao,"second read of line 1 fgets got size %d should be %d in %s\n",
202 lstrlenA(buffer), fp+ao, IOMODE);
203 ok(fgets(buffer,256,file) !=0,"line 2 fgets failed unexpected in %s\n", IOMODE);
204 fp += 2;
205 l = ftell(file);
206 ok(l == pl+fp,"line 2 ftell got %ld should be %d in %s\n", l, pl+fp, IOMODE);
207 ok(lstrlenA(buffer) == 2+ao,"line 2 fgets got size %d should be %d in %s\n",
208 lstrlenA(buffer), 2+ao, IOMODE);
210 /* test fread across buffer boundary */
211 rewind(file);
212 ok(ftell(file) == 0,"Did not start at beginning of file in %s\n", IOMODE);
213 ok(fgets(buffer,BUFSIZ-6,file) !=0,"padding line fgets failed unexpected in %s\n", IOMODE);
214 j=strlen(outbuffer);
215 i=fread(buffer,1,BUFSIZ+strlen(outbuffer),file);
216 ok(i==BUFSIZ+j,"fread failed, expected %d got %d in %s\n", BUFSIZ+j, i, IOMODE);
217 l = ftell(file);
218 ok(l == pl+j-(ao*4)-5,"ftell after fread got %ld should be %d in %s\n", l, pl+j-(ao*4)-5, IOMODE);
219 for (m=0; m<3; m++)
220 ok(buffer[m]==padbuffer[m+(BUFSIZ-4)%strlen(padbuffer)],"expected %c got %c\n", padbuffer[m], buffer[m]);
221 m+=BUFSIZ+2+ao;
222 optr = outbuffer;
223 for (; m<i; m++) {
224 ok(buffer[m]==*optr,"char %d expected %c got %c in %s\n", m, *optr, buffer[m], IOMODE);
225 optr++;
226 if (ao && (*optr == '\r'))
227 optr++;
229 /* fread should return the requested number of bytes if available */
230 rewind(file);
231 ok(ftell(file) == 0,"Did not start at beginning of file in %s\n", IOMODE);
232 ok(fgets(buffer,BUFSIZ-6,file) !=0,"padding line fgets failed unexpected in %s\n", IOMODE);
233 j = fp+10;
234 i=fread(buffer,1,j,file);
235 ok(i==j,"fread failed, expected %d got %d in %s\n", j, i, IOMODE);
236 /* test fread eof */
237 ok(fseek(file,0,SEEK_END)==0,"seek failure in %s\n", IOMODE);
238 ok(feof(file)==0,"feof failure in %s\n", IOMODE);
239 ok(fread(buffer,1,1,file)==0,"fread failure in %s\n", IOMODE);
240 ok(feof(file)!=0,"feof failure in %s\n", IOMODE);
241 ok(fseek(file,-3,SEEK_CUR)==0,"seek failure in %s\n", IOMODE);
242 todo_wine ok(feof(file)==0,"feof failure in %s\n", IOMODE);
243 ok(fread(buffer,2,1,file)==1,"fread failed in %s\n", IOMODE);
244 ok(feof(file)==0,"feof failure in %s\n", IOMODE);
245 ok(fread(buffer,2,1,file)==0,"fread failure in %s\n",IOMODE);
246 ok(feof(file)!=0,"feof failure in %s\n", IOMODE);
248 /* test some additional functions */
249 rewind(file);
250 ok(ftell(file) == 0,"Did not start at beginning of file in %s\n", IOMODE);
251 ok(fgets(buffer,2*BUFSIZ+256,file) !=0,"padding line fgets failed unexpected in %s\n", IOMODE);
252 i = _getw(file);
253 ip = (const int *)outbuffer;
254 ok(i == *ip,"_getw failed, expected %08x got %08x in %s\n", *ip, i, IOMODE);
255 for (fp=0; fp<strlen(outbuffer); fp++)
256 if (outbuffer[fp] == '\n') break;
257 fp++;
258 /* this will cause the next _getw to cross carriage return characters */
259 ok(fgets(buffer,fp-6,file) !=0,"line 1 fgets failed unexpected in %s\n", IOMODE);
260 for (i=0, j=0; i<6; i++) {
261 if (ao==0 || outbuffer[fp-3+i] != '\r')
262 buffer[j++] = outbuffer[fp-3+i];
264 i = _getw(file);
265 ip = (int *)buffer;
266 ok(i == *ip,"_getw failed, expected %08x got %08x in %s\n", *ip, i, IOMODE);
268 fclose (file);
269 unlink ("fdopen.tst");
273 static WCHAR* AtoW( const char* p )
275 WCHAR* buffer;
276 DWORD len = MultiByteToWideChar( CP_ACP, 0, p, -1, NULL, 0 );
277 buffer = malloc( len * sizeof(WCHAR) );
278 MultiByteToWideChar( CP_ACP, 0, p, -1, buffer, len );
279 return buffer;
282 static void test_fgetc( void )
284 char* tempf;
285 FILE *tempfh;
286 int ich=0xe0, ret;
288 tempf=_tempnam(".","wne");
289 tempfh = fopen(tempf,"w+");
290 fputc(ich, tempfh);
291 fputc(ich, tempfh);
292 rewind(tempfh);
293 ret = fgetc(tempfh);
294 ok(ich == ret, "First fgetc expected %x got %x\n", ich, ret);
295 ret = fgetc(tempfh);
296 ok(ich == ret, "Second fgetc expected %x got %x\n", ich, ret);
297 fclose(tempfh);
298 unlink(tempf);
301 static void test_fgetwc( void )
303 #define LLEN 512
305 char* tempf;
306 FILE *tempfh;
307 static const char mytext[]= "This is test_fgetwc\r\n";
308 WCHAR wtextW[BUFSIZ+LLEN+1];
309 WCHAR *mytextW = NULL, *aptr, *wptr;
310 BOOL diff_found = FALSE;
311 int j;
312 unsigned int i;
313 long l;
315 tempf=_tempnam(".","wne");
316 tempfh = fopen(tempf,"wb");
317 j = 'a';
318 /* pad to almost the length of the internal buffer */
319 for (i=0; i<BUFSIZ-4; i++)
320 fputc(j,tempfh);
321 j = '\r';
322 fputc(j,tempfh);
323 j = '\n';
324 fputc(j,tempfh);
325 fputs(mytext,tempfh);
326 fclose(tempfh);
327 /* in text mode, getws/c expects multibyte characters */
328 /*currently Wine only supports plain ascii, and that is all that is tested here */
329 tempfh = fopen(tempf,"rt"); /* open in TEXT mode */
330 fgetws(wtextW,LLEN,tempfh);
331 l=ftell(tempfh);
332 ok(l==BUFSIZ-2, "ftell expected %d got %ld\n", BUFSIZ-2, l);
333 fgetws(wtextW,LLEN,tempfh);
334 l=ftell(tempfh);
335 ok(l==BUFSIZ-2+strlen(mytext), "ftell expected %d got %ld\n",
336 BUFSIZ-2+strlen(mytext), l);
337 mytextW = AtoW (mytext);
338 aptr = mytextW;
339 wptr = wtextW;
340 for (i=0; i<strlen(mytext)-2; i++, aptr++, wptr++)
342 diff_found |= (*aptr != *wptr);
344 ok(!(diff_found), "fgetwc difference found in TEXT mode\n");
345 ok(*wptr == '\n', "Carriage return was not skipped\n");
346 fclose(tempfh);
347 unlink(tempf);
349 tempfh = fopen(tempf,"wb");
350 j = 'a';
351 /* pad to almost the length of the internal buffer. Use an odd number of bytes
352 to test that we can read wchars that are split across the internal buffer
353 boundary */
354 for (i=0; i<BUFSIZ-3-strlen(mytext)*sizeof(WCHAR); i++)
355 fputc(j,tempfh);
356 j = '\r';
357 fputwc(j,tempfh);
358 j = '\n';
359 fputwc(j,tempfh);
360 fputws(wtextW,tempfh);
361 fputws(wtextW,tempfh);
362 fclose(tempfh);
363 /* in binary mode, getws/c expects wide characters */
364 tempfh = fopen(tempf,"rb"); /* open in BINARY mode */
365 j=(BUFSIZ-2)/sizeof(WCHAR)-strlen(mytext);
366 fgetws(wtextW,j,tempfh);
367 l=ftell(tempfh);
368 j=(j-1)*sizeof(WCHAR);
369 ok(l==j, "ftell expected %d got %ld\n", j, l);
370 i=fgetc(tempfh);
371 ok(i=='a', "fgetc expected %d got %d\n", 0x61, i);
372 l=ftell(tempfh);
373 j++;
374 ok(l==j, "ftell expected %d got %ld\n", j, l);
375 fgetws(wtextW,3,tempfh);
376 ok(wtextW[0]=='\r',"expected carriage return got %04hx\n", wtextW[0]);
377 ok(wtextW[1]=='\n',"expected newline got %04hx\n", wtextW[1]);
378 l=ftell(tempfh);
379 j += 4;
380 ok(l==j, "ftell expected %d got %ld\n", j, l);
381 for(i=0; i<strlen(mytext); i++)
382 wtextW[i] = 0;
383 /* the first time we get the string, it should be entirely within the local buffer */
384 fgetws(wtextW,LLEN,tempfh);
385 l=ftell(tempfh);
386 j += (strlen(mytext)-1)*sizeof(WCHAR);
387 ok(l==j, "ftell expected %d got %ld\n", j, l);
388 diff_found = FALSE;
389 aptr = mytextW;
390 wptr = wtextW;
391 for (i=0; i<strlen(mytext)-2; i++, aptr++, wptr++)
393 ok(*aptr == *wptr, "Char %d expected %04hx got %04hx\n", i, *aptr, *wptr);
394 diff_found |= (*aptr != *wptr);
396 ok(!(diff_found), "fgetwc difference found in BINARY mode\n");
397 ok(*wptr == '\n', "Should get newline\n");
398 for(i=0; i<strlen(mytext); i++)
399 wtextW[i] = 0;
400 /* the second time we get the string, it should cross the local buffer boundary.
401 One of the wchars should be split across the boundary */
402 fgetws(wtextW,LLEN,tempfh);
403 diff_found = FALSE;
404 aptr = mytextW;
405 wptr = wtextW;
406 for (i=0; i<strlen(mytext)-2; i++, aptr++, wptr++)
408 ok(*aptr == *wptr, "Char %d expected %04hx got %04hx\n", i, *aptr, *wptr);
409 diff_found |= (*aptr != *wptr);
411 ok(!(diff_found), "fgetwc difference found in BINARY mode\n");
412 ok(*wptr == '\n', "Should get newline\n");
414 free(mytextW);
415 fclose(tempfh);
416 unlink(tempf);
419 static void test_ctrlz( void )
421 char* tempf;
422 FILE *tempfh;
423 static const char mytext[]= "This is test_ctrlz";
424 char buffer[256];
425 int i, j;
426 long l;
428 tempf=_tempnam(".","wne");
429 tempfh = fopen(tempf,"wb");
430 fputs(mytext,tempfh);
431 j = 0x1a; /* a ctrl-z character signals EOF in text mode */
432 fputc(j,tempfh);
433 j = '\r';
434 fputc(j,tempfh);
435 j = '\n';
436 fputc(j,tempfh);
437 j = 'a';
438 fputc(j,tempfh);
439 fclose(tempfh);
440 tempfh = fopen(tempf,"rt"); /* open in TEXT mode */
441 ok(fgets(buffer,256,tempfh) != 0,"fgets failed unexpected\n");
442 i=strlen(buffer);
443 j=strlen(mytext);
444 ok(i==j, "returned string length expected %d got %d\n", j, i);
445 j+=4; /* ftell should indicate the true end of file */
446 l=ftell(tempfh);
447 ok(l==j, "ftell expected %d got %ld\n", j, l);
448 ok(feof(tempfh), "did not get EOF\n");
449 fclose(tempfh);
451 tempfh = fopen(tempf,"rb"); /* open in BINARY mode */
452 ok(fgets(buffer,256,tempfh) != 0,"fgets failed unexpected\n");
453 i=strlen(buffer);
454 j=strlen(mytext)+3; /* should get through newline */
455 ok(i==j, "returned string length expected %d got %d\n", j, i);
456 l=ftell(tempfh);
457 ok(l==j, "ftell expected %d got %ld\n", j, l);
458 ok(fgets(buffer,256,tempfh) != 0,"fgets failed unexpected\n");
459 i=strlen(buffer);
460 ok(i==1, "returned string length expected %d got %d\n", 1, i);
461 ok(feof(tempfh), "did not get EOF\n");
462 fclose(tempfh);
463 unlink(tempf);
466 static void test_file_put_get( void )
468 char* tempf;
469 FILE *tempfh;
470 static const char mytext[]= "This is a test_file_put_get\n";
471 static const char dostext[]= "This is a test_file_put_get\r\n";
472 char btext[LLEN];
473 WCHAR wtextW[LLEN+1];
474 WCHAR *mytextW = NULL, *aptr, *wptr;
475 BOOL diff_found = FALSE;
476 unsigned int i;
478 tempf=_tempnam(".","wne");
479 tempfh = fopen(tempf,"wt"); /* open in TEXT mode */
480 fputs(mytext,tempfh);
481 fclose(tempfh);
482 tempfh = fopen(tempf,"rb"); /* open in TEXT mode */
483 fgets(btext,LLEN,tempfh);
484 ok( strlen(mytext) + 1 == strlen(btext),"TEXT/BINARY mode not handled for write\n");
485 ok( btext[strlen(mytext)-1] == '\r', "CR not written\n");
486 fclose(tempfh);
487 tempfh = fopen(tempf,"wb"); /* open in BINARY mode */
488 fputs(dostext,tempfh);
489 fclose(tempfh);
490 tempfh = fopen(tempf,"rt"); /* open in TEXT mode */
491 fgets(btext,LLEN,tempfh);
492 ok(strcmp(btext, mytext) == 0,"_O_TEXT read doesn't strip CR\n");
493 fclose(tempfh);
494 tempfh = fopen(tempf,"rb"); /* open in TEXT mode */
495 fgets(btext,LLEN,tempfh);
496 ok(strcmp(btext, dostext) == 0,"_O_BINARY read doesn't preserve CR\n");
498 fclose(tempfh);
499 tempfh = fopen(tempf,"rt"); /* open in TEXT mode */
500 fgetws(wtextW,LLEN,tempfh);
501 mytextW = AtoW (mytext);
502 aptr = mytextW;
503 wptr = wtextW;
505 for (i=0; i<strlen(mytext); i++, aptr++, wptr++)
507 diff_found |= (*aptr != *wptr);
509 ok(!(diff_found), "fgetwc doesn't strip CR in TEXT mode\n");
510 free(mytextW);
511 fclose(tempfh);
512 unlink(tempf);
515 static void test_file_write_read( void )
517 char* tempf;
518 int tempfd;
519 static const char mytext[]= "This is test_file_write_read\nsecond line\n";
520 static const char dostext[]= "This is test_file_write_read\r\nsecond line\r\n";
521 char btext[LLEN];
522 int ret, i;
524 tempf=_tempnam(".","wne");
525 tempfd = _open(tempf,_O_CREAT|_O_TRUNC|_O_BINARY|_O_RDWR,
526 _S_IREAD | _S_IWRITE);
527 ok( tempfd != -1,
528 "Can't open '%s': %d\n", tempf, errno); /* open in BINARY mode */
529 ok(_write(tempfd,dostext,strlen(dostext)) == lstrlenA(dostext),
530 "_write _O_BINARY bad return value\n");
531 _close(tempfd);
532 i = lstrlenA(mytext);
533 tempfd = _open(tempf,_O_RDONLY|_O_BINARY,0); /* open in BINARY mode */
534 ok(_read(tempfd,btext,i) == i,
535 "_read _O_BINARY got bad length\n");
536 ok( memcmp(dostext,btext,i) == 0,
537 "problems with _O_BINARY _write / _read\n");
538 _close(tempfd);
539 tempfd = _open(tempf,_O_RDONLY|_O_TEXT); /* open in TEXT mode */
540 ok(_read(tempfd,btext,i) == i-1,
541 "_read _O_TEXT got bad length\n");
542 ok( memcmp(mytext,btext,i-1) == 0,
543 "problems with _O_BINARY _write / _O_TEXT _read\n");
544 _close(tempfd);
545 tempfd = _open(tempf,_O_CREAT|_O_TRUNC|_O_TEXT|_O_RDWR,
546 _S_IREAD | _S_IWRITE);
547 ok( tempfd != -1,
548 "Can't open '%s': %d\n", tempf, errno); /* open in TEXT mode */
549 ok(_write(tempfd,mytext,strlen(mytext)) == lstrlenA(mytext),
550 "_write _O_TEXT bad return value\n");
551 _close(tempfd);
552 tempfd = _open(tempf,_O_RDONLY|_O_BINARY,0); /* open in BINARY mode */
553 ok(_read(tempfd,btext,LLEN) == lstrlenA(dostext),
554 "_read _O_BINARY got bad length\n");
555 ok( memcmp(dostext,btext,strlen(dostext)) == 0,
556 "problems with _O_TEXT _write / _O_BINARY _read\n");
557 ok( btext[strlen(dostext)-2] == '\r', "CR not written or read\n");
558 _close(tempfd);
559 tempfd = _open(tempf,_O_RDONLY|_O_TEXT); /* open in TEXT mode */
560 ok(_read(tempfd,btext,LLEN) == lstrlenA(mytext),
561 "_read _O_TEXT got bad length\n");
562 ok( memcmp(mytext,btext,strlen(mytext)) == 0,
563 "problems with _O_TEXT _write / _read\n");
564 _close(tempfd);
566 memset(btext, 0, LLEN);
567 tempfd = _open(tempf,_O_APPEND|_O_RDWR); /* open for APPEND in default mode */
568 ok(tell(tempfd) == 0, "bad position %lu expecting 0\n", tell(tempfd));
569 ok(_read(tempfd,btext,LLEN) == lstrlenA(mytext), "_read _O_APPEND got bad length\n");
570 ok( memcmp(mytext,btext,strlen(mytext)) == 0, "problems with _O_APPEND _read\n");
571 _close(tempfd);
573 /* Test reading only \n or \r */
574 tempfd = _open(tempf,_O_RDONLY|_O_TEXT); /* open in TEXT mode */
575 _lseek(tempfd, -1, FILE_END);
576 ret = _read(tempfd,btext,LLEN);
577 ok(ret == 1, "_read expected 1 got bad length: %d\n", ret);
578 _lseek(tempfd, -2, FILE_END);
579 ret = _read(tempfd,btext,LLEN);
580 ok(ret == 1 && *btext == '\n', "_read expected '\\n' got bad length: %d\n", ret);
581 _lseek(tempfd, -3, FILE_END);
582 ret = _read(tempfd,btext,2);
583 ok(ret == 1 && *btext == 'e', "_read expected 'e' got \"%.*s\" bad length: %d\n", ret, btext, ret);
584 ok(tell(tempfd) == 42, "bad position %lu expecting 42\n", tell(tempfd));
585 _close(tempfd);
587 ret = unlink(tempf);
588 ok( ret == 0 ,"Can't unlink '%s': %d\n", tempf, errno);
590 tempf=_tempnam(".","wne");
591 tempfd = _open(tempf,_O_CREAT|_O_TRUNC|_O_BINARY|_O_RDWR,0);
592 ok( tempfd != -1,
593 "Can't open '%s': %d\n", tempf, errno); /* open in BINARY mode */
594 ok(_write(tempfd,dostext,strlen(dostext)) == lstrlenA(dostext),
595 "_write _O_BINARY bad return value\n");
596 _close(tempfd);
597 tempfd = _open(tempf,_O_RDONLY|_O_BINARY,0); /* open in BINARY mode */
598 ok(_read(tempfd,btext,LLEN) == lstrlenA(dostext),
599 "_read _O_BINARY got bad length\n");
600 ok( memcmp(dostext,btext,strlen(dostext)) == 0,
601 "problems with _O_BINARY _write / _read\n");
602 ok( btext[strlen(dostext)-2] == '\r', "CR not written or read\n");
603 _close(tempfd);
604 tempfd = _open(tempf,_O_RDONLY|_O_TEXT); /* open in TEXT mode */
605 ok(_read(tempfd,btext,LLEN) == lstrlenA(mytext),
606 "_read _O_TEXT got bad length\n");
607 ok( memcmp(mytext,btext,strlen(mytext)) == 0,
608 "problems with _O_BINARY _write / _O_TEXT _read\n");
609 _close(tempfd);
611 ret =_chmod (tempf, _S_IREAD | _S_IWRITE);
612 ok( ret == 0,
613 "Can't chmod '%s' to read-write: %d\n", tempf, errno);
614 ret = unlink(tempf);
615 ok( ret == 0 ,"Can't unlink '%s': %d\n", tempf, errno);
618 static void test_file_inherit_child(const char* fd_s)
620 int fd = atoi(fd_s);
621 char buffer[32];
622 int ret;
624 ret =write(fd, "Success", 8);
625 ok( ret == 8, "Couldn't write in child process on %d (%s)\n", fd, strerror(errno));
626 lseek(fd, 0, SEEK_SET);
627 ok(read(fd, buffer, sizeof (buffer)) == 8, "Couldn't read back the data\n");
628 ok(memcmp(buffer, "Success", 8) == 0, "Couldn't read back the data\n");
631 static void test_file_inherit_child_no(const char* fd_s)
633 int fd = atoi(fd_s);
634 int ret;
636 ret = write(fd, "Success", 8);
637 ok( ret == -1 && errno == EBADF,
638 "Wrong write result in child process on %d (%s)\n", fd, strerror(errno));
641 static void test_file_inherit( const char* selfname )
643 int fd;
644 const char* arg_v[5];
645 char buffer[16];
647 fd = open ("fdopen.tst", O_CREAT | O_RDWR | O_BINARY, _S_IREAD |_S_IWRITE);
648 ok(fd != -1, "Couldn't create test file\n");
649 arg_v[0] = selfname;
650 arg_v[1] = "tests/file.c";
651 arg_v[2] = "inherit";
652 arg_v[3] = buffer; sprintf(buffer, "%d", fd);
653 arg_v[4] = 0;
654 _spawnvp(_P_WAIT, selfname, arg_v);
655 ok(tell(fd) == 8, "bad position %lu expecting 8\n", tell(fd));
656 lseek(fd, 0, SEEK_SET);
657 ok(read(fd, buffer, sizeof (buffer)) == 8 && memcmp(buffer, "Success", 8) == 0, "Couldn't read back the data\n");
658 close (fd);
659 ok(unlink("fdopen.tst") == 0, "Couldn't unlink\n");
661 fd = open ("fdopen.tst", O_CREAT | O_RDWR | O_BINARY | O_NOINHERIT, _S_IREAD |_S_IWRITE);
662 ok(fd != -1, "Couldn't create test file\n");
663 arg_v[0] = selfname;
664 arg_v[1] = "tests/file.c";
665 arg_v[2] = "inherit_no";
666 arg_v[3] = buffer; sprintf(buffer, "%d", fd);
667 arg_v[4] = 0;
668 _spawnvp(_P_WAIT, selfname, arg_v);
669 ok(tell(fd) == 0, "bad position %lu expecting 0\n", tell(fd));
670 ok(read(fd, buffer, sizeof (buffer)) == 0, "Found unexpected data (%s)\n", buffer);
671 close (fd);
672 ok(unlink("fdopen.tst") == 0, "Couldn't unlink\n");
675 static void test_tmpnam( void )
677 char name[MAX_PATH] = "abc";
678 char *res;
680 res = tmpnam(NULL);
681 ok(res != NULL, "tmpnam returned NULL\n");
682 ok(res[0] == '\\', "first character is not a backslash\n");
683 ok(strchr(res+1, '\\') == 0, "file not in the root directory\n");
684 ok(res[strlen(res)-1] == '.', "first call - last character is not a dot\n");
686 res = tmpnam(name);
687 ok(res != NULL, "tmpnam returned NULL\n");
688 ok(res == name, "supplied buffer was not used\n");
689 ok(res[0] == '\\', "first character is not a backslash\n");
690 ok(strchr(res+1, '\\') == 0, "file not in the root directory\n");
691 ok(res[strlen(res)-1] != '.', "second call - last character is a dot\n");
694 static void test_chsize( void )
696 int fd;
697 long cur, pos, count;
698 char temptext[] = "012345678";
699 char *tempfile = _tempnam( ".", "tst" );
701 ok( tempfile != NULL, "Couldn't create test file: %s\n", tempfile );
703 fd = _open( tempfile, _O_CREAT|_O_TRUNC|_O_RDWR, _S_IREAD|_S_IWRITE );
704 ok( fd > 0, "Couldn't open test file\n" );
706 count = _write( fd, temptext, sizeof(temptext) );
707 ok( count > 0, "Couldn't write to test file\n" );
709 /* get current file pointer */
710 cur = _lseek( fd, 0, SEEK_CUR );
712 /* make the file smaller */
713 ok( _chsize( fd, sizeof(temptext) / 2 ) == 0, "_chsize() failed\n" );
715 pos = _lseek( fd, 0, SEEK_CUR );
716 ok( cur == pos, "File pointer changed from: %ld to: %ld\n", cur, pos );
717 ok( _filelength( fd ) == sizeof(temptext) / 2, "Wrong file size\n" );
719 /* enlarge the file */
720 ok( _chsize( fd, sizeof(temptext) * 2 ) == 0, "_chsize() failed\n" );
722 pos = _lseek( fd, 0, SEEK_CUR );
723 ok( cur == pos, "File pointer changed from: %ld to: %ld\n", cur, pos );
724 ok( _filelength( fd ) == sizeof(temptext) * 2, "Wrong file size\n" );
726 _close( fd );
727 _unlink( tempfile );
730 static void test_fopen_fclose_fcloseall( void )
732 char fname1[] = "empty1";
733 char fname2[] = "empty2";
734 char fname3[] = "empty3";
735 FILE *stream1, *stream2, *stream3, *stream4;
736 int ret, numclosed;
738 /* testing fopen() */
739 stream1 = fopen(fname1, "w+");
740 ok(stream1 != NULL, "The file '%s' was not opened\n", fname1);
741 stream2 = fopen(fname2, "w ");
742 ok(stream2 != NULL, "The file '%s' was not opened\n", fname2 );
743 _unlink(fname3);
744 stream3 = fopen(fname3, "r");
745 ok(stream3 == NULL, "The file '%s' shouldn't exist before\n", fname3 );
746 stream3 = fopen(fname3, "w+");
747 ok(stream3 != NULL, "The file '%s' should be opened now\n", fname3 );
748 errno = 0xfaceabad;
749 stream4 = fopen("", "w+");
750 ok(stream4 == NULL && errno == ENOENT,
751 "filename is empty, errno = %d (expected 2)\n", errno);
752 errno = 0xfaceabad;
753 stream4 = fopen(NULL, "w+");
754 ok(stream4 == NULL && (errno == EINVAL || errno == ENOENT),
755 "filename is NULL, errno = %d (expected 2 or 22)\n", errno);
757 /* testing fclose() */
758 ret = fclose(stream2);
759 ok(ret == 0, "The file '%s' was not closed\n", fname2);
760 ret = fclose(stream3);
761 ok(ret == 0, "The file '%s' was not closed\n", fname3);
762 ret = fclose(stream2);
763 ok(ret == EOF, "Closing file '%s' returned %d\n", fname2, ret);
764 ret = fclose(stream3);
765 ok(ret == EOF, "Closing file '%s' returned %d\n", fname3, ret);
767 /* testing fcloseall() */
768 numclosed = _fcloseall();
769 /* fname1 should be closed here */
770 ok(numclosed == 1, "Number of files closed by fcloseall(): %u\n", numclosed);
771 numclosed = _fcloseall();
772 ok(numclosed == 0, "Number of files closed by fcloseall(): %u\n", numclosed);
774 ok(_unlink(fname1) == 0, "Couldn't unlink file named '%s'\n", fname1);
775 ok(_unlink(fname2) == 0, "Couldn't unlink file named '%s'\n", fname2);
776 ok(_unlink(fname3) == 0, "Couldn't unlink file named '%s'\n", fname3);
779 static void test_get_osfhandle(void)
781 int fd;
782 char fname[] = "t_get_osfhanle";
783 DWORD bytes_written;
784 HANDLE handle;
786 fd = _sopen(fname, _O_CREAT|_O_RDWR, _SH_DENYRW, _S_IREAD | _S_IWRITE);
787 handle = (HANDLE)_get_osfhandle(fd);
788 WriteFile(handle, "bar", 3, &bytes_written, NULL);
789 _close(fd);
790 fd = _open(fname, _O_RDONLY, 0);
791 ok(fd != -1, "Coudn't open '%s' after _get_osfhanle()\n", fname);
793 _close(fd);
794 _unlink(fname);
797 static void test_setmaxstdio(void)
799 ok(2048 == _setmaxstdio(2048),"_setmaxstdio returned %d instead of 2048\n",_setmaxstdio(2048));
800 ok(-1 == _setmaxstdio(2049),"_setmaxstdio returned %d instead of -1\n",_setmaxstdio(2049));
803 static void test_stat(void)
805 int fd;
806 int pipes[2];
807 struct stat buf;
809 /* Tests for a file */
810 fd = open("stat.tst", O_WRONLY | O_CREAT | O_BINARY, _S_IREAD |_S_IWRITE);
811 if (fd >= 0)
813 if (fstat(fd, &buf) == 0)
815 if ((buf.st_mode & _S_IFMT) == _S_IFREG)
817 ok(buf.st_dev == 0, "st_dev is %d, expected 0\n", buf.st_dev);
818 ok(buf.st_dev == buf.st_rdev, "st_dev (%d) and st_rdev (%d) differ\n",
819 buf.st_dev, buf.st_rdev);
820 ok(buf.st_nlink == 1, "st_nlink is %d, expected 1\n",
821 buf.st_nlink);
822 ok(buf.st_size == 0, "st_size is %d, expected 0\n",
823 buf.st_size);
825 else
826 skip("file is not a file?\n");
828 else
829 skip("fstat failed, errno %d\n", errno);
830 close(fd);
831 remove("stat.tst");
833 else
834 skip("open failed with errno %d\n", errno);
836 /* Tests for a char device */
837 if (_dup2(0, 10) == 0)
839 if (fstat(10, &buf) == 0)
841 if (buf.st_mode == _S_IFCHR)
843 ok(buf.st_dev == 10, "st_dev is %d, expected 10\n", buf.st_dev);
844 ok(buf.st_rdev == 10, "st_rdev is %d, expected 10\n", buf.st_rdev);
845 ok(buf.st_nlink == 1, "st_nlink is %d, expected 1\n", buf.st_nlink);
847 else
848 skip("stdin is not a char device?\n");
850 else
851 skip("fstat failed with errno %d\n", errno);
852 close(10);
854 else
855 skip("_dup2 failed with errno %d\n", errno);
857 /* Tests for pipes */
858 if (_pipe(pipes, 1024, O_BINARY) == 0)
860 if (fstat(pipes[0], &buf) == 0)
862 if (buf.st_mode == _S_IFIFO)
864 ok(buf.st_dev == pipes[0], "st_dev is %d, expected %d\n",
865 buf.st_dev, pipes[0]);
866 ok(buf.st_rdev == pipes[0], "st_rdev is %d, expected %d\n",
867 buf.st_rdev, pipes[0]);
868 ok(buf.st_nlink == 1, "st_nlink is %d, expected 1\n",
869 buf.st_nlink);
871 else
872 skip("pipe() didn't make a pipe?\n");
874 else
875 skip("fstat failed with errno %d\n", errno);
876 close(pipes[0]);
877 close(pipes[1]);
879 else
880 skip("pipe failed with errno %d\n", errno);
883 static const char* pipe_string="Hello world";
885 static void test_pipes_child(int argc, char** args)
887 int fd;
889 if (argc < 5)
891 ok(0, "not enough parameters: %d\n", argc);
892 return;
895 fd=atoi(args[3]);
896 ok(close(fd) == 0, "unable to close %d: %d\n", fd, errno);
898 fd=atoi(args[4]);
899 write(fd, pipe_string, strlen(pipe_string));
900 ok(close(fd) == 0, "unable to close %d: %d\n", fd, errno);
903 static void test_pipes(const char* selfname)
905 int pipes[2];
906 char str_fdr[12], str_fdw[12];
907 FILE* file;
908 const char* arg_v[6];
909 char buf[4096];
910 int r;
912 /* Test reading from a pipe with read() */
913 if (_pipe(pipes, 1024, O_BINARY) < 0)
915 ok(0, "pipe failed with errno %d\n", errno);
916 return;
919 arg_v[0] = selfname;
920 arg_v[1] = "tests/file.c";
921 arg_v[2] = "pipes";
922 arg_v[3] = str_fdr; sprintf(str_fdr, "%d", pipes[0]);
923 arg_v[4] = str_fdw; sprintf(str_fdw, "%d", pipes[1]);
924 arg_v[5] = NULL;
925 _spawnvp(_P_NOWAIT, selfname, arg_v);
926 ok(close(pipes[1]) == 0, "unable to close %d: %d\n", pipes[1], errno);
928 r=read(pipes[0], buf, sizeof(buf)-1);
929 ok(r == strlen(pipe_string), "expected to read %d bytes, got %d\n", strlen(pipe_string)+1, r);
930 if (r > 0)
931 buf[r]='\0';
932 ok(strcmp(buf, pipe_string) == 0, "expected to read '%s', got '%s'\n", pipe_string, buf);
933 r=read(pipes[0], buf, sizeof(buf)-1);
934 ok(r == 0, "expected to read 0 bytes, got %d\n", r);
935 ok(close(pipes[0]) == 0, "unable to close %d: %d\n", pipes[0], errno);
937 /* Test reading from a pipe with fread() */
938 if (_pipe(pipes, 1024, O_BINARY) < 0)
940 ok(0, "pipe failed with errno %d\n", errno);
941 return;
944 arg_v[0] = selfname;
945 arg_v[1] = "tests/file.c";
946 arg_v[2] = "pipes";
947 arg_v[3] = str_fdr; sprintf(str_fdr, "%d", pipes[0]);
948 arg_v[4] = str_fdw; sprintf(str_fdw, "%d", pipes[1]);
949 arg_v[5] = NULL;
950 _spawnvp(_P_NOWAIT, selfname, arg_v);
951 ok(close(pipes[1]) == 0, "unable to close %d: %d\n", pipes[1], errno);
952 file=fdopen(pipes[0], "r");
954 r=fread(buf, 1, sizeof(buf)-1, file);
955 ok(r == strlen(pipe_string), "fread() returned %d instead of %d: ferror=%d\n", r, strlen(pipe_string), ferror(file));
956 if (r > 0)
957 buf[r]='\0';
958 ok(strcmp(buf, pipe_string) == 0, "got '%s' expected '%s'\n", buf, pipe_string);
960 r=fread(buf, 1, sizeof(buf)-1, file);
961 ok(r == 0, "fread() returned %d instead of 0\n", r);
962 ok(ferror(file) == 0, "got ferror() = %d\n", ferror(file));
963 ok(feof(file), "feof() is false!\n");
965 ok(fclose(file) == 0, "unable to close the pipe: %d\n", errno);
968 START_TEST(file)
970 int arg_c;
971 char** arg_v;
973 arg_c = winetest_get_mainargs( &arg_v );
975 /* testing low-level I/O */
976 if (arg_c >= 3)
978 if (strcmp(arg_v[2], "inherit") == 0)
979 test_file_inherit_child(arg_v[3]);
980 else if (strcmp(arg_v[2], "inherit_no") == 0)
981 test_file_inherit_child_no(arg_v[3]);
982 else if (strcmp(arg_v[2], "pipes") == 0)
983 test_pipes_child(arg_c, arg_v);
984 else
985 ok(0, "invalid argument '%s'\n", arg_v[2]);
986 return;
988 test_file_inherit(arg_v[0]);
989 test_file_write_read();
990 test_chsize();
991 test_stat();
993 /* testing stream I/O */
994 test_fdopen();
995 test_fopen_fclose_fcloseall();
996 test_fileops();
997 test_readmode(FALSE); /* binary mode */
998 test_readmode(TRUE); /* ascii mode */
999 test_fgetc();
1000 test_fgetwc();
1001 test_ctrlz();
1002 test_file_put_get();
1003 test_tmpnam();
1004 test_get_osfhandle();
1005 test_setmaxstdio();
1006 test_pipes(arg_v[0]);