mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
syscall: make Seek use SetFilePointerEx on Windows, allowing large seek offsets
Fixes #21681 Updates #21728 Change-Id: I79cf4564c1355ecab891102d4215cbbffd8eb0ce Reviewed-on: https://go-review.googlesource.com/82535 Reviewed-by: Ian Lance Taylor <iant@golang.org>
This commit is contained in:
parent
9ce6b5c2ed
commit
7c46b62d0a
2 changed files with 39 additions and 11 deletions
|
|
@ -1362,14 +1362,26 @@ func TestSeek(t *testing.T) {
|
||||||
{-1, io.SeekEnd, int64(len(data)) - 1},
|
{-1, io.SeekEnd, int64(len(data)) - 1},
|
||||||
{1 << 33, io.SeekStart, 1 << 33},
|
{1 << 33, io.SeekStart, 1 << 33},
|
||||||
{1 << 33, io.SeekEnd, 1<<33 + int64(len(data))},
|
{1 << 33, io.SeekEnd, 1<<33 + int64(len(data))},
|
||||||
|
|
||||||
|
// Issue 21681, Windows 4G-1, etc:
|
||||||
|
{1<<32 - 1, io.SeekStart, 1<<32 - 1},
|
||||||
|
{0, io.SeekCurrent, 1<<32 - 1},
|
||||||
|
{2<<32 - 1, io.SeekStart, 2<<32 - 1},
|
||||||
|
{0, io.SeekCurrent, 2<<32 - 1},
|
||||||
}
|
}
|
||||||
for i, tt := range tests {
|
for i, tt := range tests {
|
||||||
|
if runtime.GOOS == "nacl" && tt.out > 1<<30 {
|
||||||
|
t.Logf("skipping test case #%d on nacl; https://golang.org/issue/21728", i)
|
||||||
|
continue
|
||||||
|
}
|
||||||
off, err := f.Seek(tt.in, tt.whence)
|
off, err := f.Seek(tt.in, tt.whence)
|
||||||
if off != tt.out || err != nil {
|
if off != tt.out || err != nil {
|
||||||
if e, ok := err.(*PathError); ok && e.Err == syscall.EINVAL && tt.out > 1<<32 {
|
if e, ok := err.(*PathError); ok && e.Err == syscall.EINVAL && tt.out > 1<<32 && runtime.GOOS == "linux" {
|
||||||
|
mounts, _ := ioutil.ReadFile("/proc/mounts")
|
||||||
|
if strings.Contains(string(mounts), "reiserfs") {
|
||||||
// Reiserfs rejects the big seeks.
|
// Reiserfs rejects the big seeks.
|
||||||
// https://golang.org/issue/91
|
t.Skipf("skipping test known to fail on reiserfs; https://golang.org/issue/91")
|
||||||
break
|
}
|
||||||
}
|
}
|
||||||
t.Errorf("#%d: Seek(%v, %v) = %v, %v want %v, nil", i, tt.in, tt.whence, off, err, tt.out)
|
t.Errorf("#%d: Seek(%v, %v) = %v, %v want %v, nil", i, tt.in, tt.whence, off, err, tt.out)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -332,6 +332,27 @@ func Write(fd Handle, p []byte) (n int, err error) {
|
||||||
|
|
||||||
var ioSync int64
|
var ioSync int64
|
||||||
|
|
||||||
|
var procSetFilePointerEx = modkernel32.NewProc("SetFilePointerEx")
|
||||||
|
|
||||||
|
const ptrSize = unsafe.Sizeof(uintptr(0))
|
||||||
|
|
||||||
|
// setFilePointerEx calls SetFilePointerEx.
|
||||||
|
// See https://msdn.microsoft.com/en-us/library/windows/desktop/aa365542(v=vs.85).aspx
|
||||||
|
func setFilePointerEx(handle Handle, distToMove int64, newFilePointer *int64, whence uint32) error {
|
||||||
|
var e1 Errno
|
||||||
|
if ptrSize == 8 {
|
||||||
|
_, _, e1 = Syscall6(procSetFilePointerEx.Addr(), 4, uintptr(handle), uintptr(distToMove), uintptr(unsafe.Pointer(newFilePointer)), uintptr(whence), 0, 0)
|
||||||
|
} else {
|
||||||
|
// distToMove is a LARGE_INTEGER:
|
||||||
|
// https://msdn.microsoft.com/en-us/library/windows/desktop/aa383713(v=vs.85).aspx
|
||||||
|
_, _, e1 = Syscall6(procSetFilePointerEx.Addr(), 5, uintptr(handle), uintptr(distToMove), uintptr(distToMove>>32), uintptr(unsafe.Pointer(newFilePointer)), uintptr(whence), 0)
|
||||||
|
}
|
||||||
|
if e1 != 0 {
|
||||||
|
return errnoErr(e1)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func Seek(fd Handle, offset int64, whence int) (newoffset int64, err error) {
|
func Seek(fd Handle, offset int64, whence int) (newoffset int64, err error) {
|
||||||
var w uint32
|
var w uint32
|
||||||
switch whence {
|
switch whence {
|
||||||
|
|
@ -342,18 +363,13 @@ func Seek(fd Handle, offset int64, whence int) (newoffset int64, err error) {
|
||||||
case 2:
|
case 2:
|
||||||
w = FILE_END
|
w = FILE_END
|
||||||
}
|
}
|
||||||
hi := int32(offset >> 32)
|
|
||||||
lo := int32(offset)
|
|
||||||
// use GetFileType to check pipe, pipe can't do seek
|
// use GetFileType to check pipe, pipe can't do seek
|
||||||
ft, _ := GetFileType(fd)
|
ft, _ := GetFileType(fd)
|
||||||
if ft == FILE_TYPE_PIPE {
|
if ft == FILE_TYPE_PIPE {
|
||||||
return 0, ESPIPE
|
return 0, ESPIPE
|
||||||
}
|
}
|
||||||
rlo, e := SetFilePointer(fd, lo, &hi, w)
|
err = setFilePointerEx(fd, offset, &newoffset, w)
|
||||||
if e != nil {
|
return
|
||||||
return 0, e
|
|
||||||
}
|
|
||||||
return int64(hi)<<32 + int64(rlo), nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func Close(fd Handle) (err error) {
|
func Close(fd Handle) (err error) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue