blob: 19018de029e393c4f56ff9d2d0bb612814484e62 [file] [log] [blame]
// Copyright 2016 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.
// +build fuchsia
package fdio
import (
"unsafe"
"syscall/zx"
)
type VMOFile struct {
h zx.VMO
off int64
len int64
end int64
at int64
}
func NewVMOFile(handle zx.Handle, extra []byte) (*VMOFile, error) {
// fdio_vmofile_create
f := &VMOFile{
h: zx.VMO(handle),
off: *(*int64)(unsafe.Pointer(&extra[0:8][0])),
len: *(*int64)(unsafe.Pointer(&extra[8:16][0])),
}
f.end = f.off + f.len
f.at = f.off
return f, nil
}
func (f *VMOFile) Read(data []byte) (n int, err error) {
if int64(len(data)) > f.end-f.at {
data = data[:f.end-f.at]
err = zx.EOF
}
if len(data) == 0 {
return 0, err
}
n, err = f.h.Read(data, uint64(f.at))
f.at += int64(n)
return n, err
}
func (f *VMOFile) ReadAt(data []byte, off int64) (n int, err error) {
if off < 0 {
return 0, zx.Error{Status: zx.ErrInvalidArgs, Text: "fdio.VMOFile.ReadAt"}
}
if off >= f.end {
return 0, zx.EOF
}
if len(data) == 0 {
return 0, zx.EOF
}
n = len(data)
max := int(f.end - off)
if max < n {
n = max
err = zx.EOF
}
data = data[:n]
if n2, err2 := f.h.Read(data, uint64(off)); err2 != nil {
return n2, err2
}
return
}
func (f *VMOFile) Write(data []byte) (int, error) {
return 0, zx.Error{Status: zx.ErrNotSupported, Text: "rio.VMOFile"}
}
func (f *VMOFile) WriteAt(data []byte, off int64) (int, error) {
return 0, zx.Error{Status: zx.ErrNotSupported, Text: "rio.VMOFile"}
}
func (f *VMOFile) Seek(offset int64, whence int) (int64, error) {
var at int64
switch whence {
case 0: // SEEK_SET
at = offset
case 1: // SEEK_CUR
at = f.at - f.off + offset
case 2: // SEEK_END
at = f.end - f.off + offset
}
if at > f.end-f.off {
return 0, zx.Error{Status: zx.ErrOutOfRange, Text: "rio.VMOFile"}
}
f.at = f.off + at
return at, nil
}
func (f *VMOFile) Close() error {
if err := f.h.Close(); err != nil {
return err
}
f.h = 0
return nil
}
func (f *VMOFile) Open(path string, flags int32, mode uint32) (FDIO, error) {
return nil, zx.Error{Status: zx.ErrNotSupported, Text: "rio.VMOFile"}
}
func (f *VMOFile) Clone() ([]zx.Handle, error) {
return nil, zx.Error{Status: zx.ErrNotSupported, Text: "rio.VMOFile"}
}
func (f *VMOFile) Ioctl(op uint32, in, out []byte) ([]zx.Handle, error) {
return nil, zx.Error{Status: zx.ErrNotSupported, Text: "rio.VMOFile"}
}
func (f *VMOFile) IoctlSetHandle(op uint32, in zx.Handle) error {
return zx.Error{Status: zx.ErrNotSupported, Text: "rio.VMOFile"}
}
func (f *VMOFile) Misc(op uint32, off int64, in, out []byte, handles []zx.Handle) (n int, err error) {
for _, h := range handles {
h.Close()
}
switch op {
case OpStat:
attr := Vnattr{
Size: uint64(f.end - f.off),
Mode: VtypeFile | VtypeIRUSR,
}
if unsafe.Sizeof(attr) > uintptr(len(out)) {
return 0, zx.Error{Status: zx.ErrInvalidArgs, Text: "rio.VMOFile"}
}
*(*Vnattr)(unsafe.Pointer(&out[0])) = attr
return int(unsafe.Sizeof(attr)), nil
default:
return 0, zx.Error{Status: zx.ErrInvalidArgs, Text: "rio.VMOFile"}
}
}