Skip to content

Commit

Permalink
os: test that copying to append-only files doesn't fail on Linux
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
tklauser authored and gopherbot committed Aug 9, 2023
1 parent 6c5fc6d commit e6637f3
Showing 1 changed file with 56 additions and 0 deletions.
56 changes: 56 additions & 0 deletions src/os/os_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
}

0 comments on commit e6637f3

Please sign in to comment.