From e8aa00b76fb9d19714a9d05dc6dd09ae10c5250e Mon Sep 17 00:00:00 2001
From: Ben Longbons <b.r.longbons@gmail.com>
Date: Mon, 25 Aug 2014 16:22:11 -0700
Subject: Fix potential file corruption with partial writes

---
 CHANGELOG             |  2 ++
 src/io/write.cpp      |  1 +
 src/io/write_test.cpp | 35 ++++++++++++++++++++++++++++++++++-
 3 files changed, 37 insertions(+), 1 deletion(-)

diff --git a/CHANGELOG b/CHANGELOG
index 4ec5e5b..da2d510 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,5 @@
+v14.4.20:
+  - fix potential file corruption with partial writes
 v14.4.19:
   - emergency backport of security fix, since v14.7.1 is too buggy
 v14.4.18:
diff --git a/src/io/write.cpp b/src/io/write.cpp
index 5993a69..a216b03 100644
--- a/src/io/write.cpp
+++ b/src/io/write.cpp
@@ -89,6 +89,7 @@ namespace io
             dat += rv;
             len -= rv;
         }
+        std::copy(dat, dat + len, buf);
         buflen = len;
 
     maybe_linebuffered:
diff --git a/src/io/write_test.cpp b/src/io/write_test.cpp
index ae8eccd..8c08833 100644
--- a/src/io/write_test.cpp
+++ b/src/io/write_test.cpp
@@ -27,7 +27,7 @@
 #include "../strings/mstring.hpp"
 #include "../strings/xstring.hpp"
 
-#include "../poison.hpp"
+//#include "../poison.hpp"
 
 static
 io::FD pipew(io::FD& rfd)
@@ -100,3 +100,36 @@ TEST(io, write2)
     EXPECT_TRUE(wf.close());
     EXPECT_EQ("XXX", pw.slurp());
 }
+
+TEST(io, write3)
+{
+    // TODO see if it's possible to get the real value
+    constexpr size_t PIPE_CAPACITY = 65536;
+    char buf[PIPE_CAPACITY];
+
+    PipeWriter pw(false);
+    io::WriteFile& wf = pw.wf;
+
+    memset(buf, 'a', sizeof(buf));
+    wf.really_put(buf, 1);
+    EXPECT_EQ("", pw.slurp());
+
+    memset(buf, 'b', sizeof(buf));
+    wf.really_put(buf, sizeof(buf));
+
+    // write 1 + PIPE_CAPACITY
+    // read 1 + N + (PIPE_CAPACITY - N)
+    size_t remaining;
+    {
+        AString a = pw.slurp();
+        XString x = a.xslice_t(1);
+        EXPECT_EQ(a.front(), 'a');
+        EXPECT_EQ(x.front(), 'b');
+        EXPECT_EQ(x.back(), 'b');
+        EXPECT_EQ(x, XString(buf, buf + x.size(), nullptr));
+        remaining = sizeof(buf) - x.size();
+    }
+
+    EXPECT_TRUE(wf.close());
+    EXPECT_EQ(pw.slurp(), XString(buf, buf + remaining, nullptr));
+}
-- 
cgit v1.2.3-70-g09d2