Fix Readdirnames to behave properly if reading in little pieces. Requires storing some
state in the FD.
This is Darwin only. Next CL will make Readdir use Readdirnames to generate its files
and move Readdir into portable code, as well as fix Readdirnames for Linux.
R=rsc
DELTA=116 (79 added, 12 deleted, 25 changed)
OCL=24756
CL=24768
diff --git a/src/lib/os/os_file.go b/src/lib/os/os_file.go
index 25b14d0..cd924bd 100644
--- a/src/lib/os/os_file.go
+++ b/src/lib/os/os_file.go
@@ -7,10 +7,18 @@
import syscall "syscall"
import os "os"
+// Auxiliary information if the FD 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.
+}
+
// FDs are wrappers for file descriptors
type FD struct {
fd int64;
name string;
+ dirinfo *DirInfo; // nil unless directory being read
}
func (fd *FD) Fd() int64 {
@@ -25,7 +33,7 @@
if fd < 0 {
return nil
}
- return &FD{fd, name}
+ return &FD{fd, name, nil}
}
var (
@@ -90,6 +98,17 @@
return int(r), ErrnoToError(e)
}
+func (fd *FD) Seek(offset int64, whence int) (ret int64, err *Error) {
+ r, e := syscall.Seek(fd.fd, offset, int64(whence));
+ if e != 0 {
+ return -1, ErrnoToError(e)
+ }
+ if fd.dirinfo != nil && r != 0 {
+ return -1, ErrnoToError(syscall.EISDIR)
+ }
+ return r, nil
+}
+
func (fd *FD) WriteString(s string) (ret int, err *Error) {
if fd == nil {
return 0, EINVAL