1
0
mirror of https://github.com/golang/go synced 2024-11-26 05:27:57 -07:00

os: make Readdir work as documented

Readdir's result should never contain a nil.

Fixes #5960.

R=golang-dev, rsc, bradfitz
CC=golang-dev
https://golang.org/cl/12261043
This commit is contained in:
Pieter Droogendijk 2013-08-08 10:44:01 -07:00 committed by Brad Fitzpatrick
parent 547f1a6fe7
commit bdbd5418f4
3 changed files with 48 additions and 4 deletions

View File

@ -7,3 +7,4 @@ package os
// Export for testing. // Export for testing.
var Atime = atime var Atime = atime
var LstatP = &lstat

View File

@ -149,6 +149,9 @@ func Lstat(name string) (fi FileInfo, err error) {
return fileInfoFromStat(&stat, name), nil return fileInfoFromStat(&stat, name), nil
} }
// lstat is overridden in tests.
var lstat = Lstat
func (f *File) readdir(n int) (fi []FileInfo, err error) { func (f *File) readdir(n int) (fi []FileInfo, err error) {
dirname := f.name dirname := f.name
if dirname == "" { if dirname == "" {
@ -158,12 +161,14 @@ func (f *File) readdir(n int) (fi []FileInfo, err error) {
names, err := f.Readdirnames(n) names, err := f.Readdirnames(n)
fi = make([]FileInfo, len(names)) fi = make([]FileInfo, len(names))
for i, filename := range names { for i, filename := range names {
fip, lerr := Lstat(dirname + filename) fip, lerr := lstat(dirname + filename)
if err == nil { if lerr == nil {
fi[i] = fip fi[i] = fip
err = lerr
} else { } else {
fi[i] = &fileStat{name: filename} fi[i] = &fileStat{name: filename}
if err == nil {
err = lerr
}
} }
} }
return fi, err return fi, err

View File

@ -28,7 +28,7 @@ func checkUidGid(t *testing.T, path string, uid, gid int) {
} }
func TestChown(t *testing.T) { func TestChown(t *testing.T) {
// Chown is not supported under windows or Plan 9. // Chown is not supported under windows os Plan 9.
// Plan9 provides a native ChownPlan9 version instead. // Plan9 provides a native ChownPlan9 version instead.
if runtime.GOOS == "windows" || runtime.GOOS == "plan9" { if runtime.GOOS == "windows" || runtime.GOOS == "plan9" {
return return
@ -74,3 +74,41 @@ func TestChown(t *testing.T) {
checkUidGid(t, f.Name(), int(sys.Uid), gid) checkUidGid(t, f.Name(), int(sys.Uid), gid)
} }
} }
func TestReaddirWithBadLstat(t *testing.T) {
handle, err := Open(sfdir)
failfile := sfdir + "/" + sfname
if err != nil {
t.Fatalf("Couldn't open %s: %s", sfdir, err)
}
*LstatP = func(file string) (FileInfo, error) {
if file == failfile {
var fi FileInfo
return fi, ErrInvalid
}
return Lstat(file)
}
defer func() { *LstatP = Lstat }()
dirs, err := handle.Readdir(-1)
if err != ErrInvalid {
t.Fatalf("Expected Readdir to return ErrInvalid, got %v", err)
}
foundfail := false
for _, dir := range dirs {
if dir.Name() == sfname {
foundfail = true
if dir.Sys() != nil {
t.Errorf("Expected Readdir for %s should not contain Sys", failfile)
}
} else {
if dir.Sys() == nil {
t.Errorf("Readdir for every file other than %s should contain Sys, but %s/%s didn't either", failfile, sfdir, dir.Name())
}
}
}
if !foundfail {
t.Fatalf("Expected %s from Readdir, but didn't find it", failfile)
}
}