Piotr Caban : msvcrt: Fixed handling of '\r' when it' s the last character in the buffer in read.

Alexandre Julliard julliard at winehq.org
Thu Jan 10 13:36:11 CST 2013


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

Author: Piotr Caban <piotr at codeweavers.com>
Date:   Thu Jan 10 11:43:37 2013 +0100

msvcrt: Fixed handling of '\r' when it's the last character in the buffer in read.

---

 dlls/msvcrt/file.c |  117 ++++++++++++++++++++++++++++++++++-----------------
 1 files changed, 78 insertions(+), 39 deletions(-)

diff --git a/dlls/msvcrt/file.c b/dlls/msvcrt/file.c
index 90330f1..feabbca 100644
--- a/dlls/msvcrt/file.c
+++ b/dlls/msvcrt/file.c
@@ -60,8 +60,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(msvcrt);
 /* values for wxflag in file descriptor */
 #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_READCR         0x04  /* underlying file is at \r */
+#define WX_PIPE           0x08
 #define WX_DONTINHERIT    0x10
 #define WX_APPEND         0x20
 #define WX_TEXT           0x80
@@ -83,7 +83,7 @@ static char utf16_bom[2] = { 0xff, 0xfe };
 typedef struct {
     HANDLE              handle;
     unsigned char       wxflag;
-    char                unk1;
+    char                lookahead[3];
     int                 exflag;
     CRITICAL_SECTION    crit;
 } ioinfo;
@@ -319,7 +319,10 @@ static int msvcrt_alloc_fd_from(HANDLE hand, int flag, int fd)
   }
 
   fdinfo->handle = hand;
-  fdinfo->wxflag = WX_OPEN | (flag & (WX_DONTINHERIT | WX_APPEND | WX_TEXT));
+  fdinfo->wxflag = WX_OPEN | (flag & (WX_DONTINHERIT | WX_APPEND | WX_TEXT | WX_PIPE));
+  fdinfo->lookahead[0] = '\n';
+  fdinfo->lookahead[1] = '\n';
+  fdinfo->lookahead[2] = '\n';
   fdinfo->exflag = 0;
 
   /* locate next free slot */
@@ -494,6 +497,9 @@ void msvcrt_init_io(void)
                                                          GetCurrentProcess(), &fdinfo->handle,
                                                          0, TRUE, DUPLICATE_SAME_ACCESS))
           fdinfo->wxflag = WX_OPEN | WX_TEXT;
+      fdinfo->lookahead[0] = '\n';
+      fdinfo->lookahead[1] = '\n';
+      fdinfo->lookahead[2] = '\n';
       fdinfo->exflag = 0;
   }
 
@@ -505,6 +511,9 @@ void msvcrt_init_io(void)
                                                          GetCurrentProcess(), &fdinfo->handle,
                                                          0, TRUE, DUPLICATE_SAME_ACCESS))
           fdinfo->wxflag = WX_OPEN | WX_TEXT;
+      fdinfo->lookahead[0] = '\n';
+      fdinfo->lookahead[1] = '\n';
+      fdinfo->lookahead[2] = '\n';
       fdinfo->exflag = 0;
   }
 
@@ -516,6 +525,9 @@ void msvcrt_init_io(void)
                                                          GetCurrentProcess(), &fdinfo->handle,
                                                          0, TRUE, DUPLICATE_SAME_ACCESS))
           fdinfo->wxflag = WX_OPEN | WX_TEXT;
+      fdinfo->lookahead[0] = '\n';
+      fdinfo->lookahead[1] = '\n';
+      fdinfo->lookahead[2] = '\n';
       fdinfo->exflag = 0;
   }
 
