| // 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.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"} |
| } |