io: fixes for Read with n > 0, os.EOF

R=rsc
CC=golang-dev
https://golang.org/cl/4271080
diff --git a/src/pkg/io/io.go b/src/pkg/io/io.go
index 3b87918..c0bc54d 100644
--- a/src/pkg/io/io.go
+++ b/src/pkg/io/io.go
@@ -182,16 +182,16 @@
 	if len(buf) < min {
 		return 0, ErrShortBuffer
 	}
-	for n < min {
-		nn, e := r.Read(buf[n:])
-		if nn > 0 {
-			n += nn
-		}
-		if e != nil {
-			if e == os.EOF && n > 0 {
-				e = ErrUnexpectedEOF
-			}
-			return n, e
+	for n < min && err == nil {
+		var nn int
+		nn, err = r.Read(buf[n:])
+		n += nn
+	}
+	if err == os.EOF {
+		if n >= min {
+			err = nil
+		} else if n > 0 {
+			err = ErrUnexpectedEOF
 		}
 	}
 	return
diff --git a/src/pkg/io/io_test.go b/src/pkg/io/io_test.go
index 4fcd85e..bc4f354 100644
--- a/src/pkg/io/io_test.go
+++ b/src/pkg/io/io_test.go
@@ -118,27 +118,50 @@
 
 func TestReadAtLeast(t *testing.T) {
 	var rb bytes.Buffer
+	testReadAtLeast(t, &rb)
+}
+
+// A version of bytes.Buffer that returns n > 0, os.EOF on Read
+// when the input is exhausted.
+type dataAndEOFBuffer struct {
+	bytes.Buffer
+}
+
+func (r *dataAndEOFBuffer) Read(p []byte) (n int, err os.Error) {
+	n, err = r.Buffer.Read(p)
+	if n > 0 && r.Buffer.Len() == 0 && err == nil {
+		err = os.EOF
+	}
+	return
+}
+
+func TestReadAtLeastWithDataAndEOF(t *testing.T) {
+	var rb dataAndEOFBuffer
+	testReadAtLeast(t, &rb)
+}
+
+func testReadAtLeast(t *testing.T, rb ReadWriter) {
 	rb.Write([]byte("0123"))
 	buf := make([]byte, 2)
-	n, err := ReadAtLeast(&rb, buf, 2)
+	n, err := ReadAtLeast(rb, buf, 2)
 	if err != nil {
 		t.Error(err)
 	}
-	n, err = ReadAtLeast(&rb, buf, 4)
+	n, err = ReadAtLeast(rb, buf, 4)
 	if err != ErrShortBuffer {
 		t.Errorf("expected ErrShortBuffer got %v", err)
 	}
 	if n != 0 {
 		t.Errorf("expected to have read 0 bytes, got %v", n)
 	}
-	n, err = ReadAtLeast(&rb, buf, 1)
+	n, err = ReadAtLeast(rb, buf, 1)
 	if err != nil {
 		t.Error(err)
 	}
 	if n != 2 {
 		t.Errorf("expected to have read 2 bytes, got %v", n)
 	}
-	n, err = ReadAtLeast(&rb, buf, 2)
+	n, err = ReadAtLeast(rb, buf, 2)
 	if err != os.EOF {
 		t.Errorf("expected EOF, got %v", err)
 	}
@@ -146,7 +169,7 @@
 		t.Errorf("expected to have read 0 bytes, got %v", n)
 	}
 	rb.Write([]byte("4"))
-	n, err = ReadAtLeast(&rb, buf, 2)
+	n, err = ReadAtLeast(rb, buf, 2)
 	if err != ErrUnexpectedEOF {
 		t.Errorf("expected ErrUnexpectedEOF, got %v", err)
 	}
diff --git a/src/pkg/io/multi.go b/src/pkg/io/multi.go
index 88e4f1b..d702d46 100644
--- a/src/pkg/io/multi.go
+++ b/src/pkg/io/multi.go
@@ -15,10 +15,8 @@
 		n, err = mr.readers[0].Read(p)
 		if n > 0 || err != os.EOF {
 			if err == os.EOF {
-				// This shouldn't happen.
-				// Well-behaved Readers should never
-				// return non-zero bytes read with an
-				// EOF.  But if so, we clean it.
+				// Don't return EOF yet. There may be more bytes
+				// in the remaining readers.
 				err = nil
 			}
 			return