Enclosed is a patch (diff to 2001.12.26 snapshot) which impements 
stdio buffering in msvcrt. Since I cannot make Visual C binaries 
could anybady with Visual C++ test it? 
I have testet it with mingw32 and I incude my test program (iotst.c).
The program prints a line indicating which test it is making 
and then complains about failures.

Comment 1: current builtin msvcrt fails test1 (and few other 
as a consequence). Some native versions of msvcrt fail test 8.

Comment 2: I wrote the test the way naive programmer would wrote 
it (IMHO). Now I think that for a testing framework we need an 
assert-like macro to make checking and printing code shorter 
and to have uniform printouts. I ommited some tests that require 
multiple processes (expandig file while it is read, checking that 
stdio buffers got flushed at exit) - I guess that doing such 
test in portable way is quite tricky.
-- 
                              Waldek Hebisch
[EMAIL PROTECTED]    or [EMAIL PROTECTED] 
diff -ru wine-20011226.orig/dlls/msvcrt/file.c wine-20011226/dlls/msvcrt/file.c
--- wine-20011226.orig/dlls/msvcrt/file.c       Wed Dec 26 20:50:58 2001
+++ wine-20011226/dlls/msvcrt/file.c    Mon Jan  7 14:18:42 2002
@@ -180,6 +180,36 @@
   }
 }
 
+/* INTERNAL: Flush stdio file buffer */
+static int msvcrt_flush_buffer(MSVCRT_FILE* file)
+{
+  if(file->_bufsiz) {
+        int cnt=file->_ptr-file->_base;
+        if(cnt>0 && _write(file->_file, file->_base, cnt) != cnt) {
+                return MSVCRT_EOF;
+        }
+        file->_ptr=file->_base;
+        file->_cnt=file->_bufsiz;
+  }
+  return 0;
+}
+
+/* INTERNAL: Allocate stdio file buffer */
+static void msvcrt_alloc_buffer(MSVCRT_FILE* file)
+{
+       file->_base = MSVCRT_calloc(MSVCRT_BUFSIZ,1);
+       if(file->_base) {
+               file->_bufsiz = MSVCRT_BUFSIZ;
+               file->_flag |= MSVCRT__IOMYBUF;
+       } else { 
+               file->_base = (unsigned char *)(&file->_charbuf);
+               /* put here 2 ??? */
+               file->_bufsiz = sizeof(file->_charbuf);
+       }
+       file->_ptr = file->_base;
+       file->_cnt = 0;
+}
+
 /*********************************************************************
  *             __p__iob(MSVCRT.@)
  */
@@ -306,6 +336,14 @@
   TRACE(":fd (%d) handle (%d)\n",fd,hand);
   if (hand == INVALID_HANDLE_VALUE)
     return -1;
+  /* flush stdio buffers */
+  if(MSVCRT_files[fd]) { 
+       if(MSVCRT_files[fd]->_flag & MSVCRT__IOWRT) 
+               MSVCRT_fflush(MSVCRT_files[fd]);
+
+       if(MSVCRT_files[fd]->_flag & MSVCRT__IOMYBUF) 
+               MSVCRT_free(MSVCRT_files[fd]->_base);
+  }
 
   /* Dont free std FILE*'s, they are not dynamic */
   if (fd > 2 && MSVCRT_files[fd])
@@ -376,7 +414,7 @@
    * will be set by the read()/write() functions.
    */
   if (MSVCRT_files[fd])
-    return MSVCRT_files[fd]->_flag & MSVCRT__IOEOF;
+    return MSVCRT_flags[fd] & MSVCRT__IOEOF;
 
   /* Otherwise we do it the hard way */
   curpos = SetFilePointer(hand, 0, NULL, SEEK_CUR);
@@ -458,8 +496,8 @@
 void MSVCRT_rewind(MSVCRT_FILE* file)
 {
   TRACE(":file (%p) fd (%d)\n",file,file->_file);
-  _lseek(file->_file,0,SEEK_SET);
-  file->_flag &= ~(MSVCRT__IOEOF | MSVCRT__IOERR);
+  MSVCRT_fseek(file, 0L, SEEK_SET);
+  MSVCRT_clearerr(file);
 }
 
 /*********************************************************************
@@ -528,10 +566,16 @@
   while(i < MSVCRT_fdend)
     if (MSVCRT_handles[i] != INVALID_HANDLE_VALUE)
     {
+#if 0
+      /* FIXME: flush, do not commit */
       if (_commit(i) == -1)
        if (MSVCRT_files[i])
          MSVCRT_files[i]->_flag |= MSVCRT__IOERR;
-      num_flushed++;
+#endif
+      if(MSVCRT_files[i] && MSVCRT_files[i]->_flag & MSVCRT__IOWRT) {
+       MSVCRT_fflush(MSVCRT_files[i]);
+        num_flushed++;
+      }
     }
 
   TRACE(":flushed (%d) handles\n",num_flushed);
@@ -905,7 +949,10 @@
     if (num_read != count && MSVCRT_files[fd])
     {
       TRACE(":EOF\n");
+       MSVCRT_flags[fd] |= MSVCRT__IOEOF;
+/*
       MSVCRT_files[fd]->_flag |= MSVCRT__IOEOF;
+*/
     }
     return num_read;
   }
@@ -1161,12 +1208,6 @@
   if (MSVCRT_flags[fd] & MSVCRT__IOAPPEND)
     _lseek(fd, 0, FILE_END);
 
-  /* Set _cnt to 0 so optimised binaries will call our implementation
-   * of putc/getc.
-   */
-  if (MSVCRT_files[fd])
-    MSVCRT_files[fd]->_cnt = 0;
-
   if (WriteFile(hand, buf, count, &num_written, NULL)
       &&  (num_written == count))
     return num_written;
@@ -1226,7 +1267,13 @@
  */
 int MSVCRT_fflush(MSVCRT_FILE* file)
 {
-  return _commit(file->_file);
+  if(!file) { 
+       _flushall();
+       return 0;
+  } else { 
+       int res=msvcrt_flush_buffer(file);
+       return res;
+  }
 }
 
 /*********************************************************************
@@ -1234,10 +1281,12 @@
  */
 int MSVCRT_fgetc(MSVCRT_FILE* file)
 {
-  char c;
-  if (_read(file->_file,&c,1) != 1)
-    return MSVCRT_EOF;
-  return c;
+  if (file->_cnt>0) { 
+       file->_cnt--;
+       return *(unsigned char *)file->_ptr++;
+  } else { 
+       return _filbuf(file);
+  }
 }
 
 /*********************************************************************
@@ -1253,7 +1302,36 @@
  */
 int _filbuf(MSVCRT_FILE* file)
 {
-  return MSVCRT_fgetc(file);
+   
+  /* Allocate buffer if needed */
+  if(file->_bufsiz == 0 && !(file->_flag & MSVCRT__IONBF) ) { 
+       msvcrt_alloc_buffer(file);
+  }
+  if(!(file->_flag & MSVCRT__IOREAD)) { 
+       if(file->_flag & MSVCRT__IORW) { 
+               file->_flag |= MSVCRT__IOREAD;
+       } else { 
+               return MSVCRT_EOF;
+       }
+  }
+  if(file->_flag & MSVCRT__IONBF) { 
+       unsigned char c;
+       if (_read(file->_file,&c,1) != 1) { 
+               file->_flag |= MSVCRT__IOEOF;
+               return MSVCRT_EOF;
+       }
+       return c;
+  } else { 
+       file->_cnt = _read(file->_file, file->_base, file->_bufsiz);
+       if(file->_cnt<0) file->_cnt = 0;
+       if(!file->_cnt) { 
+               file->_flag |= MSVCRT__IOEOF;
+               return MSVCRT_EOF;
+       }
+       file->_cnt--;
+       file->_ptr = file->_base+1;
+       return *(unsigned char *)file->_base;
+  }
 }
 
 /*********************************************************************
@@ -1261,7 +1339,7 @@
  */
 int MSVCRT_fgetpos(MSVCRT_FILE* file, MSVCRT_fpos_t *pos)
 {
-  *pos = _tell(file->_file);
+  *pos = MSVCRT_ftell(file);
   return (*pos == -1? -1 : 0);
 }
 
