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/osmman.h"
33 #include "nacl_io/ossocket.h"
34 #include "nacl_io/osstat.h"
35 #include "nacl_io/passthroughfs/passthrough_fs.h"
36 #include "nacl_io/path.h"
37 #include "nacl_io/pepper_interface.h"
38 #include "nacl_io/pipe/pipe_node.h"
39 #include "nacl_io/socket/tcp_node.h"
40 #include "nacl_io/socket/udp_node.h"
41 #include "nacl_io/stream/stream_fs.h"
42 #include "nacl_io/typed_fs_factory.h"
43 #include "sdk_util/auto_lock.h"
44 #include "sdk_util/ref_object.h"
45 #include "sdk_util/string_util.h"
48 #define MAXPATHLEN 256
53 KernelProxy::KernelProxy()
57 exit_callback_user_data_(NULL
),
58 mount_callback_(NULL
),
59 mount_callback_user_data_(NULL
),
60 signal_emitter_(new EventEmitter
) {
61 memset(&sigwinch_handler_
, 0, sizeof(sigwinch_handler_
));
62 sigwinch_handler_
.sa_handler
= SIG_DFL
;
65 KernelProxy::~KernelProxy() {
66 // Clean up the FsFactories.
67 for (FsFactoryMap_t::iterator i
= factories_
.begin(); i
!= factories_
.end();
73 Error
KernelProxy::Init(PepperInterface
* ppapi
) {
78 factories_
["memfs"] = new TypedFsFactory
<MemFs
>;
79 factories_
["dev"] = new TypedFsFactory
<DevFs
>;
80 factories_
["html5fs"] = new TypedFsFactory
<Html5Fs
>;
81 factories_
["httpfs"] = new TypedFsFactory
<HttpFs
>;
82 factories_
["passthroughfs"] = new TypedFsFactory
<PassthroughFs
>;
84 ScopedFilesystem root_fs
;
85 rtn
= MountInternal("", "/", "passthroughfs", 0, NULL
, false, &root_fs
);
90 rtn
= MountInternal("", "/dev", "dev", 0, NULL
, false, &fs
);
93 dev_fs_
= sdk_util::static_scoped_ref_cast
<DevFs
>(fs
);
95 // Create the filesystem nodes for / and /dev afterward. They can't be
96 // created the normal way because the dev filesystem didn't exist yet.
97 rtn
= CreateFsNode(root_fs
);
101 rtn
= CreateFsNode(dev_fs_
);
105 // Open the first three in order to get STDIN, STDOUT, STDERR
107 fd
= open("/dev/stdin", O_RDONLY
);
112 fd
= open("/dev/stdout", O_WRONLY
);
117 fd
= open("/dev/stderr", O_WRONLY
);
122 #ifdef PROVIDES_SOCKET_API
123 host_resolver_
.Init(ppapi_
);
129 stream_fs_
.reset(new StreamFs());
130 int result
= stream_fs_
->Init(args
);
139 bool KernelProxy::RegisterFsType(const char* fs_type
,
140 fuse_operations
* fuse_ops
) {
141 FsFactoryMap_t::iterator iter
= factories_
.find(fs_type
);
142 if (iter
!= factories_
.end())
145 factories_
[fs_type
] = new FuseFsFactory(fuse_ops
);
149 bool KernelProxy::UnregisterFsType(const char* fs_type
) {
150 FsFactoryMap_t::iterator iter
= factories_
.find(fs_type
);
151 if (iter
== factories_
.end())
155 factories_
.erase(iter
);
159 void KernelProxy::SetExitCallback(nacl_io_exit_callback_t exit_callback
,
161 exit_callback_
= exit_callback
;
162 exit_callback_user_data_
= user_data
;
165 void KernelProxy::SetMountCallback(nacl_io_mount_callback_t mount_callback
,
167 mount_callback_
= mount_callback
;
168 mount_callback_user_data_
= user_data
;
171 int KernelProxy::open_resource(const char* path
) {
175 Error error
= AcquireFsAndRelPath(path
, &fs
, &rel
);
182 error
= fs
->OpenResource(rel
, &node
);
184 // OpenResource failed, try Open().
185 error
= fs
->Open(rel
, O_RDONLY
, &node
);
192 ScopedKernelHandle
handle(new KernelHandle(fs
, node
));
193 error
= handle
->Init(O_RDONLY
);
199 return AllocateFD(handle
, path
);
202 int KernelProxy::open(const char* path
, int open_flags
) {
206 Error error
= AcquireFsAndNode(path
, open_flags
, &fs
, &node
);
212 ScopedKernelHandle
handle(new KernelHandle(fs
, node
));
213 error
= handle
->Init(open_flags
);
219 return AllocateFD(handle
, path
);
222 int KernelProxy::pipe(int pipefds
[2]) {
223 PipeNode
* pipe
= new PipeNode(stream_fs_
.get());
224 ScopedNode
node(pipe
);
226 if (pipe
->Init(O_RDWR
) == 0) {
227 ScopedKernelHandle
handle0(new KernelHandle(stream_fs_
, node
));
228 ScopedKernelHandle
handle1(new KernelHandle(stream_fs_
, node
));
230 // Should never fail, but...
231 if (handle0
->Init(O_RDONLY
) || handle1
->Init(O_WRONLY
)) {
236 pipefds
[0] = AllocateFD(handle0
);
237 pipefds
[1] = AllocateFD(handle1
);
245 int KernelProxy::close(int fd
) {
246 ScopedKernelHandle handle
;
247 Error error
= AcquireHandle(fd
, &handle
);
253 // Remove the FD from the process open file descriptor map
258 int KernelProxy::dup(int oldfd
) {
259 ScopedKernelHandle handle
;
261 Error error
= AcquireHandleAndPath(oldfd
, &handle
, &path
);
266 return AllocateFD(handle
, path
);
269 int KernelProxy::dup2(int oldfd
, int newfd
) {
270 // If it's the same file handle, just return
274 ScopedKernelHandle old_handle
;
275 std::string old_path
;
276 Error error
= AcquireHandleAndPath(oldfd
, &old_handle
, &old_path
);
282 FreeAndReassignFD(newfd
, old_handle
, old_path
);
286 int KernelProxy::chdir(const char* path
) {
287 Error error
= SetCWD(path
);
295 void KernelProxy::exit(int status
) {
297 exit_callback_(status
, exit_callback_user_data_
);
300 char* KernelProxy::getcwd(char* buf
, size_t size
) {
306 std::string cwd
= GetCWD();
308 // Verify the buffer is large enough
309 if (size
<= cwd
.size()) {
314 strcpy(buf
, cwd
.c_str());
318 char* KernelProxy::getwd(char* buf
) {
323 return getcwd(buf
, MAXPATHLEN
);
326 int KernelProxy::chmod(const char* path
, mode_t mode
) {
327 int fd
= KernelProxy::open(path
, O_RDONLY
);
331 int result
= fchmod(fd
, mode
);
336 int KernelProxy::chown(const char* path
, uid_t owner
, gid_t group
) {
340 int KernelProxy::fchown(int fd
, uid_t owner
, gid_t group
) {
344 int KernelProxy::lchown(const char* path
, uid_t owner
, gid_t group
) {
348 int KernelProxy::utime(const char* filename
, const struct utimbuf
* times
) {
352 int KernelProxy::mkdir(const char* path
, mode_t mode
) {
356 Error error
= AcquireFsAndRelPath(path
, &fs
, &rel
);
362 error
= fs
->Mkdir(rel
, mode
);
371 int KernelProxy::rmdir(const char* path
) {
375 Error error
= AcquireFsAndRelPath(path
, &fs
, &rel
);
381 error
= fs
->Rmdir(rel
);
390 int KernelProxy::stat(const char* path
, struct stat
* buf
) {
391 int fd
= open(path
, O_RDONLY
);
395 int result
= fstat(fd
, buf
);
400 int KernelProxy::mount(const char* source
,
402 const char* filesystemtype
,
403 unsigned long mountflags
,
406 Error error
= MountInternal(
407 source
, target
, filesystemtype
, mountflags
, data
, true, &fs
);
416 Error
KernelProxy::MountInternal(const char* source
,
418 const char* filesystemtype
,
419 unsigned long mountflags
,
422 ScopedFilesystem
* out_filesystem
) {
423 std::string abs_path
= GetAbsParts(target
).Join();
425 // Find a factory of that type
426 FsFactoryMap_t::iterator factory
= factories_
.find(filesystemtype
);
427 if (factory
== factories_
.end()) {
428 LOG_ERROR("Unknown filesystem type: %s", filesystemtype
);
432 // Create a map of settings
434 smap
["SOURCE"] = source
;
437 std::vector
<std::string
> elements
;
438 sdk_util::SplitString(static_cast<const char*>(data
), ',', &elements
);
440 for (std::vector
<std::string
>::const_iterator it
= elements
.begin();
441 it
!= elements
.end();
443 size_t location
= it
->find('=');
444 if (location
!= std::string::npos
) {
445 std::string key
= it
->substr(0, location
);
446 std::string val
= it
->substr(location
+ 1);
456 args
.string_map
= smap
;
460 Error error
= factory
->second
->CreateFilesystem(args
, &fs
);
464 error
= AttachFsAtPath(fs
, abs_path
);
468 if (create_fs_node
) {
469 error
= CreateFsNode(fs
);
471 DetachFsAtPath(abs_path
, &fs
);
476 *out_filesystem
= fs
;
478 if (mount_callback_
) {
479 mount_callback_(source
,
485 mount_callback_user_data_
);
491 Error
KernelProxy::CreateFsNode(const ScopedFilesystem
& fs
) {
494 return dev_fs_
->CreateFsNode(fs
.get());
497 int KernelProxy::umount(const char* path
) {
499 Error error
= DetachFsAtPath(path
, &fs
);
505 error
= dev_fs_
->DestroyFsNode(fs
.get());
507 // Ignore any errors here, just log.
508 LOG_ERROR("Unable to destroy FsNode: %s", strerror(error
));
513 ssize_t
KernelProxy::read(int fd
, void* buf
, size_t nbytes
) {
514 ScopedKernelHandle handle
;
515 Error error
= AcquireHandle(fd
, &handle
);
522 error
= handle
->Read(buf
, nbytes
, &cnt
);
531 ssize_t
KernelProxy::write(int fd
, const void* buf
, size_t nbytes
) {
532 ScopedKernelHandle handle
;
533 Error error
= AcquireHandle(fd
, &handle
);
540 error
= handle
->Write(buf
, nbytes
, &cnt
);
549 int KernelProxy::fstat(int fd
, struct stat
* buf
) {
550 ScopedKernelHandle handle
;
551 Error error
= AcquireHandle(fd
, &handle
);
557 error
= handle
->node()->GetStat(buf
);
566 int KernelProxy::getdents(int fd
, void* buf
, unsigned int count
) {
567 ScopedKernelHandle handle
;
568 Error error
= AcquireHandle(fd
, &handle
);
575 error
= handle
->GetDents(static_cast<dirent
*>(buf
), count
, &cnt
);
582 int KernelProxy::fchdir(int fd
) {
583 ScopedKernelHandle handle
;
585 Error error
= AcquireHandleAndPath(fd
, &handle
, &path
);
591 if (!handle
->node()->IsaDir()) {
601 error
= SetCWD(path
);
603 // errno is return value from SetCWD
610 int KernelProxy::ftruncate(int fd
, off_t length
) {
611 ScopedKernelHandle handle
;
612 Error error
= AcquireHandle(fd
, &handle
);
618 error
= handle
->node()->FTruncate(length
);
627 int KernelProxy::fsync(int fd
) {
628 ScopedKernelHandle handle
;
629 Error error
= AcquireHandle(fd
, &handle
);
635 error
= handle
->node()->FSync();
644 int KernelProxy::fdatasync(int fd
) {
649 int KernelProxy::isatty(int fd
) {
650 ScopedKernelHandle handle
;
651 Error error
= AcquireHandle(fd
, &handle
);
657 error
= handle
->node()->Isatty();
666 int KernelProxy::ioctl(int fd
, int request
, va_list args
) {
667 ScopedKernelHandle handle
;
668 Error error
= AcquireHandle(fd
, &handle
);
674 error
= handle
->node()->VIoctl(request
, args
);
683 off_t
KernelProxy::lseek(int fd
, off_t offset
, int whence
) {
684 ScopedKernelHandle handle
;
685 Error error
= AcquireHandle(fd
, &handle
);
692 error
= handle
->Seek(offset
, whence
, &new_offset
);
701 int KernelProxy::unlink(const char* path
) {
705 Error error
= AcquireFsAndRelPath(path
, &fs
, &rel
);
711 error
= fs
->Unlink(rel
);
720 int KernelProxy::truncate(const char* path
, off_t len
) {
721 int fd
= KernelProxy::open(path
, O_WRONLY
);
725 int result
= ftruncate(fd
, len
);
730 int KernelProxy::lstat(const char* path
, struct stat
* buf
) {
731 return stat(path
, buf
);
734 int KernelProxy::rename(const char* path
, const char* newpath
) {
737 Error error
= AcquireFsAndRelPath(path
, &fs
, &rel
);
743 ScopedFilesystem newfs
;
745 error
= AcquireFsAndRelPath(newpath
, &newfs
, &newrel
);
751 if (newfs
.get() != fs
.get()) {
752 // Renaming accross mountpoints is not allowed
757 // They already point to the same path
761 error
= fs
->Rename(rel
, newrel
);
770 int KernelProxy::remove(const char* path
) {
774 Error error
= AcquireFsAndRelPath(path
, &fs
, &rel
);
780 error
= fs
->Remove(rel
);
789 // TODO(noelallen): Needs implementation.
790 int KernelProxy::fchmod(int fd
, int mode
) {
791 ScopedKernelHandle handle
;
792 Error error
= AcquireHandle(fd
, &handle
);
801 int KernelProxy::fcntl(int fd
, int request
, va_list args
) {
804 // F_GETFD and F_SETFD are descriptor specific flags that
805 // are stored in the KernelObject's decriptor map unlike
806 // F_GETFL and F_SETFL which are handle specific.
810 error
= GetFDFlags(fd
, &rtn
);
818 int flags
= va_arg(args
, int);
819 error
= SetFDFlags(fd
, flags
);
828 ScopedKernelHandle handle
;
829 error
= AcquireHandle(fd
, &handle
);
836 error
= handle
->VFcntl(request
, &rtn
, args
);
845 int KernelProxy::access(const char* path
, int amode
) {
849 Error error
= AcquireFsAndRelPath(path
, &fs
, &rel
);
855 error
= fs
->Access(rel
, amode
);
863 int KernelProxy::readlink(const char* path
, char* buf
, size_t count
) {
864 LOG_TRACE("readlink is not implemented.");
869 int KernelProxy::utimes(const char* filename
, const struct timeval times
[2]) {
870 LOG_TRACE("utimes is not implemented.");
875 // TODO(noelallen): Needs implementation.
876 int KernelProxy::link(const char* oldpath
, const char* newpath
) {
877 LOG_TRACE("link is not implemented.");
882 int KernelProxy::symlink(const char* oldpath
, const char* newpath
) {
883 LOG_TRACE("symlink is not implemented.");
888 void* KernelProxy::mmap(void* addr
,
894 // We shouldn't be getting anonymous mmaps here.
895 assert((flags
& MAP_ANONYMOUS
) == 0);
898 ScopedKernelHandle handle
;
899 Error error
= AcquireHandle(fd
, &handle
);
906 error
= handle
->node()->MMap(addr
, length
, prot
, flags
, offset
, &new_addr
);
915 int KernelProxy::munmap(void* addr
, size_t length
) {
916 // NOTE: The comment below is from a previous discarded implementation that
917 // tracks mmap'd regions. For simplicity, we no longer do this; because we
918 // "snapshot" the contents of the file in mmap(), and don't support
919 // write-back or updating the mapped region when the file is written, holding
920 // on to the KernelHandle is pointless.
922 // If we ever do, these threading issues should be considered.
925 // WARNING: this function may be called by free().
927 // There is a potential deadlock scenario:
928 // Thread 1: open() -> takes lock1 -> free() -> takes lock2
929 // Thread 2: free() -> takes lock2 -> munmap() -> takes lock1
931 // Note that open() above could be any function that takes a lock that is
932 // shared with munmap (this includes munmap!)
934 // To prevent this, we avoid taking locks in munmap() that are used by other
935 // nacl_io functions that may call free. Specifically, we only take the
936 // mmap_lock, which is only shared with mmap() above. There is still a
937 // possibility of deadlock if mmap() or munmap() calls free(), so this is not
940 // Unfortunately, munmap still needs to acquire other locks; see the call to
941 // ReleaseHandle below which takes the process lock. This is safe as long as
942 // this is never executed from free() -- we can be reasonably sure this is
943 // true, because malloc only makes anonymous mmap() requests, and should only
944 // be munmapping those allocations. We never add to mmap_info_list_ for
945 // anonymous maps, so the unmap_list should always be empty when called from
950 int KernelProxy::tcflush(int fd
, int queue_selector
) {
951 ScopedKernelHandle handle
;
952 Error error
= AcquireHandle(fd
, &handle
);
958 error
= handle
->node()->Tcflush(queue_selector
);
967 int KernelProxy::tcgetattr(int fd
, struct termios
* termios_p
) {
968 ScopedKernelHandle handle
;
969 Error error
= AcquireHandle(fd
, &handle
);
975 error
= handle
->node()->Tcgetattr(termios_p
);
984 int KernelProxy::tcsetattr(int fd
,
985 int optional_actions
,
986 const struct termios
* termios_p
) {
987 ScopedKernelHandle handle
;
988 Error error
= AcquireHandle(fd
, &handle
);
994 error
= handle
->node()->Tcsetattr(optional_actions
, termios_p
);
1003 int KernelProxy::kill(pid_t pid
, int sig
) {
1004 // Currently we don't even pretend that other processes exist
1005 // so we can only send a signal to outselves. For kill(2)
1006 // pid 0 means the current process group and -1 means all the
1007 // processes we have permission to send signals to.
1008 if (pid
!= getpid() && pid
!= -1 && pid
!= 0) {
1013 // Raise an event so that select/poll get interrupted.
1014 AUTO_LOCK(signal_emitter_
->GetLock())
1015 signal_emitter_
->RaiseEvents_Locked(POLLERR
);
1018 if (sigwinch_handler_
.sa_handler
!= SIG_IGN
&&
1019 sigwinch_handler_
.sa_handler
!= SIG_DFL
) {
1020 sigwinch_handler_
.sa_handler(SIGWINCH
);
1029 LOG_TRACE("Unsupported signal: %d", sig
);
1036 int KernelProxy::sigaction(int signum
,
1037 const struct sigaction
* action
,
1038 struct sigaction
* oaction
) {
1039 if (action
&& action
->sa_flags
& SA_SIGINFO
) {
1040 // We don't support SA_SIGINFO (sa_sigaction field) yet
1049 *oaction
= sigwinch_handler_
;
1051 sigwinch_handler_
= *action
;
1070 if (action
&& action
->sa_handler
!= SIG_DFL
) {
1071 // Trying to set this action to anything other than SIG_DFL
1072 // is not yet supported.
1073 LOG_TRACE("sigaction on signal %d != SIG_DFL not supported.", sig
);
1079 memset(oaction
, 0, sizeof(*oaction
));
1080 oaction
->sa_handler
= SIG_DFL
;
1084 // KILL and STOP cannot be handled
1087 LOG_TRACE("sigaction on SIGKILL/SIGSTOP not supported.");
1097 #ifdef PROVIDES_SOCKET_API
1099 int KernelProxy::select(int nfds
,
1103 struct timeval
* timeout
) {
1104 std::vector
<pollfd
> pollfds
;
1106 for (int fd
= 0; fd
< nfds
; fd
++) {
1108 if (readfds
&& FD_ISSET(fd
, readfds
)) {
1110 FD_CLR(fd
, readfds
);
1113 if (writefds
&& FD_ISSET(fd
, writefds
)) {
1115 FD_CLR(fd
, writefds
);
1118 if (exceptfds
&& FD_ISSET(fd
, exceptfds
)) {
1119 events
|= POLLERR
| POLLHUP
;
1120 FD_CLR(fd
, exceptfds
);
1126 info
.events
= events
;
1127 pollfds
.push_back(info
);
1131 // NULL timeout signals wait forever.
1132 int ms_timeout
= -1;
1133 if (timeout
!= NULL
) {
1134 int64_t ms
= timeout
->tv_sec
* 1000 + ((timeout
->tv_usec
+ 500) / 1000);
1136 // If the timeout is invalid or too long (larger than signed 32 bit).
1137 if ((timeout
->tv_sec
< 0) || (timeout
->tv_sec
>= (INT_MAX
/ 1000)) ||
1138 (timeout
->tv_usec
< 0) || (timeout
->tv_usec
>= 1000000) || (ms
< 0) ||
1140 LOG_TRACE("Invalid timeout: tv_sec=%d tv_usec=%d.",
1147 ms_timeout
= static_cast<int>(ms
);
1150 int result
= poll(&pollfds
[0], pollfds
.size(), ms_timeout
);
1155 for (size_t index
= 0; index
< pollfds
.size(); index
++) {
1156 pollfd
* info
= &pollfds
[index
];
1157 if (info
->revents
& POLLIN
) {
1158 FD_SET(info
->fd
, readfds
);
1161 if (info
->revents
& POLLOUT
) {
1162 FD_SET(info
->fd
, writefds
);
1165 if (info
->revents
& (POLLHUP
| POLLERR
)) {
1166 FD_SET(info
->fd
, exceptfds
);
1175 PollInfo() : index(-1) {};
1177 std::vector
<struct pollfd
*> fds
;
1181 typedef std::map
<EventEmitter
*, PollInfo
> EventPollMap_t
;
1183 int KernelProxy::poll(struct pollfd
* fds
, nfds_t nfds
, int timeout
) {
1184 EventPollMap_t event_map
;
1186 std::vector
<EventRequest
> requests
;
1187 size_t event_cnt
= 0;
1189 for (int index
= 0; static_cast<nfds_t
>(index
) < nfds
; index
++) {
1190 ScopedKernelHandle handle
;
1191 struct pollfd
* fd_info
= &fds
[index
];
1192 Error err
= AcquireHandle(fd_info
->fd
, &handle
);
1194 fd_info
->revents
= 0;
1196 // If the node isn't open, or somehow invalid, mark it so.
1198 fd_info
->revents
= POLLNVAL
;
1203 // If it's already signaled, then just capture the event
1204 ScopedEventEmitter
emitter(handle
->node()->GetEventEmitter());
1205 int events
= POLLIN
| POLLOUT
;
1207 events
= emitter
->GetEventStatus();
1209 if (events
& fd_info
->events
) {
1210 fd_info
->revents
= events
& fd_info
->events
;
1215 if (NULL
== emitter
) {
1216 fd_info
->revents
= POLLNVAL
;
1221 // Otherwise try to track it.
1222 PollInfo
* info
= &event_map
[emitter
.get()];
1223 if (info
->index
== -1) {
1224 EventRequest request
;
1225 request
.emitter
= emitter
;
1226 request
.filter
= fd_info
->events
;
1229 info
->index
= requests
.size();
1230 requests
.push_back(request
);
1232 info
->fds
.push_back(fd_info
);
1233 requests
[info
->index
].filter
|= fd_info
->events
;
1236 // If nothing is signaled, then we must wait on the event map
1237 if (0 == event_cnt
) {
1238 EventListenerPoll wait
;
1239 Error err
= wait
.WaitOnAny(&requests
[0], requests
.size(), timeout
);
1240 if ((err
!= 0) && (err
!= ETIMEDOUT
)) {
1245 for (size_t rindex
= 0; rindex
< requests
.size(); rindex
++) {
1246 EventRequest
* request
= &requests
[rindex
];
1247 if (request
->events
) {
1248 PollInfo
* poll_info
= &event_map
[request
->emitter
.get()];
1249 for (size_t findex
= 0; findex
< poll_info
->fds
.size(); findex
++) {
1250 struct pollfd
* fd_info
= poll_info
->fds
[findex
];
1251 uint32_t events
= fd_info
->events
& request
->events
;
1253 fd_info
->revents
= events
;
1265 int KernelProxy::accept(int fd
, struct sockaddr
* addr
, socklen_t
* len
) {
1266 if (NULL
== addr
|| NULL
== len
) {
1271 ScopedKernelHandle handle
;
1272 Error error
= AcquireHandle(fd
, &handle
);
1278 PP_Resource new_sock
= 0;
1279 error
= handle
->Accept(&new_sock
, addr
, len
);
1285 SocketNode
* sock
= new TcpNode(stream_fs_
.get(), new_sock
);
1287 // The SocketNode now holds a reference to the new socket
1288 // so we release ours.
1289 ppapi_
->ReleaseResource(new_sock
);
1290 error
= sock
->Init(O_RDWR
);
1296 ScopedNode
node(sock
);
1297 ScopedKernelHandle
new_handle(new KernelHandle(stream_fs_
, node
));
1298 error
= new_handle
->Init(O_RDWR
);
1304 return AllocateFD(new_handle
);
1307 int KernelProxy::bind(int fd
, const struct sockaddr
* addr
, socklen_t len
) {
1313 ScopedKernelHandle handle
;
1314 if (AcquireSocketHandle(fd
, &handle
) == -1)
1317 Error err
= handle
->socket_node()->Bind(addr
, len
);
1326 int KernelProxy::connect(int fd
, const struct sockaddr
* addr
, socklen_t len
) {
1332 ScopedKernelHandle handle
;
1333 Error error
= AcquireHandle(fd
, &handle
);
1339 error
= handle
->Connect(addr
, len
);
1348 void KernelProxy::freeaddrinfo(struct addrinfo
* res
) {
1349 return host_resolver_
.freeaddrinfo(res
);
1352 int KernelProxy::getaddrinfo(const char* node
,
1353 const char* service
,
1354 const struct addrinfo
* hints
,
1355 struct addrinfo
** res
) {
1356 return host_resolver_
.getaddrinfo(node
, service
, hints
, res
);
1359 struct hostent
* KernelProxy::gethostbyname(const char* name
) {
1360 return host_resolver_
.gethostbyname(name
);
1363 int KernelProxy::getpeername(int fd
, struct sockaddr
* addr
, socklen_t
* len
) {
1364 if (NULL
== addr
|| NULL
== len
) {
1369 ScopedKernelHandle handle
;
1370 if (AcquireSocketHandle(fd
, &handle
) == -1)
1373 Error err
= handle
->socket_node()->GetPeerName(addr
, len
);
1382 int KernelProxy::getsockname(int fd
, struct sockaddr
* addr
, socklen_t
* len
) {
1383 if (NULL
== addr
|| NULL
== len
) {
1388 ScopedKernelHandle handle
;
1389 if (AcquireSocketHandle(fd
, &handle
) == -1)
1392 Error err
= handle
->socket_node()->GetSockName(addr
, len
);
1401 int KernelProxy::getsockopt(int fd
,
1406 if (NULL
== optval
|| NULL
== len
) {
1411 ScopedKernelHandle handle
;
1412 if (AcquireSocketHandle(fd
, &handle
) == -1)
1415 Error err
= handle
->socket_node()->GetSockOpt(lvl
, optname
, optval
, len
);
1424 int KernelProxy::listen(int fd
, int backlog
) {
1425 ScopedKernelHandle handle
;
1426 if (AcquireSocketHandle(fd
, &handle
) == -1)
1429 Error err
= handle
->socket_node()->Listen(backlog
);
1438 ssize_t
KernelProxy::recv(int fd
, void* buf
, size_t len
, int flags
) {
1444 ScopedKernelHandle handle
;
1445 Error error
= AcquireHandle(fd
, &handle
);
1452 error
= handle
->Recv(buf
, len
, flags
, &out_len
);
1458 return static_cast<ssize_t
>(out_len
);
1461 ssize_t
KernelProxy::recvfrom(int fd
,
1465 struct sockaddr
* addr
,
1466 socklen_t
* addrlen
) {
1467 // According to the manpage, recvfrom with a null addr is identical to recv.
1469 return recv(fd
, buf
, len
, flags
);
1472 if (NULL
== buf
|| NULL
== addrlen
) {
1477 ScopedKernelHandle handle
;
1478 Error error
= AcquireHandle(fd
, &handle
);
1485 error
= handle
->RecvFrom(buf
, len
, flags
, addr
, addrlen
, &out_len
);
1491 return static_cast<ssize_t
>(out_len
);
1494 ssize_t
KernelProxy::recvmsg(int fd
, struct msghdr
* msg
, int flags
) {
1500 ScopedKernelHandle handle
;
1501 if (AcquireSocketHandle(fd
, &handle
) == -1)
1508 ssize_t
KernelProxy::send(int fd
, const void* buf
, size_t len
, int flags
) {
1514 ScopedKernelHandle handle
;
1515 Error error
= AcquireHandle(fd
, &handle
);
1522 error
= handle
->Send(buf
, len
, flags
, &out_len
);
1528 return static_cast<ssize_t
>(out_len
);
1531 ssize_t
KernelProxy::sendto(int fd
,
1535 const struct sockaddr
* addr
,
1536 socklen_t addrlen
) {
1537 // According to the manpage, sendto with a null addr is identical to send.
1539 return send(fd
, buf
, len
, flags
);
1547 ScopedKernelHandle handle
;
1548 Error error
= AcquireHandle(fd
, &handle
);
1555 error
= handle
->SendTo(buf
, len
, flags
, addr
, addrlen
, &out_len
);
1561 return static_cast<ssize_t
>(out_len
);
1564 ssize_t
KernelProxy::sendmsg(int fd
, const struct msghdr
* msg
, int flags
) {
1570 ScopedKernelHandle handle
;
1571 if (AcquireSocketHandle(fd
, &handle
) == -1)
1578 int KernelProxy::setsockopt(int fd
,
1583 if (NULL
== optval
) {
1588 ScopedKernelHandle handle
;
1589 if (AcquireSocketHandle(fd
, &handle
) == -1)
1592 Error err
= handle
->socket_node()->SetSockOpt(lvl
, optname
, optval
, len
);
1601 int KernelProxy::shutdown(int fd
, int how
) {
1602 ScopedKernelHandle handle
;
1603 if (AcquireSocketHandle(fd
, &handle
) == -1)
1606 Error err
= handle
->socket_node()->Shutdown(how
);
1615 int KernelProxy::socket(int domain
, int type
, int protocol
) {
1616 if (AF_INET
!= domain
&& AF_INET6
!= domain
) {
1617 errno
= EAFNOSUPPORT
;
1621 int open_flags
= O_RDWR
;
1623 if (type
& SOCK_CLOEXEC
) {
1625 // The NaCl newlib version of fcntl.h doesn't currently define
1627 // TODO(sbc): remove this guard once it gets added.
1628 open_flags
|= O_CLOEXEC
;
1630 type
&= ~SOCK_CLOEXEC
;
1633 if (type
& SOCK_NONBLOCK
) {
1634 open_flags
|= O_NONBLOCK
;
1635 type
&= ~SOCK_NONBLOCK
;
1638 SocketNode
* sock
= NULL
;
1641 sock
= new UdpNode(stream_fs_
.get());
1645 sock
= new TcpNode(stream_fs_
.get());
1648 case SOCK_SEQPACKET
:
1651 errno
= EPROTONOSUPPORT
;
1659 ScopedNode
node(sock
);
1660 Error rtn
= sock
->Init(O_RDWR
);
1666 ScopedKernelHandle
handle(new KernelHandle(stream_fs_
, node
));
1667 rtn
= handle
->Init(open_flags
);
1673 return AllocateFD(handle
);
1676 int KernelProxy::socketpair(int domain
, int type
, int protocol
, int* sv
) {
1682 // Catch-22: We don't support AF_UNIX, but any other AF doesn't support
1683 // socket pairs. Thus, this function always fails.
1684 if (AF_UNIX
!= domain
) {
1685 errno
= EPROTONOSUPPORT
;
1689 if (AF_INET
!= domain
&& AF_INET6
!= domain
) {
1690 errno
= EAFNOSUPPORT
;
1694 // We cannot reach this point.
1699 int KernelProxy::AcquireSocketHandle(int fd
, ScopedKernelHandle
* handle
) {
1700 Error error
= AcquireHandle(fd
, handle
);
1707 if ((handle
->get()->node_
->GetType() & S_IFSOCK
) == 0) {
1715 #endif // PROVIDES_SOCKET_API
1717 } // namespace_nacl_io