| // Copyright 2017 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 |
| // +build cgo |
| |
| package mxc |
| |
| // #cgo fuchsia LDFLAGS: -lfdio |
| // #include <zircon/types.h> |
| // #include <zircon/syscalls.h> |
| // #include <stdlib.h> |
| // #include <lib/fdio/util.h> |
| import "C" |
| import ( |
| "errors" |
| "syscall/zx" |
| "syscall/zx/fdio" |
| "syscall/zx/fidl" |
| "syscall/zx/io" |
| ) |
| |
| func transferFDIOFromCFD(fd int) (fdio.FDIO, error) { |
| handlesC := make([]C.zx_handle_t, fdio.MaxUnderlyingHandles) |
| typesC := make([]C.uint32_t, fdio.MaxUnderlyingHandles) |
| status := C.fdio_transfer_fd(C.int(fd), 0, (*C.zx_handle_t)(&handlesC[0]), (*C.uint32_t)(&typesC[0])) |
| if status < 0 { |
| return nil, zx.Error{Status: zx.Status(status), Text: "mxc"} |
| } else if status == 0 || fdio.MaxUnderlyingHandles < status { |
| return nil, errors.New("Invalid handle from fdio_transfer_fd") |
| } |
| handles := make([]zx.Handle, int(status)) |
| for i := 0; i < int(status); i++ { |
| handles[i] = zx.Handle(handlesC[i]) |
| } |
| switch zx.HandleInfo(typesC[0]).Type() { |
| case fdio.HandleTypeRemote: |
| obj := (*io.ObjectInterface)(&fidl.Proxy{Channel: zx.Channel(handles[0])}) |
| if len(handles) > 1 { |
| for _, h := range handles[1:] { |
| h.Close() |
| } |
| } |
| return &fdio.File{Node: fdio.Node{Object: fdio.Object{obj}}}, nil |
| case fdio.HandleTypePipe: |
| if len(handles) > 1 { |
| for _, h := range handles[1:] { |
| h.Close() |
| } |
| } |
| return fdio.NewPipe(zx.Socket(handles[0])), nil |
| default: |
| for _, h := range handles { |
| h.Close() |
| } |
| return nil, errors.New("Unexpected C handle type") |
| } |
| } |