blob: dd6795cd14147ae6931ba72629a8102d71d8ccab [file] [log] [blame]
// 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")
}
}