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
);
426 * newlib's scandir() assumes that directories are empty if st_size == 0.
427 * This is probably a bad assumption, but until we fix newlib always return
428 * a non-zero directory size.
430 if (node
->IsaDir() && buf
->st_size
== 0)
436 int KernelProxy::mount(const char* source
,
438 const char* filesystemtype
,
439 unsigned long mountflags
,
442 Error error
= MountInternal(
443 source
, target
, filesystemtype
, mountflags
, data
, true, &fs
);
452 Error
KernelProxy::MountInternal(const char* source
,
454 const char* filesystemtype
,
455 unsigned long mountflags
,
458 ScopedFilesystem
* out_filesystem
) {
459 std::string abs_path
= GetAbsParts(target
).Join();
461 // Find a factory of that type
462 FsFactoryMap_t::iterator factory
= factories_
.find(filesystemtype
);
463 if (factory
== factories_
.end()) {
464 LOG_ERROR("Unknown filesystem type: %s", filesystemtype
);
468 // Create a map of settings
470 smap
["SOURCE"] = source
;
473 std::vector
<std::string
> elements
;
474 sdk_util::SplitString(static_cast<const char*>(data
), ',', &elements
);
476 for (std::vector
<std::string
>::const_iterator it
= elements
.begin();
477 it
!= elements
.end();
479 size_t location
= it
->find('=');
480 if (location
!= std::string::npos
) {
481 std::string key
= it
->substr(0, location
);
482 std::string val
= it
->substr(location
+ 1);
492 args
.string_map
= smap
;
496 Error error
= factory
->second
->CreateFilesystem(args
, &fs
);
500 error
= AttachFsAtPath(fs
, abs_path
);
504 if (create_fs_node
) {
505 error
= CreateFsNode(fs
);
507 DetachFsAtPath(abs_path
, &fs
);
512 *out_filesystem
= fs
;
514 if (mount_callback_
) {
515 mount_callback_(source
,
521 mount_callback_user_data_
);
527 Error
KernelProxy::CreateFsNode(const ScopedFilesystem
& fs
) {
530 return dev_fs_
->CreateFsNode(fs
.get());
533 int KernelProxy::umount(const char* path
) {
535 Error error
= DetachFsAtPath(path
, &fs
);
541 error
= dev_fs_
->DestroyFsNode(fs
.get());
543 // Ignore any errors here, just log.
544 LOG_ERROR("Unable to destroy FsNode: %s", strerror(error
));
549 ssize_t
KernelProxy::read(int fd
, void* buf
, size_t nbytes
) {
550 ScopedKernelHandle handle
;
551 Error error
= AcquireHandle(fd
, &handle
);
558 error
= handle
->Read(buf
, nbytes
, &cnt
);
567 ssize_t
KernelProxy::write(int fd
, const void* buf
, size_t nbytes
) {
568 ScopedKernelHandle handle
;
569 Error error
= AcquireHandle(fd
, &handle
);
576 error
= handle
->Write(buf
, nbytes
, &cnt
);
585 int KernelProxy::fstat(int fd
, struct stat
* buf
) {
586 ScopedKernelHandle handle
;
587 Error error
= AcquireHandle(fd
, &handle
);
593 error
= handle
->node()->GetStat(buf
);
600 * newlib's scandir() assumes that directories are empty if st_size == 0.
601 * This is probably a bad assumption, but until we fix newlib always return
602 * a non-zero directory size.
604 if (handle
->node()->IsaDir() && buf
->st_size
== 0)
610 int KernelProxy::getdents(int fd
, struct dirent
* buf
, unsigned int count
) {
611 ScopedKernelHandle handle
;
612 Error error
= AcquireHandle(fd
, &handle
);
619 error
= handle
->GetDents(buf
, count
, &cnt
);
626 int KernelProxy::fchdir(int fd
) {
627 ScopedKernelHandle handle
;
629 Error error
= AcquireHandleAndPath(fd
, &handle
, &path
);
635 if (!handle
->node()->IsaDir()) {
645 error
= SetCWD(path
);
647 // errno is return value from SetCWD
654 int KernelProxy::ftruncate(int fd
, off_t length
) {
655 ScopedKernelHandle handle
;
656 Error error
= AcquireHandle(fd
, &handle
);
662 if (handle
->OpenMode() == O_RDONLY
) {
667 error
= handle
->node()->FTruncate(length
);
676 int KernelProxy::fsync(int fd
) {
677 ScopedKernelHandle handle
;
678 Error error
= AcquireHandle(fd
, &handle
);
684 error
= handle
->node()->FSync();
693 int KernelProxy::fdatasync(int fd
) {
698 int KernelProxy::isatty(int fd
) {
699 ScopedKernelHandle handle
;
700 Error error
= AcquireHandle(fd
, &handle
);
706 error
= handle
->node()->Isatty();
715 int KernelProxy::ioctl(int fd
, int request
, va_list args
) {
716 ScopedKernelHandle handle
;
717 Error error
= AcquireHandle(fd
, &handle
);
723 error
= handle
->node()->VIoctl(request
, args
);
732 int KernelProxy::futimens(int fd
, const struct timespec times
[2]) {
733 ScopedKernelHandle handle
;
734 Error error
= AcquireHandle(fd
, &handle
);
740 return FutimensInternal(handle
->node(), times
);
743 Error
KernelProxy::FutimensInternal(const ScopedNode
& node
,
744 const struct timespec times
[2]) {
747 struct timespec now
[2];
749 error
= gettimeofday(&tm
, NULL
);
755 now
[0].tv_sec
= now
[1].tv_sec
= tm
.tv_sec
;
756 now
[0].tv_nsec
= now
[1].tv_nsec
= tm
.tv_usec
* 1000;
757 error
= node
->Futimens(now
);
759 error
= node
->Futimens(times
);
770 off_t
KernelProxy::lseek(int fd
, off_t offset
, int whence
) {
771 ScopedKernelHandle handle
;
772 Error error
= AcquireHandle(fd
, &handle
);
779 error
= handle
->Seek(offset
, whence
, &new_offset
);
788 int KernelProxy::unlink(const char* path
) {
792 Error error
= AcquireFsAndRelPath(path
, &fs
, &rel
);
798 error
= fs
->Unlink(rel
);
807 int KernelProxy::truncate(const char* path
, off_t len
) {
811 Error error
= AcquireFsAndNode(path
, O_WRONLY
, 0, &fs
, &node
);
817 // Directories cannot be truncated.
818 if (node
->IsaDir()) {
822 if (!node
->CanOpen(O_WRONLY
)) {
827 error
= node
->FTruncate(len
);
836 int KernelProxy::lstat(const char* path
, struct stat
* buf
) {
837 return stat(path
, buf
);
840 int KernelProxy::rename(const char* path
, const char* newpath
) {
843 Error error
= AcquireFsAndRelPath(path
, &fs
, &rel
);
849 ScopedFilesystem newfs
;
851 error
= AcquireFsAndRelPath(newpath
, &newfs
, &newrel
);
857 if (newfs
.get() != fs
.get()) {
858 // Renaming accross mountpoints is not allowed
863 // They already point to the same path
867 error
= fs
->Rename(rel
, newrel
);
876 int KernelProxy::remove(const char* path
) {
880 Error error
= AcquireFsAndRelPath(path
, &fs
, &rel
);
886 error
= fs
->Remove(rel
);
895 int KernelProxy::fchmod(int fd
, mode_t mode
) {
896 ScopedKernelHandle handle
;
897 Error error
= AcquireHandle(fd
, &handle
);
903 error
= handle
->node()->Fchmod(mode
& S_MODEBITS
);
912 int KernelProxy::fcntl(int fd
, int request
, va_list args
) {
915 // F_GETFD and F_SETFD are descriptor specific flags that
916 // are stored in the KernelObject's decriptor map unlike
917 // F_GETFL and F_SETFL which are handle specific.
921 error
= GetFDFlags(fd
, &rtn
);
929 int flags
= va_arg(args
, int);
930 error
= SetFDFlags(fd
, flags
);
939 ScopedKernelHandle handle
;
940 error
= AcquireHandle(fd
, &handle
);
947 error
= handle
->VFcntl(request
, &rtn
, args
);
956 int KernelProxy::access(const char* path
, int amode
) {
958 int rtn
= stat(path
, &buf
);
962 if (((amode
& R_OK
) && !(buf
.st_mode
& S_IREAD
)) ||
963 ((amode
& W_OK
) && !(buf
.st_mode
& S_IWRITE
)) ||
964 ((amode
& X_OK
) && !(buf
.st_mode
& S_IEXEC
))) {
972 int KernelProxy::readlink(const char* path
, char* buf
, size_t count
) {
973 LOG_TRACE("readlink is not implemented.");
978 int KernelProxy::utimens(const char* path
, const struct timespec times
[2]) {
982 Error error
= AcquireFsAndNode(path
, O_WRONLY
, 0, &fs
, &node
);
988 return FutimensInternal(node
, times
);
991 // TODO(bradnelson): Needs implementation.
992 int KernelProxy::link(const char* oldpath
, const char* newpath
) {
993 LOG_TRACE("link is not implemented.");
998 int KernelProxy::symlink(const char* oldpath
, const char* newpath
) {
999 LOG_TRACE("symlink is not implemented.");
1004 void* KernelProxy::mmap(void* addr
,
1010 // We shouldn't be getting anonymous mmaps here.
1011 assert((flags
& MAP_ANONYMOUS
) == 0);
1014 ScopedKernelHandle handle
;
1015 Error error
= AcquireHandle(fd
, &handle
);
1022 error
= handle
->node()->MMap(addr
, length
, prot
, flags
, offset
, &new_addr
);
1031 int KernelProxy::munmap(void* addr
, size_t length
) {
1032 // NOTE: The comment below is from a previous discarded implementation that
1033 // tracks mmap'd regions. For simplicity, we no longer do this; because we
1034 // "snapshot" the contents of the file in mmap(), and don't support
1035 // write-back or updating the mapped region when the file is written, holding
1036 // on to the KernelHandle is pointless.
1038 // If we ever do, these threading issues should be considered.
1041 // WARNING: this function may be called by free().
1043 // There is a potential deadlock scenario:
1044 // Thread 1: open() -> takes lock1 -> free() -> takes lock2
1045 // Thread 2: free() -> takes lock2 -> munmap() -> takes lock1
1047 // Note that open() above could be any function that takes a lock that is
1048 // shared with munmap (this includes munmap!)
1050 // To prevent this, we avoid taking locks in munmap() that are used by other
1051 // nacl_io functions that may call free. Specifically, we only take the
1052 // mmap_lock, which is only shared with mmap() above. There is still a
1053 // possibility of deadlock if mmap() or munmap() calls free(), so this is not
1056 // Unfortunately, munmap still needs to acquire other locks; see the call to
1057 // ReleaseHandle below which takes the process lock. This is safe as long as
1058 // this is never executed from free() -- we can be reasonably sure this is
1059 // true, because malloc only makes anonymous mmap() requests, and should only
1060 // be munmapping those allocations. We never add to mmap_info_list_ for
1061 // anonymous maps, so the unmap_list should always be empty when called from
1066 int KernelProxy::tcflush(int fd
, int queue_selector
) {
1067 ScopedKernelHandle handle
;
1068 Error error
= AcquireHandle(fd
, &handle
);
1074 error
= handle
->node()->Tcflush(queue_selector
);
1083 int KernelProxy::tcgetattr(int fd
, struct termios
* termios_p
) {
1084 ScopedKernelHandle handle
;
1085 Error error
= AcquireHandle(fd
, &handle
);
1091 error
= handle
->node()->Tcgetattr(termios_p
);
1100 int KernelProxy::tcsetattr(int fd
,
1101 int optional_actions
,
1102 const struct termios
* termios_p
) {
1103 ScopedKernelHandle handle
;
1104 Error error
= AcquireHandle(fd
, &handle
);
1110 error
= handle
->node()->Tcsetattr(optional_actions
, termios_p
);
1119 int KernelProxy::kill(pid_t pid
, int sig
) {
1120 // Currently we don't even pretend that other processes exist
1121 // so we can only send a signal to outselves. For kill(2)
1122 // pid 0 means the current process group and -1 means all the
1123 // processes we have permission to send signals to.
1124 if (pid
!= getpid() && pid
!= -1 && pid
!= 0) {
1129 // Raise an event so that select/poll get interrupted.
1130 AUTO_LOCK(signal_emitter_
->GetLock())
1131 signal_emitter_
->RaiseEvents_Locked(POLLERR
);
1134 if (sigwinch_handler_
.sa_handler
!= SIG_IGN
&&
1135 sigwinch_handler_
.sa_handler
!= SIG_DFL
) {
1136 sigwinch_handler_
.sa_handler(SIGWINCH
);
1145 LOG_TRACE("Unsupported signal: %d", sig
);
1152 int KernelProxy::sigaction(int signum
,
1153 const struct sigaction
* action
,
1154 struct sigaction
* oaction
) {
1155 #if defined(SA_SIGINFO)
1156 if (action
&& action
->sa_flags
& SA_SIGINFO
) {
1157 // We don't support SA_SIGINFO (sa_sigaction field) yet
1167 *oaction
= sigwinch_handler_
;
1169 sigwinch_handler_
= *action
;
1178 #if defined(SIGPOLL)
1190 if (action
&& action
->sa_handler
!= SIG_DFL
) {
1191 // Trying to set this action to anything other than SIG_DFL
1192 // is not yet supported.
1193 LOG_TRACE("sigaction on signal %d != SIG_DFL not supported.", signum
);
1199 memset(oaction
, 0, sizeof(*oaction
));
1200 oaction
->sa_handler
= SIG_DFL
;
1204 // KILL and STOP cannot be handled
1207 LOG_TRACE("sigaction on SIGKILL/SIGSTOP not supported.");
1217 mode_t
KernelProxy::umask(mode_t mask
) {
1218 return SetUmask(mask
& S_MODEBITS
);
1221 #ifdef PROVIDES_SOCKET_API
1223 int KernelProxy::select(int nfds
,
1227 struct timeval
* timeout
) {
1228 std::vector
<pollfd
> pollfds
;
1230 for (int fd
= 0; fd
< nfds
; fd
++) {
1232 if (readfds
&& FD_ISSET(fd
, readfds
)) {
1234 FD_CLR(fd
, readfds
);
1237 if (writefds
&& FD_ISSET(fd
, writefds
)) {
1239 FD_CLR(fd
, writefds
);
1242 if (exceptfds
&& FD_ISSET(fd
, exceptfds
)) {
1243 events
|= POLLERR
| POLLHUP
;
1244 FD_CLR(fd
, exceptfds
);
1250 info
.events
= events
;
1251 pollfds
.push_back(info
);
1255 // NULL timeout signals wait forever.
1256 int ms_timeout
= -1;
1257 if (timeout
!= NULL
) {
1258 int64_t ms
= timeout
->tv_sec
* 1000 + ((timeout
->tv_usec
+ 500) / 1000);
1260 // If the timeout is invalid or too long (larger than signed 32 bit).
1261 if ((timeout
->tv_sec
< 0) || (timeout
->tv_sec
>= (INT_MAX
/ 1000)) ||
1262 (timeout
->tv_usec
< 0) || (timeout
->tv_usec
>= 1000000) || (ms
< 0) ||
1264 LOG_TRACE("Invalid timeout: tv_sec=%" PRIi64
" tv_usec=%ld.",
1271 ms_timeout
= static_cast<int>(ms
);
1274 int result
= poll(&pollfds
[0], pollfds
.size(), ms_timeout
);
1279 for (size_t index
= 0; index
< pollfds
.size(); index
++) {
1280 pollfd
* info
= &pollfds
[index
];
1281 if (info
->revents
& POLLIN
) {
1282 FD_SET(info
->fd
, readfds
);
1285 if (info
->revents
& POLLOUT
) {
1286 FD_SET(info
->fd
, writefds
);
1289 if (info
->revents
& (POLLHUP
| POLLERR
)) {
1290 FD_SET(info
->fd
, exceptfds
);
1299 PollInfo() : index(-1) {};
1301 std::vector
<struct pollfd
*> fds
;
1305 typedef std::map
<EventEmitter
*, PollInfo
> EventPollMap_t
;
1307 int KernelProxy::poll(struct pollfd
* fds
, nfds_t nfds
, int timeout
) {
1308 EventPollMap_t event_map
;
1310 std::vector
<EventRequest
> requests
;
1311 size_t event_cnt
= 0;
1313 for (int index
= 0; static_cast<nfds_t
>(index
) < nfds
; index
++) {
1314 ScopedKernelHandle handle
;
1315 struct pollfd
* fd_info
= &fds
[index
];
1316 Error err
= AcquireHandle(fd_info
->fd
, &handle
);
1318 fd_info
->revents
= 0;
1320 // If the node isn't open, or somehow invalid, mark it so.
1322 fd_info
->revents
= POLLNVAL
;
1327 // If it's already signaled, then just capture the event
1328 ScopedEventEmitter
emitter(handle
->node()->GetEventEmitter());
1329 int events
= POLLIN
| POLLOUT
;
1331 events
= emitter
->GetEventStatus();
1333 if (events
& fd_info
->events
) {
1334 fd_info
->revents
= events
& fd_info
->events
;
1339 if (NULL
== emitter
) {
1340 fd_info
->revents
= POLLNVAL
;
1345 // Otherwise try to track it.
1346 PollInfo
* info
= &event_map
[emitter
.get()];
1347 if (info
->index
== -1) {
1348 EventRequest request
;
1349 request
.emitter
= emitter
;
1350 request
.filter
= fd_info
->events
;
1353 info
->index
= requests
.size();
1354 requests
.push_back(request
);
1356 info
->fds
.push_back(fd_info
);
1357 requests
[info
->index
].filter
|= fd_info
->events
;
1360 // If nothing is signaled, then we must wait on the event map
1361 if (0 == event_cnt
) {
1362 EventListenerPoll wait
;
1363 Error err
= wait
.WaitOnAny(&requests
[0], requests
.size(), timeout
);
1364 if ((err
!= 0) && (err
!= ETIMEDOUT
)) {
1369 for (size_t rindex
= 0; rindex
< requests
.size(); rindex
++) {
1370 EventRequest
* request
= &requests
[rindex
];
1371 if (request
->events
) {
1372 PollInfo
* poll_info
= &event_map
[request
->emitter
.get()];
1373 for (size_t findex
= 0; findex
< poll_info
->fds
.size(); findex
++) {
1374 struct pollfd
* fd_info
= poll_info
->fds
[findex
];
1375 uint32_t events
= fd_info
->events
& request
->events
;
1377 fd_info
->revents
= events
;
1389 int KernelProxy::accept(int fd
, struct sockaddr
* addr
, socklen_t
* len
) {
1390 ScopedKernelHandle handle
;
1391 Error error
= AcquireHandle(fd
, &handle
);
1397 PP_Resource new_sock
= 0;
1398 error
= handle
->Accept(&new_sock
, addr
, len
);
1404 SocketNode
* sock
= new TcpNode(stream_fs_
.get(), new_sock
);
1406 // The SocketNode now holds a reference to the new socket
1407 // so we release ours.
1408 ppapi_
->ReleaseResource(new_sock
);
1409 error
= sock
->Init(O_RDWR
);
1415 ScopedNode
node(sock
);
1416 ScopedKernelHandle
new_handle(new KernelHandle(stream_fs_
, node
));
1417 error
= new_handle
->Init(O_RDWR
);
1423 return AllocateFD(new_handle
);
1426 int KernelProxy::bind(int fd
, const struct sockaddr
* addr
, socklen_t len
) {
1432 ScopedKernelHandle handle
;
1433 if (AcquireSocketHandle(fd
, &handle
) == -1)
1436 Error err
= handle
->socket_node()->Bind(addr
, len
);
1445 int KernelProxy::connect(int fd
, const struct sockaddr
* addr
, socklen_t len
) {
1451 ScopedKernelHandle handle
;
1452 Error error
= AcquireHandle(fd
, &handle
);
1458 error
= handle
->Connect(addr
, len
);
1467 void KernelProxy::freeaddrinfo(struct addrinfo
* res
) {
1468 return host_resolver_
.freeaddrinfo(res
);
1471 int KernelProxy::getaddrinfo(const char* node
,
1472 const char* service
,
1473 const struct addrinfo
* hints
,
1474 struct addrinfo
** res
) {
1475 return host_resolver_
.getaddrinfo(node
, service
, hints
, res
);
1478 int KernelProxy::getnameinfo(const struct sockaddr
*sa
,
1485 return host_resolver_
.getnameinfo(sa
, salen
, host
, hostlen
, serv
, servlen
,
1489 struct hostent
* KernelProxy::gethostbyname(const char* name
) {
1490 return host_resolver_
.gethostbyname(name
);
1493 int KernelProxy::getpeername(int fd
, struct sockaddr
* addr
, socklen_t
* len
) {
1494 if (NULL
== addr
|| NULL
== len
) {
1499 ScopedKernelHandle handle
;
1500 if (AcquireSocketHandle(fd
, &handle
) == -1)
1503 Error err
= handle
->socket_node()->GetPeerName(addr
, len
);
1512 int KernelProxy::getsockname(int fd
, struct sockaddr
* addr
, socklen_t
* len
) {
1513 if (NULL
== addr
|| NULL
== len
) {
1518 ScopedKernelHandle handle
;
1519 if (AcquireSocketHandle(fd
, &handle
) == -1)
1522 Error err
= handle
->socket_node()->GetSockName(addr
, len
);
1531 int KernelProxy::getsockopt(int fd
,
1536 if (NULL
== optval
|| NULL
== len
) {
1541 ScopedKernelHandle handle
;
1542 if (AcquireSocketHandle(fd
, &handle
) == -1)
1545 Error err
= handle
->socket_node()->GetSockOpt(lvl
, optname
, optval
, len
);
1554 int KernelProxy::listen(int fd
, int backlog
) {
1555 ScopedKernelHandle handle
;
1556 if (AcquireSocketHandle(fd
, &handle
) == -1)
1559 Error err
= handle
->socket_node()->Listen(backlog
);
1568 ssize_t
KernelProxy::recv(int fd
, void* buf
, size_t len
, int flags
) {
1574 ScopedKernelHandle handle
;
1575 Error error
= AcquireHandle(fd
, &handle
);
1582 error
= handle
->Recv(buf
, len
, flags
, &out_len
);
1588 return static_cast<ssize_t
>(out_len
);
1591 ssize_t
KernelProxy::recvfrom(int fd
,
1595 struct sockaddr
* addr
,
1596 socklen_t
* addrlen
) {
1597 // According to the manpage, recvfrom with a null addr is identical to recv.
1599 return recv(fd
, buf
, len
, flags
);
1602 if (NULL
== buf
|| NULL
== addrlen
) {
1607 ScopedKernelHandle handle
;
1608 Error error
= AcquireHandle(fd
, &handle
);
1615 error
= handle
->RecvFrom(buf
, len
, flags
, addr
, addrlen
, &out_len
);
1621 return static_cast<ssize_t
>(out_len
);
1624 ssize_t
KernelProxy::recvmsg(int fd
, struct msghdr
* msg
, int flags
) {
1630 ScopedKernelHandle handle
;
1631 if (AcquireSocketHandle(fd
, &handle
) == -1)
1638 ssize_t
KernelProxy::send(int fd
, const void* buf
, size_t len
, int flags
) {
1644 ScopedKernelHandle handle
;
1645 Error error
= AcquireHandle(fd
, &handle
);
1652 error
= handle
->Send(buf
, len
, flags
, &out_len
);
1658 return static_cast<ssize_t
>(out_len
);
1661 ssize_t
KernelProxy::sendto(int fd
,
1665 const struct sockaddr
* addr
,
1666 socklen_t addrlen
) {
1667 // According to the manpage, sendto with a null addr is identical to send.
1669 return send(fd
, buf
, len
, flags
);
1677 ScopedKernelHandle handle
;
1678 Error error
= AcquireHandle(fd
, &handle
);
1685 error
= handle
->SendTo(buf
, len
, flags
, addr
, addrlen
, &out_len
);
1691 return static_cast<ssize_t
>(out_len
);
1694 ssize_t
KernelProxy::sendmsg(int fd
, const struct msghdr
* msg
, int flags
) {
1700 ScopedKernelHandle handle
;
1701 if (AcquireSocketHandle(fd
, &handle
) == -1)
1708 int KernelProxy::setsockopt(int fd
,
1713 if (NULL
== optval
) {
1718 ScopedKernelHandle handle
;
1719 if (AcquireSocketHandle(fd
, &handle
) == -1)
1722 Error err
= handle
->socket_node()->SetSockOpt(lvl
, optname
, optval
, len
);
1731 int KernelProxy::shutdown(int fd
, int how
) {
1732 ScopedKernelHandle handle
;
1733 if (AcquireSocketHandle(fd
, &handle
) == -1)
1736 Error err
= handle
->socket_node()->Shutdown(how
);
1745 int KernelProxy::socket(int domain
, int type
, int protocol
) {
1746 if (AF_INET
!= domain
&& AF_INET6
!= domain
) {
1747 errno
= EAFNOSUPPORT
;
1751 int open_flags
= O_RDWR
;
1753 #if defined(SOCK_CLOEXEC)
1754 if (type
& SOCK_CLOEXEC
) {
1755 #if defined(O_CLOEXEC)
1756 // The NaCl newlib version of fcntl.h doesn't currently define
1758 // TODO(sbc): remove this guard once it gets added.
1759 open_flags
|= O_CLOEXEC
;
1761 type
&= ~SOCK_CLOEXEC
;
1765 #if defined(SOCK_NONBLOCK)
1766 if (type
& SOCK_NONBLOCK
) {
1767 open_flags
|= O_NONBLOCK
;
1768 type
&= ~SOCK_NONBLOCK
;
1772 SocketNode
* sock
= NULL
;
1775 sock
= new UdpNode(stream_fs_
.get());
1779 sock
= new TcpNode(stream_fs_
.get());
1782 case SOCK_SEQPACKET
:
1785 errno
= EPROTONOSUPPORT
;
1793 ScopedNode
node(sock
);
1794 Error rtn
= sock
->Init(O_RDWR
);
1800 ScopedKernelHandle
handle(new KernelHandle(stream_fs_
, node
));
1801 rtn
= handle
->Init(open_flags
);
1807 return AllocateFD(handle
);
1810 int KernelProxy::socketpair(int domain
, int type
, int protocol
, int* sv
) {
1816 // Catch-22: We don't support AF_UNIX, but any other AF doesn't support
1817 // socket pairs. Thus, this function always fails.
1818 if (AF_UNIX
!= domain
) {
1819 errno
= EPROTONOSUPPORT
;
1823 if (AF_INET
!= domain
&& AF_INET6
!= domain
) {
1824 errno
= EAFNOSUPPORT
;
1828 // We cannot reach this point.
1833 int KernelProxy::AcquireSocketHandle(int fd
, ScopedKernelHandle
* handle
) {
1834 Error error
= AcquireHandle(fd
, handle
);
1841 if ((handle
->get()->node_
->GetType() & S_IFSOCK
) == 0) {
1849 #endif // PROVIDES_SOCKET_API
1851 } // namespace_nacl_io