d.dir = 0
}
-func (f *File) seekInvalidate() {
- if f.dirinfo == nil {
- return
- }
- // Free cached dirinfo, so we allocate a new one if we
- // access this file as a directory again. See #35767.
- f.dirinfo.close()
- f.dirinfo = nil
-}
-
func (f *File) readdirnames(n int) (names []string, err error) {
if f.dirinfo == nil {
dir, call, errno := f.pfd.OpenDir()
func (d *dirInfo) close() {}
-func (f *File) seekInvalidate() {}
-
func (f *File) readdirnames(n int) (names []string, err error) {
// If this file has no dirinfo, create one.
if f.dirinfo == nil {
// relative to the current offset, and 2 means relative to the end.
// It returns the new offset and an error, if any.
func (f *File) seek(offset int64, whence int) (ret int64, err error) {
- f.seekInvalidate()
+ if f.dirinfo != nil {
+ // Free cached dirinfo, so we allocate a new one if we
+ // access this file as a directory again. See #35767 and #37161.
+ f.dirinfo.close()
+ f.dirinfo = nil
+ }
ret, err = f.pfd.Seek(offset, whence)
runtime.KeepAlive(f)
return ret, err
}
}
}
+
+func TestReaddirSmallSeek(t *testing.T) {
+ // See issue 37161. Read only one entry from a directory,
+ // seek to the beginning, and read again. We should not see
+ // duplicate entries.
+ if runtime.GOOS == "windows" {
+ testenv.SkipFlaky(t, 36019)
+ }
+ wd, err := Getwd()
+ if err != nil {
+ t.Fatal(err)
+ }
+ df, err := Open(filepath.Join(wd, "testdata", "issue37161"))
+ if err != nil {
+ t.Fatal(err)
+ }
+ names1, err := df.Readdirnames(1)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if _, err = df.Seek(0, 0); err != nil {
+ t.Fatal(err)
+ }
+ names2, err := df.Readdirnames(0)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if len(names2) != 3 {
+ t.Fatalf("first names: %v, second names: %v", names1, names2)
+ }
+}