| // Copyright 2018 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/fidl" |
| "syscall/zx/io" |
| ) |
| |
| func nodeFromInfo(info *io.NodeInfo, node *io.NodeInterface) (result FDIO, err error) { |
| if info == nil { |
| if err = ((*fidl.ChannelProxy)(node)).Channel.Close(); err != nil { |
| return nil, err |
| } |
| return nil, zx.Error{Status: zx.ErrNotSupported, Text: "io.node"} |
| } |
| switch info.NodeInfoTag { |
| case io.NodeInfoService: |
| // TODO(mknyszek): Figure out the correct type to return here. |
| result = &Node{NodeInterface: node} |
| case io.NodeInfoFile: |
| result = &File{ |
| Node: Node{NodeInterface: node}, |
| Event: info.File.Event, |
| } |
| case io.NodeInfoDevice: |
| result = &File{ |
| Node: Node{NodeInterface: node}, |
| Event: info.Device.Event, |
| } |
| case io.NodeInfoDirectory: |
| result = &Directory{Node: Node{NodeInterface: node}} |
| case io.NodeInfoPipe: |
| if err = ((*fidl.ChannelProxy)(node)).Channel.Close(); err != nil { |
| return nil, err |
| } |
| result = NewPipe(info.Pipe.Socket) |
| case io.NodeInfoVmofile: |
| if err = ((*fidl.ChannelProxy)(node)).Channel.Close(); err != nil { |
| return nil, err |
| } |
| result, err = NewVMOFile(info.Vmofile.Vmo, info.Vmofile.Offset, info.Vmofile.Length) |
| if err != nil { |
| return nil, err |
| } |
| default: |
| if err = ((*fidl.ChannelProxy)(node)).Channel.Close(); err != nil { |
| return nil, err |
| } |
| return nil, zx.Error{Status: zx.ErrNotSupported, Text: "io.node"} |
| } |
| return result, nil |
| } |
| |
| // Node is a wrapper around an NodeInterface which implements FDIO. |
| type Node struct { |
| *io.NodeInterface |
| } |
| |
| // IsValid returns true if the Node is valid. |
| func (n *Node) IsValid() bool { |
| if n.NodeInterface == nil { |
| return false |
| } |
| return ((*fidl.ChannelProxy)(n.NodeInterface)).IsValid() |
| } |
| |
| // Handles returns a slice of untyped zx handles containing the underlying |
| // channel of the Node. |
| func (n *Node) Handles() []zx.Handle { |
| return []zx.Handle{ |
| zx.Handle(((*fidl.ChannelProxy)(n.NodeInterface)).Channel), |
| } |
| } |
| |
| // Clone makes a clone of the node. |
| func (n *Node) Clone() (FDIO, error) { |
| req, newNode, err := io.NewNodeInterfaceRequest() |
| if err != nil { |
| return nil, err |
| } |
| if err := n.NodeInterface.Clone(io.OpenFlagDescribe, req); err != nil { |
| ((*fidl.ChannelProxy)(newNode)).Close() |
| return nil, err |
| } |
| status, info, err := newNode.ExpectOnOpen() |
| if err != nil { |
| ((*fidl.ChannelProxy)(newNode)).Close() |
| return nil, err |
| } else if status != zx.ErrOk { |
| ((*fidl.ChannelProxy)(newNode)).Close() |
| return nil, zx.Error{Status: status, Text: "io.node"} |
| } |
| return nodeFromInfo(info, newNode) |
| } |
| |
| // Close closes the node. |
| func (n *Node) Close() error { |
| defer ((*fidl.ChannelProxy)(n.NodeInterface)).Close() |
| if status, err := n.NodeInterface.Close(); err != nil { |
| return err |
| } else if status != zx.ErrOk { |
| return zx.Error{Status: status, Text: "io.node"} |
| } |
| return nil |
| } |
| |
| // Sync performs a sync operation on a Node. |
| func (n *Node) Sync() error { |
| if status, err := n.NodeInterface.Sync(); err != nil { |
| return err |
| } else if status != zx.ErrOk { |
| return zx.Error{Status: status, Text: "io.node"} |
| } |
| return nil |
| } |
| |
| // GetAttr returns the attributes for the Node. |
| func (n *Node) GetAttr() (io.NodeAttributes, error) { |
| status, attrs, err := n.NodeInterface.GetAttr() |
| if err != nil { |
| return io.NodeAttributes{}, err |
| } else if status != zx.ErrOk { |
| return io.NodeAttributes{}, zx.Error{Status: status, Text: "io.node"} |
| } |
| return attrs, nil |
| } |
| |
| // SetAttr sets the attributes for Node as defined by flags. |
| func (n *Node) SetAttr(flags uint32, attr io.NodeAttributes) error { |
| if status, err := n.NodeInterface.SetAttr(flags, attr); err != nil { |
| return err |
| } else if status != zx.ErrOk { |
| return zx.Error{Status: status, Text: "io.node"} |
| } |
| return nil |
| } |
| |
| // Ioctl calls an ioctl on Node. |
| func (n *Node) Ioctl(op uint32, max uint64, in []byte, handles []zx.Handle) ([]byte, []zx.Handle, error) { |
| status, h, b, err := n.NodeInterface.Ioctl(op, max, handles, in) |
| if err != nil { |
| return nil, nil, err |
| } else if status != zx.ErrOk { |
| return nil, nil, zx.Error{Status: status, Text: "io.node"} |
| } |
| return b, h, nil |
| } |
| |
| // Read implements FDIO for Node. |
| func (n *Node) Read(data []byte) (int, error) { |
| return 0, zx.Error{Status: zx.ErrNotSupported, Text: "io.node"} |
| } |
| |
| // ReadAt implements FDIO for Node. |
| func (n *Node) ReadAt(data []byte, off int64) (int, error) { |
| return 0, zx.Error{Status: zx.ErrNotSupported, Text: "io.node"} |
| } |
| |
| // Write implements FDIO for Node. |
| func (n *Node) Write(data []byte) (int, error) { |
| return 0, zx.Error{Status: zx.ErrNotSupported, Text: "io.node"} |
| } |
| |
| // WriteAt implements FDIO for Node. |
| func (n *Node) WriteAt(data []byte, off int64) (int, error) { |
| return 0, zx.Error{Status: zx.ErrNotSupported, Text: "io.node"} |
| } |
| |
| // Seek implements FDIO for Node. |
| func (n *Node) Seek(offset int64, whence int) (int64, error) { |
| return 0, zx.Error{Status: zx.ErrNotSupported, Text: "io.node"} |
| } |
| |
| // Truncate implements FDIO for Node. |
| func (n *Node) Truncate(length uint64) error { |
| return zx.Error{Status: zx.ErrNotSupported, Text: "io.node"} |
| } |
| |
| // Open implements FDIO for Node. |
| func (n *Node) Open(path string, flags uint32, mode uint32) (FDIO, error) { |
| return nil, zx.Error{Status: zx.ErrNotSupported, Text: "io.node"} |
| } |
| |
| // Link implements FDIO for Node. |
| func (n *Node) Link(oldpath, newpath string) error { |
| return zx.Error{Status: zx.ErrNotSupported, Text: "io.node"} |
| } |
| |
| // Rename implements FDIO for Node. |
| func (n *Node) Rename(oldpath, newpath string) error { |
| return zx.Error{Status: zx.ErrNotSupported, Text: "io.node"} |
| } |
| |
| // Unlink implements FDIO for Node. |
| func (n *Node) Unlink(path string) error { |
| return zx.Error{Status: zx.ErrNotSupported, Text: "io.node"} |
| } |
| |
| // ReadDirents implements FDIO for Node. |
| func (n *Node) ReadDirents(max uint64) ([]byte, error) { |
| return nil, zx.Error{Status: zx.ErrNotSupported, Text: "io.node"} |
| } |
| |
| // Rewind implements FDIO for Node. |
| func (n *Node) Rewind() error { |
| return zx.Error{Status: zx.ErrNotSupported, Text: "io.node"} |
| } |