Uwe Bonnes : msvcrt: Handle CR at buffer boundary and test case.

Alexandre Julliard julliard at winehq.org
Mon Jan 18 10:58:56 CST 2010


Module: wine
Branch: master
Commit: e6f1ae029e39d24ca3c56175df966ffb39ba532e
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=e6f1ae029e39d24ca3c56175df966ffb39ba532e

Author: Uwe Bonnes <bon at elektron.ikp.physik.tu-darmstadt.de>
Date:   Sat Jan 16 17:24:19 2010 +0100

msvcrt: Handle CR at buffer boundary and test case.

---

 dlls/msvcrt/file.c       |   22 ++++++++++++++++++++++
 dlls/msvcrt/tests/file.c |   42 ++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 62 insertions(+), 2 deletions(-)

diff --git a/dlls/msvcrt/file.c b/dlls/msvcrt/file.c
index a9678ed..655f17e 100644
--- a/dlls/msvcrt/file.c
+++ b/dlls/msvcrt/file.c
@@ -60,6 +60,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(msvcrt);
 #define WX_OPEN           0x01
 #define WX_ATEOF          0x02
 #define WX_READEOF        0x04  /* like ATEOF, but for underlying file rather than buffer */
+#define WX_READCR         0x08  /* underlying file is at \r */
 #define WX_DONTINHERIT    0x10
 #define WX_APPEND         0x20
 #define WX_TEXT           0x80
@@ -941,6 +942,9 @@ int CDECL MSVCRT_fseek(MSVCRT_FILE* file, MSVCRT_long offset, int whence)
 			if (file->_ptr[i] == '\n')
 				offset--;
 		}
+		/* Black magic when reading CR at buffer boundary*/
+		if(MSVCRT_fdesc[file->_file].wxflag & WX_READCR)
+		    offset--;
 	}
   }
   /* Discard buffered input */
@@ -1742,6 +1746,10 @@ int CDECL _rmtmp(void)
 
 /*********************************************************************
  * (internal) read_i
+ *
+ * When reading \r as last character in text mode, read() positions
+ * the file pointer on the \r character while getc() goes on to
+ * the following \n
  */
 static int read_i(int fd, void *buf, unsigned int count)
 {
@@ -1768,6 +1776,13 @@ static int read_i(int fd, void *buf, unsigned int count)
         if (MSVCRT_fdesc[fd].wxflag & WX_TEXT)
         {
             DWORD i, j;
+            if (bufstart[num_read-1] == '\r')
+            {
+	        MSVCRT_fdesc[fd].wxflag  |= WX_READCR;
+	        num_read--;
+            }
+	    else
+	      MSVCRT_fdesc[fd].wxflag  &=  ~WX_READCR;
             for (i=0, j=0; i<num_read; i++)
             {
                 /* in text mode, a ctrl-z signals EOF */
@@ -2890,6 +2905,10 @@ LONG CDECL MSVCRT_ftell(MSVCRT_FILE* file)
 				if (file->_ptr[i] == '\n')
 					off--;
 			}
+		        /* Black magic when reading CR at buffer boundary*/
+			if(MSVCRT_fdesc[file->_file].wxflag & WX_READCR)
+			  off--;
+
 		}
 	}
   }
@@ -2916,6 +2935,9 @@ int CDECL MSVCRT_fgetpos(MSVCRT_FILE* file, MSVCRT_fpos_t *pos)
 				if (file->_ptr[i] == '\n')
 					off--;
 			}
+		        /* Black magic when reading CR at buffer boundary*/
+			if(MSVCRT_fdesc[file->_file].wxflag & WX_READCR)
+			  off--;
 		}
 	}
   }
diff --git a/dlls/msvcrt/tests/file.c b/dlls/msvcrt/tests/file.c
index 042a82e..18247ad 100644
--- a/dlls/msvcrt/tests/file.c
+++ b/dlls/msvcrt/tests/file.c
@@ -422,6 +422,35 @@ static WCHAR* AtoW( const char* p )
     return buffer;
 }
 
+/* Test reading in text mode when the 512'th character read is \r*/
+static void test_readboundary(void)
+{
+  FILE *fp;
+  char buf[513], rbuf[513];
+  int i, j;
+  for (i = 0; i < 511; i++)
+    {
+      j = (i%('~' - ' ')+ ' ');
+      buf[i] = j;
+    }
+  buf[511] = '\n';
+  buf[512] =0;
+  fp = fopen("boundary.tst", "wt");
+  fwrite(buf, 512,1,fp);
+  fclose(fp);
+  fp = fopen("boundary.tst", "rt");
+  for(i=0; i<512; i++)
+    {
+      fseek(fp,0 , SEEK_CUR);
+      rbuf[i] = fgetc(fp);
+    }
+  rbuf[512] =0;
+  fclose(fp);
+  unlink("boundary.tst");
+
+  ok(strcmp(buf, rbuf) == 0,"CRLF on buffer boundary failure\n");
+  }
+
 static void test_fgetc( void )
 {
   char* tempf;
@@ -808,15 +837,23 @@ static void test_file_write_read( void )
   tempfd = _open(tempf,_O_RDONLY|_O_TEXT); /* open in TEXT mode */
   _lseek(tempfd, -1, FILE_END);
   ret = _read(tempfd,btext,LLEN);
-  ok(ret == 1, "_read expected 1 got bad length: %d\n", ret);
+  ok(ret == 1 && *btext == '\n', "_read expected 1 got bad length: %d\n", ret);
   _lseek(tempfd, -2, FILE_END);
   ret = _read(tempfd,btext,LLEN);
   ok(ret == 1 && *btext == '\n', "_read expected '\\n' got bad length: %d\n", ret);
   _lseek(tempfd, -3, FILE_END);
+  ret = _read(tempfd,btext,1);
+  ok(ret == 1 && *btext == 'e', "_read expected 'e' got \"%.*s\" bad length: %d\n", ret, btext, ret);
+  ok(tell(tempfd) == 41, "bad position %u expecting 41\n", tell(tempfd));
+  _lseek(tempfd, -3, FILE_END);
   ret = _read(tempfd,btext,2);
   ok(ret == 1 && *btext == 'e', "_read expected 'e' got \"%.*s\" bad length: %d\n", ret, btext, ret);
   ok(tell(tempfd) == 42, "bad position %u expecting 42\n", tell(tempfd));
-  _close(tempfd);
+  _lseek(tempfd, -3, FILE_END);
+  ret = _read(tempfd,btext,3);
+  ok(ret == 2 && *btext == 'e', "_read expected 'e' got \"%.*s\" bad length: %d\n", ret, btext, ret);
+  ok(tell(tempfd) == 43, "bad position %u expecting 43\n", tell(tempfd));
+   _close(tempfd);
 
   ret = unlink(tempf);
   ok( ret == 0 ,"Can't unlink '%s': %d\n", tempf, errno);
@@ -1402,6 +1439,7 @@ START_TEST(file)
     test_asciimode2();
     test_readmode(FALSE); /* binary mode */
     test_readmode(TRUE);  /* ascii mode */
+    test_readboundary();
     test_fgetc();
     test_fputc();
     test_flsbuf();




More information about the wine-cvs mailing list