Chromium Code Reviews| Index: src/untrusted/irt/irt_manifest.c |
| =================================================================== |
| --- src/untrusted/irt/irt_manifest.c (revision 0) |
| +++ src/untrusted/irt/irt_manifest.c (revision 0) |
| @@ -0,0 +1,161 @@ |
| +#include <errno.h> |
| +#include <stdio.h> |
| +#include <stdlib.h> |
| +#include <string.h> |
| +#include <sys/fcntl.h> |
| +#include <nacl/nacl_srpc.h> |
| +#include <sys/nacl_name_service.h> |
| +#include <sys/nacl_syscalls.h> |
| + |
| +#include "native_client/src/untrusted/irt/irt.h" |
| +#include "native_client/src/untrusted/irt/irt_interfaces.h" |
| + |
| +static void print_error(const char *message) { |
| + write(2, message, strlen(message)); |
| +} |
| + |
| +/* |
| + * TODO(halyavin): move to separate file because name service channel can be |
| + * useful for other APIs. |
| + */ |
| +/* Mutex to guard name service channel initialization. */ |
| +static int name_service_mutex; |
| +static int ns_channel_initialized = 0; |
| +static struct NaClSrpcChannel ns_channel; |
| + |
| +/* IRT is static, we don't need destructor. */ |
| +static __attribute__((constructor)) void init_ns_mutex(void) { |
|
Roland McGrath
2011/08/16 17:32:50
Just use a pthread_mutex_t here, and a simple C st
halyavin
2011/08/16 18:06:25
Done.
|
| + nacl_irt_mutex.mutex_create(&name_service_mutex); |
| +} |
| + |
| +static int get_nameservice_channel_locked(struct NaClSrpcChannel **result) { |
| + int ns; |
| + int connected_socket; |
| + if (ns_channel_initialized) { |
| + *result = &ns_channel; |
| + return 0; |
| + } |
| + *result = 0; |
| + ns = -1; |
| + nacl_nameservice(&ns); |
| + if (-1 == ns) { |
| + print_error("Can't get name service descriptor\n"); |
| + return EIO; |
| + } |
| + connected_socket = imc_connect(ns); |
| + if (-1 == connected_socket) { |
| + print_error("Can't connect to name service\n"); |
| + return EIO; |
| + } |
| + close(ns); |
| + if (!NaClSrpcClientCtor(&ns_channel, connected_socket)) { |
| + print_error("Srpc client channel ctor failed\n"); |
| + return EIO; |
| + } |
| + *result = &ns_channel; |
| + ns_channel_initialized = 1; |
| + return 0; |
| +} |
| + |
| +/* |
| + * Get name service channel. |
| + * If successfull, function sets pointer to name service channel and returns 0. |
| + * In case of error, function sets pointer to zero and returns error code. |
| + */ |
| +int get_nameservice_channel(struct NaClSrpcChannel **result) { |
| + int error; |
| + nacl_irt_mutex.mutex_lock(name_service_mutex); |
| + error = get_nameservice_channel_locked(result); |
| + nacl_irt_mutex.mutex_unlock(name_service_mutex); |
| + return error; |
| +} |
| + |
| +/* |
| + * We use separate mutex so that nameservice initialization can be moved to |
| + * another file. In this case name_service_mutex would not be public. |
| + */ |
| +/* Mutex to guard manifest channel initialization. */ |
| +static int manifest_service_mutex; |
| +static int manifest_channel_initialized = 0; |
| +static struct NaClSrpcChannel manifest_channel; |
| + |
| +static __attribute__((constructor)) void init_manifest_mutex(void) { |
|
Roland McGrath
2011/08/16 17:32:50
Use pthread_mutex_t here too.
halyavin
2011/08/16 18:06:25
Done.
|
| + nacl_irt_mutex.mutex_create(&manifest_service_mutex); |
| +} |
| + |
| +static int get_manifest_channel_locked(struct NaClSrpcChannel **result) { |
| + int status; |
| + int manifest; |
| + int manifest_conn; |
| + struct NaClSrpcChannel* ns_channel; |
|
Roland McGrath
2011/08/16 17:32:50
Use C style: 'struct NaClSrpcChannel *ns_channel;'
halyavin
2011/08/16 18:06:25
Done.
|
| + if (manifest_channel_initialized) { |
| + *result = &manifest_channel; |
| + return 0; |
| + } |
| + *result = 0; |
| + status = get_nameservice_channel(&ns_channel); |
| + if (0 != status) { |
| + return status; |
| + } |
| + if (NACL_SRPC_RESULT_OK != NaClSrpcInvokeBySignature( |
| + ns_channel, NACL_NAME_SERVICE_LOOKUP, "ManifestNameService", O_RDWR, |
| + &status, &manifest)) { |
| + print_error("Nameservice lookup failed, status\n"); |
| + return EIO; |
| + } |
| + if (-1 == manifest) { |
| + print_error("Manifest descriptor is invalid\n"); |
| + return EIO; |
| + } |
| + manifest_conn = imc_connect(manifest); |
| + if (-1 == manifest_conn) { |
| + print_error("Can't connect to manifest service\n"); |
| + return EIO; |
| + } |
| + close(manifest); |
| + if (!NaClSrpcClientCtor(&manifest_channel, manifest_conn)) { |
| + print_error("Can't create manifest srpc channel\n"); |
| + return EIO; |
| + } |
| + *result = &manifest_channel; |
| + manifest_channel_initialized = 1; |
| + return 0; |
| +} |
| + |
| +int get_manifest_channel(struct NaClSrpcChannel **result) { |
| + int error; |
| + nacl_irt_mutex.mutex_lock(manifest_service_mutex); |
| + error = get_manifest_channel_locked(result); |
| + nacl_irt_mutex.mutex_unlock(manifest_service_mutex); |
| + return error; |
| +} |
| + |
| +char kFiles[] = "files/"; |
| +int kFilesLen = 6; |
| +/* |
| + * Returns file descriptor or error code. |
| + */ |
| +static int irt_open_resource(const char *file, int *fd) { |
| + int status; |
| + struct NaClSrpcChannel* manifest_channel; |
| + status = get_manifest_channel(&manifest_channel); |
| + if (0 != status) { |
| + return status; |
| + } |
| + char* path = malloc(strlen(file) + 1 + kFilesLen); |
| + path[0] = 0; |
| + strcpy(path, kFiles); |
| + strcat(path, file); |
| + if (NACL_SRPC_RESULT_OK != NaClSrpcInvokeBySignature( |
|
Roland McGrath
2011/08/16 17:32:50
This call cannot be used on the same NaClSrpcChann
halyavin
2011/08/16 18:06:25
Done.
|
| + manifest_channel, NACL_NAME_SERVICE_LOOKUP, path, O_RDONLY, |
| + &status, fd)) { |
| + free(path); |
| + return status; |
| + } |
| + free(path); |
| + return 0; |
| +} |
| + |
| +const struct nacl_irt_resource_open nacl_irt_resource_open = { |
| + irt_open_resource |
| +}; |