mvcrt patch

Waldek Hebisch hebisch at math.uni.wroc.pl
Mon Jan 7 08:58:44 CST 2002


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
hebisch at math.uni.wroc.pl    or hebisch at hera.math.uni.wroc.pl 
-------------- next part --------------
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)
-------------- next part --------------
#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);
}	


More information about the wine-devel mailing list