Rename os.FD to os.File.

Make Fstat, Readdirnames, and Readdir methods
on os.File.

R=r
DELTA=281  (79 added, 3 deleted, 199 changed)
OCL=25891
CL=26130
diff --git a/src/lib/exec.go b/src/lib/exec.go
index 36ded93..c832c17 100644
--- a/src/lib/exec.go
+++ b/src/lib/exec.go
@@ -18,20 +18,20 @@
 )
 
 // A Cmd represents a running command.
-// Stdin, Stdout, and Stderr are file descriptors to pipes
+// Stdin, Stdout, and Stderr are Files representing pipes
 // connected to the running command's standard input, output, and error,
 // or else nil, depending on the arguments to Run.
 // Pid is the running command's operating system process ID.
 type Cmd struct {
-	Stdin *os.FD;
-	Stdout *os.FD;
-	Stderr *os.FD;
+	Stdin *os.File;
+	Stdout *os.File;
+	Stderr *os.File;
 	Pid int;
 }
 
-// Given mode (DevNull, etc), return fd for child
-// and fd to record in Cmd structure.
-func modeToFDs(mode, fd int) (*os.FD, *os.FD, *os.Error) {
+// Given mode (DevNull, etc), return file for child
+// and file to record in Cmd structure.
+func modeToFiles(mode, fd int) (*os.File, *os.File, *os.Error) {
 	switch mode {
 	case DevNull:
 		rw := os.O_WRONLY;
@@ -80,17 +80,17 @@
 func Run(argv0 string, argv, envv []string, stdin, stdout, stderr int) (p *Cmd, err *os.Error)
 {
 	p = new(Cmd);
-	var fd [3]*os.FD;
+	var fd [3]*os.File;
 
-	if fd[0], p.Stdin, err = modeToFDs(stdin, 0); err != nil {
+	if fd[0], p.Stdin, err = modeToFiles(stdin, 0); err != nil {
 		goto Error;
 	}
-	if fd[1], p.Stdout, err = modeToFDs(stdout, 1); err != nil {
+	if fd[1], p.Stdout, err = modeToFiles(stdout, 1); err != nil {
 		goto Error;
 	}
 	if stderr == MergeWithStdout {
 		p.Stderr = p.Stdout;
-	} else if fd[2], p.Stderr, err = modeToFDs(stderr, 2); err != nil {
+	} else if fd[2], p.Stderr, err = modeToFiles(stderr, 2); err != nil {
 		goto Error;
 	}
 
diff --git a/src/lib/http/server.go b/src/lib/http/server.go
index ffb81cc..df2ce36 100644
--- a/src/lib/http/server.go
+++ b/src/lib/http/server.go
@@ -22,23 +22,28 @@
 	"strconv";
 )
 
-var ErrWriteAfterFlush = os.NewError("Conn.Write called after Flush")
-var ErrHijacked = os.NewError("Conn has been hijacked")
+// Errors introduced by the HTTP server.
+var (
+	ErrWriteAfterFlush = os.NewError("Conn.Write called after Flush");
+	ErrHijacked = os.NewError("Conn has been hijacked");
+)
 
 type Conn struct
 
-// Interface implemented by servers using this library.
+// Objects implemeting the Handler interface can be
+// registered to serve a particular path or subtree
+// in the HTTP server.
 type Handler interface {
 	ServeHTTP(*Conn, *Request);
 }
 
-// Active HTTP connection (server side).
+// A Conn represents the server side of a single active HTTP connection.
 type Conn struct {
 	RemoteAddr string;	// network address of remote side
-	Req *Request;	// current HTTP request
+	Req *Request;		// current HTTP request
 
-	fd io.ReadWriteClose;	// i/o connection
-	buf *bufio.BufReadWrite;	// buffered fd
+	rwc io.ReadWriteClose;	// i/o connection
+	buf *bufio.BufReadWrite;	// buffered rwc
 	handler Handler;	// request handler
 	hijacked bool;	// connection has been hijacked by handler
 
@@ -54,7 +59,7 @@
 	c = new(Conn);
 	c.RemoteAddr = raddr;
 	c.handler = handler;
-	c.fd = rwc;
+	c.rwc = rwc;
 	br := bufio.NewBufRead(rwc);
 	bw := bufio.NewBufWrite(rwc);
 	c.buf = bufio.NewBufReadWrite(br, bw);
@@ -99,11 +104,25 @@
 	return req, nil
 }
 
+// SetHeader sets a header line in the eventual reply.
+// For example, SetHeader("Content-Type", "text/html; charset=utf-8")
+// will result in the header line
+//
+//	Content-Type: text/html; charset=utf-8
+//
+// being sent.  UTF-8 encoded HTML is the default setting for
+// Content-Type in this library, so users need not make that
+// particular call.  Calls to SetHeader after WriteHeader (or Write)
+// are ignored.
 func (c *Conn) SetHeader(hdr, val string) {
 	c.header[CanonicalHeaderKey(hdr)] = val;
 }
 
-// Write header.
+// WriteHeader sends an HTTP response header with status code.
+// If WriteHeader is not called explicitly, the first call to Write
+// will trigger an implicit WriteHeader(http.StatusOK).
+// Thus explicit calls to WriteHeader are mainly used to
+// send error codes.
 func (c *Conn) WriteHeader(code int) {
 	if c.hijacked {
 		log.Stderr("http: Conn.WriteHeader on hijacked connection");
@@ -133,10 +152,10 @@
 	io.WriteString(c.buf, "\r\n");
 }
 
-// TODO(rsc): BUG in 6g: must return "nn int" not "n int"
-// so that the implicit struct assignment in
-// return c.buf.Write(data) works.  oops
-func (c *Conn) Write(data []byte) (nn int, err *os.Error) {
+// Write writes the data to the connection as part of an HTTP reply.
+// If WriteHeader has not yet been called, Write calls WriteHeader(http.StatusOK)
+// before writing the data.
+func (c *Conn) Write(data []byte) (n int, err *os.Error) {
 	if c.hijacked {
 		log.Stderr("http: Conn.Write on hijacked connection");
 		return 0, ErrHijacked
@@ -175,9 +194,9 @@
 		c.buf.Flush();
 		c.buf = nil;
 	}
-	if c.fd != nil {
-		c.fd.Close();
-		c.fd = nil;
+	if c.rwc != nil {
+		c.rwc.Close();
+		c.rwc = nil;
 	}
 }
 
@@ -203,25 +222,30 @@
 	c.close();
 }
 
-// Allow client to take over the connection.
-// After a handler calls c.Hijack(), the HTTP server library
-// will never touch the connection again.
-// It is the caller's responsibility to manage and close
-// the connection.
-func (c *Conn) Hijack() (fd io.ReadWriteClose, buf *bufio.BufReadWrite, err *os.Error) {
+// Hijack lets the caller take over the connection.
+// After a call to c.Hijack(), the HTTP server library
+// will not do anything else with the connection.
+// It becomes the caller's responsibility to manage
+// and close the connection.
+func (c *Conn) Hijack() (rwc io.ReadWriteClose, buf *bufio.BufReadWrite, err *os.Error) {
 	if c.hijacked {
 		return nil, nil, ErrHijacked;
 	}
 	c.hijacked = true;
-	fd = c.fd;
+	rwc = c.rwc;
 	buf = c.buf;
-	c.fd = nil;
+	c.rwc = nil;
 	c.buf = nil;
 	return;
 }
 
-// Adapter: can use HandlerFunc(f) as Handler
+// The HandlerFunc type is an adapter to allow the use of
+// ordinary functions as HTTP handlers.  If f is a function
+// with the appropriate signature, HandlerFunc(f) is a
+// Handler object that calls f.
 type HandlerFunc func(*Conn, *Request)
+
+// ServeHTTP calls f(c, req).
 func (f HandlerFunc) ServeHTTP(c *Conn, req *Request) {
 	f(c, req);
 }
@@ -235,7 +259,11 @@
 	io.WriteString(c, "404 page not found\n");
 }
 
-var NotFoundHandler = HandlerFunc(notFound)
+// NotFoundHandler returns a simple request handler
+// that replies to each request with a ``404 page not found'' reply.
+func NotFoundHandler() Handler {
+	return HandlerFunc(notFound)
+}
 
 // Redirect to a fixed URL
 type redirectHandler struct {
@@ -246,28 +274,42 @@
 	c.WriteHeader(StatusMovedPermanently);
 }
 
-func RedirectHandler(to string) Handler {
-	return &redirectHandler{to};
+// RedirectHandler returns a request handler that redirects
+// each request it receives to the given url.
+func RedirectHandler(url string) Handler {
+	return &redirectHandler{url};
 }
 
-// Path-based HTTP request multiplexer.
-// Patterns name fixed paths, like "/favicon.ico",
-// or subtrees, like "/images/".
-// For now, patterns must begin with /.
-// Eventually, might want to allow host name
-// at beginning of pattern, so that you could register
-//	/codesearch
-//	codesearch.google.com/
-// but not take over /.
-
+// ServeMux is an HTTP request multiplexer.
+// It matches the URL of each incoming request against a list of registered
+// patterns and calls the handler for the pattern that
+// most closely matches the URL.
+//
+// Patterns named fixed paths, like "/favicon.ico",
+// or subtrees, like "/images/" (note the trailing slash).
+// Patterns must begin with /.
+// Longer patterns take precedence over shorter ones, so that
+// if there are handlers registered for both "/images/"
+// and "/images/thumbnails/", the latter handler will be
+// called for paths beginning "/images/thumbnails/" and the
+// former will receiver requests for any other paths in the
+// "/images/" subtree.
+//
+// In the future, the pattern syntax may be relaxed to allow
+// an optional host-name at the beginning of the pattern,
+// so that a handler might register for the two patterns
+// "/codesearch" and "codesearch.google.com/"
+// without taking over requests for http://www.google.com/.
 type ServeMux struct {
 	m map[string] Handler
 }
 
+// NewServeMux allocates and returns a new ServeMux.
 func NewServeMux() *ServeMux {
 	return &ServeMux{make(map[string] Handler)};
 }
 
+// DefaultServeMux is the default ServeMux used by Serve.
 var DefaultServeMux = NewServeMux();
 
 // Does path match pattern?
@@ -283,6 +325,8 @@
 	return len(path) >= n && path[0:n] == pattern;
 }
 
+// ServeHTTP dispatches the request to the handler whose
+// pattern most closely matches the request URL.
 func (mux *ServeMux) ServeHTTP(c *Conn, req *Request) {
 	// Most-specific (longest) pattern wins.
 	var h Handler;
@@ -297,11 +341,12 @@
 		}
 	}
 	if h == nil {
-		h = NotFoundHandler;
+		h = NotFoundHandler();
 	}
 	h.ServeHTTP(c, req);
 }
 
+// Handle registers the handler for the given pattern.
 func (mux *ServeMux) Handle(pattern string, handler Handler) {
 	if pattern == "" || pattern[0] != '/' {
 		panicln("http: invalid pattern", pattern);
@@ -317,12 +362,16 @@
 	}
 }
 
-func Handle(pattern string, h Handler) {
-	DefaultServeMux.Handle(pattern, h);
+// Handle registers the handler for the given pattern
+// in the DefaultServeMux.
+func Handle(pattern string, handler Handler) {
+	DefaultServeMux.Handle(pattern, handler);
 }
 
-
-// Web server: listening on l, call handler.ServeHTTP for each request.
+// Serve accepts incoming HTTP connections on the listener l,
+// creating a new service thread for each.  The service threads
+// read requests and then call handler to reply to them.
+// Handler is typically nil, in which case the DefaultServeMux is used.
 func Serve(l net.Listener, handler Handler) *os.Error {
 	if handler == nil {
 		handler = DefaultServeMux;
@@ -341,7 +390,32 @@
 	panic("not reached")
 }
 
-// Web server: listen on address, call f for each request.
+// ListenAndServe listens on the TCP network address addr
+// and then calls Serve with handler to handle requests
+// on incoming connections.  Handler is typically nil,
+// in which case the DefaultServeMux is used.
+//
+// A trivial example server is:
+//
+//	package main
+//
+//	import (
+//		"http";
+//		"io";
+//	)
+//
+//	// hello world, the web server
+//	func HelloServer(c *http.Conn, req *http.Request) {
+//		io.WriteString(c, "hello, world!\n");
+//	}
+//
+//	func main() {
+//		http.Handle("/hello", http.HandlerFunc(HelloServer));
+//		err := http.ListenAndServe(":12345", nil);
+//		if err != nil {
+//			panic("ListenAndServe: ", err.String())
+//		}
+//	}
 func ListenAndServe(addr string, handler Handler) *os.Error {
 	l, e := net.Listen("tcp", addr);
 	if e != nil {
diff --git a/src/lib/http/triv.go b/src/lib/http/triv.go
index ea17d15..daf5eb8 100644
--- a/src/lib/http/triv.go
+++ b/src/lib/http/triv.go
@@ -35,14 +35,15 @@
 func FileServer(c *http.Conn, req *http.Request) {
 	c.SetHeader("content-type", "text/plain; charset=utf-8");
 	path := *webroot + req.Url.Path;	// TODO: insecure: use os.CleanName
-	fd, err := os.Open(path, os.O_RDONLY, 0);
+	f, err := os.Open(path, os.O_RDONLY, 0);
 	if err != nil {
 		c.WriteHeader(http.StatusNotFound);
 		fmt.Fprintf(c, "open %s: %v\n", path, err);
 		return;
 	}
-	n, err1 := io.Copy(fd, c);
+	n, err1 := io.Copy(f, c);
 	fmt.Fprintf(c, "[%d bytes]\n", n);
+	f.Close();
 }
 
 // simple flag server
diff --git a/src/lib/log_test.go b/src/lib/log_test.go
index 23e58b9..2d9e1ab 100644
--- a/src/lib/log_test.go
+++ b/src/lib/log_test.go
@@ -47,14 +47,14 @@
 
 // Test using Log("hello", 23, "world") or using Logf("hello %d world", 23)
 func testLog(t *testing.T, flag int, prefix string, pattern string, useLogf bool) {
-	fd0, fd1, err1 := os.Pipe();
+	r, w, err1 := os.Pipe();
 	if err1 != nil {
 		t.Fatal("pipe", err1);
 	}
-	defer fd0.Close();
-	defer fd1.Close();
-	buf := bufio.NewBufRead(fd0);
-	l := NewLogger(fd1, nil, prefix, flag);
+	defer r.Close();
+	defer w.Close();
+	buf := bufio.NewBufRead(r);
+	l := NewLogger(w, nil, prefix, flag);
 	if useLogf {
 		l.Logf("hello %d world", 23);
 	} else {
diff --git a/src/lib/net/fd.go b/src/lib/net/fd.go
index 7509231..6066bd5 100644
--- a/src/lib/net/fd.go
+++ b/src/lib/net/fd.go
@@ -18,7 +18,7 @@
 type netFD struct {
 	// immutable until Close
 	fd int64;
-	osfd *os.FD;
+	file *os.File;
 	cr chan *netFD;
 	cw chan *netFD;
 	net string;
@@ -90,7 +90,7 @@
 
 type pollServer struct {
 	cr, cw chan *netFD;	// buffered >= 1
-	pr, pw *os.FD;
+	pr, pw *os.File;
 	pending map[int64] *netFD;
 	poll *pollster;	// low-level OS hooks
 	deadline int64;	// next deadline (nsec since 1970)
@@ -309,14 +309,14 @@
 	f.net = net;
 	f.laddr = laddr;
 	f.raddr = raddr;
-	f.osfd = os.NewFD(fd, "net: " + net + " " + laddr + " " + raddr);
+	f.file = os.NewFile(fd, "net: " + net + " " + laddr + " " + raddr);
 	f.cr = make(chan *netFD, 1);
 	f.cw = make(chan *netFD, 1);
 	return f, nil
 }
 
 func (fd *netFD) Close() *os.Error {
-	if fd == nil || fd.osfd == nil {
+	if fd == nil || fd.file == nil {
 		return os.EINVAL
 	}
 
@@ -326,16 +326,16 @@
 	// we can handle the extra OS processes.
 	// Otherwise we'll need to use the pollserver
 	// for Close too.  Sigh.
-	setBlock(fd.osfd.Fd());
+	setBlock(fd.file.Fd());
 
-	e := fd.osfd.Close();
-	fd.osfd = nil;
+	e := fd.file.Close();
+	fd.file = nil;
 	fd.fd = -1;
 	return e
 }
 
 func (fd *netFD) Read(p []byte) (n int, err *os.Error) {
-	if fd == nil || fd.osfd == nil {
+	if fd == nil || fd.file == nil {
 		return -1, os.EINVAL
 	}
 	fd.rio.Lock();
@@ -345,16 +345,16 @@
 	} else {
 		fd.rdeadline = 0;
 	}
-	n, err = fd.osfd.Read(p);
+	n, err = fd.file.Read(p);
 	for err == os.EAGAIN && fd.rdeadline >= 0 {
 		pollserver.WaitRead(fd);
-		n, err = fd.osfd.Read(p)
+		n, err = fd.file.Read(p)
 	}
 	return n, err
 }
 
 func (fd *netFD) Write(p []byte) (n int, err *os.Error) {
-	if fd == nil || fd.osfd == nil {
+	if fd == nil || fd.file == nil {
 		return -1, os.EINVAL
 	}
 	fd.wio.Lock();
@@ -367,7 +367,7 @@
 	err = nil;
 	nn := 0;
 	for nn < len(p) {
-		n, err = fd.osfd.Write(p[nn:len(p)]);
+		n, err = fd.file.Write(p[nn:len(p)]);
 		if n > 0 {
 			nn += n
 		}
@@ -388,7 +388,7 @@
 func sockaddrToHostPort(sa *syscall.Sockaddr) (hostport string, err *os.Error)
 
 func (fd *netFD) Accept(sa *syscall.Sockaddr) (nfd *netFD, err *os.Error) {
-	if fd == nil || fd.osfd == nil {
+	if fd == nil || fd.file == nil {
 		return nil, os.EINVAL
 	}
 
diff --git a/src/lib/net/net.go b/src/lib/net/net.go
index 7ea5d2d..e3e7baa 100644
--- a/src/lib/net/net.go
+++ b/src/lib/net/net.go
@@ -187,11 +187,11 @@
 	raddr string;
 }
 
-func (c *connBase) FD() *os.FD {
+func (c *connBase) File() *os.File {
 	if c == nil {
 		return nil
 	}
-	return c.fd.osfd;
+	return c.fd.file;
 }
 
 func (c *connBase) sysFD() int64 {
diff --git a/src/lib/net/parse.go b/src/lib/net/parse.go
index e9aaf06..194f412 100644
--- a/src/lib/net/parse.go
+++ b/src/lib/net/parse.go
@@ -13,12 +13,12 @@
 )
 
 type file struct {
-	fd *os.FD;
+	file *os.File;
 	data []byte;
 }
 
 func (f *file) close() {
-	f.fd.Close()
+	f.file.Close()
 }
 
 func (f *file) getLineFromData() (s string, ok bool) {
@@ -46,7 +46,7 @@
 	}
 	if len(f.data) < cap(f.data) {
 		ln := len(f.data);
-		n, err := io.Readn(f.fd, f.data[ln:cap(f.data)]);
+		n, err := io.Readn(f.file, f.data[ln:cap(f.data)]);
 		if n >= 0 {
 			f.data = f.data[0:ln+n];
 		}
diff --git a/src/lib/os/dir_amd64_darwin.go b/src/lib/os/dir_amd64_darwin.go
index 41f6211..c62f74d 100644
--- a/src/lib/os/dir_amd64_darwin.go
+++ b/src/lib/os/dir_amd64_darwin.go
@@ -15,15 +15,15 @@
 )
 
 // Negative count means read until EOF.
-func Readdirnames(fd *FD, count int) (names []string, err *os.Error) {
-	// If this fd has no dirinfo, create one.
-	if fd.dirinfo == nil {
-		fd.dirinfo = new(dirInfo);
+func readdirnames(file *File, count int) (names []string, err *os.Error) {
+	// If this file has no dirinfo, create one.
+	if file.dirinfo == nil {
+		file.dirinfo = new(dirInfo);
 		// The buffer must be at least a block long.
 		// TODO(r): use fstatfs to find fs block size.
-		fd.dirinfo.buf = make([]byte, blockSize);
+		file.dirinfo.buf = make([]byte, blockSize);
 	}
-	d := fd.dirinfo;
+	d := file.dirinfo;
 	size := count;
 	if size < 0 {
 		size = 100
@@ -34,7 +34,7 @@
 		if d.bufp == d.nbuf {
 			var errno int64;
 			// Final argument is (basep *int64) and the syscall doesn't take nil.
-			d.nbuf, errno = syscall.Getdirentries(fd.fd, &d.buf[0], int64(len(d.buf)), new(int64));
+			d.nbuf, errno = syscall.Getdirentries(file.fd, &d.buf[0], int64(len(d.buf)), new(int64));
 			if d.nbuf < 0 {
 				return names, os.ErrnoToError(errno)
 			}
diff --git a/src/lib/os/dir_amd64_linux.go b/src/lib/os/dir_amd64_linux.go
index 7a2ec73..cbb0d13 100644
--- a/src/lib/os/dir_amd64_linux.go
+++ b/src/lib/os/dir_amd64_linux.go
@@ -24,15 +24,15 @@
 }
 
 // Negative count means read until EOF.
-func Readdirnames(fd *FD, count int) (names []string, err *os.Error) {
-	// If this fd has no dirinfo, create one.
-	if fd.dirinfo == nil {
-		fd.dirinfo = new(dirInfo);
+func readdirnames(file *File, count int) (names []string, err *os.Error) {
+	// If this file has no dirinfo, create one.
+	if file.dirinfo == nil {
+		file.dirinfo = new(dirInfo);
 		// The buffer must be at least a block long.
 		// TODO(r): use fstatfs to find fs block size.
-		fd.dirinfo.buf = make([]byte, blockSize);
+		file.dirinfo.buf = make([]byte, blockSize);
 	}
-	d := fd.dirinfo;
+	d := file.dirinfo;
 	size := count;
 	if size < 0 {
 		size = 100
@@ -43,7 +43,7 @@
 		if d.bufp == d.nbuf {
 			var errno int64;
 			dbuf := (*syscall.Dirent)(unsafe.Pointer(&d.buf[0]));
-			d.nbuf, errno = syscall.Getdents(fd.fd, dbuf, int64(len(d.buf)));
+			d.nbuf, errno = syscall.Getdents(file.fd, dbuf, int64(len(d.buf)));
 			if d.nbuf < 0 {
 				return names, os.ErrnoToError(errno)
 			}
diff --git a/src/lib/os/exec.go b/src/lib/os/exec.go
index b16a6c4..f987f7a 100644
--- a/src/lib/os/exec.go
+++ b/src/lib/os/exec.go
@@ -15,7 +15,7 @@
 // file descriptors to be set up in the new process: fd[0] will be Unix file
 // descriptor 0 (standard input), fd[1] descriptor 1, and so on.  A nil entry
 // will cause the child to have no open file descriptor with that index.
-func ForkExec(argv0 string, argv []string, envv []string, fd []*FD)
+func ForkExec(argv0 string, argv []string, envv []string, fd []*File)
 	(pid int, err *Error)
 {
 	// Create array of integer (system) fds.
diff --git a/src/lib/os/file.go b/src/lib/os/file.go
index 1fb2a64..3010dee 100644
--- a/src/lib/os/file.go
+++ b/src/lib/os/file.go
@@ -11,45 +11,44 @@
 	"syscall";
 )
 
-// Auxiliary information if the FD describes a directory
+// Auxiliary information if the File describes a directory
 type dirInfo struct {	// TODO(r): 6g bug means this can't be private
 	buf	[]byte;	// buffer for directory I/O
 	nbuf	int64;	// length of buf; return value from Getdirentries
 	bufp	int64;	// location of next record in buf.
 }
 
-// FD represents an open file.
-// TODO(r): is FD the right name? Would File be better?
-type FD struct {
+// File represents an open file descriptor.
+type File struct {
 	fd int64;
 	name	string;
 	dirinfo	*dirInfo;	// nil unless directory being read
 }
 
 // Fd returns the integer Unix file descriptor referencing the open file.
-func (fd *FD) Fd() int64 {
-	return fd.fd
+func (file *File) Fd() int64 {
+	return file.fd
 }
 
 // Name returns the name of the file as presented to Open.
-func (fd *FD) Name() string {
-	return fd.name
+func (file *File) Name() string {
+	return file.name
 }
 
-// NewFD returns a new FD with the given file descriptor and name.
-func NewFD(fd int64, name string) *FD {
-	if fd < 0 {
+// NewFile returns a new File with the given file descriptor and name.
+func NewFile(file int64, name string) *File {
+	if file < 0 {
 		return nil
 	}
-	return &FD{fd, name, nil}
+	return &File{file, name, nil}
 }
 
-// Stdin, Stdout, and Stderr are open FDs pointing to the standard input,
+// Stdin, Stdout, and Stderr are open Files pointing to the standard input,
 // standard output, and standard error file descriptors.
 var (
-	Stdin = NewFD(0, "/dev/stdin");
-	Stdout = NewFD(1, "/dev/stdout");
-	Stderr = NewFD(2, "/dev/stderr");
+	Stdin  = NewFile(0, "/dev/stdin");
+	Stdout = NewFile(1, "/dev/stdout");
+	Stderr = NewFile(2, "/dev/stderr");
 )
 
 // Flags to Open wrapping those of the underlying system. Not all flags
@@ -69,9 +68,9 @@
 )
 
 // Open opens the named file with specified flag (O_RDONLY etc.) and perm, (0666 etc.)
-// if applicable.  If successful, methods on the returned FD can be used for I/O.
-// It returns the FD and an Error, if any.
-func Open(name string, flag int, perm int) (fd *FD, err *Error) {
+// if applicable.  If successful, methods on the returned File can be used for I/O.
+// It returns the File and an Error, if any.
+func Open(name string, flag int, perm int) (file *File, err *Error) {
 	r, e := syscall.Open(name, int64(flag | syscall.O_CLOEXEC), int64(perm));
 	if e != 0 {
 		return nil, ErrnoToError(e);
@@ -83,31 +82,31 @@
 		syscall.CloseOnExec(r);
 	}
 
-	return NewFD(r, name), ErrnoToError(e)
+	return NewFile(r, name), ErrnoToError(e)
 }
 
-// Close closes the FD, rendering it unusable for I/O.
+// Close closes the File, rendering it unusable for I/O.
 // It returns an Error, if any.
-func (fd *FD) Close() *Error {
-	if fd == nil {
+func (file *File) Close() *Error {
+	if file == nil {
 		return EINVAL
 	}
-	r, e := syscall.Close(fd.fd);
-	fd.fd = -1;  // so it can't be closed again
+	r, e := syscall.Close(file.fd);
+	file.fd = -1;  // so it can't be closed again
 	return ErrnoToError(e)
 }
 
-// Read reads up to len(b) bytes from the FD.
+// Read reads up to len(b) bytes from the File.
 // It returns the number of bytes read and an Error, if any.
 // EOF is signaled by a zero count with a nil Error.
 // TODO(r): Add Pread, Pwrite (maybe ReadAt, WriteAt).
-func (fd *FD) Read(b []byte) (ret int, err *Error) {
-	if fd == nil {
+func (file *File) Read(b []byte) (ret int, err *Error) {
+	if file == nil {
 		return 0, EINVAL
 	}
 	var r, e int64;
 	if len(b) > 0 {  // because we access b[0]
-		r, e = syscall.Read(fd.fd, &b[0], int64(len(b)));
+		r, e = syscall.Read(file.fd, &b[0], int64(len(b)));
 		if r < 0 {
 			r = 0
 		}
@@ -115,16 +114,16 @@
 	return int(r), ErrnoToError(e)
 }
 
-// Write writes len(b) bytes to the FD.
+// Write writes len(b) bytes to the File.
 // It returns the number of bytes written and an Error, if any.
 // If the byte count differs from len(b), it usually implies an error occurred.
-func (fd *FD) Write(b []byte) (ret int, err *Error) {
-	if fd == nil {
+func (file *File) Write(b []byte) (ret int, err *Error) {
+	if file == nil {
 		return 0, EINVAL
 	}
 	var r, e int64;
 	if len(b) > 0 {  // because we access b[0]
-		r, e = syscall.Write(fd.fd, &b[0], int64(len(b)));
+		r, e = syscall.Write(file.fd, &b[0], int64(len(b)));
 		if r < 0 {
 			r = 0
 		}
@@ -132,16 +131,16 @@
 	return int(r), ErrnoToError(e)
 }
 
-// Seek sets the offset for the next Read or Write on FD to offset, interpreted
+// Seek sets the offset for the next Read or Write on file to offset, interpreted
 // according to whence: 0 means relative to the origin of the file, 1 means
 // relative to the current offset, and 2 means relative to the end.
 // It returns the new offset and an Error, if any.
-func (fd *FD) Seek(offset int64, whence int) (ret int64, err *Error) {
-	r, e := syscall.Seek(fd.fd, offset, int64(whence));
+func (file *File) Seek(offset int64, whence int) (ret int64, err *Error) {
+	r, e := syscall.Seek(file.fd, offset, int64(whence));
 	if e != 0 {
 		return -1, ErrnoToError(e)
 	}
-	if fd.dirinfo != nil && r != 0 {
+	if file.dirinfo != nil && r != 0 {
 		return -1, ErrnoToError(syscall.EISDIR)
 	}
 	return r, nil
@@ -149,20 +148,20 @@
 
 // WriteString is like Write, but writes the contents of string s rather than
 // an array of bytes.
-func (fd *FD) WriteString(s string) (ret int, err *Error) {
-	if fd == nil {
+func (file *File) WriteString(s string) (ret int, err *Error) {
+	if file == nil {
 		return 0, EINVAL
 	}
-	r, e := syscall.Write(fd.fd, syscall.StringBytePtr(s), int64(len(s)));
+	r, e := syscall.Write(file.fd, syscall.StringBytePtr(s), int64(len(s)));
 	if r < 0 {
 		r = 0
 	}
 	return int(r), ErrnoToError(e)
 }
 
-// Pipe returns a connected pair of FDs; reads from r return bytes written to w.
-// It returns the FDs and an Error, if any.
-func Pipe() (r *FD, w *FD, err *Error) {
+// Pipe returns a connected pair of Files; reads from r return bytes written to w.
+// It returns the files and an Error, if any.
+func Pipe() (r *File, w *File, err *Error) {
 	var p [2]int64;
 
 	// See ../syscall/exec.go for description of lock.
@@ -176,7 +175,7 @@
 	syscall.CloseOnExec(p[1]);
 	syscall.ForkLock.RUnlock();
 
-	return NewFD(p[0], "|0"), NewFD(p[1], "|1"), nil
+	return NewFile(p[0], "|0"), NewFile(p[1], "|1"), nil
 }
 
 // Mkdir creates a new directory with the specified name and permission bits.
@@ -199,15 +198,15 @@
 	return dirFromStat(name, new(Dir), stat), nil
 }
 
-// Fstat returns the Dir structure describing the file associated with the FD.
+// Stat returns the Dir structure describing file.
 // It returns the Dir and an error, if any.
-func Fstat(fd *FD) (dir *Dir, err *Error) {
+func (file *File) Stat() (dir *Dir, err *Error) {
 	stat := new(syscall.Stat_t);
-	r, e := syscall.Fstat(fd.fd, stat);
+	r, e := syscall.Fstat(file.fd, stat);
 	if e != 0 {
 		return nil, ErrnoToError(e)
 	}
-	return dirFromStat(fd.name, new(Dir), stat), nil
+	return dirFromStat(file.name, new(Dir), stat), nil
 }
 
 // Lstat returns the Dir structure describing the named file. If the file
@@ -224,26 +223,29 @@
 
 // Readdirnames has a non-portable implemenation so its code is separated into an
 // operating-system-dependent file.
+func readdirnames(file *File, count int) (names []string, err *os.Error)
 
-// Readdirnames reads the contents of the directory associated with fd and
+// Readdirnames reads the contents of the directory associated with file and
 // returns an array of up to count names, in directory order.  Subsequent
-// calls on the same fd will yield further names.
+// calls on the same file will yield further names.
 // A negative count means to read until EOF.
 // It returns the array and an Error, if any.
-func Readdirnames(fd *FD, count int) (names []string, err *os.Error)
+func (file *File) Readdirnames(count int) (names []string, err *os.Error) {
+	return readdirnames(file, count);
+}
 
-// Readdir reads the contents of the directory associated with fd and
+// Readdir reads the contents of the directory associated with file and
 // returns an array of up to count Dir structures, in directory order.  Subsequent
-// calls on the same fd will yield further Dirs.
+// calls on the same file will yield further Dirs.
 // A negative count means to read until EOF.
 // It returns the array and an Error, if any.
-func Readdir(fd *FD, count int) (dirs []Dir, err *os.Error) {
-	dirname := fd.name;
+func (file *File) Readdir(count int) (dirs []Dir, err *os.Error) {
+	dirname := file.name;
 	if dirname == "" {
 		dirname = ".";
 	}
 	dirname += "/";
-	names, err1 := Readdirnames(fd, count);
+	names, err1 := file.Readdirnames(count);
 	if err1 != nil {
 		return nil, err1
 	}
diff --git a/src/lib/os/os_test.go b/src/lib/os/os_test.go
index 535008e..2f0cd88 100644
--- a/src/lib/os/os_test.go
+++ b/src/lib/os/os_test.go
@@ -29,16 +29,16 @@
 	"passwd",
 }
 
-func size(file string, t *testing.T) uint64 {
-	fd, err := Open(file, O_RDONLY, 0);
-	defer fd.Close();
+func size(name string, t *testing.T) uint64 {
+	file, err := Open(name, O_RDONLY, 0);
+	defer file.Close();
 	if err != nil {
 		t.Fatal("open failed:", err);
 	}
 	var buf [100]byte;
 	len := 0;
 	for {
-		n, e := fd.Read(buf);
+		n, e := file.Read(buf);
 		if n < 0 || e != nil {
 			t.Fatal("read failed:", err);
 		}
@@ -65,12 +65,12 @@
 }
 
 func TestFstat(t *testing.T) {
-	fd, err1 := Open("/etc/passwd", O_RDONLY, 0);
-	defer fd.Close();
+	file, err1 := Open("/etc/passwd", O_RDONLY, 0);
+	defer file.Close();
 	if err1 != nil {
 		t.Fatal("open failed:", err1);
 	}
-	dir, err2 := Fstat(fd);
+	dir, err2 := file.Stat();
 	if err2 != nil {
 		t.Fatal("fstat failed:", err2);
 	}
@@ -98,12 +98,12 @@
 }
 
 func testReaddirnames(dir string, contents []string, t *testing.T) {
-	fd, err := Open(dir, O_RDONLY, 0);
-	defer fd.Close();
+	file, err := Open(dir, O_RDONLY, 0);
+	defer file.Close();
 	if err != nil {
 		t.Fatalf("open %q failed: %v", dir, err);
 	}
-	s, err2 := Readdirnames(fd, -1);
+	s, err2 := file.Readdirnames(-1);
 	if err2 != nil {
 		t.Fatalf("readdirnames %q failed: %v", err2);
 	}
@@ -124,12 +124,12 @@
 }
 
 func testReaddir(dir string, contents []string, t *testing.T) {
-	fd, err := Open(dir, O_RDONLY, 0);
-	defer fd.Close();
+	file, err := Open(dir, O_RDONLY, 0);
+	defer file.Close();
 	if err != nil {
 		t.Fatalf("open %q failed: %v", dir, err);
 	}
-	s, err2 := Readdir(fd, -1);
+	s, err2 := file.Readdir(-1);
 	if err2 != nil {
 		t.Fatalf("readdir %q failed: %v", dir, err2);
 	}
@@ -160,13 +160,13 @@
 }
 
 // Read the directory one entry at a time.
-func smallReaddirnames(fd *FD, length int, t *testing.T) []string {
+func smallReaddirnames(file *File, length int, t *testing.T) []string {
 	names := make([]string, length);
 	count := 0;
 	for {
-		d, err := Readdirnames(fd, 1);
+		d, err := file.Readdirnames(1);
 		if err != nil {
-			t.Fatalf("readdir %q failed: %v", fd.Name(), err);
+			t.Fatalf("readdir %q failed: %v", file.Name(), err);
 		}
 		if len(d) == 0 {
 			break
@@ -181,20 +181,20 @@
 // as reading it all at once.
 func TestReaddirnamesOneAtATime(t *testing.T) {
 	dir := "/usr/bin";	// big directory that doesn't change often.
-	fd, err := Open(dir, O_RDONLY, 0);
-	defer fd.Close();
+	file, err := Open(dir, O_RDONLY, 0);
+	defer file.Close();
 	if err != nil {
 		t.Fatalf("open %q failed: %v", dir, err);
 	}
-	all, err1 := Readdirnames(fd, -1);
+	all, err1 := file.Readdirnames(-1);
 	if err1 != nil {
 		t.Fatalf("readdirnames %q failed: %v", dir, err1);
 	}
-	fd1, err2 := Open(dir, O_RDONLY, 0);
+	file1, err2 := Open(dir, O_RDONLY, 0);
 	if err2 != nil {
 		t.Fatalf("open %q failed: %v", dir, err2);
 	}
-	small := smallReaddirnames(fd1, len(all)+100, t);	// +100 in case we screw up
+	small := smallReaddirnames(file1, len(all)+100, t);	// +100 in case we screw up
 	for i, n := range all {
 		if small[i] != n {
 			t.Errorf("small read %q %q mismatch: %v", small[i], n);
diff --git a/src/lib/strconv/fp_test.go b/src/lib/strconv/fp_test.go
index 7bc85a3..33491fa 100644
--- a/src/lib/strconv/fp_test.go
+++ b/src/lib/strconv/fp_test.go
@@ -94,12 +94,13 @@
 }
 
 func TestFp(t *testing.T) {
-	fd, err := os.Open("testfp.txt", os.O_RDONLY, 0);
+	f, err := os.Open("testfp.txt", os.O_RDONLY, 0);
 	if err != nil {
 		panicln("testfp: open testfp.txt:", err.String());
 	}
+	defer f.Close();
 
-	b := bufio.NewBufRead(fd);
+	b := bufio.NewBufRead(f);
 
 	lineno := 0;
 	for {
diff --git a/src/lib/time/zoneinfo.go b/src/lib/time/zoneinfo.go
index 62f8649..8790f0e 100644
--- a/src/lib/time/zoneinfo.go
+++ b/src/lib/time/zoneinfo.go
@@ -204,13 +204,13 @@
 }
 
 func readfile(name string, max int) (p []byte, err *os.Error) {
-	fd, e := os.Open(name, os.O_RDONLY, 0);
+	f, e := os.Open(name, os.O_RDONLY, 0);
 	if e != nil {
 		return nil, e;
 	}
 	p = make([]byte, max);
-	n, err1 := io.Readn(fd, p);
-	fd.Close();
+	n, err1 := io.Readn(f, p);
+	f.Close();
 	if err1 == nil {	// too long
 		return nil, badZoneinfo;
 	}