1
0
mirror of https://github.com/golang/go synced 2024-09-29 04:14:27 -06:00

syscall: in TestDirent, make as many ReadDirent calls as are needed

ReadDirent returns only as many directory entries as will fit in the
buffer, and each entry is variable-length — so we have no guarantee in
general that a buffer of a given arbitrary size can hold even one
entry, let alone all ten entries expected by the test.

Instead, iterate calls to ReadDirent until one of the calls returns
zero entries and no error, indicating that the directory has been read
to completion.

Fixes #37323

Change-Id: I7f1cedde7666107256604e4ea1ac13c71f22151a
Reviewed-on: https://go-review.googlesource.com/c/go/+/376334
Trust: Bryan Mills <bcmills@google.com>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Run-TryBot: Bryan Mills <bcmills@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
This commit is contained in:
Bryan C. Mills 2022-01-07 09:54:44 -05:00 committed by Bryan Mills
parent f1596d76f4
commit be26ca972d

View File

@ -22,7 +22,7 @@ import (
func TestDirent(t *testing.T) {
const (
direntBufSize = 2048
direntBufSize = 2048 // arbitrary? See https://go.dev/issue/37323.
filenameMinSize = 11
)
@ -37,23 +37,38 @@ func TestDirent(t *testing.T) {
}
}
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)