@@ -1050,7 +1062,7 @@ __int64 CDECL MSVCRT__lseeki64(int fd, __int64 offset, int whence)
   if ((ofs.u.LowPart = SetFilePointer(hand, ofs.u.LowPart, &ofs.u.HighPart, whence)) != INVALID_SET_FILE_POINTER ||
       GetLastError() == ERROR_SUCCESS)
   {
-    msvcrt_get_ioinfo(fd)->wxflag &= ~(WX_ATEOF|WX_READEOF);
+    msvcrt_get_ioinfo(fd)->wxflag &= ~WX_ATEOF;
     /* FIXME: What if we seek _to_ EOF - is EOF set? */
 
     return ofs.QuadPart;
@@ -1727,11 +1739,11 @@ int CDECL MSVCRT__pipe(int *pfds, unsigned int psize, int textmode)
     int fd;
 
     LOCK_FILES();
-    fd = msvcrt_alloc_fd(readHandle, wxflags);
+    fd = msvcrt_alloc_fd(readHandle, wxflags|WX_PIPE);
     if (fd != -1)
     {
       pfds[0] = fd;
-      fd = msvcrt_alloc_fd(writeHandle, wxflags);
+      fd = msvcrt_alloc_fd(writeHandle, wxflags|WX_PIPE);
       if (fd != -1)
       {
         pfds[1] = fd;
@@ -2109,33 +2121,40 @@ int CDECL MSVCRT__rmtmp(void)
  */
 static int read_i(int fd, void *buf, unsigned int count)
 {
-  DWORD num_read;
-  char *bufstart = buf;
-  HANDLE hand = msvcrt_fdtoh(fd);
-  ioinfo *fdinfo = msvcrt_get_ioinfo(fd);
+    DWORD num_read;
+    char *bufstart = buf;
+    HANDLE hand = msvcrt_fdtoh(fd);
+    ioinfo *fdinfo = msvcrt_get_ioinfo(fd);
 
-  if (count == 0)
-    return 0;
+    if (count == 0)
+        return 0;
 
-  if (fdinfo->wxflag & WX_READEOF) {
-     fdinfo->wxflag |= WX_ATEOF;
-     TRACE("already at EOF, returning 0\n");
-     return 0;
-  }
-  /* Don't trace small reads, it gets *very* annoying */
-  if (count > 4)
-    TRACE(":fd (%d) handle (%p) buf (%p) len (%d)\n",fd,hand,buf,count);
-  if (hand == INVALID_HANDLE_VALUE)
-    return -1;
+    if (fdinfo->wxflag & WX_ATEOF) {
+        TRACE("already at EOF, returning 0\n");
+        return 0;
+    }
+    /* Don't trace small reads, it gets *very* annoying */
+    if (count > 4)
+        TRACE(":fd (%d) handle (%p) buf (%p) len (%d)\n",fd,hand,buf,count);
+    if (hand == INVALID_HANDLE_VALUE)
+        return -1;
 
-  /* Reading single bytes in O_TEXT mode makes things slow
-   * So read big chunks
-   */
-    if (ReadFile(hand, bufstart, count, &num_read, NULL))
+    if (fdinfo->lookahead[0]!='\n' || ReadFile(hand, bufstart, count, &num_read, NULL))
     {
+        if (fdinfo->lookahead[0] != '\n')
+        {
+            bufstart[0] = fdinfo->lookahead[0];
+            fdinfo->lookahead[0] = '\n';
+
+            if(count>1 && ReadFile(hand, bufstart+1, count-1, &num_read, NULL))
+                num_read++;
+            else
+                num_read = 1;
+        }
+
         if (count != 0 && num_read == 0)
         {
-            fdinfo->wxflag |= (WX_ATEOF|WX_READEOF);
+            fdinfo->wxflag |= WX_ATEOF;
             TRACE(":EOF %s\n",debugstr_an(buf,num_read));
         }
         else if (fdinfo->wxflag & WX_TEXT)
@@ -2161,16 +2180,36 @@ static int read_i(int fd, void *buf, unsigned int count)
                 /* in text mode, a ctrl-z signals EOF */
                 if (bufstart[i] == 0x1a)
                 {
-                    fdinfo->wxflag |= (WX_ATEOF|WX_READEOF);
+                    fdinfo->wxflag |= WX_ATEOF;
                     TRACE(":^Z EOF %s\n",debugstr_an(buf,num_read));
                     break;
                 }
-                /* in text mode, strip \r if followed by \n.
-                 * BUG: should save state across calls somehow, so CR LF that
-                 * straddles buffer boundary gets recognized properly?
-                 */
-		if ((bufstart[i] != '\r')
-                ||  ((i+1) < num_read && bufstart[i+1] != '\n'))
+
+                /* in text mode, strip \r if followed by \n */
+                if (bufstart[i]=='\r' && i+1==num_read)
+                {
+                    char lookahead;
+                    DWORD len;
+
+                    if (ReadFile(hand, &lookahead, 1, &len, NULL) && len)
+                    {
+                        if(lookahead=='\n' && j==0)
+                            bufstart[j++] = '\n';
+                        else
+                        {
+                            if(lookahead != '\n')
+                                bufstart[j++] = '\r';
+
+                            if (fdinfo->wxflag & WX_PIPE)
+                                fdinfo->lookahead[0] = lookahead;
+                            else
+                                SetFilePointer(fdinfo->handle, -1, NULL, FILE_CURRENT);
+                        }
+                    }
+                    else
+                        bufstart[j++] = '\r';
+                }
+                else if(bufstart[i]!='\r' || bufstart[i+1]!='\n')
 		    bufstart[j++] = bufstart[i];
             }
             num_read = j;
@@ -2181,7 +2220,7 @@ static int read_i(int fd, void *buf, unsigned int count)
         if (GetLastError() == ERROR_BROKEN_PIPE)
         {
             TRACE(":end-of-pipe\n");
-            fdinfo->wxflag |= (WX_ATEOF|WX_READEOF);
+            fdinfo->wxflag |= WX_ATEOF;
             return 0;
         }
         else
@@ -2191,9 +2230,9 @@ static int read_i(int fd, void *buf, unsigned int count)
         }
     }
 
-  if (count > 4)
-      TRACE("(%u), %s\n",num_read,debugstr_an(buf, num_read));
-  return num_read;
+    if (count > 4)
+        TRACE("(%u), %s\n",num_read,debugstr_an(buf, num_read));
+    return num_read;
 }
 
 /*********************************************************************




More information about the wine-cvs mailing list