rpcrt4: Try a lot harder to resuse existing connections by comparing inside the RpcQu...
[wine] / dlls / msvcrt / tests / file.c
1 /*
2  * Unit test suite for file functions
3  *
4  * Copyright 2002 Bill Currie
5  * Copyright 2005 Paul Rupe
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21
22 #include "wine/test.h"
23 #include <stdarg.h>
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <fcntl.h>
27 #include <share.h>
28 #include <sys/stat.h>
29 #include <io.h>
30 #include <direct.h>
31 #include <windef.h>
32 #include <winbase.h>
33 #include <winnls.h>
34 #include <process.h>
35 #include <errno.h>
36
37 static void test_fdopen( void )
38 {
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;
43
44     fd = open ("fdopen.tst", O_WRONLY | O_CREAT | O_BINARY, _S_IREAD |_S_IWRITE);
45     write (fd, buffer, sizeof (buffer));
46     close (fd);
47
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");
55 }
56
57 static void test_fileops( void )
58 {
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;
66
67     fd = open ("fdopen.tst", O_WRONLY | O_CREAT | O_BINARY, _S_IREAD |_S_IWRITE);
68     write (fd, outbuffer, sizeof (outbuffer));
69     close (fd);
70
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");
83
84     rewind(file);
85     for (i = 0, c = EOF; i < sizeof(outbuffer); i++)
86     {
87         ok((c = fgetc(file)) == outbuffer[i], "fgetc returned wrong data\n");
88     }
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");
103
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);
111
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);
124
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);
132
133     unlink ("fdopen.tst");
134 }
135
136 #define IOMODE (ao?"ascii mode":"binary mode")
137 static void test_readmode( BOOL ascii_mode )
138 {
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;
150
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 
154      */
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);
164     
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 */
170     }
171     else {
172         fd = open ("fdopen.tst", O_RDONLY | O_BINARY);
173         file = fdopen (fd, "rb");
174         ao = 0;
175     }
176     
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);
209     
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++;
228     }
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);
247     
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];
263     }
264     i = _getw(file);
265     ip = (int *)buffer;
266     ok(i == *ip,"_getw failed, expected %08x got %08x in %s\n", *ip, i, IOMODE);
267
268     fclose (file);
269     unlink ("fdopen.tst");
270 }
271
272
273 static WCHAR* AtoW( const char* p )
274 {
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;
280 }
281
282 static void test_fgetc( void )
283 {
284   char* tempf;
285   FILE *tempfh;
286   int  ich=0xe0, ret;
287
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);
299 }
300
301 static void test_fgetwc( void )
302 {
303 #define LLEN 512
304
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;
314
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++)
341     {
342       diff_found |= (*aptr != *wptr);
343     }
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);
348   
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++)
392     {
393       ok(*aptr == *wptr, "Char %d expected %04hx got %04hx\n", i, *aptr, *wptr);
394       diff_found |= (*aptr != *wptr);
395     }
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++)
407     {
408       ok(*aptr == *wptr, "Char %d expected %04hx got %04hx\n", i, *aptr, *wptr);
409       diff_found |= (*aptr != *wptr);
410     }
411   ok(!(diff_found), "fgetwc difference found in BINARY mode\n");
412   ok(*wptr == '\n', "Should get newline\n");
413
414   free(mytextW);
415   fclose(tempfh);
416   unlink(tempf);
417 }
418
419 static void test_ctrlz( void )
420 {
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;
427
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);
450   
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);
464 }
465
466 static void test_file_put_get( void )
467 {
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;
477
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");
497
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;
504
505   for (i=0; i<strlen(mytext); i++, aptr++, wptr++)
506     {
507       diff_found |= (*aptr != *wptr);
508     }
509   ok(!(diff_found), "fgetwc doesn't strip CR in TEXT mode\n");
510   free(mytextW);
511   fclose(tempfh);
512   unlink(tempf);
513 }
514
515 static void test_file_write_read( void )
516 {
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;
523
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);
565
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);
572
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);
586
587   ret = unlink(tempf);
588   ok( ret == 0 ,"Can't unlink '%s': %d\n", tempf, errno);
589
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);
610
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);
616 }
617
618 static void test_file_inherit_child(const char* fd_s)
619 {
620     int fd = atoi(fd_s);
621     char buffer[32];
622     int ret;
623
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");
629 }
630
631 static void test_file_inherit_child_no(const char* fd_s)
632 {
633     int fd = atoi(fd_s);
634     int ret;
635
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));
639 }
640  
641 static void test_file_inherit( const char* selfname )
642 {
643     int                 fd;
644     const char*         arg_v[5];
645     char                buffer[16];
646
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");
660     
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");
673 }
674
675 static void test_tmpnam( void )
676 {
677   char name[MAX_PATH] = "abc";
678   char *res;
679
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");
685
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");
692 }
693
694 static void test_chsize( void )
695 {
696     int fd;
697     long cur, pos, count;
698     char temptext[] = "012345678";
699     char *tempfile = _tempnam( ".", "tst" );
700     
701     ok( tempfile != NULL, "Couldn't create test file: %s\n", tempfile );
702
703     fd = _open( tempfile, _O_CREAT|_O_TRUNC|_O_RDWR, _S_IREAD|_S_IWRITE );
704     ok( fd > 0, "Couldn't open test file\n" );
705
706     count = _write( fd, temptext, sizeof(temptext) );
707     ok( count > 0, "Couldn't write to test file\n" );
708
709     /* get current file pointer */
710     cur = _lseek( fd, 0, SEEK_CUR );
711
712     /* make the file smaller */
713     ok( _chsize( fd, sizeof(temptext) / 2 ) == 0, "_chsize() failed\n" );
714
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" );
718
719     /* enlarge the file */
720     ok( _chsize( fd, sizeof(temptext) * 2 ) == 0, "_chsize() failed\n" ); 
721
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" );
725
726     _close( fd );
727     _unlink( tempfile );
728 }
729
730 static void test_fopen_fclose_fcloseall( void )
731 {
732     char fname1[] = "empty1";
733     char fname2[] = "empty2";
734     char fname3[] = "empty3";
735     FILE *stream1, *stream2, *stream3, *stream4;
736     int ret, numclosed;
737
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);
756
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);
766
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);
773
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);
777 }
778
779 static void test_get_osfhandle(void)
780 {
781     int fd;
782     char fname[] = "t_get_osfhanle";
783     DWORD bytes_written;
784     HANDLE handle;
785
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);
792
793     _close(fd);
794     _unlink(fname);
795 }
796
797 static void test_setmaxstdio(void)
798 {
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));
801 }
802
803 static void test_stat(void)
804 {
805     int fd;
806     int pipes[2];
807     struct stat buf;
808
809     /* Tests for a file */
810     fd = open("stat.tst", O_WRONLY | O_CREAT | O_BINARY, _S_IREAD |_S_IWRITE);
811     if (fd >= 0)
812     {
813         if (fstat(fd, &buf) == 0)
814         {
815             if ((buf.st_mode & _S_IFMT) == _S_IFREG)
816             {
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);
824             }
825             else
826                 skip("file is not a file?\n");
827         }
828         else
829             skip("fstat failed, errno %d\n", errno);
830         close(fd);
831         remove("stat.tst");
832     }
833     else
834         skip("open failed with errno %d\n", errno);
835
836     /* Tests for a char device */
837     if (_dup2(0, 10) == 0)
838     {
839         if (fstat(10, &buf) == 0)
840         {
841             if (buf.st_mode == _S_IFCHR)
842             {
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);
846             }
847             else
848                 skip("stdin is not a char device?\n");
849         }
850         else
851             skip("fstat failed with errno %d\n", errno);
852         close(10);
853     }
854     else
855         skip("_dup2 failed with errno %d\n", errno);
856
857     /* Tests for pipes */
858     if (_pipe(pipes, 1024, O_BINARY) == 0)
859     {
860         if (fstat(pipes[0], &buf) == 0)
861         {
862             if (buf.st_mode == _S_IFIFO)
863             {
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);
870             }
871             else
872                 skip("pipe() didn't make a pipe?\n");
873         }
874         else
875             skip("fstat failed with errno %d\n", errno);
876         close(pipes[0]);
877         close(pipes[1]);
878     }
879     else
880         skip("pipe failed with errno %d\n", errno);
881 }
882
883 static const char* pipe_string="Hello world";
884
885 static void test_pipes_child(int argc, char** args)
886 {
887     int fd;
888
889     if (argc < 5)
890     {
891         ok(0, "not enough parameters: %d\n", argc);
892         return;
893     }
894
895     fd=atoi(args[3]);
896     ok(close(fd) == 0, "unable to close %d: %d\n", fd, errno);
897
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);
901 }
902
903 static void test_pipes(const char* selfname)
904 {
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;
911
912     /* Test reading from a pipe with read() */
913     if (_pipe(pipes, 1024, O_BINARY) < 0)
914     {
915         ok(0, "pipe failed with errno %d\n", errno);
916         return;
917     }
918
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);
927
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);
936
937     /* Test reading from a pipe with fread() */
938     if (_pipe(pipes, 1024, O_BINARY) < 0)
939     {
940         ok(0, "pipe failed with errno %d\n", errno);
941         return;
942     }
943
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");
953
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);
959
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");
964
965     ok(fclose(file) == 0, "unable to close the pipe: %d\n", errno);
966 }
967
968 START_TEST(file)
969 {
970     int arg_c;
971     char** arg_v;
972
973     arg_c = winetest_get_mainargs( &arg_v );
974
975     /* testing low-level I/O */
976     if (arg_c >= 3)
977     {
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;
987     }
988     test_file_inherit(arg_v[0]);
989     test_file_write_read();
990     test_chsize();
991     test_stat();
992
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]);
1007 }