Implement a "full reader" wrapper for io.Read, guaranteeing that
either the buffer is full, zero bytes were read, or an error is returned.

R=rsc
DELTA=44  (42 added, 0 deleted, 2 changed)
OCL=19027
CL=19047
diff --git a/src/lib/io.go b/src/lib/io.go
index 20b7b90..44d072c 100644
--- a/src/lib/io.go
+++ b/src/lib/io.go
@@ -3,8 +3,13 @@
 // license that can be found in the LICENSE file.
 
 package io
-import os "os"
-import syscall "syscall"
+
+import (
+	"os";
+	"syscall";
+)
+
+export var ErrEOF = os.NewError("EOF")
 
 export type Read interface {
 	Read(p *[]byte) (n int, err *os.Error);
@@ -34,3 +39,40 @@
 	r, e := w.Write(b[0:len(s)]);
 	return r, e
 }
+
+// Read until buffer is full,  EOF, or error
+export func Readn(fd Read, buf *[]byte) (n int, err *os.Error) {
+	n = 0;
+	for n < len(buf) {
+		nn, e := fd.Read(buf[n:len(buf)]);
+		if nn > 0 {
+			n += nn
+		}
+		if e != nil {
+			return n, e
+		}
+		if nn <= 0 {
+			return n, ErrEOF	// no error but insufficient data
+		}
+	}
+	return n, nil
+}
+
+// Convert something that implements Read into something
+// whose Reads are always Readn
+type FullRead struct {
+	fd	Read;
+}
+
+func (fd *FullRead) Read(p *[]byte) (n int, err *os.Error) {
+	n, err = Readn(fd, p);
+	return n, err
+}
+
+export func MakeFullReader(fd Read) Read {
+	if fr, ok := fd.(*FullRead); ok {
+		// already a FullRead
+		return fd
+	}
+	return &FullRead{fd}
+}