aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFazlul Shahriar <fshahriar@gmail.com>2011-04-12 16:58:56 -0700
committerRob Pike <r@golang.org>2011-04-12 16:58:56 -0700
commit08b092777168a3377067531307ffd20dd85becba (patch)
tree3ebe0aaa6319bd72bb693ccd6a2afd2103f8c847
parent36b6d1aaf20fa78532f83df48ebf1a12a2dd81af (diff)
downloadgo-08b092777168a3377067531307ffd20dd85becba.tar.gz
go-08b092777168a3377067531307ffd20dd85becba.zip
os: fix Readdir in Plan 9
'TestReaddir.*' tests now passes. R=golang-dev, lucio, r CC=golang-dev https://golang.org/cl/4381048
-rw-r--r--src/pkg/os/dir_plan9.go80
-rw-r--r--src/pkg/os/error_plan9.go3
-rw-r--r--src/pkg/os/file_plan9.go7
-rw-r--r--src/pkg/os/os_test.go16
4 files changed, 57 insertions, 49 deletions
diff --git a/src/pkg/os/dir_plan9.go b/src/pkg/os/dir_plan9.go
index 7bb0642e47..a53c764e38 100644
--- a/src/pkg/os/dir_plan9.go
+++ b/src/pkg/os/dir_plan9.go
@@ -8,72 +8,56 @@ import (
"syscall"
)
-type dirInfo int
-
-var markDirectory dirInfo = ^0
-
// Readdir reads the contents of the directory associated with file and
-// returns an array of up to count FileInfo structures, as would be returned
-// by Lstat, in directory order. Subsequent calls on the same file will yield
-// further FileInfos. A negative count means to read the entire directory.
+// returns an array of up to count FileInfo structures, in directory order.
+// Subsequent calls on the same file will yield further FileInfos.
+// A negative count means to read until EOF.
// Readdir returns the array and an Error, if any.
func (file *File) Readdir(count int) (fi []FileInfo, err Error) {
// If this file has no dirinfo, create one.
if file.dirinfo == nil {
- file.dirinfo = &markDirectory
+ file.dirinfo = new(dirInfo)
}
-
+ d := file.dirinfo
size := count
if size < 0 {
size = 100
}
-
- result := make([]FileInfo, 0, size)
- var buf [syscall.STATMAX]byte
-
- for {
- n, e := file.Read(buf[:])
-
- if e != nil {
+ result := make([]FileInfo, 0, size) // Empty with room to grow.
+ for count != 0 {
+ // Refill the buffer if necessary
+ if d.bufp >= d.nbuf {
+ d.bufp = 0
+ var e Error
+ d.nbuf, e = file.Read(d.buf[:])
+ if e != nil && e != EOF {
+ return nil, &PathError{"readdir", file.name, e}
+ }
if e == EOF {
break
}
-
- return []FileInfo{}, &PathError{"readdir", file.name, e}
+ if d.nbuf < syscall.STATFIXLEN {
+ return nil, &PathError{"readdir", file.name, Eshortstat}
+ }
}
- if n < syscall.STATFIXLEN {
- return []FileInfo{}, &PathError{"readdir", file.name, Eshortstat}
+ // Get a record from buffer
+ m, _ := gbit16(d.buf[d.bufp:])
+ m += 2
+ if m < syscall.STATFIXLEN {
+ return nil, &PathError{"readdir", file.name, Eshortstat}
}
-
- for i := 0; i < n; {
- m, _ := gbit16(buf[i:])
- m += 2
-
- if m < syscall.STATFIXLEN {
- return []FileInfo{}, &PathError{"readdir", file.name, Eshortstat}
- }
-
- d, e := UnmarshalDir(buf[i : i+int(m)])
-
- if e != nil {
- return []FileInfo{}, &PathError{"readdir", file.name, e}
- }
-
- var f FileInfo
- fileInfoFromStat(&f, d)
-
- result = append(result, f)
-
- // a negative count means to read until EOF.
- if count > 0 && len(result) >= count {
- break
- }
-
- i += int(m)
+ dir, e := UnmarshalDir(d.buf[d.bufp : d.bufp+int(m)])
+ if e != nil {
+ return nil, &PathError{"readdir", file.name, e}
}
- }
+ var f FileInfo
+ fileInfoFromStat(&f, dir)
+ result = append(result, f)
+ d.bufp += int(m)
+ count--
+ }
return result, nil
}
diff --git a/src/pkg/os/error_plan9.go b/src/pkg/os/error_plan9.go
index d6575864e8..3374775b8e 100644
--- a/src/pkg/os/error_plan9.go
+++ b/src/pkg/os/error_plan9.go
@@ -37,12 +37,15 @@ var (
Enonexist = NewError("file does not exist")
Eexist = NewError("file already exists")
Eio = NewError("i/o error")
+ Eperm = NewError("permission denied")
EINVAL = Ebadarg
ENOTDIR = Enotdir
ENOENT = Enonexist
EEXIST = Eexist
EIO = Eio
+ EACCES = Eperm
+ EISDIR = syscall.EISDIR
ENAMETOOLONG = NewError("file name too long")
ERANGE = NewError("math result not representable")
diff --git a/src/pkg/os/file_plan9.go b/src/pkg/os/file_plan9.go
index b79256c51e..c8d0efba40 100644
--- a/src/pkg/os/file_plan9.go
+++ b/src/pkg/os/file_plan9.go
@@ -9,6 +9,13 @@ import (
"syscall"
)
+// Auxiliary information if the File describes a directory
+type dirInfo struct {
+ buf [syscall.STATMAX]byte // buffer for directory I/O
+ nbuf int // length of buf; return value from Read
+ bufp int // location of next record in buf.
+}
+
func epipecheck(file *File, e syscall.Error) {
}
diff --git a/src/pkg/os/os_test.go b/src/pkg/os/os_test.go
index 71ea45ec7f..551b865085 100644
--- a/src/pkg/os/os_test.go
+++ b/src/pkg/os/os_test.go
@@ -45,6 +45,14 @@ var sysdir = func() (sd *sysDir) {
"services",
},
}
+ case "plan9":
+ sd = &sysDir{
+ "/lib/ndb",
+ []string{
+ "common",
+ "local",
+ },
+ }
default:
sd = &sysDir{
"/etc",
@@ -245,8 +253,11 @@ func smallReaddirnames(file *File, length int, t *testing.T) []string {
func TestReaddirnamesOneAtATime(t *testing.T) {
// big directory that doesn't change often.
dir := "/usr/bin"
- if syscall.OS == "windows" {
+ switch syscall.OS {
+ case "windows":
dir = Getenv("SystemRoot") + "\\system32"
+ case "plan9":
+ dir = "/bin"
}
file, err := Open(dir)
defer file.Close()
@@ -262,6 +273,9 @@ func TestReaddirnamesOneAtATime(t *testing.T) {
t.Fatalf("open %q failed: %v", dir, err2)
}
small := smallReaddirnames(file1, len(all)+100, t) // +100 in case we screw up
+ if len(small) < len(all) {
+ t.Fatalf("len(small) is %d, less than %d", len(small), len(all))
+ }
for i, n := range all {
if small[i] != n {
t.Errorf("small read %q mismatch: %v", small[i], n)