1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "nacl_io/kernel_proxy.h"
21 #include "nacl_io/devfs/dev_fs.h"
22 #include "nacl_io/filesystem.h"
23 #include "nacl_io/fusefs/fuse_fs_factory.h"
24 #include "nacl_io/host_resolver.h"
25 #include "nacl_io/html5fs/html5_fs.h"
26 #include "nacl_io/httpfs/http_fs.h"
27 #include "nacl_io/kernel_handle.h"
28 #include "nacl_io/kernel_wrap_real.h"
29 #include "nacl_io/log.h"
30 #include "nacl_io/memfs/mem_fs.h"
31 #include "nacl_io/node.h"
32 #include "nacl_io/osinttypes.h"
33 #include "nacl_io/osmman.h"
34 #include "nacl_io/ossocket.h"
35 #include "nacl_io/osstat.h"
36 #include "nacl_io/passthroughfs/passthrough_fs.h"
37 #include "nacl_io/path.h"
38 #include "nacl_io/pepper_interface.h"
39 #include "nacl_io/pipe/pipe_node.h"
40 #include "nacl_io/socket/tcp_node.h"
41 #include "nacl_io/socket/udp_node.h"
42 #include "nacl_io/stream/stream_fs.h"
43 #include "nacl_io/typed_fs_factory.h"
44 #include "sdk_util/auto_lock.h"
45 #include "sdk_util/ref_object.h"
46 #include "sdk_util/string_util.h"
49 #define MAXPATHLEN 256
54 KernelProxy::KernelProxy()
58 exit_callback_user_data_(NULL
),
59 mount_callback_(NULL
),
60 mount_callback_user_data_(NULL
),
61 signal_emitter_(new EventEmitter
) {
62 memset(&sigwinch_handler_
, 0, sizeof(sigwinch_handler_
));
63 sigwinch_handler_
.sa_handler
= SIG_DFL
;
66 KernelProxy::~KernelProxy() {
67 // Clean up the FsFactories.
68 for (FsFactoryMap_t::iterator i
= factories_
.begin(); i
!= factories_
.end();
74 Error
KernelProxy::Init(PepperInterface
* ppapi
) {
79 factories_
["memfs"] = new TypedFsFactory
<MemFs
>;
80 factories_
["dev"] = new TypedFsFactory
<DevFs
>;
81 factories_
["html5fs"] = new TypedFsFactory
<Html5Fs
>;
82 factories_
["httpfs"] = new TypedFsFactory
<HttpFs
>;
83 factories_
["passthroughfs"] = new TypedFsFactory
<PassthroughFs
>;
85 ScopedFilesystem root_fs
;
86 rtn
= MountInternal("", "/", "passthroughfs", 0, NULL
, false, &root_fs
);
91 rtn
= MountInternal("", "/dev", "dev", 0, NULL
, false, &fs
);
94 dev_fs_
= sdk_util::static_scoped_ref_cast
<DevFs
>(fs
);
96 // Create the filesystem nodes for / and /dev afterward. They can't be
97 // created the normal way because the dev filesystem didn't exist yet.
98 rtn
= CreateFsNode(root_fs
);
102 rtn
= CreateFsNode(dev_fs_
);
106 // Open the first three in order to get STDIN, STDOUT, STDERR
108 fd
= open("/dev/stdin", O_RDONLY
, 0);
110 LOG_ERROR("failed to open /dev/stdin: %s", strerror(errno
));
115 fd
= open("/dev/stdout", O_WRONLY
, 0);
117 LOG_ERROR("failed to open /dev/stdout: %s", strerror(errno
));
122 fd
= open("/dev/stderr", O_WRONLY
, 0);
124 LOG_ERROR("failed to open /dev/sterr: %s", strerror(errno
));
129 #ifdef PROVIDES_SOCKET_API
130 host_resolver_
.Init(ppapi_
);
136 stream_fs_
.reset(new StreamFs());
137 int result
= stream_fs_
->Init(args
);
139 LOG_ERROR("initializing streamfs failed: %s", strerror(result
));
146 bool KernelProxy::RegisterFsType(const char* fs_type
,
147 fuse_operations
* fuse_ops
) {
148 FsFactoryMap_t::iterator iter
= factories_
.find(fs_type
);
149 if (iter
!= factories_
.end())
152 factories_
[fs_type
] = new FuseFsFactory(fuse_ops
);
156 bool KernelProxy::UnregisterFsType(const char* fs_type
) {
157 FsFactoryMap_t::iterator iter
= factories_
.find(fs_type
);
158 if (iter
== factories_
.end())
162 factories_
.erase(iter
);
166 void KernelProxy::SetExitCallback(nacl_io_exit_callback_t exit_callback
,
168 exit_callback_
= exit_callback
;
169 exit_callback_user_data_
= user_data
;
172 void KernelProxy::SetMountCallback(nacl_io_mount_callback_t mount_callback
,
174 mount_callback_
= mount_callback
;
175 mount_callback_user_data_
= user_data
;
178 int KernelProxy::open_resource(const char* path
) {
182 Error error
= AcquireFsAndRelPath(path
, &fs
, &rel
);
189 error
= fs
->OpenResource(rel
, &node
);
191 // OpenResource failed, try Open().
192 error
= fs
->Open(rel
, O_RDONLY
, &node
);
199 ScopedKernelHandle
handle(new KernelHandle(fs
, node
));
200 error
= handle
->Init(O_RDONLY
);
206 return AllocateFD(handle
, path
);
209 int KernelProxy::open(const char* path
, int open_flags
, mode_t mode
) {
212 mode_t mask
= ~GetUmask() & S_MODEBITS
;
214 Error error
= AcquireFsAndNode(path
, open_flags
, mode
& mask
, &fs
, &node
);
220 ScopedKernelHandle
handle(new KernelHandle(fs
, node
));
221 error
= handle
->Init(open_flags
);
227 return AllocateFD(handle
, path
);
230 int KernelProxy::pipe(int pipefds
[2]) {
231 PipeNode
* pipe
= new PipeNode(stream_fs_
.get());
232 ScopedNode
node(pipe
);
234 if (pipe
->Init(O_RDWR
) == 0) {
235 ScopedKernelHandle
handle0(new KernelHandle(stream_fs_
, node
));
236 ScopedKernelHandle
handle1(new KernelHandle(stream_fs_
, node
));
238 // Should never fail, but...
239 if (handle0
->Init(O_RDONLY
) || handle1
->Init(O_WRONLY
)) {
244 pipefds
[0] = AllocateFD(handle0
);
245 pipefds
[1] = AllocateFD(handle1
);
253 int KernelProxy::close(int fd
) {
254 ScopedKernelHandle handle
;
255 Error error
= AcquireHandle(fd
, &handle
);
261 // Remove the FD from the process open file descriptor map
266 int KernelProxy::dup(int oldfd
) {
267 ScopedKernelHandle handle
;
269 Error error
= AcquireHandleAndPath(oldfd
, &handle
, &path
);
274 return AllocateFD(handle
, path
);
277 int KernelProxy::dup2(int oldfd
, int newfd
) {
278 // If it's the same file handle, just return
287 ScopedKernelHandle old_handle
;
288 std::string old_path
;
289 Error error
= AcquireHandleAndPath(oldfd
, &old_handle
, &old_path
);
295 FreeAndReassignFD(newfd
, old_handle
, old_path
);
299 int KernelProxy::chdir(const char* path
) {
300 Error error
= SetCWD(path
);
308 void KernelProxy::exit(int status
) {
310 exit_callback_(status
, exit_callback_user_data_
);
313 char* KernelProxy::getcwd(char* buf
, size_t size
) {
319 std::string cwd
= GetCWD();
321 // Verify the buffer is large enough
322 if (size
<= cwd
.size()) {
327 strcpy(buf
, cwd
.c_str());
331 char* KernelProxy::getwd(char* buf
) {
336 return getcwd(buf
, MAXPATHLEN
);
339 int KernelProxy::chmod(const char* path
, mode_t mode
) {
343 Error error
= AcquireFsAndNode(path
, O_RDONLY
, 0, &fs
, &node
);
349 error
= node
->Fchmod(mode
& S_MODEBITS
);
358 int KernelProxy::chown(const char* path
, uid_t owner
, gid_t group
) {
362 int KernelProxy::fchown(int fd
, uid_t owner
, gid_t group
) {
366 int KernelProxy::lchown(const char* path
, uid_t owner
, gid_t group
) {
370 int KernelProxy::mkdir(const char* path
, mode_t mode
) {
374 Error error
= AcquireFsAndRelPath(path
, &fs
, &rel
);
380 mode_t mask
= ~GetUmask() & S_MODEBITS
;
381 error
= fs
->Mkdir(rel
, mode
& mask
);
390 int KernelProxy::rmdir(const char* path
) {
394 Error error
= AcquireFsAndRelPath(path
, &fs
, &rel
);
400 error
= fs
->Rmdir(rel
);
409 int KernelProxy::stat(const char* path
, struct stat
* buf
) {
413 Error error
= AcquireFsAndNode(path
, O_RDONLY
, 0, &fs
, &node
);
419 error
= node
->GetStat(buf
);
428 int KernelProxy::mount(const char* source
,
430 const char* filesystemtype
,
431 unsigned long mountflags
,
434 Error error
= MountInternal(
435 source
, target
, filesystemtype
, mountflags
, data
, true, &fs
);
444 Error
KernelProxy::MountInternal(const char* source
,
446 const char* filesystemtype
,
447 unsigned long mountflags
,
450 ScopedFilesystem
* out_filesystem
) {
451 std::string abs_path
= GetAbsParts(target
).Join();
453 // Find a factory of that type
454 FsFactoryMap_t::iterator factory
= factories_
.find(filesystemtype
);
455 if (factory
== factories_
.end()) {
456 LOG_ERROR("Unknown filesystem type: %s", filesystemtype
);
460 // Create a map of settings
462 smap
["SOURCE"] = source
;
465 std::vector
<std::string
> elements
;
466 sdk_util::SplitString(static_cast<const char*>(data
), ',', &elements
);
468 for (std::vector
<std::string
>::const_iterator it
= elements
.begin();
469 it
!= elements
.end();
471 size_t location
= it
->find('=');
472 if (location
!= std::string::npos
) {
473 std::string key
= it
->substr(0, location
);
474 std::string val
= it
->substr(location
+ 1);
484 args
.string_map
= smap
;
488 Error error
= factory
->second
->CreateFilesystem(args
, &fs
);
492 error
= AttachFsAtPath(fs
, abs_path
);
496 if (create_fs_node
) {
497 error
= CreateFsNode(fs
);
499 DetachFsAtPath(abs_path
, &fs
);
504 *out_filesystem
= fs
;
506 if (mount_callback_
) {
507 mount_callback_(source
,
513 mount_callback_user_data_
);
519 Error
KernelProxy::CreateFsNode(const ScopedFilesystem
& fs
) {
522 return dev_fs_
->CreateFsNode(fs
.get());
525 int KernelProxy::umount(const char* path
) {
527 Error error
= DetachFsAtPath(path
, &fs
);
533 error
= dev_fs_
->DestroyFsNode(fs
.get());
535 // Ignore any errors here, just log.
536 LOG_ERROR("Unable to destroy FsNode: %s", strerror(error
));
541 ssize_t
KernelProxy::read(int fd
, void* buf
, size_t nbytes
) {
542 ScopedKernelHandle handle
;
543 Error error
= AcquireHandle(fd
, &handle
);
550 error
= handle
->Read(buf
, nbytes
, &cnt
);
559 ssize_t
KernelProxy::write(int fd
, const void* buf
, size_t nbytes
) {
560 ScopedKernelHandle handle
;
561 Error error
= AcquireHandle(fd
, &handle
);
568 error
= handle
->Write(buf
, nbytes
, &cnt
);
577 int KernelProxy::fstat(int fd
, struct stat
* buf
) {
578 ScopedKernelHandle handle
;
579 Error error
= AcquireHandle(fd
, &handle
);
585 error
= handle
->node()->GetStat(buf
);
594 int KernelProxy::getdents(int fd
, void* buf
, unsigned int count
) {
595 ScopedKernelHandle handle
;
596 Error error
= AcquireHandle(fd
, &handle
);
603 error
= handle
->GetDents(static_cast<dirent
*>(buf
), count
, &cnt
);
610 int KernelProxy::fchdir(int fd
) {
611 ScopedKernelHandle handle
;
613 Error error
= AcquireHandleAndPath(fd
, &handle
, &path
);
619 if (!handle
->node()->IsaDir()) {
629 error
= SetCWD(path
);
631 // errno is return value from SetCWD
638 int KernelProxy::ftruncate(int fd
, off_t length
) {
639 ScopedKernelHandle handle
;
640 Error error
= AcquireHandle(fd
, &handle
);
646 if (handle
->OpenMode() == O_RDONLY
) {
651 error
= handle
->node()->FTruncate(length
);
660 int KernelProxy::fsync(int fd
) {
661 ScopedKernelHandle handle
;
662 Error error
= AcquireHandle(fd
, &handle
);
668 error
= handle
->node()->FSync();
677 int KernelProxy::fdatasync(int fd
) {
682 int KernelProxy::isatty(int fd
) {
683 ScopedKernelHandle handle
;
684 Error error
= AcquireHandle(fd
, &handle
);
690 error
= handle
->node()->Isatty();
699 int KernelProxy::ioctl(int fd
, int request
, va_list args
) {
700 ScopedKernelHandle handle
;
701 Error error
= AcquireHandle(fd
, &handle
);
707 error
= handle
->node()->VIoctl(request
, args
);
716 int KernelProxy::futimens(int fd
, const struct timespec times
[2]) {
717 ScopedKernelHandle handle
;
718 Error error
= AcquireHandle(fd
, &handle
);
724 return FutimensInternal(handle
->node(), times
);
727 Error
KernelProxy::FutimensInternal(const ScopedNode
& node
,
728 const struct timespec times
[2]) {
731 struct timespec now
[2];
733 error
= gettimeofday(&tm
, NULL
);
739 now
[0].tv_sec
= now
[1].tv_sec
= tm
.tv_sec
;
740 now
[0].tv_nsec
= now
[1].tv_nsec
= tm
.tv_usec
* 1000;
741 error
= node
->Futimens(now
);
743 error
= node
->Futimens(times
);
754 off_t
KernelProxy::lseek(int fd
, off_t offset
, int whence
) {
755 ScopedKernelHandle handle
;
756 Error error
= AcquireHandle(fd
, &handle
);
763 error
= handle
->Seek(offset
, whence
, &new_offset
);
772 int KernelProxy::unlink(const char* path
) {
776 Error error
= AcquireFsAndRelPath(path
, &fs
, &rel
);
782 error
= fs
->Unlink(rel
);
791 int KernelProxy::truncate(const char* path
, off_t len
) {
795 Error error
= AcquireFsAndNode(path
, O_WRONLY
, 0, &fs
, &node
);
801 // Directories cannot be truncated.
802 if (node
->IsaDir()) {
806 if (!node
->CanOpen(O_WRONLY
)) {
811 error
= node
->FTruncate(len
);
820 int KernelProxy::lstat(const char* path
, struct stat
* buf
) {
821 return stat(path
, buf
);
824 int KernelProxy::rename(const char* path
, const char* newpath
) {
827 Error error
= AcquireFsAndRelPath(path
, &fs
, &rel
);
833 ScopedFilesystem newfs
;
835 error
= AcquireFsAndRelPath(newpath
, &newfs
, &newrel
);
841 if (newfs
.get() != fs
.get()) {
842 // Renaming accross mountpoints is not allowed
847 // They already point to the same path
851 error
= fs
->Rename(rel
, newrel
);
860 int KernelProxy::remove(const char* path
) {
864 Error error
= AcquireFsAndRelPath(path
, &fs
, &rel
);
870 error
= fs
->Remove(rel
);
879 int KernelProxy::fchmod(int fd
, mode_t mode
) {
880 ScopedKernelHandle handle
;
881 Error error
= AcquireHandle(fd
, &handle
);
887 error
= handle
->node()->Fchmod(mode
& S_MODEBITS
);
896 int KernelProxy::fcntl(int fd
, int request
, va_list args
) {
899 // F_GETFD and F_SETFD are descriptor specific flags that
900 // are stored in the KernelObject's decriptor map unlike
901 // F_GETFL and F_SETFL which are handle specific.
905 error
= GetFDFlags(fd
, &rtn
);
913 int flags
= va_arg(args
, int);
914 error
= SetFDFlags(fd
, flags
);
923 ScopedKernelHandle handle
;
924 error
= AcquireHandle(fd
, &handle
);
931 error
= handle
->VFcntl(request
, &rtn
, args
);
940 int KernelProxy::access(const char* path
, int amode
) {
942 int rtn
= stat(path
, &buf
);
946 if (((amode
& R_OK
) && !(buf
.st_mode
& S_IREAD
)) ||
947 ((amode
& W_OK
) && !(buf
.st_mode
& S_IWRITE
)) ||
948 ((amode
& X_OK
) && !(buf
.st_mode
& S_IEXEC
))) {
956 int KernelProxy::readlink(const char* path
, char* buf
, size_t count
) {
957 LOG_TRACE("readlink is not implemented.");
962 int KernelProxy::utimens(const char* path
, const struct timespec times
[2]) {
966 Error error
= AcquireFsAndNode(path
, O_WRONLY
, 0, &fs
, &node
);
972 return FutimensInternal(node
, times
);
975 // TODO(bradnelson): Needs implementation.
976 int KernelProxy::link(const char* oldpath
, const char* newpath
) {
977 LOG_TRACE("link is not implemented.");
982 int KernelProxy::symlink(const char* oldpath
, const char* newpath
) {
983 LOG_TRACE("symlink is not implemented.");
988 void* KernelProxy::mmap(void* addr
,
994 // We shouldn't be getting anonymous mmaps here.
995 assert((flags
& MAP_ANONYMOUS
) == 0);
998 ScopedKernelHandle handle
;
999 Error error
= AcquireHandle(fd
, &handle
);
1006 error
= handle
->node()->MMap(addr
, length
, prot
, flags
, offset
, &new_addr
);
1015 int KernelProxy::munmap(void* addr
, size_t length
) {
1016 // NOTE: The comment below is from a previous discarded implementation that
1017 // tracks mmap'd regions. For simplicity, we no longer do this; because we
1018 // "snapshot" the contents of the file in mmap(), and don't support
1019 // write-back or updating the mapped region when the file is written, holding
1020 // on to the KernelHandle is pointless.
1022 // If we ever do, these threading issues should be considered.
1025 // WARNING: this function may be called by free().
1027 // There is a potential deadlock scenario:
1028 // Thread 1: open() -> takes lock1 -> free() -> takes lock2
1029 // Thread 2: free() -> takes lock2 -> munmap() -> takes lock1
1031 // Note that open() above could be any function that takes a lock that is
1032 // shared with munmap (this includes munmap!)
1034 // To prevent this, we avoid taking locks in munmap() that are used by other
1035 // nacl_io functions that may call free. Specifically, we only take the
1036 // mmap_lock, which is only shared with mmap() above. There is still a
1037 // possibility of deadlock if mmap() or munmap() calls free(), so this is not
1040 // Unfortunately, munmap still needs to acquire other locks; see the call to
1041 // ReleaseHandle below which takes the process lock. This is safe as long as
1042 // this is never executed from free() -- we can be reasonably sure this is
1043 // true, because malloc only makes anonymous mmap() requests, and should only
1044 // be munmapping those allocations. We never add to mmap_info_list_ for
1045 // anonymous maps, so the unmap_list should always be empty when called from
1050 int KernelProxy::tcflush(int fd
, int queue_selector
) {
1051 ScopedKernelHandle handle
;
1052 Error error
= AcquireHandle(fd
, &handle
);
1058 error
= handle
->node()->Tcflush(queue_selector
);
1067 int KernelProxy::tcgetattr(int fd
, struct termios
* termios_p
) {
1068 ScopedKernelHandle handle
;
1069 Error error
= AcquireHandle(fd
, &handle
);
1075 error
= handle
->node()->Tcgetattr(termios_p
);
1084 int KernelProxy::tcsetattr(int fd
,
1085 int optional_actions
,
1086 const struct termios
* termios_p
) {
1087 ScopedKernelHandle handle
;
1088 Error error
= AcquireHandle(fd
, &handle
);
1094 error
= handle
->node()->Tcsetattr(optional_actions
, termios_p
);
1103 int KernelProxy::kill(pid_t pid
, int sig
) {
1104 // Currently we don't even pretend that other processes exist
1105 // so we can only send a signal to outselves. For kill(2)
1106 // pid 0 means the current process group and -1 means all the
1107 // processes we have permission to send signals to.
1108 if (pid
!= getpid() && pid
!= -1 && pid
!= 0) {
1113 // Raise an event so that select/poll get interrupted.
1114 AUTO_LOCK(signal_emitter_
->GetLock())
1115 signal_emitter_
->RaiseEvents_Locked(POLLERR
);
1118 if (sigwinch_handler_
.sa_handler
!= SIG_IGN
&&
1119 sigwinch_handler_
.sa_handler
!= SIG_DFL
) {
1120 sigwinch_handler_
.sa_handler(SIGWINCH
);
1129 LOG_TRACE("Unsupported signal: %d", sig
);
1136 int KernelProxy::sigaction(int signum
,
1137 const struct sigaction
* action
,
1138 struct sigaction
* oaction
) {
1139 if (action
&& action
->sa_flags
& SA_SIGINFO
) {
1140 // We don't support SA_SIGINFO (sa_sigaction field) yet
1149 *oaction
= sigwinch_handler_
;
1151 sigwinch_handler_
= *action
;
1160 #if defined(SIGPOLL)
1172 if (action
&& action
->sa_handler
!= SIG_DFL
) {
1173 // Trying to set this action to anything other than SIG_DFL
1174 // is not yet supported.
1175 LOG_TRACE("sigaction on signal %d != SIG_DFL not supported.", signum
);
1181 memset(oaction
, 0, sizeof(*oaction
));
1182 oaction
->sa_handler
= SIG_DFL
;
1186 // KILL and STOP cannot be handled
1189 LOG_TRACE("sigaction on SIGKILL/SIGSTOP not supported.");
1199 mode_t
KernelProxy::umask(mode_t mask
) {
1200 return SetUmask(mask
& S_MODEBITS
);
1203 #ifdef PROVIDES_SOCKET_API
1205 int KernelProxy::select(int nfds
,
1209 struct timeval
* timeout
) {
1210 std::vector
<pollfd
> pollfds
;
1212 for (int fd
= 0; fd
< nfds
; fd
++) {
1214 if (readfds
&& FD_ISSET(fd
, readfds
)) {
1216 FD_CLR(fd
, readfds
);
1219 if (writefds
&& FD_ISSET(fd
, writefds
)) {
1221 FD_CLR(fd
, writefds
);
1224 if (exceptfds
&& FD_ISSET(fd
, exceptfds
)) {
1225 events
|= POLLERR
| POLLHUP
;
1226 FD_CLR(fd
, exceptfds
);
1232 info
.events
= events
;
1233 pollfds
.push_back(info
);
1237 // NULL timeout signals wait forever.
1238 int ms_timeout
= -1;
1239 if (timeout
!= NULL
) {
1240 int64_t ms
= timeout
->tv_sec
* 1000 + ((timeout
->tv_usec
+ 500) / 1000);
1242 // If the timeout is invalid or too long (larger than signed 32 bit).
1243 if ((timeout
->tv_sec
< 0) || (timeout
->tv_sec
>= (INT_MAX
/ 1000)) ||
1244 (timeout
->tv_usec
< 0) || (timeout
->tv_usec
>= 1000000) || (ms
< 0) ||
1246 LOG_TRACE("Invalid timeout: tv_sec=%" PRIi64
" tv_usec=%ld.",
1253 ms_timeout
= static_cast<int>(ms
);
1256 int result
= poll(&pollfds
[0], pollfds
.size(), ms_timeout
);
1261 for (size_t index
= 0; index
< pollfds
.size(); index
++) {
1262 pollfd
* info
= &pollfds
[index
];
1263 if (info
->revents
& POLLIN
) {
1264 FD_SET(info
->fd
, readfds
);
1267 if (info
->revents
& POLLOUT
) {
1268 FD_SET(info
->fd
, writefds
);
1271 if (info
->revents
& (POLLHUP
| POLLERR
)) {
1272 FD_SET(info
->fd
, exceptfds
);
1281 PollInfo() : index(-1) {};
1283 std::vector
<struct pollfd
*> fds
;
1287 typedef std::map
<EventEmitter
*, PollInfo
> EventPollMap_t
;
1289 int KernelProxy::poll(struct pollfd
* fds
, nfds_t nfds
, int timeout
) {
1290 EventPollMap_t event_map
;
1292 std::vector
<EventRequest
> requests
;
1293 size_t event_cnt
= 0;
1295 for (int index
= 0; static_cast<nfds_t
>(index
) < nfds
; index
++) {
1296 ScopedKernelHandle handle
;
1297 struct pollfd
* fd_info
= &fds
[index
];
1298 Error err
= AcquireHandle(fd_info
->fd
, &handle
);
1300 fd_info
->revents
= 0;
1302 // If the node isn't open, or somehow invalid, mark it so.
1304 fd_info
->revents
= POLLNVAL
;
1309 // If it's already signaled, then just capture the event
1310 ScopedEventEmitter
emitter(handle
->node()->GetEventEmitter());
1311 int events
= POLLIN
| POLLOUT
;
1313 events
= emitter
->GetEventStatus();
1315 if (events
& fd_info
->events
) {
1316 fd_info
->revents
= events
& fd_info
->events
;
1321 if (NULL
== emitter
) {
1322 fd_info
->revents
= POLLNVAL
;
1327 // Otherwise try to track it.
1328 PollInfo
* info
= &event_map
[emitter
.get()];
1329 if (info
->index
== -1) {
1330 EventRequest request
;
1331 request
.emitter
= emitter
;
1332 request
.filter
= fd_info
->events
;
1335 info
->index
= requests
.size();
1336 requests
.push_back(request
);
1338 info
->fds
.push_back(fd_info
);
1339 requests
[info
->index
].filter
|= fd_info
->events
;
1342 // If nothing is signaled, then we must wait on the event map
1343 if (0 == event_cnt
) {
1344 EventListenerPoll wait
;
1345 Error err
= wait
.WaitOnAny(&requests
[0], requests
.size(), timeout
);
1346 if ((err
!= 0) && (err
!= ETIMEDOUT
)) {
1351 for (size_t rindex
= 0; rindex
< requests
.size(); rindex
++) {
1352 EventRequest
* request
= &requests
[rindex
];
1353 if (request
->events
) {
1354 PollInfo
* poll_info
= &event_map
[request
->emitter
.get()];
1355 for (size_t findex
= 0; findex
< poll_info
->fds
.size(); findex
++) {
1356 struct pollfd
* fd_info
= poll_info
->fds
[findex
];
1357 uint32_t events
= fd_info
->events
& request
->events
;
1359 fd_info
->revents
= events
;
1371 int KernelProxy::accept(int fd
, struct sockaddr
* addr
, socklen_t
* len
) {
1372 ScopedKernelHandle handle
;
1373 Error error
= AcquireHandle(fd
, &handle
);
1379 PP_Resource new_sock
= 0;
1380 error
= handle
->Accept(&new_sock
, addr
, len
);
1386 SocketNode
* sock
= new TcpNode(stream_fs_
.get(), new_sock
);
1388 // The SocketNode now holds a reference to the new socket
1389 // so we release ours.
1390 ppapi_
->ReleaseResource(new_sock
);
1391 error
= sock
->Init(O_RDWR
);
1397 ScopedNode
node(sock
);
1398 ScopedKernelHandle
new_handle(new KernelHandle(stream_fs_
, node
));
1399 error
= new_handle
->Init(O_RDWR
);
1405 return AllocateFD(new_handle
);
1408 int KernelProxy::bind(int fd
, const struct sockaddr
* addr
, socklen_t len
) {
1414 ScopedKernelHandle handle
;
1415 if (AcquireSocketHandle(fd
, &handle
) == -1)
1418 Error err
= handle
->socket_node()->Bind(addr
, len
);
1427 int KernelProxy::connect(int fd
, const struct sockaddr
* addr
, socklen_t len
) {
1433 ScopedKernelHandle handle
;
1434 Error error
= AcquireHandle(fd
, &handle
);
1440 error
= handle
->Connect(addr
, len
);
1449 void KernelProxy::freeaddrinfo(struct addrinfo
* res
) {
1450 return host_resolver_
.freeaddrinfo(res
);
1453 int KernelProxy::getaddrinfo(const char* node
,
1454 const char* service
,
1455 const struct addrinfo
* hints
,
1456 struct addrinfo
** res
) {
1457 return host_resolver_
.getaddrinfo(node
, service
, hints
, res
);
1460 int KernelProxy::getnameinfo(const struct sockaddr
*sa
,
1467 return host_resolver_
.getnameinfo(sa
, salen
, host
, hostlen
, serv
, servlen
,
1471 struct hostent
* KernelProxy::gethostbyname(const char* name
) {
1472 return host_resolver_
.gethostbyname(name
);
1475 int KernelProxy::getpeername(int fd
, struct sockaddr
* addr
, socklen_t
* len
) {
1476 if (NULL
== addr
|| NULL
== len
) {
1481 ScopedKernelHandle handle
;
1482 if (AcquireSocketHandle(fd
, &handle
) == -1)
1485 Error err
= handle
->socket_node()->GetPeerName(addr
, len
);
1494 int KernelProxy::getsockname(int fd
, struct sockaddr
* addr
, socklen_t
* len
) {
1495 if (NULL
== addr
|| NULL
== len
) {
1500 ScopedKernelHandle handle
;
1501 if (AcquireSocketHandle(fd
, &handle
) == -1)
1504 Error err
= handle
->socket_node()->GetSockName(addr
, len
);
1513 int KernelProxy::getsockopt(int fd
,
1518 if (NULL
== optval
|| NULL
== len
) {
1523 ScopedKernelHandle handle
;
1524 if (AcquireSocketHandle(fd
, &handle
) == -1)
1527 Error err
= handle
->socket_node()->GetSockOpt(lvl
, optname
, optval
, len
);
1536 int KernelProxy::listen(int fd
, int backlog
) {
1537 ScopedKernelHandle handle
;
1538 if (AcquireSocketHandle(fd
, &handle
) == -1)
1541 Error err
= handle
->socket_node()->Listen(backlog
);
1550 ssize_t
KernelProxy::recv(int fd
, void* buf
, size_t len
, int flags
) {
1556 ScopedKernelHandle handle
;
1557 Error error
= AcquireHandle(fd
, &handle
);
1564 error
= handle
->Recv(buf
, len
, flags
, &out_len
);
1570 return static_cast<ssize_t
>(out_len
);
1573 ssize_t
KernelProxy::recvfrom(int fd
,
1577 struct sockaddr
* addr
,
1578 socklen_t
* addrlen
) {
1579 // According to the manpage, recvfrom with a null addr is identical to recv.
1581 return recv(fd
, buf
, len
, flags
);
1584 if (NULL
== buf
|| NULL
== addrlen
) {
1589 ScopedKernelHandle handle
;
1590 Error error
= AcquireHandle(fd
, &handle
);
1597 error
= handle
->RecvFrom(buf
, len
, flags
, addr
, addrlen
, &out_len
);
1603 return static_cast<ssize_t
>(out_len
);
1606 ssize_t
KernelProxy::recvmsg(int fd
, struct msghdr
* msg
, int flags
) {
1612 ScopedKernelHandle handle
;
1613 if (AcquireSocketHandle(fd
, &handle
) == -1)
1620 ssize_t
KernelProxy::send(int fd
, const void* buf
, size_t len
, int flags
) {
1626 ScopedKernelHandle handle
;
1627 Error error
= AcquireHandle(fd
, &handle
);
1634 error
= handle
->Send(buf
, len
, flags
, &out_len
);
1640 return static_cast<ssize_t
>(out_len
);
1643 ssize_t
KernelProxy::sendto(int fd
,
1647 const struct sockaddr
* addr
,
1648 socklen_t addrlen
) {
1649 // According to the manpage, sendto with a null addr is identical to send.
1651 return send(fd
, buf
, len
, flags
);
1659 ScopedKernelHandle handle
;
1660 Error error
= AcquireHandle(fd
, &handle
);
1667 error
= handle
->SendTo(buf
, len
, flags
, addr
, addrlen
, &out_len
);
1673 return static_cast<ssize_t
>(out_len
);
1676 ssize_t
KernelProxy::sendmsg(int fd
, const struct msghdr
* msg
, int flags
) {
1682 ScopedKernelHandle handle
;
1683 if (AcquireSocketHandle(fd
, &handle
) == -1)
1690 int KernelProxy::setsockopt(int fd
,
1695 if (NULL
== optval
) {
1700 ScopedKernelHandle handle
;
1701 if (AcquireSocketHandle(fd
, &handle
) == -1)
1704 Error err
= handle
->socket_node()->SetSockOpt(lvl
, optname
, optval
, len
);
1713 int KernelProxy::shutdown(int fd
, int how
) {
1714 ScopedKernelHandle handle
;
1715 if (AcquireSocketHandle(fd
, &handle
) == -1)
1718 Error err
= handle
->socket_node()->Shutdown(how
);
1727 int KernelProxy::socket(int domain
, int type
, int protocol
) {
1728 if (AF_INET
!= domain
&& AF_INET6
!= domain
) {
1729 errno
= EAFNOSUPPORT
;
1733 int open_flags
= O_RDWR
;
1735 #if defined(SOCK_CLOEXEC)
1736 if (type
& SOCK_CLOEXEC
) {
1737 #if defined(O_CLOEXEC)
1738 // The NaCl newlib version of fcntl.h doesn't currently define
1740 // TODO(sbc): remove this guard once it gets added.
1741 open_flags
|= O_CLOEXEC
;
1743 type
&= ~SOCK_CLOEXEC
;
1747 #if defined(SOCK_NONBLOCK)
1748 if (type
& SOCK_NONBLOCK
) {
1749 open_flags
|= O_NONBLOCK
;
1750 type
&= ~SOCK_NONBLOCK
;
1754 SocketNode
* sock
= NULL
;
1757 sock
= new UdpNode(stream_fs_
.get());
1761 sock
= new TcpNode(stream_fs_
.get());
1764 case SOCK_SEQPACKET
:
1767 errno
= EPROTONOSUPPORT
;
1775 ScopedNode
node(sock
);
1776 Error rtn
= sock
->Init(O_RDWR
);
1782 ScopedKernelHandle
handle(new KernelHandle(stream_fs_
, node
));
1783 rtn
= handle
->Init(open_flags
);
1789 return AllocateFD(handle
);
1792 int KernelProxy::socketpair(int domain
, int type
, int protocol
, int* sv
) {
1798 // Catch-22: We don't support AF_UNIX, but any other AF doesn't support
1799 // socket pairs. Thus, this function always fails.
1800 if (AF_UNIX
!= domain
) {
1801 errno
= EPROTONOSUPPORT
;
1805 if (AF_INET
!= domain
&& AF_INET6
!= domain
) {
1806 errno
= EAFNOSUPPORT
;
1810 // We cannot reach this point.
1815 int KernelProxy::AcquireSocketHandle(int fd
, ScopedKernelHandle
* handle
) {
1816 Error error
= AcquireHandle(fd
, handle
);
1823 if ((handle
->get()->node_
->GetType() & S_IFSOCK
) == 0) {
1831 #endif // PROVIDES_SOCKET_API
1833 } // namespace_nacl_io