@@ -1305,7 +1383,7 @@
  */
 MSVCRT_wint_t MSVCRT_fgetwc(MSVCRT_FILE* file)
 {
-  MSVCRT_wint_t wc;
+  WCHAR wc; 
   if (_read(file->_file, &wc, sizeof(wc)) != sizeof(wc))
     return MSVCRT_WEOF;
   return wc;
@@ -1336,11 +1414,48 @@
 }
 
 /*********************************************************************
+ *              fgetws (MSVCRT.@)
+ */
+WCHAR *MSVCRT_fgetws(WCHAR *s, int size, MSVCRT_FILE* file)
+{
+  int    cc;
+  WCHAR * buf_start = s;
+
+  TRACE(":file(%p) fd (%d) str (%p) len (%d)\n",
+        file,file->_file,s,size);
+
+  /* BAD, for the whole WINE process blocks... just done this way to test
+   * windows95's ftp.exe.
+   * JG - Is this true now we use ReadFile() on stdin too?
+   */
+  for(cc = MSVCRT_fgetwc(file); cc != MSVCRT_WEOF && cc != L'\n';
+      cc = MSVCRT_fgetwc(file))
+    if (cc != L'\r')
+    {
+      if (--size <= 0) break;
+      *s++ = cc;
+    }
+  if ((cc == MSVCRT_EOF) && (s == buf_start)) /* If nothing read, return 0*/
+  {
+    TRACE(":nothing read\n");
+    return 0;
+  }
+  if (cc == L'\n')
+    if (--size > 0)
+      *s++ = '\n';
+  *s = '\0';
+/*  TRACE(":got '%s'\n", buf_start); */
+  return buf_start;
+}
+
+
+/*********************************************************************
  *             fputwc (MSVCRT.@)
  */
 MSVCRT_wint_t MSVCRT_fputwc(MSVCRT_wint_t wc, MSVCRT_FILE* file)
 {
-  if (_write(file->_file, &wc, sizeof(wc)) != sizeof(wc))
+  WCHAR mwc=wc;
+  if (MSVCRT_fwrite( &mwc, 1, sizeof(mwc), file) != sizeof(mwc))
     return MSVCRT_WEOF;
   return wc;
 }
