Index: src/untrusted/init/name_service.cc |
diff --git a/src/untrusted/init/name_service.cc b/src/untrusted/init/name_service.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..0a42f62e3129ca940975474520e826dd2599a9e0 |
--- /dev/null |
+++ b/src/untrusted/init/name_service.cc |
@@ -0,0 +1,237 @@ |
+// Copyright (c) 2013 The Native Client Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "native_client/src/untrusted/init/process_lib.h" |
+ |
+#include <errno.h> |
+#include <fcntl.h> |
+#include <stdlib.h> |
+#include <unistd.h> |
+ |
+#include "native_client/src/public/imc_syscalls.h" |
+#include "native_client/src/public/name_service.h" |
+#include "native_client/src/trusted/service_runtime/include/bits/nacl_syscalls.h" |
+#include "native_client/src/trusted/service_runtime/include/sys/nacl_kernel_service.h" |
+ |
+#include "native_client/src/trusted/service_runtime/nacl_config.h" |
+ |
+namespace { |
+ |
+void InsertHandler( |
+ struct NaClSrpcRpc *rpc, |
+ struct NaClSrpcArg *in_args[], |
+ struct NaClSrpcArg *out_args[], |
+ struct NaClSrpcClosure *done_cls) { |
+ NameService *service = |
+ reinterpret_cast<NameService *>(rpc->channel->server_instance_data); |
+ NaClSrpcClosureRunner on_return(done_cls); |
+ rpc->result = NACL_SRPC_RESULT_OK; |
+ |
+ char *name = in_args[0]->arrays.str; |
+ int mode = in_args[1]->u.ival; |
+ int d = in_args[2]->u.hval; |
+ |
+ out_args[0]->u.ival = service->CreateEntry(std::string(name), mode, d); |
+} |
+ |
+void LookupHandler( |
+ struct NaClSrpcRpc *rpc, |
+ struct NaClSrpcArg **in_args, |
+ struct NaClSrpcArg **out_args, |
+ struct NaClSrpcClosure *done_cls) { |
+ NameService *service = |
+ reinterpret_cast<NameService *>(rpc->channel->server_instance_data); |
+ NaClSrpcClosureRunner on_return(done_cls); |
+ rpc->result = NACL_SRPC_RESULT_OK; |
+ |
+ char *name = in_args[0]->arrays.str; |
+ int flags = in_args[1]->u.ival; |
+ int d; |
+ |
+ int status = service->Resolve(std::string(name), flags, &d); |
+ out_args[0]->u.ival = status; |
+ out_args[1]->u.hval = (NACL_NAME_SERVICE_SUCCESS == status) ? d : -1; |
+} |
+ |
+void DeleteHandler( |
+ struct NaClSrpcRpc *rpc, |
+ struct NaClSrpcArg **in_args, |
+ struct NaClSrpcArg **out_args, |
+ struct NaClSrpcClosure *done_cls) { |
+ NameService *service = |
+ reinterpret_cast<NameService *>(rpc->channel->server_instance_data); |
+ NaClSrpcClosureRunner on_return(done_cls); |
+ rpc->result = NACL_SRPC_RESULT_OK; |
+ |
+ char *name = in_args[0]->arrays.str; |
+ |
+ out_args[0]->u.ival = static_cast<int32_t>( |
+ service->Delete(std::string(name))); |
+} |
+ |
+void ListHandler( |
+ struct NaClSrpcRpc *rpc, |
+ struct NaClSrpcArg *in_args[], |
+ struct NaClSrpcArg *out_args[], |
+ struct NaClSrpcClosure *done_cls) { |
+ NameService *service = |
+ reinterpret_cast<NameService *>(rpc->channel->server_instance_data); |
+ NaClSrpcClosureRunner on_return(done_cls); |
+ rpc->result = NACL_SRPC_RESULT_OK; |
+ |
+ size_t nbytes = out_args[0]->u.count; |
+ char *dest = out_args[0]->arrays.carr; |
+ |
+ out_args[0]->u.count = static_cast<uint32_t>( |
+ service->Enumerate(dest, nbytes)); |
+} |
+ |
+} |
+ |
+namespace nacl { |
+ |
+struct NaClSrpcHandlerDesc const NameService::handlers[] = { |
+ { NACL_NAME_SERVICE_LIST, ListHandler, }, |
+ { NACL_NAME_SERVICE_INSERT, InsertHandler, }, |
+ { NACL_NAME_SERVICE_LOOKUP, LookupHandler, }, |
+ { NACL_NAME_SERVICE_DELETE, DeleteHandler, }, |
+ { static_cast<char const *>(NULL), static_cast<NaClSrpcMethod>(NULL), }, |
+}; |
+ |
+int NameService::CreateEntry(std::string name, int mode, int d) { |
+} |
+ |
+int NameService::ResolveEntry(std::string name, int flags, int *out) { |
+ int status = NACL_NAME_SERVICE_NAME_NOT_FOUND; |
+ |
+ iterator it = entries_.find(name); |
+ if (it != entries_.end()) { |
+ } |
+ return status; |
+} |
+ |
+int NameService::DeleteEntry(std::string name) { |
+ ScopedLock(mu_); |
+ |
+ iterator it = entries_.find(name); |
+ if (it != entries_.end()) { |
+ entries_.erase(it); |
+ |
+ } |
+ |
+ entries_.erase(name); |
+ |
+ return status; |
+} |
+ |
+int NameService::List() { |
+} |
+ |
+std::vector<std::string> NameServiceClient::List() { |
+ std::vector<std::string> rv; |
+ if (!initialized()) { |
+ return rv; |
+ } |
+ NaClSrpcResultCodes result; |
+ uint32_t buffer_size = 4096; |
+ uint32_t used_bytes; |
+ char *buffer = NULL; |
+ for (;;) { |
+ buffer = new char[buffer_size]; |
+ used_bytes = buffer_size; |
+ result = NaClSrpcInvokeBySignature(chan(), |
+ NACL_NAME_SERVICE_LIST, |
+ &used_bytes, buffer); |
+ if (NACL_SRPC_RESULT_OK != result) { |
+ // Some kind of internal error, abort and indicate by returning |
+ // an empty vector. |
+ return rv; |
+ } |
+ if (used_bytes < buffer_size) { |
+ break; |
+ } |
+ buffer_size = 2 * buffer_size; |
+ delete[] buffer; |
+ buffer = new char[buffer_size]; |
+ } |
+ std::string name_list(buffer, used_bytes); |
+ delete[] buffer; |
+ // Parse name_list, separating at the ASCII NUL character |
+ // (forbidden in names), into a vector of strings. |
+ size_t start_ix = 0; |
+ size_t space_ix; |
+ |
+ while (start_ix < name_list.size()) { |
+ space_ix = name_list.find('\0', start_ix); |
+ if (space_ix == std::string::npos) { |
+ space_ix = used_bytes; |
+ } |
+ rv.push_back(name_list.substr(start_ix, space_ix - start_ix)); |
+ if (space_ix != std::string::npos) { |
+ start_ix = space_ix + 1; |
+ } else { |
+ start_ix = space_ix; |
+ } |
+ } |
+ return rv; |
+} |
+ |
+int NameServiceClient::Resolve(std::string name) { |
+ NaClSrpcResultCodes result; |
+ int status; |
+ int desc = -1; |
+ if (!initialized()) { |
+ return -1; |
+ } |
+ result = NaClSrpcInvokeBySignature(chan(), NACL_NAME_SERVICE_LOOKUP, |
+ name.c_str(), O_RDONLY, |
+ &status, &desc); |
+ if (NACL_SRPC_RESULT_OK != result) { |
+ fprintf(stderr, "Service lookup RPC failed (%d): %s\n", result, |
+ NaClSrpcErrorString(result)); |
+ return -1; |
+ } |
+ if (NACL_NAME_SERVICE_SUCCESS != status) { |
+ fprintf(stderr, "Resolve failed for \"%s\"; error %d\n", name.c_str(), |
+ status); |
+ return -1; |
+ } |
+ |
+ return desc; |
+} |
+ |
+int NameServiceFactory::name_service_cap; |
+NameServiceFactory *NameServiceFactory::singleton = NULL; |
+ |
+NameServiceFactory *NameServiceFactory::NameServiceFactorySingleton() { |
+ return singleton; |
+} |
+ |
+NameServiceFactory::NameServiceFactory() {} |
+ |
+typedef int (*nameservice_tramp_t)(int *desc); |
+ |
+bool NameServiceFactory::Init() { |
+ if (NULL != singleton) { |
+ return false; |
+ } |
+ |
+ name_service_cap = -1; |
+ if (-1 == nacl_nameservice(&name_service_cap)) { |
+ return false; |
+ } |
+ singleton = new NameServiceFactory(); |
+ return (NULL != singleton); |
+} |
+ |
+NameServiceClient *NameServiceFactory::NameService() { |
+ NameServiceClient *client = new NameServiceClient(); |
+ if (!client->InitializeFromConnectionCapability(name_service_cap)) { |
+ delete client; |
+ return NULL; |
+ } |
+ return client; |
+} |
+ |
+} // namespace nacl |