#include <iterator>
#include <string>
+#include "nacl_io/devfs/dev_fs.h"
+#include "nacl_io/filesystem.h"
+#include "nacl_io/fusefs/fuse_fs_factory.h"
#include "nacl_io/host_resolver.h"
+#include "nacl_io/html5fs/html5_fs.h"
+#include "nacl_io/httpfs/http_fs.h"
#include "nacl_io/kernel_handle.h"
#include "nacl_io/kernel_wrap_real.h"
-#include "nacl_io/mount.h"
-#include "nacl_io/mount_dev.h"
-#include "nacl_io/mount_html5fs.h"
-#include "nacl_io/mount_http.h"
-#include "nacl_io/mount_mem.h"
-#include "nacl_io/mount_node.h"
-#include "nacl_io/mount_node_pipe.h"
-#include "nacl_io/mount_node_tcp.h"
-#include "nacl_io/mount_node_udp.h"
-#include "nacl_io/mount_passthrough.h"
-#include "nacl_io/mount_stream.h"
+#include "nacl_io/log.h"
+#include "nacl_io/memfs/mem_fs.h"
+#include "nacl_io/node.h"
#include "nacl_io/osmman.h"
#include "nacl_io/ossocket.h"
#include "nacl_io/osstat.h"
+#include "nacl_io/passthroughfs/passthrough_fs.h"
#include "nacl_io/path.h"
#include "nacl_io/pepper_interface.h"
-#include "nacl_io/typed_mount_factory.h"
+#include "nacl_io/pipe/pipe_node.h"
+#include "nacl_io/socket/tcp_node.h"
+#include "nacl_io/socket/udp_node.h"
+#include "nacl_io/stream/stream_fs.h"
+#include "nacl_io/typed_fs_factory.h"
#include "sdk_util/auto_lock.h"
#include "sdk_util/ref_object.h"
#include "sdk_util/string_util.h"
namespace nacl_io {
-
-KernelProxy::KernelProxy() : dev_(0), ppapi_(NULL),
- sigwinch_handler_(SIG_IGN),
- signal_emitter_(new EventEmitter) {
-
+KernelProxy::KernelProxy()
+ : dev_(0),
+ ppapi_(NULL),
+ exit_callback_(NULL),
+ exit_callback_user_data_(NULL),
+ mount_callback_(NULL),
+ mount_callback_user_data_(NULL),
+ signal_emitter_(new EventEmitter) {
+ memset(&sigwinch_handler_, 0, sizeof(sigwinch_handler_));
+ sigwinch_handler_.sa_handler = SIG_DFL;
}
KernelProxy::~KernelProxy() {
- // Clean up the MountFactories.
- for (MountFactoryMap_t::iterator i = factories_.begin();
- i != factories_.end();
+ // Clean up the FsFactories.
+ for (FsFactoryMap_t::iterator i = factories_.begin(); i != factories_.end();
++i) {
delete i->second;
}
-
- delete ppapi_;
}
Error KernelProxy::Init(PepperInterface* ppapi) {
ppapi_ = ppapi;
dev_ = 1;
- factories_["memfs"] = new TypedMountFactory<MountMem>;
- factories_["dev"] = new TypedMountFactory<MountDev>;
- factories_["html5fs"] = new TypedMountFactory<MountHtml5Fs>;
- factories_["httpfs"] = new TypedMountFactory<MountHttp>;
- factories_["passthroughfs"] = new TypedMountFactory<MountPassthrough>;
+ factories_["memfs"] = new TypedFsFactory<MemFs>;
+ factories_["dev"] = new TypedFsFactory<DevFs>;
+ factories_["html5fs"] = new TypedFsFactory<Html5Fs>;
+ 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;
host_resolver_.Init(ppapi_);
#endif
- StringMap_t args;
- stream_mount_.reset(new MountStream());
- result = stream_mount_->Init(0, args, ppapi);
+ FsInitArgs args;
+ args.dev = dev_++;
+ args.ppapi = ppapi_;
+ stream_fs_.reset(new StreamFs());
+ int result = stream_fs_->Init(args);
if (result != 0) {
assert(false);
rtn = result;
return rtn;
}
+bool KernelProxy::RegisterFsType(const char* fs_type,
+ fuse_operations* fuse_ops) {
+ FsFactoryMap_t::iterator iter = factories_.find(fs_type);
+ if (iter != factories_.end())
+ return false;
+
+ factories_[fs_type] = new FuseFsFactory(fuse_ops);
+ return true;
+}
+
+bool KernelProxy::UnregisterFsType(const char* fs_type) {
+ FsFactoryMap_t::iterator iter = factories_.find(fs_type);
+ if (iter == factories_.end())
+ return false;
+
+ delete iter->second;
+ factories_.erase(iter);
+ return true;
+}
+
+void KernelProxy::SetExitCallback(nacl_io_exit_callback_t exit_callback,
+ void* user_data) {
+ exit_callback_ = exit_callback;
+ exit_callback_user_data_ = user_data;
+}
+
+void KernelProxy::SetMountCallback(nacl_io_mount_callback_t mount_callback,
+ void* user_data) {
+ mount_callback_ = mount_callback;
+ mount_callback_user_data_ = user_data;
+}
+
int KernelProxy::open_resource(const char* path) {
- ScopedMount mnt;
+ ScopedFilesystem fs;
Path rel;
- Error error = AcquireMountAndRelPath(path, &mnt, &rel);
+ Error error = AcquireFsAndRelPath(path, &fs, &rel);
if (error) {
errno = error;
return -1;
}
- ScopedMountNode node;
- error = mnt->OpenResource(rel, &node);
+ ScopedNode node;
+ error = fs->OpenResource(rel, &node);
if (error) {
// OpenResource failed, try Open().
- error = mnt->Open(rel, O_RDONLY, &node);
+ error = fs->Open(rel, O_RDONLY, &node);
if (error) {
errno = error;
return -1;
}
}
- ScopedKernelHandle handle(new KernelHandle(mnt, node));
+ ScopedKernelHandle handle(new KernelHandle(fs, node));
error = handle->Init(O_RDONLY);
if (error) {
errno = error;
return -1;
}
- return AllocateFD(handle);
+ return AllocateFD(handle, path);
}
int KernelProxy::open(const char* path, int open_flags) {
- ScopedMount mnt;
- ScopedMountNode node;
+ ScopedFilesystem fs;
+ ScopedNode node;
- Error error = AcquireMountAndNode(path, open_flags, &mnt, &node);
+ Error error = AcquireFsAndNode(path, open_flags, &fs, &node);
if (error) {
errno = error;
return -1;
}
- ScopedKernelHandle handle(new KernelHandle(mnt, node));
+ ScopedKernelHandle handle(new KernelHandle(fs, node));
error = handle->Init(open_flags);
if (error) {
errno = error;
return -1;
}
- return AllocateFD(handle);
+ return AllocateFD(handle, path);
}
int KernelProxy::pipe(int pipefds[2]) {
- MountNodePipe* pipe = new MountNodePipe(stream_mount_.get());
- ScopedMountNode node(pipe);
+ PipeNode* pipe = new PipeNode(stream_fs_.get());
+ ScopedNode node(pipe);
- if (pipe->Init(S_IREAD | S_IWRITE) == 0) {
- ScopedKernelHandle handle0(new KernelHandle(stream_mount_, node));
- ScopedKernelHandle handle1(new KernelHandle(stream_mount_, node));
+ if (pipe->Init(O_RDWR) == 0) {
+ ScopedKernelHandle handle0(new KernelHandle(stream_fs_, node));
+ ScopedKernelHandle handle1(new KernelHandle(stream_fs_, node));
// Should never fail, but...
- if (handle0->Init(S_IREAD) || handle1->Init(S_IWRITE)) {
+ if (handle0->Init(O_RDONLY) || handle1->Init(O_WRONLY)) {
errno = EACCES;
return -1;
}
int KernelProxy::dup(int oldfd) {
ScopedKernelHandle handle;
- Error error = AcquireHandle(oldfd, &handle);
+ std::string path;
+ Error error = AcquireHandleAndPath(oldfd, &handle, &path);
if (error) {
errno = error;
return -1;
}
-
- return AllocateFD(handle);
+ return AllocateFD(handle, path);
}
int KernelProxy::dup2(int oldfd, int newfd) {
return newfd;
ScopedKernelHandle old_handle;
- Error error = AcquireHandle(oldfd, &old_handle);
+ std::string old_path;
+ Error error = AcquireHandleAndPath(oldfd, &old_handle, &old_path);
if (error) {
errno = error;
return -1;
}
- FreeAndReassignFD(newfd, old_handle);
+ FreeAndReassignFD(newfd, old_handle, old_path);
return newfd;
}
return 0;
}
-char* KernelProxy::getcwd(char* buf, size_t size) {
- std::string cwd = GetCWD();
+void KernelProxy::exit(int status) {
+ if (exit_callback_)
+ exit_callback_(status, exit_callback_user_data_);
+}
- if (size <= 0) {
- errno = EINVAL;
+char* KernelProxy::getcwd(char* buf, size_t size) {
+ if (NULL == buf) {
+ errno = EFAULT;
return NULL;
}
- // If size is 0, allocate as much as we need.
- if (size == 0) {
- size = cwd.size() + 1;
- }
+ std::string cwd = GetCWD();
// Verify the buffer is large enough
if (size <= cwd.size()) {
return NULL;
}
- // Allocate the buffer if needed
- if (buf == NULL) {
- buf = static_cast<char*>(malloc(size));
- }
-
strcpy(buf, cwd.c_str());
return buf;
}
}
int KernelProxy::mkdir(const char* path, mode_t mode) {
- ScopedMount mnt;
+ ScopedFilesystem fs;
Path rel;
- Error error = AcquireMountAndRelPath(path, &mnt, &rel);
+ Error error = AcquireFsAndRelPath(path, &fs, &rel);
if (error) {
errno = error;
return -1;
}
- error = mnt->Mkdir(rel, mode);
+ error = fs->Mkdir(rel, mode);
if (error) {
errno = error;
return -1;
}
int KernelProxy::rmdir(const char* path) {
- ScopedMount mnt;
+ ScopedFilesystem fs;
Path rel;
- Error error = AcquireMountAndRelPath(path, &mnt, &rel);
+ Error error = AcquireFsAndRelPath(path, &fs, &rel);
if (error) {
errno = error;
return -1;
}
- error = mnt->Rmdir(rel);
+ error = fs->Rmdir(rel);
if (error) {
errno = error;
return -1;
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
- MountFactoryMap_t::iterator factory = factories_.find(filesystemtype);
+ FsFactoryMap_t::iterator factory = factories_.find(filesystemtype);
if (factory == factories_.end()) {
- errno = ENODEV;
- return -1;
+ LOG_ERROR("Unknown filesystem type: %s", filesystemtype);
+ return ENODEV;
}
// Create a map of settings
StringMap_t smap;
smap["SOURCE"] = source;
- smap["TARGET"] = abs_path;
if (data) {
std::vector<std::string> elements;
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);
}
}
- ScopedMount mnt;
- Error error = factory->second->CreateMount(dev_++, smap, ppapi_, &mnt);
- if (error) {
- errno = error;
- return -1;
+ FsInitArgs args;
+ args.dev = dev_++;
+ args.string_map = smap;
+ args.ppapi = ppapi_;
+
+ ScopedFilesystem fs;
+ Error error = factory->second->CreateFilesystem(args, &fs);
+ if (error)
+ return error;
+
+ error = AttachFsAtPath(fs, abs_path);
+ if (error)
+ return error;
+
+ if (create_fs_node) {
+ error = CreateFsNode(fs);
+ if (error) {
+ DetachFsAtPath(abs_path, &fs);
+ return error;
+ }
}
- error = AttachMountAtPath(mnt, abs_path);
- if (error) {
- errno = error;
- return -1;
+ *out_filesystem = fs;
+
+ if (mount_callback_) {
+ mount_callback_(source,
+ target,
+ filesystemtype,
+ mountflags,
+ data,
+ fs->dev(),
+ mount_callback_user_data_);
}
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 = DetachMountAtPath(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;
}
}
int KernelProxy::fchdir(int fd) {
- errno = ENOSYS;
- return -1;
+ ScopedKernelHandle handle;
+ std::string path;
+ Error error = AcquireHandleAndPath(fd, &handle, &path);
+ if (error) {
+ errno = error;
+ return -1;
+ }
+
+ if (!handle->node()->IsaDir()) {
+ errno = ENOTDIR;
+ return -1;
+ }
+
+ if (path.empty()) {
+ errno = EBADF;
+ return -1;
+ }
+
+ error = SetCWD(path);
+ if (error) {
+ // errno is return value from SetCWD
+ errno = error;
+ return -1;
+ }
+ return 0;
}
int KernelProxy::ftruncate(int fd, off_t length) {
Error error = AcquireHandle(fd, &handle);
if (error) {
errno = error;
- return -1;
+ return 0;
}
- error = handle->node()->IsaTTY();
+ error = handle->node()->Isatty();
if (error) {
errno = error;
- return -1;
+ return 0;
}
- return 0;
+ return 1;
}
int KernelProxy::ioctl(int fd, int request, va_list args) {
}
int KernelProxy::unlink(const char* path) {
- ScopedMount mnt;
+ ScopedFilesystem fs;
Path rel;
- Error error = AcquireMountAndRelPath(path, &mnt, &rel);
+ Error error = AcquireFsAndRelPath(path, &fs, &rel);
if (error) {
errno = error;
return -1;
}
- error = mnt->Unlink(rel);
+ error = fs->Unlink(rel);
if (error) {
errno = error;
return -1;
}
int KernelProxy::truncate(const char* path, off_t len) {
- errno = ENOSYS;
- return -1;
+ int fd = KernelProxy::open(path, O_WRONLY);
+ if (-1 == fd)
+ return -1;
+
+ int result = ftruncate(fd, len);
+ close(fd);
+ return result;
}
int KernelProxy::lstat(const char* path, struct stat* buf) {
- errno = ENOSYS;
- return -1;
+ return stat(path, buf);
}
int KernelProxy::rename(const char* path, const char* newpath) {
- errno = ENOSYS;
- return -1;
+ ScopedFilesystem fs;
+ Path rel;
+ Error error = AcquireFsAndRelPath(path, &fs, &rel);
+ if (error) {
+ errno = error;
+ return -1;
+ }
+
+ ScopedFilesystem newfs;
+ Path newrel;
+ error = AcquireFsAndRelPath(newpath, &newfs, &newrel);
+ if (error) {
+ errno = error;
+ return -1;
+ }
+
+ if (newfs.get() != fs.get()) {
+ // Renaming accross mountpoints is not allowed
+ errno = EXDEV;
+ return -1;
+ }
+
+ // They already point to the same path
+ if (rel == newrel)
+ return 0;
+
+ error = fs->Rename(rel, newrel);
+ if (error) {
+ errno = error;
+ return -1;
+ }
+
+ return 0;
}
int KernelProxy::remove(const char* path) {
- ScopedMount mnt;
+ ScopedFilesystem fs;
Path rel;
- Error error = AcquireMountAndRelPath(path, &mnt, &rel);
+ Error error = AcquireFsAndRelPath(path, &fs, &rel);
if (error) {
errno = error;
return -1;
}
- error = mnt->Remove(rel);
+ error = fs->Remove(rel);
if (error) {
errno = error;
return -1;
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: {
}
int KernelProxy::access(const char* path, int amode) {
- ScopedMount mnt;
+ ScopedFilesystem fs;
Path rel;
- Error error = AcquireMountAndRelPath(path, &mnt, &rel);
+ Error error = AcquireFsAndRelPath(path, &fs, &rel);
if (error) {
errno = error;
return -1;
}
- error = mnt->Access(rel, amode);
+ error = fs->Access(rel, amode);
if (error) {
errno = error;
return -1;
return 0;
}
-int KernelProxy::readlink(const char *path, char *buf, size_t count) {
+int KernelProxy::readlink(const char* path, char* buf, size_t count) {
+ LOG_TRACE("readlink is not implemented.");
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]) {
+ LOG_TRACE("utimes is not implemented.");
errno = EINVAL;
return -1;
}
// TODO(noelallen): Needs implementation.
int KernelProxy::link(const char* oldpath, const char* newpath) {
+ LOG_TRACE("link is not implemented.");
errno = EINVAL;
return -1;
}
int KernelProxy::symlink(const char* oldpath, const char* newpath) {
+ LOG_TRACE("symlink is not implemented.");
errno = EINVAL;
return -1;
}
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) {
signal_emitter_->RaiseEvents_Locked(POLLERR);
switch (sig) {
case SIGWINCH:
- if (sigwinch_handler_ != SIG_IGN)
- sigwinch_handler_(SIGWINCH);
+ if (sigwinch_handler_.sa_handler != SIG_IGN &&
+ sigwinch_handler_.sa_handler != SIG_DFL) {
+ sigwinch_handler_.sa_handler(SIGWINCH);
+ }
break;
case SIGUSR1:
break;
default:
+ LOG_TRACE("Unsupported signal: %d", sig);
errno = EINVAL;
return -1;
}
return 0;
}
-sighandler_t KernelProxy::sigset(int signum, sighandler_t handler) {
+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
+ errno = EINVAL;
+ return -1;
+ }
+
switch (signum) {
// Handled signals.
case SIGWINCH: {
- sighandler_t old_value = sigwinch_handler_;
- if (handler == SIG_DFL)
- handler = SIG_IGN;
- sigwinch_handler_ = handler;
- return old_value;
+ if (oaction)
+ *oaction = sigwinch_handler_;
+ if (action) {
+ sigwinch_handler_ = *action;
+ }
+ return 0;
}
// Known signals
case SIGHUP:
case SIGINT:
- case SIGKILL:
case SIGPIPE:
case SIGPOLL:
case SIGPROF:
case SIGQUIT:
case SIGSEGV:
case SIGTRAP:
- if (handler == SIG_DFL)
- return SIG_DFL;
- break;
+ if (action && action->sa_handler != SIG_DFL) {
+ // Trying to set this action to anything other than SIG_DFL
+ // is not yet supported.
+ LOG_TRACE("sigaction on signal %d != SIG_DFL not supported.", sig);
+ errno = EINVAL;
+ return -1;
+ }
+
+ if (oaction) {
+ memset(oaction, 0, sizeof(*oaction));
+ oaction->sa_handler = SIG_DFL;
+ }
+ return 0;
+
+ // KILL and STOP cannot be handled
+ case SIGKILL:
+ case SIGSTOP:
+ LOG_TRACE("sigaction on SIGKILL/SIGSTOP not supported.");
+ errno = EINVAL;
+ return -1;
}
+ // Unknown signum
errno = EINVAL;
- return SIG_ERR;
+ return -1;
}
#ifdef PROVIDES_SOCKET_API
-int KernelProxy::select(int nfds, fd_set* readfds, fd_set* writefds,
- fd_set* exceptfds, struct timeval* timeout) {
- fd_set ignore;
+int KernelProxy::select(int nfds,
+ fd_set* readfds,
+ fd_set* writefds,
+ fd_set* exceptfds,
+ struct timeval* timeout) {
std::vector<pollfd> pollfds;
- // Simplify logic, by using an IGNORE set for any undefined set
- FD_ZERO(&ignore);
- if (NULL == readfds)
- readfds = &ignore;
- if (NULL == writefds)
- writefds = &ignore;
- if (NULL == exceptfds)
- exceptfds = &ignore;
-
for (int fd = 0; fd < nfds; fd++) {
int events = 0;
- if (FD_ISSET(fd, readfds))
+ if (readfds && FD_ISSET(fd, readfds)) {
events |= POLLIN;
+ FD_CLR(fd, readfds);
+ }
- if (FD_ISSET(fd, writefds))
+ if (writefds && FD_ISSET(fd, writefds)) {
events |= POLLOUT;
+ FD_CLR(fd, writefds);
+ }
- if (FD_ISSET(fd, exceptfds))
+ if (exceptfds && FD_ISSET(fd, exceptfds)) {
events |= POLLERR | POLLHUP;
+ FD_CLR(fd, exceptfds);
+ }
if (events) {
pollfd info;
}
}
- FD_ZERO(readfds);
- FD_ZERO(writefds);
- FD_ZERO(exceptfds);
-
// NULL timeout signals wait forever.
int ms_timeout = -1;
if (timeout != NULL) {
// 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)) {
+ LOG_TRACE("Invalid timeout: tv_sec=%d tv_usec=%d.",
+ timeout->tv_sec,
+ timeout->tv_usec);
errno = EINVAL;
return -1;
}
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;
return event_cnt;
}
-
// Socket Functions
int KernelProxy::accept(int fd, struct sockaddr* addr, socklen_t* len) {
if (NULL == addr || NULL == len) {
return -1;
}
- MountNodeSocket* sock = new MountNodeTCP(stream_mount_.get(), new_sock);
+ SocketNode* sock = new TcpNode(stream_fs_.get(), new_sock);
- // The MountNodeSocket now holds a reference to the new socket
+ // The SocketNode now holds a reference to the new socket
// so we release ours.
ppapi_->ReleaseResource(new_sock);
- error = sock->Init(S_IREAD | S_IWRITE);
+ error = sock->Init(O_RDWR);
if (error != 0) {
errno = error;
return -1;
}
- ScopedMountNode node(sock);
- ScopedKernelHandle new_handle(new KernelHandle(stream_mount_, node));
- error = sock->Init(O_RDWR);
+ ScopedNode node(sock);
+ ScopedKernelHandle new_handle(new KernelHandle(stream_fs_, node));
+ error = new_handle->Init(O_RDWR);
if (error != 0) {
errno = error;
return -1;
return 0;
}
+void KernelProxy::freeaddrinfo(struct addrinfo* res) {
+ return host_resolver_.freeaddrinfo(res);
+}
+
+int KernelProxy::getaddrinfo(const char* node,
+ const char* service,
+ const struct addrinfo* hints,
+ struct addrinfo** res) {
+ return host_resolver_.getaddrinfo(node, service, hints, res);
+}
+
struct hostent* KernelProxy::gethostbyname(const char* name) {
return host_resolver_.gethostbyname(name);
}
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;
}
ssize_t KernelProxy::recvmsg(int fd, struct msghdr* msg, int flags) {
- if (NULL == msg ) {
+ if (NULL == msg) {
errno = EFAULT;
return -1;
}
return -1;
}
- MountNodeSocket* sock = NULL;
+ int open_flags = O_RDWR;
+
+ if (type & SOCK_CLOEXEC) {
+#ifdef O_CLOEXEC
+ // The NaCl newlib version of fcntl.h doesn't currently define
+ // O_CLOEXEC.
+ // TODO(sbc): remove this guard once it gets added.
+ open_flags |= O_CLOEXEC;
+#endif
+ type &= ~SOCK_CLOEXEC;
+ }
+
+ if (type & SOCK_NONBLOCK) {
+ open_flags |= O_NONBLOCK;
+ type &= ~SOCK_NONBLOCK;
+ }
+
+ SocketNode* sock = NULL;
switch (type) {
case SOCK_DGRAM:
- sock = new MountNodeUDP(stream_mount_.get());
+ sock = new UdpNode(stream_fs_.get());
break;
case SOCK_STREAM:
- sock = new MountNodeTCP(stream_mount_.get());
+ sock = new TcpNode(stream_fs_.get());
break;
- default:
+ case SOCK_SEQPACKET:
+ case SOCK_RDM:
+ case SOCK_RAW:
errno = EPROTONOSUPPORT;
return -1;
+
+ default:
+ errno = EINVAL;
+ return -1;
}
- ScopedMountNode node(sock);
- Error rtn = sock->Init(S_IREAD | S_IWRITE);
+ ScopedNode node(sock);
+ Error rtn = sock->Init(O_RDWR);
if (rtn != 0) {
errno = rtn;
return -1;
}
- ScopedKernelHandle handle(new KernelHandle(stream_mount_, node));
- rtn = handle->Init(O_RDWR);
+ ScopedKernelHandle handle(new KernelHandle(stream_fs_, node));
+ rtn = handle->Init(open_flags);
if (rtn != 0) {
errno = rtn;
return -1;