blob: db21dcb806adedbb25ea5a9f74dd411bcb751d6a [file] [log] [blame]
// Copyright 2011 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 cgo
// +build fuchsia
#include "libcgo.h"
#include <stdlib.h>
#include <zircon/process.h>
#include <zircon/processargs.h>
#include <lib/fdio/io.h>
#include <lib/fdio/namespace.h>
#include <lib/fdio/util.h>
extern char **environ;
// fdio_init matches a Go struct of the same name in os_fuchsia.go.
struct fdio_init {
zx_handle_t stdioClones[3 * FDIO_MAX_HANDLES];
uint32_t stdioCloneNumHandles[3];
uint32_t stdioCloneTypes[3];
zx_handle_t processSelf;
zx_handle_t vmarRootSelf;
int32_t unused;
int32_t envlen;
char** environ;
int32_t unused2;
int32_t rootNSNumHandles;
zx_handle_t *rootNSHandles;
char** rootNSPaths;
};
void
x_cgo_get_initial_handles(struct fdio_init *handles)
{
// When running with cgo support, there are two FDIO libraries in the
// same process. We let the C FDIO start first, then clone its root
// and use that for Go.
// TODO: there is some small amount of fdio library state we
// have to share between Go and C, in particular, cwd.
// Work out how.
// fdio may have initialized std{in,out,err} with a single fd if the FDIO_FLAG_USE_FOR_STDIO
// flag was set, or have separate in/out/err fds. We clone fds {0,1,2} to separate fds for use
// in the Go runtime. The cloned fds aren't installed into fdio's fd table so they are only
// usable from Go's table.
zx_status_t r;
for (int i = 0; i < 3; ++i) {
uint32_t handle_types[FDIO_MAX_HANDLES];
r = fdio_clone_fd(i, 0, &handles->stdioClones[i * FDIO_MAX_HANDLES], handle_types);
if (r <= 0) {
printf("runtime/cgo: fdio_clone_fd of stdio[%d] failed: %d\n", i, r);
handles->stdioCloneNumHandles[i] = 0;
} else {
handles->stdioCloneNumHandles[i] = r;
handles->stdioCloneTypes[i] = PA_HND_TYPE(handle_types[0]);
}
}
handles->processSelf = zx_process_self();
handles->vmarRootSelf = zx_vmar_root_self();
for (char** env = environ; *env; env++) {
handles->envlen++;
}
handles->environ = environ;
fdio_flat_namespace_t* rootNS;
r = fdio_ns_export_root(&rootNS);
if (r < 0) {
handles->rootNSNumHandles = 0;
handles->rootNSHandles = NULL;
handles->rootNSPaths = NULL;
} else {
handles->rootNSNumHandles = (int32_t)rootNS->count;
handles->rootNSHandles = rootNS->handle;
handles->rootNSPaths = (char**)rootNS->path;
}
}