blob: 139a6424f48c557a189df9fd17401597a1703b7f [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 (
"syscall/zx"
"syscall/zx/io"
"syscall/zx/zxwait"
)
type Pipe struct {
s zx.Socket
}
func NewPipes() (*Pipe, *Pipe, error) {
s0, s1, err := zx.NewSocket(0)
if err != nil {
return nil, nil, err
}
return &Pipe{s0}, &Pipe{s1}, nil
}
func NewPipe(s zx.Socket) *Pipe {
return &Pipe{s}
}
func (f *Pipe) Wait(signals zx.Signals, timeout zx.Time) (observed zx.Signals, err error) {
return zxwait.Wait(zx.Handle(f.s), signals, timeout)
}
func (f *Pipe) Handles() []zx.Handle {
return []zx.Handle{zx.Handle(f.s)}
}
func (f *Pipe) Clone() (FDIO, error) {
h, err := f.s.Handle().Duplicate(zx.RightSameRights)
if err != nil {
return nil, err
}
return NewPipe(zx.Socket(h)), nil
}
func (f *Pipe) Close() error {
if err := f.s.Close(); err != nil {
return err
}
f.s = zx.Socket(zx.HandleInvalid)
return nil
}
func (f *Pipe) Sync() error {
return zx.Error{Status: zx.ErrNotSupported, Text: "fdio.Pipe"}
}
func (f *Pipe) GetAttr() (io.NodeAttributes, error) {
return io.NodeAttributes{}, zx.Error{Status: zx.ErrNotSupported, Text: "fdio.Pipe"}
}
func (f *Pipe) SetAttr(flags uint32, attr io.NodeAttributes) error {
return zx.Error{Status: zx.ErrNotSupported, Text: "fdio.Pipe"}
}
func (f *Pipe) Ioctl(op uint32, max uint64, in []byte, handles []zx.Handle) ([]byte, []zx.Handle, error) {
return nil, nil, zx.Error{Status: zx.ErrNotSupported, Text: "fdio.Pipe"}
}
func (f *Pipe) Read(data []byte) (n int, err error) {
for {
n, err = f.s.Read(data, 0)
if err == nil {
return n, nil
}
mxerr, ok := err.(zx.Error)
if !ok {
return n, err
}
switch mxerr.Status {
case zx.ErrPeerClosed:
return 0, zx.EOF
case zx.ErrShouldWait:
pending, err := f.Wait(zx.SignalSocketReadable|zx.SignalSocketPeerClosed, zx.TimensecInfinite)
if err != nil {
return 0, err
}
if pending&zx.SignalSocketReadable != 0 {
continue
}
if pending&zx.SignalSocketPeerClosed != 0 {
return 0, zx.EOF
}
// impossible
return 0, zx.Error{Status: zx.ErrInternal, Text: "fdio.Pipe"}
}
return 0, err
}
}
func (f *Pipe) ReadAt(data []byte, off int64) (int, error) {
return 0, zx.Error{Status: zx.ErrNotSupported, Text: "fdio.Pipe"}
}
func (f *Pipe) Write(data []byte) (n int, err error) {
for {
n, err = f.s.Write(data, 0)
if err == nil {
return n, nil
}
mxerr, ok := err.(zx.Error)
if !ok {
return n, err
}
switch mxerr.Status {
case zx.ErrPeerClosed:
return 0, zx.EOF
return 0, zx.EPIPE
case zx.ErrShouldWait:
pending, err := f.Wait(zx.SignalSocketWritable|zx.SignalSocketPeerClosed, zx.TimensecInfinite)
if err != nil {
return 0, err
}
if pending&zx.SignalSocketWritable != 0 {
continue
}
if pending&zx.SignalSocketPeerClosed != 0 {
return 0, zx.EPIPE
}
// impossible
return 0, zx.Error{Status: zx.ErrInternal, Text: "fdio.Pipe"}
}
return 0, err
}
}
func (f *Pipe) WriteAt(data []byte, off int64) (int, error) {
return 0, zx.Error{Status: zx.ErrNotSupported, Text: "fdio.Pipe"}
}
func (f *Pipe) Seek(offset int64, whence int) (int64, error) {
return 0, zx.Error{Status: zx.ErrNotSupported, Text: "fdio.Pipe"}
}
func (f *Pipe) Truncate(length uint64) error {
return zx.Error{Status: zx.ErrNotSupported, Text: "fdio.Pipe"}
}
func (f *Pipe) Open(path string, flags uint32, mode uint32) (FDIO, error) {
return nil, zx.Error{Status: zx.ErrNotSupported, Text: "fdio.Pipe"}
}
func (f *Pipe) Link(oldpath, newpath string) error {
return zx.Error{Status: zx.ErrNotSupported, Text: "fdio.Pipe"}
}
func (f *Pipe) Rename(oldpath, newpath string) error {
return zx.Error{Status: zx.ErrNotSupported, Text: "fdio.Pipe"}
}
func (f *Pipe) Unlink(path string) error {
return zx.Error{Status: zx.ErrNotSupported, Text: "fdio.Pipe"}
}
func (f *Pipe) ReadDirents(max uint64) ([]byte, error) {
return nil, zx.Error{Status: zx.ErrNotSupported, Text: "fdio.Pipe"}
}
func (f *Pipe) Rewind() error {
return zx.Error{Status: zx.ErrNotSupported, Text: "fdio.Pipe"}
}