{-1, io.SeekEnd, int64(len(data)) - 1},
{1 << 33, io.SeekStart, 1 << 33},
{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 {
+ 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)
if off != tt.out || err != nil {
- if e, ok := err.(*PathError); ok && e.Err == syscall.EINVAL && tt.out > 1<<32 {
- // Reiserfs rejects the big seeks.
- // https://golang.org/issue/91
- break
+ 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.
+ t.Skipf("skipping test known to fail on reiserfs; https://golang.org/issue/91")
+ }
}
t.Errorf("#%d: Seek(%v, %v) = %v, %v want %v, nil", i, tt.in, tt.whence, off, err, tt.out)
}
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) {
var w uint32
switch whence {
case 2:
w = FILE_END
}
- hi := int32(offset >> 32)
- lo := int32(offset)
// use GetFileType to check pipe, pipe can't do seek
ft, _ := GetFileType(fd)
if ft == FILE_TYPE_PIPE {
return 0, ESPIPE
}
- rlo, e := SetFilePointer(fd, lo, &hi, w)
- if e != nil {
- return 0, e
- }
- return int64(hi)<<32 + int64(rlo), nil
+ err = setFilePointerEx(fd, offset, &newoffset, w)
+ return
}
func Close(fd Handle) (err error) {