@@ -1463,7 +1578,13 @@
  */
 int MSVCRT_fputc(int c, MSVCRT_FILE* file)
 {
-  return _write(file->_file, &c, 1) == 1? c : MSVCRT_EOF;
+  if(file->_cnt>0) { 
+       *file->_ptr++=c;
+       file->_cnt--;
+       return c;
+  } else { 
+       return _flsbuf(c, file);
+  }
 }
 
 /*********************************************************************
@@ -1471,7 +1592,24 @@
  */
 int _flsbuf(int c, MSVCRT_FILE* file)
 {
-  return MSVCRT_fputc(c,file);
+  /* Flush output buffer */
+  if(file->_bufsiz == 0 && !(file->_flag & MSVCRT__IONBF)) {
+       msvcrt_alloc_buffer(file);
+  }
+  if(!(file->_flag & MSVCRT__IOWRT)) { 
+       if(file->_flag & MSVCRT__IORW) { 
+               file->_flag |= MSVCRT__IOWRT;
+       } else { 
+               return MSVCRT_EOF;
+       }
+  }
+  if(file->_bufsiz) {
+        int res=msvcrt_flush_buffer(file);
+       return res?res : MSVCRT_fputc(c, file);
+  } else { 
+       unsigned char cc=c;
+       return _write(file->_file, &cc, 1) == 1? c : MSVCRT_EOF;
+  }
 }
 
 /*********************************************************************
@@ -1486,10 +1624,28 @@
  *             fread (MSVCRT.@)
  */
 MSVCRT_size_t MSVCRT_fread(void *ptr, MSVCRT_size_t size, MSVCRT_size_t nmemb, 
MSVCRT_FILE* file)
-{
-  int read = _read(file->_file,ptr, size * nmemb);
-  if (read <= 0)
-    return 0;
+{ MSVCRT_size_t rcnt=size * nmemb;
+  MSVCRT_size_t read=0;
+  int pread=0;
+  /* first buffered data */
+  if(file->_cnt>0) { 
+       int pcnt= (rcnt>file->_cnt)? file->_cnt:rcnt;
+       memcpy(ptr, file->_ptr, pcnt);
+       file->_cnt -= pcnt;
+       file->_ptr += pcnt;
+       read += pcnt ;
+       rcnt -= pcnt ;
+       ptr += pcnt;
+  } else if(!(file->_flag & MSVCRT__IOREAD )) { 
+       if(file->_flag & MSVCRT__IORW) { 
+               file->_flag |= MSVCRT__IOREAD;
+       } else 
+               return 0;
+  }
+  if(rcnt) pread = _read(file->_file,ptr, rcnt);
+  if (pread <= 0)
+    pread = 0;
+  read+=pread;
   return read / size;
 }
 
@@ -1508,9 +1664,14 @@
 
   if (fd > 2)
   {
+#if 0
     FIXME(":reopen on user file not implemented!\n");
     MSVCRT__set_errno(ERROR_CALL_NOT_IMPLEMENTED);
     return NULL;
+#endif
+    if(MSVCRT_fclose(file)) 
+       return NULL;
+    return MSVCRT_fopen(path, mode);
   }
 
   /* first, create the new file */
@@ -1675,6 +1836,20 @@
  */
 int MSVCRT_fseek(MSVCRT_FILE* file, long offset, int whence)
 {
+  /* Flush output if needed */
+  if(file->_flag & MSVCRT__IOWRT) 
+       msvcrt_flush_buffer(file);
+  
+  if(whence == SEEK_CUR && file->_flag & MSVCRT__IOREAD ) {
+       offset -= file->_cnt;
+  }
+  /* Discard buffered input */
+  file->_cnt = 0;
+  file->_ptr = file->_base; 
+  /* Reset direction of i/o */
+  if(file->_flag & MSVCRT__IORW) {
+        file->_flag &= ~(MSVCRT__IOREAD|MSVCRT__IOWRT);
+  }
   return _lseek(file->_file,offset,whence);
 }
 
@@ -1683,7 +1858,18 @@
  */
 LONG MSVCRT_ftell(MSVCRT_FILE* file)
 {
-  return _tell(file->_file);
+  int off=0;
+  long pos;
+  if(file->_bufsiz)  { 
+       if( file->_flag & MSVCRT__IOWRT ) {
+               off = file->_ptr - file->_base;
+       } else { 
+               off = -file->_cnt;
+       }
+  }
+  pos = _tell(file->_file);
+  if(pos == -1) return pos;
+  return off + pos;
 }
 
 /*********************************************************************
@@ -1691,9 +1877,31 @@
  */
 MSVCRT_size_t MSVCRT_fwrite(const void *ptr, MSVCRT_size_t size, MSVCRT_size_t nmemb, 
MSVCRT_FILE* file)
 {
-  int written = _write(file->_file, ptr, size * nmemb);
-  if (written <= 0)
-    return 0;
+  MSVCRT_size_t wrcnt=size * nmemb;
+  int written = 0;
+  if(file->_cnt) { 
+       int pcnt=(file->_cnt>wrcnt)? file->_cnt: wrcnt;
+       memcpy(file->_ptr, ptr, pcnt);
+       file->_cnt -= pcnt;
+       file->_ptr += pcnt;
+       written = pcnt;
+       wrcnt -= pcnt;
+       ptr += pcnt;
+  } else if(!(file->_flag & MSVCRT__IOWRT)) { 
+       if(file->_flag & MSVCRT__IORW) { 
+               file->_flag |= MSVCRT__IOWRT;
+       } else 
+               return 0;
+  }
+  if(wrcnt) {
+       /* Flush buffer */
+       int res=msvcrt_flush_buffer(file);
+       if(!res) { 
+               int pwritten = _write(file->_file, ptr, wrcnt);
+               if (pwritten <= 0) pwritten=0;
+               written += pwritten;
+       }
+  }
   return written / size;
 }
 
@@ -1860,8 +2068,22 @@
  */
 int MSVCRT_setvbuf(MSVCRT_FILE* file, char *buf, int mode, MSVCRT_size_t size)
 {
-  FIXME("(%p,%p,%d,%d)stub\n",file, buf, mode, size);
-  return -1;
+  /* TODO: Check if file busy */
+  if(file->_bufsiz) { 
+       MSVCRT_free(file->_base);
+       file->_bufsiz = 0;
+       file->_cnt = 0;
+  }
+  if(mode == MSVCRT__IOFBF) { 
+       file->_flag &= ~MSVCRT__IONBF;
+       file->_base = file->_ptr = buf;
+       if(buf) { 
+               file->_bufsiz = size;
+       }  
+  } else {
+       file->_flag |= MSVCRT__IONBF;
+  }
+  return 0;
 }
 
 /*********************************************************************
@@ -1869,7 +2091,7 @@
  */
 void MSVCRT_setbuf(MSVCRT_FILE* file, char *buf)
 {
-  MSVCRT_setvbuf(file, buf, buf ? MSVCRT__IOFBF : MSVCRT__IONBF, BUFSIZ);
+  MSVCRT_setvbuf(file, buf, buf ? MSVCRT__IOFBF : MSVCRT__IONBF, MSVCRT_BUFSIZ);
 }
 
 /*********************************************************************
@@ -1932,6 +2154,9 @@
 
 /*********************************************************************
  *             vfwprintf (MSVCRT.@)
+ * FIXME: 
+ * Is final char included in written (then resize is too big) or not
+ * (then we must test for equality too)?
  */
 int MSVCRT_vfwprintf(MSVCRT_FILE* file, const WCHAR *format, va_list valist)
 {
@@ -1944,7 +2169,7 @@
     resize = (written == -1 ? resize * 2 : written + sizeof(WCHAR));
     if (mem != buf)
       MSVCRT_free (mem);
-    if (!(mem = (WCHAR *)MSVCRT_malloc(resize)))
+    if (!(mem = (WCHAR *)MSVCRT_malloc(resize*sizeof(*mem))))
       return MSVCRT_EOF;
   }
   retval = MSVCRT_fwrite(mem, 1, written * sizeof (WCHAR), file);
@@ -2006,6 +2231,39 @@
     res = MSVCRT_vfprintf(MSVCRT_stdout, format, valist);
     va_end(valist);
     return res;
+}
+
+/*********************************************************************
+ *             ungetc (MSVCRT.@)
+ */
+int MSVCRT_ungetc(int c, MSVCRT_FILE * file)
+{
+       if(file->_bufsiz == 0 && !(file->_flag & MSVCRT__IONBF)) { 
+               msvcrt_alloc_buffer(file);
+               file->_ptr++;
+       }
+       if(file->_ptr>file->_base) { 
+               file->_ptr--;
+               *file->_ptr=c;
+               file->_cnt++;
+               return c;
+       }
+       return MSVCRT_EOF;
+}
+
+/*********************************************************************
+ *              ungetwc (MSVCRT.@)
+ */
+MSVCRT_wint_t MSVCRT_ungetwc(MSVCRT_wint_t wc, MSVCRT_FILE * file)
+{
+       WCHAR mwc = wc;
+       char * pp = &mwc;
+       int i;
+       for(i=sizeof(WCHAR)-1;i>=0;i--) { 
+               if(pp[i] != MSVCRT_ungetc(pp[i],file))
+                       return MSVCRT_WEOF;
+       }
+       return mwc;
 }
 
 /*********************************************************************
diff -ru wine-20011226.orig/dlls/msvcrt/msvcrt.spec 
wine-20011226/dlls/msvcrt/msvcrt.spec
--- wine-20011226.orig/dlls/msvcrt/msvcrt.spec  Fri Dec 21 21:27:39 2001
+++ wine-20011226/dlls/msvcrt/msvcrt.spec       Mon Jan  7 14:18:55 2002
@@ -605,7 +605,7 @@
 @ cdecl fgetpos(ptr ptr) MSVCRT_fgetpos
 @ cdecl fgets(str long ptr) MSVCRT_fgets
 @ cdecl fgetwc(ptr) MSVCRT_fgetwc
-@ stub fgetws #(wstr long ptr)
+@ cdecl fgetws(wstr long ptr) MSVCRT_fgetws
 @ forward -noimport floor ntdll.floor
 @ cdecl fmod(double double) fmod
 @ cdecl fopen(str str) MSVCRT_fopen
@@ -736,8 +736,8 @@
 @ cdecl toupper(long) toupper
 @ forward -noimport towlower ntdll.towlower
 @ forward -noimport towupper ntdll.towupper
-@ stub ungetc #(long ptr)
-@ stub ungetwc #(long ptr)
+@ cdecl ungetc(long ptr) MSVCRT_ungetc
+@ cdecl ungetwc(long ptr) MSVCRT_ungetwc
 @ cdecl vfprintf(ptr str long) MSVCRT_vfprintf
 @ cdecl vfwprintf(ptr wstr long) MSVCRT_vfwprintf
 @ cdecl vprintf(str long) MSVCRT_vprintf
diff -ru wine-20011226.orig/include/msvcrt/stdio.h wine-20011226/include/msvcrt/stdio.h
--- wine-20011226.orig/include/msvcrt/stdio.h   Mon Oct 22 20:59:23 2001
+++ wine-20011226/include/msvcrt/stdio.h        Mon Jan  7 14:19:21 2002
@@ -72,6 +72,8 @@
 
 #define MSVCRT_EOF       (-1)
 
+#define MSVCRT_BUFSIZ    512
+
 #endif /* USE_MSVCRT_PREFIX */
 
 typedef struct MSVCRT(_iobuf)
