os, syscall: implement ReadAt for unix
Windows will take more work, so test is skipped there.
Этот коммит содержится в:
родитель
47db50b273
коммит
f79f6b0e62
7 изменённых файлов: 102 добавлений и 3 удалений
|
@ -107,8 +107,15 @@ func (f *File) Read(b []byte) (n int, err error) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *File) ReadAt(b []byte, off int64) (n int, err error) {
|
// ReadAt reads up to len(b) bytes from the File at the given absolute offset.
|
||||||
return 0, ErrNotImplemented
|
// It returns the number of bytes read and any error encountered, possible io.EOF.
|
||||||
|
// At end of file, Read returns 0, io.EOF.
|
||||||
|
func (f *File) ReadAt(b []byte, offset int64) (n int, err error) {
|
||||||
|
n, err = f.handle.ReadAt(b, offset)
|
||||||
|
if err != nil && err != io.EOF {
|
||||||
|
err = &PathError{"readat", f.name, err}
|
||||||
|
}
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write writes len(b) bytes to the File. It returns the number of bytes written
|
// Write writes len(b) bytes to the File. It returns the number of bytes written
|
||||||
|
|
|
@ -27,6 +27,10 @@ func (f stdioFileHandle) Read(b []byte) (n int, err error) {
|
||||||
return 0, ErrUnsupported
|
return 0, ErrUnsupported
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (f stdioFileHandle) ReadAt(b []byte, off int64) (n int, err error) {
|
||||||
|
return 0, ErrNotImplemented
|
||||||
|
}
|
||||||
|
|
||||||
// Write writes len(b) bytes to the output. It returns the number of bytes
|
// Write writes len(b) bytes to the output. It returns the number of bytes
|
||||||
// written or an error if this file is not stdout or stderr.
|
// written or an error if this file is not stdout or stderr.
|
||||||
func (f stdioFileHandle) Write(b []byte) (n int, err error) {
|
func (f stdioFileHandle) Write(b []byte) (n int, err error) {
|
||||||
|
|
|
@ -2,7 +2,10 @@
|
||||||
|
|
||||||
package os
|
package os
|
||||||
|
|
||||||
import "syscall"
|
import (
|
||||||
|
"io"
|
||||||
|
"syscall"
|
||||||
|
)
|
||||||
|
|
||||||
type syscallFd = int
|
type syscallFd = int
|
||||||
|
|
||||||
|
@ -22,3 +25,16 @@ func Pipe() (r *File, w *File, err error) {
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ReadAt reads up to len(b) bytes from the File starting at the given absolute offset.
|
||||||
|
// It returns the number of bytes read and any error encountered, possibly io.EOF.
|
||||||
|
// At end of file, Pread returns 0, io.EOF.
|
||||||
|
// TODO: move to file_anyos once ReadAt is implemented for windows
|
||||||
|
func (f unixFileHandle) ReadAt(b []byte, offset int64) (n int, err error) {
|
||||||
|
n, err = syscall.Pread(syscallFd(f), b, offset)
|
||||||
|
err = handleSyscallError(err)
|
||||||
|
if n == 0 && err == nil {
|
||||||
|
err = io.EOF
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
|
@ -22,3 +22,11 @@ func Pipe() (r *File, w *File, err error) {
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ReadAt reads up to len(b) bytes from the File starting at the given absolute offset.
|
||||||
|
// It returns the number of bytes read and any error encountered, possibly io.EOF.
|
||||||
|
// At end of file, Pread returns 0, io.EOF.
|
||||||
|
// TODO: move to file_anyos once ReadAt is implemented for windows
|
||||||
|
func (f unixFileHandle) ReadAt(b []byte, offset int64) (n int, err error) {
|
||||||
|
return -1, ErrNotImplemented
|
||||||
|
}
|
||||||
|
|
|
@ -46,6 +46,9 @@ type FileHandle interface {
|
||||||
// Read reads up to len(b) bytes from the file.
|
// Read reads up to len(b) bytes from the file.
|
||||||
Read(b []byte) (n int, err error)
|
Read(b []byte) (n int, err error)
|
||||||
|
|
||||||
|
// ReadAt reads up to len(b) bytes from the file starting at the given absolute offset
|
||||||
|
ReadAt(b []byte, offset int64) (n int, err error)
|
||||||
|
|
||||||
// Write writes up to len(b) bytes to the file.
|
// Write writes up to len(b) bytes to the file.
|
||||||
Write(b []byte) (n int, err error)
|
Write(b []byte) (n int, err error)
|
||||||
|
|
||||||
|
|
48
src/os/os_test.go
Обычный файл
48
src/os/os_test.go
Обычный файл
|
@ -0,0 +1,48 @@
|
||||||
|
// Copyright 2009 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package os_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
. "os"
|
||||||
|
"runtime"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
// localTmp returns a local temporary directory not on NFS.
|
||||||
|
func localTmp() string {
|
||||||
|
return TempDir()
|
||||||
|
}
|
||||||
|
|
||||||
|
func newFile(testName string, t *testing.T) (f *File) {
|
||||||
|
// TODO: use CreateTemp when it lands
|
||||||
|
f, err := OpenFile(TempDir()+"/_Go_"+testName, O_RDWR|O_CREATE, 0644)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("TempFile %s: %s", testName, err)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestReadAt(t *testing.T) {
|
||||||
|
if runtime.GOOS == "windows" {
|
||||||
|
t.Log("TODO: implement Pread for Windows")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
f := newFile("TestReadAt", t)
|
||||||
|
defer Remove(f.Name())
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
const data = "hello, world\n"
|
||||||
|
io.WriteString(f, data)
|
||||||
|
|
||||||
|
b := make([]byte, 5)
|
||||||
|
n, err := f.ReadAt(b, 7)
|
||||||
|
if err != nil || n != len(b) {
|
||||||
|
t.Fatalf("ReadAt 7: %d, %v", n, err)
|
||||||
|
}
|
||||||
|
if string(b) != "world" {
|
||||||
|
t.Fatalf("ReadAt 7: have %q want %q", string(b), "world")
|
||||||
|
}
|
||||||
|
}
|
|
@ -37,6 +37,15 @@ func Read(fd int, p []byte) (n int, err error) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Pread(fd int, p []byte, offset int64) (n int, err error) {
|
||||||
|
buf, count := splitSlice(p)
|
||||||
|
n = libc_pread(int32(fd), buf, uint(count), offset)
|
||||||
|
if n < 0 {
|
||||||
|
err = getErrno()
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
func Seek(fd int, offset int64, whence int) (off int64, err error) {
|
func Seek(fd int, offset int64, whence int) (off int64, err error) {
|
||||||
return 0, ENOSYS // TODO
|
return 0, ENOSYS // TODO
|
||||||
}
|
}
|
||||||
|
@ -169,6 +178,10 @@ func libc_getenv(name *byte) *byte
|
||||||
//export read
|
//export read
|
||||||
func libc_read(fd int32, buf *byte, count uint) int
|
func libc_read(fd int32, buf *byte, count uint) int
|
||||||
|
|
||||||
|
// ssize_t pread(int fd, void *buf, size_t count, off_t offset);
|
||||||
|
//export pread
|
||||||
|
func libc_pread(fd int32, buf *byte, count uint, offset int64) int
|
||||||
|
|
||||||
// int open(const char *pathname, int flags, mode_t mode);
|
// int open(const char *pathname, int flags, mode_t mode);
|
||||||
//export open
|
//export open
|
||||||
func libc_open(pathname *byte, flags int32, mode uint32) int32
|
func libc_open(pathname *byte, flags int32, mode uint32) int32
|
||||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче