func TestDirent(t *testing.T) {
const (
- direntBufSize = 2048
+ direntBufSize = 2048 // arbitrary? See https://go.dev/issue/37323.
filenameMinSize = 11
)
}
}
- buf := bytes.Repeat([]byte("DEADBEAF"), direntBufSize/8)
+ names := make([]string, 0, 10)
+
fd, err := syscall.Open(d, syscall.O_RDONLY, 0)
if err != nil {
t.Fatalf("syscall.open: %v", err)
}
defer syscall.Close(fd)
- n, err := syscall.ReadDirent(fd, buf)
- if err != nil {
- t.Fatalf("syscall.readdir: %v", err)
- }
- buf = buf[:n]
- names := make([]string, 0, 10)
- for len(buf) > 0 {
- var bc int
- bc, _, names = syscall.ParseDirent(buf, -1, names)
- buf = buf[bc:]
+ buf := bytes.Repeat([]byte{0xCD}, direntBufSize)
+ for {
+ n, err := syscall.ReadDirent(fd, buf)
+ if err == syscall.EINVAL {
+ // On linux, 'man getdents64' says that EINVAL indicates “result buffer is too small”.
+ // Try a bigger buffer.
+ t.Logf("ReadDirent: %v; retrying with larger buffer", err)
+ buf = bytes.Repeat([]byte{0xCD}, len(buf)*2)
+ continue
+ }
+ if err != nil {
+ t.Fatalf("syscall.readdir: %v", err)
+ }
+ t.Logf("ReadDirent: read %d bytes", n)
+ if n == 0 {
+ break
+ }
+
+ var consumed, count int
+ consumed, count, names = syscall.ParseDirent(buf[:n], -1, names)
+ t.Logf("ParseDirent: %d new name(s)", count)
+ if consumed != n {
+ t.Fatalf("ParseDirent: consumed %d bytes; expected %d", consumed, n)
+ }
}
sort.Strings(names)