https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=eb4bfe4621ecaa49d0b4e586315286f8e4731046

commit eb4bfe4621ecaa49d0b4e586315286f8e4731046
Author: Corinna Vinschen <[email protected]>
Date:   Tue Dec 19 18:58:06 2017 +0100

    cygwin: block devices: fix file offset after short writes
    
    When reading/writing block devices, Cygwin emulates Linux, providing
    a byte-exact file position, albeit the underlying device drivers don't.
    
    Unfortunately this only worked correctly for reading.  The raw_write
    method failed to revalidate the buffer after the read-modify-write
    cycle in case len is not a multiple of the sector length.  This in
    turn resulted in lseek reporting a wrong file pointer.
    
    Also, fix a condition for invalidating the buffer after writing from
    a remaining read buffer.
    
    Signed-off-by: Corinna Vinschen <[email protected]>

Diff:
---
 winsup/cygwin/fhandler_floppy.cc | 12 ++++++++++--
 winsup/cygwin/release/2.10.0     |  3 +++
 2 files changed, 13 insertions(+), 2 deletions(-)

diff --git a/winsup/cygwin/fhandler_floppy.cc b/winsup/cygwin/fhandler_floppy.cc
index de9e163..cca00ba 100644
--- a/winsup/cygwin/fhandler_floppy.cc
+++ b/winsup/cygwin/fhandler_floppy.cc
@@ -566,11 +566,11 @@ fhandler_dev_floppy::raw_write (const void *ptr, size_t 
len)
          /* Align pointers, lengths, etc. */
          cplen = MIN (cplen, written);
          devbufstart += cplen;
+         if (devbufstart >= devbufend)
+           devbufstart = devbufend = 0;
          p += cplen;
          len -= cplen;
          bytes_written += cplen;
-         if (len)
-           devbufstart = devbufend = 0;
        }
       /* As long as there's still something left in the input buffer ... */
       while (len)
@@ -607,6 +607,14 @@ fhandler_dev_floppy::raw_write (const void *ptr, size_t 
len)
          p += cplen;
          len -= cplen;
          bytes_written += cplen;
+         /* If we overwrote, revalidate devbuf.  It still contains the
+            content from the above read/modify/write.  Revalidating makes
+            sure lseek reports the correct position. */
+         if (cplen < bytes_per_sector)
+           {
+             devbufstart = cplen;
+             devbufend = bytes_per_sector;
+           }
        }
       return bytes_written;
     }
diff --git a/winsup/cygwin/release/2.10.0 b/winsup/cygwin/release/2.10.0
index 3afc4b7..0c6b406 100644
--- a/winsup/cygwin/release/2.10.0
+++ b/winsup/cygwin/release/2.10.0
@@ -31,3 +31,6 @@ Bug Fixes
 
 - Remove a call to fflush from ftell{o}, which may result in wrong offsets.
   Addresses: https://cygwin.com/ml/cygwin/2017-12/msg00151.html
+
+- Fix file pointer computation after short writes on block devices.
+  Addresses: https://cygwin.com/ml/cygwin/2017-12/msg00151.html

Reply via email to