| OLD | NEW |
| (Empty) | |
| 1 /* |
| 2 * Copyright (c) 2011 The Native Client Authors. All rights reserved. |
| 3 * Use of this source code is governed by a BSD-style license that can be |
| 4 * found in the LICENSE file. |
| 5 */ |
| 6 |
| 7 #include <errno.h> |
| 8 #include <pthread.h> |
| 9 #include <stdio.h> |
| 10 #include <stdlib.h> |
| 11 #include <string.h> |
| 12 #include <sys/fcntl.h> |
| 13 #include <nacl/nacl_srpc.h> |
| 14 #include <sys/nacl_name_service.h> |
| 15 #include <sys/nacl_syscalls.h> |
| 16 |
| 17 #include "native_client/src/untrusted/irt/irt.h" |
| 18 #include "native_client/src/untrusted/irt/irt_interfaces.h" |
| 19 |
| 20 static void print_error(const char *message) { |
| 21 write(2, message, strlen(message)); |
| 22 } |
| 23 |
| 24 /* |
| 25 * TODO(halyavin): move to separate file because name service channel can be |
| 26 * useful for other APIs. |
| 27 */ |
| 28 /* Mutex to guard name service channel initialization. */ |
| 29 static pthread_mutex_t name_service_mutex = PTHREAD_MUTEX_INITIALIZER; |
| 30 static int ns_channel_initialized = 0; |
| 31 static struct NaClSrpcChannel ns_channel; |
| 32 |
| 33 static int get_nameservice_channel_locked(struct NaClSrpcChannel **result) { |
| 34 int ns; |
| 35 int connected_socket; |
| 36 if (ns_channel_initialized) { |
| 37 *result = &ns_channel; |
| 38 return 0; |
| 39 } |
| 40 *result = 0; |
| 41 ns = -1; |
| 42 nacl_nameservice(&ns); |
| 43 if (-1 == ns) { |
| 44 print_error("Can't get name service descriptor\n"); |
| 45 return EIO; |
| 46 } |
| 47 connected_socket = imc_connect(ns); |
| 48 if (-1 == connected_socket) { |
| 49 print_error("Can't connect to name service\n"); |
| 50 return EIO; |
| 51 } |
| 52 close(ns); |
| 53 if (!NaClSrpcClientCtor(&ns_channel, connected_socket)) { |
| 54 print_error("Srpc client channel ctor failed\n"); |
| 55 return EIO; |
| 56 } |
| 57 *result = &ns_channel; |
| 58 ns_channel_initialized = 1; |
| 59 return 0; |
| 60 } |
| 61 |
| 62 /* |
| 63 * Get name service channel. |
| 64 * If successfull, function sets pointer to name service channel and returns 0. |
| 65 * In case of error, function sets pointer to zero and returns error code. |
| 66 */ |
| 67 int get_nameservice_channel(struct NaClSrpcChannel **result) { |
| 68 int error; |
| 69 pthread_mutex_lock(&name_service_mutex); |
| 70 error = get_nameservice_channel_locked(result); |
| 71 pthread_mutex_unlock(&name_service_mutex); |
| 72 return error; |
| 73 } |
| 74 |
| 75 /* |
| 76 * We use separate mutex so that nameservice initialization can be moved to |
| 77 * another file. In this case name_service_mutex would not be public. |
| 78 */ |
| 79 /* Mutex to guard manifest channel initialization. */ |
| 80 static pthread_mutex_t manifest_service_mutex = PTHREAD_MUTEX_INITIALIZER; |
| 81 static int manifest_channel_initialized = 0; |
| 82 static struct NaClSrpcChannel manifest_channel; |
| 83 |
| 84 static int get_manifest_channel_locked(struct NaClSrpcChannel **result) { |
| 85 int status; |
| 86 int manifest; |
| 87 int manifest_conn; |
| 88 struct NaClSrpcChannel *ns_channel; |
| 89 if (manifest_channel_initialized) { |
| 90 *result = &manifest_channel; |
| 91 return 0; |
| 92 } |
| 93 *result = 0; |
| 94 status = get_nameservice_channel(&ns_channel); |
| 95 if (0 != status) { |
| 96 return status; |
| 97 } |
| 98 if (NACL_SRPC_RESULT_OK != NaClSrpcInvokeBySignature( |
| 99 ns_channel, NACL_NAME_SERVICE_LOOKUP, "ManifestNameService", O_RDWR, |
| 100 &status, &manifest)) { |
| 101 print_error("Nameservice lookup failed, status\n"); |
| 102 return EIO; |
| 103 } |
| 104 if (-1 == manifest) { |
| 105 print_error("Manifest descriptor is invalid\n"); |
| 106 return EIO; |
| 107 } |
| 108 manifest_conn = imc_connect(manifest); |
| 109 if (-1 == manifest_conn) { |
| 110 print_error("Can't connect to manifest service\n"); |
| 111 return EIO; |
| 112 } |
| 113 close(manifest); |
| 114 if (!NaClSrpcClientCtor(&manifest_channel, manifest_conn)) { |
| 115 print_error("Can't create manifest srpc channel\n"); |
| 116 return EIO; |
| 117 } |
| 118 *result = &manifest_channel; |
| 119 manifest_channel_initialized = 1; |
| 120 return 0; |
| 121 } |
| 122 |
| 123 int get_manifest_channel(struct NaClSrpcChannel **result) { |
| 124 int error; |
| 125 pthread_mutex_lock(&manifest_service_mutex); |
| 126 error = get_manifest_channel_locked(result); |
| 127 pthread_mutex_unlock(&manifest_service_mutex); |
| 128 return error; |
| 129 } |
| 130 |
| 131 char kFiles[] = "files/"; |
| 132 int kFilesLen = 6; |
| 133 /* |
| 134 * Returns file descriptor or error code. |
| 135 */ |
| 136 static int irt_open_resource(const char *file, int *fd) { |
| 137 int status; |
| 138 struct NaClSrpcChannel *manifest_channel; |
| 139 status = get_manifest_channel(&manifest_channel); |
| 140 if (0 != status) { |
| 141 return status; |
| 142 } |
| 143 char* path = malloc(strlen(file) + 1 + kFilesLen); |
| 144 strcpy(path, kFiles); |
| 145 if ('/' == file[0]) { |
| 146 strcat(path, file + 1); |
| 147 } else { |
| 148 strcat(path, file); |
| 149 } |
| 150 pthread_mutex_lock(&manifest_service_mutex); |
| 151 if (NACL_SRPC_RESULT_OK == NaClSrpcInvokeBySignature( |
| 152 manifest_channel, NACL_NAME_SERVICE_LOOKUP, path, O_RDONLY, |
| 153 &status, fd)) { |
| 154 status = 0; |
| 155 } |
| 156 pthread_mutex_unlock(&manifest_service_mutex); |
| 157 free(path); |
| 158 return status; |
| 159 } |
| 160 |
| 161 const struct nacl_irt_resource_open nacl_irt_resource_open = { |
| 162 irt_open_resource |
| 163 }; |
| OLD | NEW |