Index: native_client_sdk/src/libraries/nacl_io/kernel_proxy.cc |
diff --git a/native_client_sdk/src/libraries/nacl_io/kernel_proxy.cc b/native_client_sdk/src/libraries/nacl_io/kernel_proxy.cc |
index 65265ba925fead166f37f2e8a1eb32525762ce78..0110bfa448d409a61f1f13ca634692a0187bbed8 100644 |
--- a/native_client_sdk/src/libraries/nacl_io/kernel_proxy.cc |
+++ b/native_client_sdk/src/libraries/nacl_io/kernel_proxy.cc |
@@ -26,6 +26,7 @@ |
#include "nacl_io/httpfs/http_fs.h" |
#include "nacl_io/kernel_handle.h" |
#include "nacl_io/kernel_wrap_real.h" |
+#include "nacl_io/log.h" |
#include "nacl_io/memfs/mem_fs.h" |
#include "nacl_io/node.h" |
#include "nacl_io/osmman.h" |
@@ -49,16 +50,17 @@ |
namespace nacl_io { |
- |
-KernelProxy::KernelProxy() : dev_(0), ppapi_(NULL), |
- exit_handler_(NULL), |
- signal_emitter_(new EventEmitter) { |
- memset(&sigwinch_handler_, 0, sizeof(sigwinch_handler_)); |
- sigwinch_handler_.sa_handler = SIG_DFL; |
+KernelProxy::KernelProxy() |
+ : dev_(0), |
+ ppapi_(NULL), |
+ exit_handler_(NULL), |
+ signal_emitter_(new EventEmitter) { |
+ memset(&sigwinch_handler_, 0, sizeof(sigwinch_handler_)); |
+ sigwinch_handler_.sa_handler = SIG_DFL; |
} |
KernelProxy::~KernelProxy() { |
- // Clean up the MountFactories. |
+ // Clean up the FsFactories. |
for (FsFactoryMap_t::iterator i = factories_.begin(); i != factories_.end(); |
++i) { |
delete i->second; |
@@ -76,18 +78,26 @@ Error KernelProxy::Init(PepperInterface* ppapi) { |
factories_["httpfs"] = new TypedFsFactory<HttpFs>; |
factories_["passthroughfs"] = new TypedFsFactory<PassthroughFs>; |
- int result; |
- result = mount("", "/", "passthroughfs", 0, NULL); |
- if (result != 0) { |
+ ScopedFilesystem root_fs; |
+ rtn = MountInternal("", "/", "passthroughfs", 0, NULL, false, &root_fs); |
+ if (rtn != 0) |
assert(false); |
- rtn = errno; |
- } |
- result = mount("", "/dev", "dev", 0, NULL); |
- if (result != 0) { |
+ ScopedFilesystem fs; |
+ rtn = MountInternal("", "/dev", "dev", 0, NULL, false, &fs); |
+ if (rtn != 0) |
+ assert(false); |
+ dev_fs_ = sdk_util::static_scoped_ref_cast<DevFs>(fs); |
+ |
+ // Create the filesystem nodes for / and /dev afterward. They can't be |
+ // created the normal way because the dev filesystem didn't exist yet. |
+ rtn = CreateFsNode(root_fs); |
+ if (rtn != 0) |
+ assert(false); |
+ |
+ rtn = CreateFsNode(dev_fs_); |
+ if (rtn != 0) |
assert(false); |
- rtn = errno; |
- } |
// Open the first three in order to get STDIN, STDOUT, STDERR |
int fd; |
@@ -113,8 +123,8 @@ Error KernelProxy::Init(PepperInterface* ppapi) { |
FsInitArgs args; |
args.dev = dev_++; |
args.ppapi = ppapi_; |
- stream_mount_.reset(new StreamFs()); |
- result = stream_mount_->Init(args); |
+ stream_fs_.reset(new StreamFs()); |
+ int result = stream_fs_->Init(args); |
if (result != 0) { |
assert(false); |
rtn = result; |
@@ -204,12 +214,12 @@ int KernelProxy::open(const char* path, int open_flags) { |
} |
int KernelProxy::pipe(int pipefds[2]) { |
- PipeNode* pipe = new PipeNode(stream_mount_.get()); |
+ PipeNode* pipe = new PipeNode(stream_fs_.get()); |
ScopedNode node(pipe); |
if (pipe->Init(O_RDWR) == 0) { |
- ScopedKernelHandle handle0(new KernelHandle(stream_mount_, node)); |
- ScopedKernelHandle handle1(new KernelHandle(stream_mount_, node)); |
+ ScopedKernelHandle handle0(new KernelHandle(stream_fs_, node)); |
+ ScopedKernelHandle handle1(new KernelHandle(stream_fs_, node)); |
// Should never fail, but... |
if (handle0->Init(O_RDONLY) || handle1->Init(O_WRONLY)) { |
@@ -381,20 +391,35 @@ int KernelProxy::stat(const char* path, struct stat* buf) { |
return result; |
} |
- |
int KernelProxy::mount(const char* source, |
const char* target, |
const char* filesystemtype, |
unsigned long mountflags, |
const void* data) { |
+ ScopedFilesystem fs; |
+ Error error = MountInternal( |
+ source, target, filesystemtype, mountflags, data, true, &fs); |
+ if (error) { |
+ errno = error; |
+ return -1; |
+ } |
+ |
+ return 0; |
+} |
+ |
+Error KernelProxy::MountInternal(const char* source, |
+ const char* target, |
+ const char* filesystemtype, |
+ unsigned long mountflags, |
+ const void* data, |
+ bool create_fs_node, |
+ ScopedFilesystem* out_filesystem) { |
std::string abs_path = GetAbsParts(target).Join(); |
// Find a factory of that type |
FsFactoryMap_t::iterator factory = factories_.find(filesystemtype); |
- if (factory == factories_.end()) { |
- errno = ENODEV; |
- return -1; |
- } |
+ if (factory == factories_.end()) |
+ return ENODEV; |
// Create a map of settings |
StringMap_t smap; |
@@ -406,7 +431,8 @@ int KernelProxy::mount(const char* source, |
sdk_util::SplitString(static_cast<const char*>(data), ',', &elements); |
for (std::vector<std::string>::const_iterator it = elements.begin(); |
- it != elements.end(); ++it) { |
+ it != elements.end(); |
+ ++it) { |
size_t location = it->find('='); |
if (location != std::string::npos) { |
std::string key = it->substr(0, location); |
@@ -425,26 +451,42 @@ int KernelProxy::mount(const char* source, |
ScopedFilesystem fs; |
Error error = factory->second->CreateFilesystem(args, &fs); |
- if (error) { |
- errno = error; |
- return -1; |
- } |
+ if (error) |
+ return error; |
error = AttachFsAtPath(fs, abs_path); |
- if (error) { |
- errno = error; |
- return -1; |
+ if (error) |
+ return error; |
+ |
+ if (create_fs_node) { |
+ error = CreateFsNode(fs); |
+ if (error) |
+ return error; |
} |
+ *out_filesystem = fs; |
return 0; |
} |
+Error KernelProxy::CreateFsNode(const ScopedFilesystem& fs) { |
+ assert(dev_fs_); |
+ |
+ return dev_fs_->CreateFsNode(fs.get()); |
+} |
+ |
int KernelProxy::umount(const char* path) { |
- Error error = DetachFsAtPath(path); |
+ ScopedFilesystem fs; |
+ Error error = DetachFsAtPath(path, &fs); |
if (error) { |
errno = error; |
return -1; |
} |
+ |
+ error = dev_fs_->DestroyFsNode(fs.get()); |
+ if (error) { |
+ // Ignore any errors here, just log. |
+ LOG_ERROR("Unable to destroy FsNode: %s", strerror(error)); |
+ } |
return 0; |
} |
@@ -739,8 +781,8 @@ int KernelProxy::fchmod(int fd, int mode) { |
int KernelProxy::fcntl(int fd, int request, va_list args) { |
Error error = 0; |
- // F_GETFD and F_SETFD are descirptor specific flags that |
- // are stored in the KernelObject's decriptor map unlink |
+ // F_GETFD and F_SETFD are descriptor specific flags that |
+ // are stored in the KernelObject's decriptor map unlike |
// F_GETFL and F_SETFL which are handle specific. |
switch (request) { |
case F_GETFD: { |
@@ -798,12 +840,12 @@ int KernelProxy::access(const char* path, int amode) { |
return 0; |
} |
-int KernelProxy::readlink(const char *path, char *buf, size_t count) { |
+int KernelProxy::readlink(const char* path, char* buf, size_t count) { |
errno = EINVAL; |
return -1; |
} |
-int KernelProxy::utimes(const char *filename, const struct timeval times[2]) { |
+int KernelProxy::utimes(const char* filename, const struct timeval times[2]) { |
errno = EINVAL; |
return -1; |
} |
@@ -915,8 +957,9 @@ int KernelProxy::tcgetattr(int fd, struct termios* termios_p) { |
return 0; |
} |
-int KernelProxy::tcsetattr(int fd, int optional_actions, |
- const struct termios *termios_p) { |
+int KernelProxy::tcsetattr(int fd, |
+ int optional_actions, |
+ const struct termios* termios_p) { |
ScopedKernelHandle handle; |
Error error = AcquireHandle(fd, &handle); |
if (error) { |
@@ -965,7 +1008,8 @@ int KernelProxy::kill(pid_t pid, int sig) { |
return 0; |
} |
-int KernelProxy::sigaction(int signum, const struct sigaction* action, |
+int KernelProxy::sigaction(int signum, |
+ const struct sigaction* action, |
struct sigaction* oaction) { |
if (action && action->sa_flags & SA_SIGINFO) { |
// We don't support SA_SIGINFO (sa_sigaction field) yet |
@@ -1025,8 +1069,11 @@ int KernelProxy::sigaction(int signum, const struct sigaction* action, |
#ifdef PROVIDES_SOCKET_API |
-int KernelProxy::select(int nfds, fd_set* readfds, fd_set* writefds, |
- fd_set* exceptfds, struct timeval* timeout) { |
+int KernelProxy::select(int nfds, |
+ fd_set* readfds, |
+ fd_set* writefds, |
+ fd_set* exceptfds, |
+ struct timeval* timeout) { |
std::vector<pollfd> pollfds; |
for (int fd = 0; fd < nfds; fd++) { |
@@ -1061,8 +1108,8 @@ int KernelProxy::select(int nfds, fd_set* readfds, fd_set* writefds, |
// If the timeout is invalid or too long (larger than signed 32 bit). |
if ((timeout->tv_sec < 0) || (timeout->tv_sec >= (INT_MAX / 1000)) || |
- (timeout->tv_usec < 0) || (timeout->tv_usec >= 1000000) || |
- (ms < 0) || (ms >= INT_MAX)) { |
+ (timeout->tv_usec < 0) || (timeout->tv_usec >= 1000000) || (ms < 0) || |
+ (ms >= INT_MAX)) { |
errno = EINVAL; |
return -1; |
} |
@@ -1103,7 +1150,7 @@ struct PollInfo { |
typedef std::map<EventEmitter*, PollInfo> EventPollMap_t; |
-int KernelProxy::poll(struct pollfd *fds, nfds_t nfds, int timeout) { |
+int KernelProxy::poll(struct pollfd* fds, nfds_t nfds, int timeout) { |
EventPollMap_t event_map; |
std::vector<EventRequest> requests; |
@@ -1184,7 +1231,6 @@ int KernelProxy::poll(struct pollfd *fds, nfds_t nfds, int timeout) { |
return event_cnt; |
} |
- |
// Socket Functions |
int KernelProxy::accept(int fd, struct sockaddr* addr, socklen_t* len) { |
if (NULL == addr || NULL == len) { |
@@ -1206,7 +1252,7 @@ int KernelProxy::accept(int fd, struct sockaddr* addr, socklen_t* len) { |
return -1; |
} |
- SocketNode* sock = new TcpNode(stream_mount_.get(), new_sock); |
+ SocketNode* sock = new TcpNode(stream_fs_.get(), new_sock); |
// The SocketNode now holds a reference to the new socket |
// so we release ours. |
@@ -1218,7 +1264,7 @@ int KernelProxy::accept(int fd, struct sockaddr* addr, socklen_t* len) { |
} |
ScopedNode node(sock); |
- ScopedKernelHandle new_handle(new KernelHandle(stream_mount_, node)); |
+ ScopedKernelHandle new_handle(new KernelHandle(stream_fs_, node)); |
error = new_handle->Init(O_RDWR); |
if (error != 0) { |
errno = error; |
@@ -1269,11 +1315,12 @@ int KernelProxy::connect(int fd, const struct sockaddr* addr, socklen_t len) { |
return 0; |
} |
-void KernelProxy::freeaddrinfo(struct addrinfo *res) { |
+void KernelProxy::freeaddrinfo(struct addrinfo* res) { |
return host_resolver_.freeaddrinfo(res); |
} |
-int KernelProxy::getaddrinfo(const char* node, const char* service, |
+int KernelProxy::getaddrinfo(const char* node, |
+ const char* service, |
const struct addrinfo* hints, |
struct addrinfo** res) { |
return host_resolver_.getaddrinfo(node, service, hints, res); |
@@ -1358,10 +1405,7 @@ int KernelProxy::listen(int fd, int backlog) { |
return 0; |
} |
-ssize_t KernelProxy::recv(int fd, |
- void* buf, |
- size_t len, |
- int flags) { |
+ssize_t KernelProxy::recv(int fd, void* buf, size_t len, int flags) { |
if (NULL == buf) { |
errno = EFAULT; |
return -1; |
@@ -1418,7 +1462,7 @@ ssize_t KernelProxy::recvfrom(int fd, |
} |
ssize_t KernelProxy::recvmsg(int fd, struct msghdr* msg, int flags) { |
- if (NULL == msg ) { |
+ if (NULL == msg) { |
errno = EFAULT; |
return -1; |
} |
@@ -1564,11 +1608,11 @@ int KernelProxy::socket(int domain, int type, int protocol) { |
SocketNode* sock = NULL; |
switch (type) { |
case SOCK_DGRAM: |
- sock = new UdpNode(stream_mount_.get()); |
+ sock = new UdpNode(stream_fs_.get()); |
break; |
case SOCK_STREAM: |
- sock = new TcpNode(stream_mount_.get()); |
+ sock = new TcpNode(stream_fs_.get()); |
break; |
case SOCK_SEQPACKET: |
@@ -1589,7 +1633,7 @@ int KernelProxy::socket(int domain, int type, int protocol) { |
return -1; |
} |
- ScopedKernelHandle handle(new KernelHandle(stream_mount_, node)); |
+ ScopedKernelHandle handle(new KernelHandle(stream_fs_, node)); |
rtn = handle->Init(open_flags); |
if (rtn != 0) { |
errno = rtn; |