1
0
mirror of https://github.com/golang/go synced 2024-11-23 07:10:05 -07:00

os: test that copying to append-only files doesn't fail on Linux

Before CL 494915, this test would fail on Linux in io.Copy with error
"write /dev/stdout: copy_file_range: bad file descriptor" because the
copy_file_range syscall doesn't support destination files opened with
O_APPEND, see
https://man7.org/linux/man-pages/man2/copy_file_range.2.html#ERRORS

For #60181

Change-Id: I2eb4bcac71175121821e0033eb2297a2bc4ec759
Reviewed-on: https://go-review.googlesource.com/c/go/+/517755
Auto-Submit: Tobias Klauser <tobias.klauser@gmail.com>
Reviewed-by: Bryan Mills <bcmills@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
Run-TryBot: Tobias Klauser <tobias.klauser@gmail.com>
This commit is contained in:
Tobias Klauser 2023-08-09 16:51:10 +02:00 committed by Gopher Robot
parent 6c5fc6d7ce
commit e6637f3293

View File

@ -3270,3 +3270,59 @@ func TestPipeCloseRace(t *testing.T) {
t.Errorf("got nils %d errs %d, want 2 2", nils, errs)
}
}
// Test that copying to files opened with O_APPEND works and
// the copy_file_range syscall isn't used on Linux.
//
// Regression test for go.dev/issue/60181
func TestIssue60181(t *testing.T) {
defer chtmpdir(t)()
want := "hello gopher"
a, err := CreateTemp("", "a")
if err != nil {
t.Fatal(err)
}
a.WriteString(want[:5])
a.Close()
b, err := CreateTemp("", "b")
if err != nil {
t.Fatal(err)
}
b.WriteString(want[5:])
b.Close()
afd, err := syscall.Open(a.Name(), syscall.O_RDWR|syscall.O_APPEND, 0)
if err != nil {
t.Fatal(err)
}
bfd, err := syscall.Open(b.Name(), syscall.O_RDONLY, 0)
if err != nil {
t.Fatal(err)
}
aa := NewFile(uintptr(afd), a.Name())
defer aa.Close()
bb := NewFile(uintptr(bfd), b.Name())
defer bb.Close()
// This would fail on Linux in case the copy_file_range syscall was used because it doesn't
// support destination files opened with O_APPEND, see
// https://man7.org/linux/man-pages/man2/copy_file_range.2.html#ERRORS
_, err = io.Copy(aa, bb)
if err != nil {
t.Fatal(err)
}
buf, err := ReadFile(aa.Name())
if err != nil {
t.Fatal(err)
}
if got := string(buf); got != want {
t.Errorf("files not concatenated: got %q, want %q", got, want)
}
}