#include <stdio.h>
#include <string.h>

#define MY_BSIZE 10000

int main(void)
{
        FILE * file=fopen("ble.txt", "w+b");
        unsigned char buff[MY_BSIZE], ibuff[MY_BSIZE];
        long i, cnt;
        int c;
        printf("Testing binary input-output\n");
        /* fill buffer */
        for(i=0;i<MY_BSIZE;i++) { 
                buff[i] = i&0xff;
        }

        /* Write one block, read char by char */
        printf("Test 1\n");
        cnt=fwrite(buff,MY_BSIZE,1,file);
        if(cnt!=1) printf("Short write, disk full ??\n");
        fseek(file, 0L, SEEK_SET);
        /* read char by char */
        for(i=0;i<MY_BSIZE;i++) {
                int c=getc(file);
                if(c<0 || c>255) { 
                        printf("Char value out of range%s\n",
                        (c==EOF)?", maybe unexpected EOF":""); 
                        break;
                }
                ibuff[i]=c;
        }
        if(memcmp(buff, ibuff, MY_BSIZE)) 
                printf("Read different values then written\n");

        /* Read all file at once as one record */
        printf("Test 2\n");
        fseek(file, 0L, SEEK_SET);
        cnt=fread(ibuff, MY_BSIZE, 1, file);
        if(cnt!=1) printf("Short read\n");
        if(memcmp(buff, ibuff, MY_BSIZE)) 
                printf("Read different values then written\n");
        
        /* Read all file at once as one byte records */
        printf("Test 3\n");
        fseek(file, 0L, SEEK_SET);
        cnt=fread(ibuff, 1, MY_BSIZE, file);
        if(cnt!=MY_BSIZE) printf("Short read\n");
        if(memcmp(buff, ibuff, MY_BSIZE)) 
                printf("Read different values then written\n");

        /* fread - small blocks proportional to buffer */
        printf("Test 4\n");
        fseek(file, 0L, SEEK_SET);
        for(i=0;i<MY_BSIZE;i+=16) {
                int pcnt=(MY_BSIZE-i)<16?(MY_BSIZE-i):16;
                cnt=fread(ibuff+i, pcnt, 1, file);
                if(cnt!=1) { 
                        printf("Short read\n");
                        break;
                }
        }
        if(memcmp(buff, ibuff, MY_BSIZE))
                printf("Read different values then written\n");

        /* Mixing getc and fread */
        printf("Test 5\n");
        fseek(file, 0L, SEEK_SET);
        for(i=0;i<MY_BSIZE;i+=160) {
                int pcnt=(MY_BSIZE-i)<160?(MY_BSIZE-i):160;
                int pcnt1=pcnt<80?pcnt:80;
                int j;
                cnt=fread(ibuff+i, pcnt1, 1, file);
                if(cnt!=1) {
                        printf("Short read\n");
                        break;
                }
                for(j=pcnt1;j<pcnt;j++) { 
                        int c=getc(file);
                        if(c==EOF) { 
                                printf("Unexpected EOF\n");
                                goto fail1;
                        }
                        ibuff[i+j]=c;
                }
        }
        if(memcmp(buff, ibuff, MY_BSIZE))
                printf("Read different values then written\n");
    fail1:

        /* Reading backwards */
        printf("Test 6\n");
        i=MY_BSIZE;
        do {
                i-=100;
                cnt=i>0?100:100+i;
                fseek(file, i>0? i:0, SEEK_SET);
                cnt=fread(ibuff+i, cnt, 1, file);
                if(cnt!=1) { 
                        printf("Short read\n");
                        break;
                }
        } while (i>0);
        if(memcmp(buff, ibuff, MY_BSIZE))
                printf("Read different values then written\n");

        /* Reading backwards, mixing getc and fread */
        printf("Test 7\n");
        i=MY_BSIZE;
        c=0;
        do {
                i-=100;
                cnt=i>0?100:100+i;
                fseek(file, i>0? i:0, SEEK_SET);
                c=1-c;
                if(c) { 
                cnt=fread(ibuff+i, cnt, 1, file);
                if(cnt!=1) {
                        printf("Short read\n");
                        break;
                }
                } else { 
                        int j;
                        for(j=0;j<100;j++) { 
                                int cc=getc(file);
                                if(cc==EOF) {
                                        printf("Unexpected EOF\n");
                                        goto fail2;
                                }
                                ibuff[i+j]=cc;
                        }
                }
        } while (i>0);
        if(memcmp(buff, ibuff, MY_BSIZE))
                printf("Read different values then written\n");
fail2:

        /* Using fgetpos and fsetpos */
        printf("Test 8\n"); {
        fpos_t pos;
        long off;
        fseek(file, 0L, SEEK_SET);
        for(i=0;i<200;i++) {
                int cc = getc(file);
                if(cc==EOF) {
                        printf("Unexpected EOF\n");
                        goto fail3;
                }
                ibuff[i]=cc;
        }
        fgetpos(file, &pos); 
        /* off = ftell(file); */
        fseek(file, 512, SEEK_SET);
        cnt=fread(ibuff+512,MY_BSIZE-512,1,file);
        if(cnt!=1) { 
                printf("Short read\n");
                goto fail3;
        }
        fsetpos(file, &pos); 
        /* fseek(file, off, SEEK_SET); */
        cnt=fread(ibuff+200,312,1,file);
        if(cnt!=1) {
                printf("Short read\n");
                goto fail3;
        }
        }
        if(memcmp(buff, ibuff, MY_BSIZE))
                printf("Read different values then written\n");
  fail3:
        
        /* Writing backwards, mixing fwrite and fputc */
        printf("Test 9\n");
        i=MY_BSIZE;
        c=0;
        do {
                i-=100;
                cnt=i>0?100:100+i;
                fseek(file, i>0? i:0, SEEK_SET);
                c=1-c;
                if(c) { 
                cnt=fwrite(buff+i, cnt, 1, file);
                if(cnt!=1) {
                        printf("Short write\n");
                        break;
                }
                } else { 
                        int j;
                        for(j=0;j<100;j++) { 
                                putc(buff[i+j], file);
                        }
                }
        } while (i>0);
        fseek(file, 0L, SEEK_SET);
        cnt=fread(ibuff, MY_BSIZE, 1, file);
        if(cnt!=1) {
          printf("Short read\n");
        }
        if(memcmp(buff, ibuff, MY_BSIZE))
                printf("Read different values then written\n"); 

        /* Test of EOF conditions (feof, getc) */
        printf("Test 10\n");
        fseek(file, 0L, SEEK_SET);
        if(feof(file)) {
                printf("Unexpected EOF (1)\n");
        }
        fread(ibuff,MY_BSIZE,1,file);
        if(feof(file)) {
                printf("Unexpected EOF (2)\n");
        }
        getc(file);
        if(!feof(file)) {
                printf("Expected EOF, feof disagrees\n");
        }
        fseek(file, 0L, SEEK_SET);
        if(feof(file)) {
                printf("Unexpected EOF (3)\n");
        }
        for(i=0;i<MY_BSIZE+2;i++) { 
                if(getc(file)==EOF) break;
        }
        if(i!=MY_BSIZE) { 
            if(i<MY_BSIZE) { 
                printf("Unexpected EOF\n");
            } else { 
                printf("Expected EOF, getc have not deliverd\n");
            }
        }
        if(!feof(file)) {
                printf("Expected EOF, feof disagrees\n");
        }
        clearerr(file);
        if(feof(file)) {
                printf("Unexpected EOF (4)\n");
        }
        
        
        return(0);
}       

Reply via email to