Commit f7e92c59 authored by Russ Cox's avatar Russ Cox

os.File.ReadAt/WriteAt

R=r
DELTA=84  (81 added, 0 deleted, 3 changed)
OCL=34006
CL=34006
parent 185ae4f9
......@@ -115,7 +115,7 @@ var EOF Error = eofError(0)
// It returns the number of bytes read and an Error, if any.
// EOF is signaled by a zero count with err set to EOF.
// TODO(r): Add Pread, Pwrite (maybe ReadAt, WriteAt).
func (file *File) Read(b []byte) (ret int, err Error) {
func (file *File) Read(b []byte) (n int, err Error) {
if file == nil {
return 0, EINVAL
}
......@@ -132,10 +132,31 @@ func (file *File) Read(b []byte) (ret int, err Error) {
return n, err
}
// ReadAt reads len(b) bytes from the File starting at byte offset off.
// It returns the number of bytes read and the Error, if any.
// EOF is signaled by a zero count with err set to EOF.
// ReadAt always returns a non-nil Error when n != len(b).
func (file *File) ReadAt(b []byte, off int64) (n int, err Error) {
if file == nil {
return 0, EINVAL;
}
for len(b) > 0 {
m, e := syscall.Pread(file.fd, b, off);
n += m;
if e != 0 {
err = &PathError{"read", file.name, Errno(e)};
break;
}
b = b[m:len(b)];
off += int64(m);
}
return;
}
// Write writes len(b) bytes to the File.
// It returns the number of bytes written and an Error, if any.
// If the byte count differs from len(b), it usually implies an error occurred.
func (file *File) Write(b []byte) (ret int, err Error) {
// Write returns a non-nil Error when n != len(b).
func (file *File) Write(b []byte) (n int, err Error) {
if file == nil {
return 0, EINVAL
}
......@@ -157,6 +178,26 @@ func (file *File) Write(b []byte) (ret int, err Error) {
return n, err
}
// WriteAt writes len(b) bytes to the File starting at byte offset off.
// It returns the number of bytes written and an Error, if any.
// WriteAt returns a non-nil Error when n != len(b).
func (file *File) WriteAt(b []byte, off int64) (n int, err Error) {
if file == nil {
return 0, EINVAL;
}
for len(b) > 0 {
m, e := syscall.Pwrite(file.fd, b, off);
n += m;
if e != 0 {
err = &PathError{"write", file.name, Errno(e)};
break;
}
b = b[m:len(b)];
off += int64(m);
}
return;
}
// Seek sets the offset for the next Read or Write on file to offset, interpreted
// according to whence: 0 means relative to the origin of the file, 1 means
// relative to the current offset, and 2 means relative to the end.
......
......@@ -628,3 +628,43 @@ func TestHostname(t *testing.T) {
t.Errorf("Hostname() = %q, want %q", hostname, want);
}
}
func TestReadAt(t *testing.T) {
f, err := Open("_obj/readtest", O_CREAT|O_RDWR|O_TRUNC, 0666);
if err != nil {
t.Fatalf("open _obj/readtest: %s", err);
}
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, %r", n, err);
}
if string(b) != "world" {
t.Fatalf("ReadAt 7: have %q want %q", string(b), "world");
}
}
func TestWriteAt(t *testing.T) {
f, err := Open("_obj/writetest", O_CREAT|O_RDWR|O_TRUNC, 0666);
if err != nil {
t.Fatalf("open _obj/writetest: %s", err);
}
const data = "hello, world\n";
io.WriteString(f, data);
n, err := f.WriteAt(strings.Bytes("WORLD"), 7);
if err != nil || n != 5 {
t.Fatalf("WriteAt 7: %d, %v", n, err);
}
b, err := io.ReadFile("_obj/writetest");
if err != nil {
t.Fatalf("ReadFile _obj/writetest: %v", err);
}
if string(b) != "hello, WORLD\n" {
t.Fatalf("after write: have %q want %q", string(b), "hello, WORLD\n");
}
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment