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/host_resolver.h"
22 #include "nacl_io/kernel_handle.h"
23 #include "nacl_io/kernel_wrap_real.h"
24 #include "nacl_io/mount.h"
25 #include "nacl_io/mount_dev.h"
26 #include "nacl_io/mount_html5fs.h"
27 #include "nacl_io/mount_http.h"
28 #include "nacl_io/mount_mem.h"
29 #include "nacl_io/mount_node.h"
30 #include "nacl_io/mount_node_pipe.h"
31 #include "nacl_io/mount_node_tcp.h"
32 #include "nacl_io/mount_node_udp.h"
33 #include "nacl_io/mount_passthrough.h"
34 #include "nacl_io/mount_stream.h"
35 #include "nacl_io/osmman.h"
36 #include "nacl_io/ossocket.h"
37 #include "nacl_io/osstat.h"
38 #include "nacl_io/path.h"
39 #include "nacl_io/pepper_interface.h"
40 #include "nacl_io/typed_mount_factory.h"
41 #include "sdk_util/auto_lock.h"
42 #include "sdk_util/ref_object.h"
43 #include "sdk_util/string_util.h"
46 #define MAXPATHLEN 256
52 KernelProxy::KernelProxy() : dev_(0), ppapi_(NULL),
53 sigwinch_handler_(SIG_IGN),
54 signal_emitter_(new EventEmitter) {
58 KernelProxy::~KernelProxy() {
59 // Clean up the MountFactories.
60 for (MountFactoryMap_t::iterator i = factories_.begin();
61 i != factories_.end();
69 Error KernelProxy::Init(PepperInterface* ppapi) {
74 factories_["memfs"] = new TypedMountFactory<MountMem>;
75 factories_["dev"] = new TypedMountFactory<MountDev>;
76 factories_["html5fs"] = new TypedMountFactory<MountHtml5Fs>;
77 factories_["httpfs"] = new TypedMountFactory<MountHttp>;
78 factories_["passthroughfs"] = new TypedMountFactory<MountPassthrough>;
81 result = mount("", "/", "passthroughfs", 0, NULL);
87 result = mount("", "/dev", "dev", 0, NULL);
93 // Open the first three in order to get STDIN, STDOUT, STDERR
95 fd = open("/dev/stdin", O_RDONLY);
100 fd = open("/dev/stdout", O_WRONLY);
105 fd = open("/dev/stderr", O_WRONLY);
110 #ifdef PROVIDES_SOCKET_API
111 host_resolver_.Init(ppapi_);
115 stream_mount_.reset(new MountStream());
116 result = stream_mount_->Init(0, args, ppapi);
125 int KernelProxy::open_resource(const char* path) {
129 Error error = AcquireMountAndRelPath(path, &mnt, &rel);
135 ScopedMountNode node;
136 error = mnt->OpenResource(rel, &node);
138 // OpenResource failed, try Open().
139 error = mnt->Open(rel, O_RDONLY, &node);
146 ScopedKernelHandle handle(new KernelHandle(mnt, node));
147 error = handle->Init(O_RDONLY);
153 return AllocateFD(handle);
156 int KernelProxy::open(const char* path, int open_flags) {
158 ScopedMountNode node;
160 Error error = AcquireMountAndNode(path, open_flags, &mnt, &node);
166 ScopedKernelHandle handle(new KernelHandle(mnt, node));
167 error = handle->Init(open_flags);
173 return AllocateFD(handle);
176 int KernelProxy::pipe(int pipefds[2]) {
177 MountNodePipe* pipe = new MountNodePipe(stream_mount_.get());
178 ScopedMountNode node(pipe);
180 if (pipe->Init(S_IREAD | S_IWRITE) == 0) {
181 ScopedKernelHandle handle0(new KernelHandle(stream_mount_, node));
182 ScopedKernelHandle handle1(new KernelHandle(stream_mount_, node));
184 // Should never fail, but...
185 if (handle0->Init(S_IREAD) || handle1->Init(S_IWRITE)) {
190 pipefds[0] = AllocateFD(handle0);
191 pipefds[1] = AllocateFD(handle1);
199 int KernelProxy::close(int fd) {
200 ScopedKernelHandle handle;
201 Error error = AcquireHandle(fd, &handle);
207 // Remove the FD from the process open file descriptor map
212 int KernelProxy::dup(int oldfd) {
213 ScopedKernelHandle handle;
214 Error error = AcquireHandle(oldfd, &handle);
220 return AllocateFD(handle);
223 int KernelProxy::dup2(int oldfd, int newfd) {
224 // If it's the same file handle, just return
228 ScopedKernelHandle old_handle;
229 Error error = AcquireHandle(oldfd, &old_handle);
235 FreeAndReassignFD(newfd, old_handle);
239 int KernelProxy::chdir(const char* path) {
240 Error error = SetCWD(path);
248 char* KernelProxy::getcwd(char* buf, size_t size) {
249 std::string cwd = GetCWD();
256 // If size is 0, allocate as much as we need.
258 size = cwd.size() + 1;
261 // Verify the buffer is large enough
262 if (size <= cwd.size()) {
267 // Allocate the buffer if needed
269 buf = static_cast<char*>(malloc(size));
272 strcpy(buf, cwd.c_str());
276 char* KernelProxy::getwd(char* buf) {
281 return getcwd(buf, MAXPATHLEN);
284 int KernelProxy::chmod(const char* path, mode_t mode) {
285 int fd = KernelProxy::open(path, O_RDONLY);
289 int result = fchmod(fd, mode);
294 int KernelProxy::chown(const char* path, uid_t owner, gid_t group) {
298 int KernelProxy::fchown(int fd, uid_t owner, gid_t group) {
302 int KernelProxy::lchown(const char* path, uid_t owner, gid_t group) {
306 int KernelProxy::utime(const char* filename, const struct utimbuf* times) {
310 int KernelProxy::mkdir(const char* path, mode_t mode) {
314 Error error = AcquireMountAndRelPath(path, &mnt, &rel);
320 error = mnt->Mkdir(rel, mode);
329 int KernelProxy::rmdir(const char* path) {
333 Error error = AcquireMountAndRelPath(path, &mnt, &rel);
339 error = mnt->Rmdir(rel);
348 int KernelProxy::stat(const char* path, struct stat* buf) {
349 int fd = open(path, O_RDONLY);
353 int result = fstat(fd, buf);
359 int KernelProxy::mount(const char* source,
361 const char* filesystemtype,
362 unsigned long mountflags,
364 std::string abs_path = GetAbsParts(target).Join();
366 // Find a factory of that type
367 MountFactoryMap_t::iterator factory = factories_.find(filesystemtype);
368 if (factory == factories_.end()) {
373 // Create a map of settings
375 smap["SOURCE"] = source;
376 smap["TARGET"] = abs_path;
379 std::vector<std::string> elements;
380 sdk_util::SplitString(static_cast<const char*>(data), ',', &elements);
382 for (std::vector<std::string>::const_iterator it = elements.begin();
383 it != elements.end(); ++it) {
384 size_t location = it->find('=');
385 if (location != std::string::npos) {
386 std::string key = it->substr(0, location);
387 std::string val = it->substr(location + 1);
396 Error error = factory->second->CreateMount(dev_++, smap, ppapi_, &mnt);
402 error = AttachMountAtPath(mnt, abs_path);
411 int KernelProxy::umount(const char* path) {
412 Error error = DetachMountAtPath(path);
420 ssize_t KernelProxy::read(int fd, void* buf, size_t nbytes) {
421 ScopedKernelHandle handle;
422 Error error = AcquireHandle(fd, &handle);
429 error = handle->Read(buf, nbytes, &cnt);
438 ssize_t KernelProxy::write(int fd, const void* buf, size_t nbytes) {
439 ScopedKernelHandle handle;
440 Error error = AcquireHandle(fd, &handle);
447 error = handle->Write(buf, nbytes, &cnt);
456 int KernelProxy::fstat(int fd, struct stat* buf) {
457 ScopedKernelHandle handle;
458 Error error = AcquireHandle(fd, &handle);
464 error = handle->node()->GetStat(buf);
473 int KernelProxy::getdents(int fd, void* buf, unsigned int count) {
474 ScopedKernelHandle handle;
475 Error error = AcquireHandle(fd, &handle);
482 error = handle->GetDents(static_cast<dirent*>(buf), count, &cnt);
489 int KernelProxy::fchdir(int fd) {
494 int KernelProxy::ftruncate(int fd, off_t length) {
495 ScopedKernelHandle handle;
496 Error error = AcquireHandle(fd, &handle);
502 error = handle->node()->FTruncate(length);
511 int KernelProxy::fsync(int fd) {
512 ScopedKernelHandle handle;
513 Error error = AcquireHandle(fd, &handle);
519 error = handle->node()->FSync();
528 int KernelProxy::fdatasync(int fd) {
533 int KernelProxy::isatty(int fd) {
534 ScopedKernelHandle handle;
535 Error error = AcquireHandle(fd, &handle);
541 error = handle->node()->IsaTTY();
550 int KernelProxy::ioctl(int fd, int request, va_list args) {
551 ScopedKernelHandle handle;
552 Error error = AcquireHandle(fd, &handle);
558 error = handle->node()->VIoctl(request, args);
567 off_t KernelProxy::lseek(int fd, off_t offset, int whence) {
568 ScopedKernelHandle handle;
569 Error error = AcquireHandle(fd, &handle);
576 error = handle->Seek(offset, whence, &new_offset);
585 int KernelProxy::unlink(const char* path) {
589 Error error = AcquireMountAndRelPath(path, &mnt, &rel);
595 error = mnt->Unlink(rel);
604 int KernelProxy::truncate(const char* path, off_t len) {
609 int KernelProxy::lstat(const char* path, struct stat* buf) {
614 int KernelProxy::rename(const char* path, const char* newpath) {
619 int KernelProxy::remove(const char* path) {
623 Error error = AcquireMountAndRelPath(path, &mnt, &rel);
629 error = mnt->Remove(rel);
638 // TODO(noelallen): Needs implementation.
639 int KernelProxy::fchmod(int fd, int mode) {
640 ScopedKernelHandle handle;
641 Error error = AcquireHandle(fd, &handle);
650 int KernelProxy::fcntl(int fd, int request, va_list args) {
653 // F_GETFD and F_SETFD are descirptor specific flags that
654 // are stored in the KernelObject's decriptor map unlink
655 // F_GETFL and F_SETFL which are handle specific.
659 error = GetFDFlags(fd, &rtn);
667 int flags = va_arg(args, int);
668 error = SetFDFlags(fd, flags);
677 ScopedKernelHandle handle;
678 error = AcquireHandle(fd, &handle);
685 error = handle->VFcntl(request, &rtn, args);
694 int KernelProxy::access(const char* path, int amode) {
698 Error error = AcquireMountAndRelPath(path, &mnt, &rel);
704 error = mnt->Access(rel, amode);
712 int KernelProxy::readlink(const char *path, char *buf, size_t count) {
717 int KernelProxy::utimes(const char *filename, const struct timeval times[2]) {
722 // TODO(noelallen): Needs implementation.
723 int KernelProxy::link(const char* oldpath, const char* newpath) {
728 int KernelProxy::symlink(const char* oldpath, const char* newpath) {
733 void* KernelProxy::mmap(void* addr,
739 // We shouldn't be getting anonymous mmaps here.
740 assert((flags & MAP_ANONYMOUS) == 0);
743 ScopedKernelHandle handle;
744 Error error = AcquireHandle(fd, &handle);
751 error = handle->node()->MMap(addr, length, prot, flags, offset, &new_addr);
760 int KernelProxy::munmap(void* addr, size_t length) {
761 // NOTE: The comment below is from a previous discarded implementation that
762 // tracks mmap'd regions. For simplicity, we no longer do this; because we
763 // "snapshot" the contents of the file in mmap(), and don't support
764 // write-back or updating the mapped region when the file is written, holding
765 // on to the KernelHandle is pointless.
767 // If we ever do, these threading issues should be considered.
770 // WARNING: this function may be called by free().
772 // There is a potential deadlock scenario:
773 // Thread 1: open() -> takes lock1 -> free() -> takes lock2
774 // Thread 2: free() -> takes lock2 -> munmap() -> takes lock1
776 // Note that open() above could be any function that takes a lock that is
777 // shared with munmap (this includes munmap!)
779 // To prevent this, we avoid taking locks in munmap() that are used by other
780 // nacl_io functions that may call free. Specifically, we only take the
781 // mmap_lock, which is only shared with mmap() above. There is still a
782 // possibility of deadlock if mmap() or munmap() calls free(), so this is not
785 // Unfortunately, munmap still needs to acquire other locks; see the call to
786 // ReleaseHandle below which takes the process lock. This is safe as long as
787 // this is never executed from free() -- we can be reasonably sure this is
788 // true, because malloc only makes anonymous mmap() requests, and should only
789 // be munmapping those allocations. We never add to mmap_info_list_ for
790 // anonymous maps, so the unmap_list should always be empty when called from
795 int KernelProxy::tcflush(int fd, int queue_selector) {
796 ScopedKernelHandle handle;
797 Error error = AcquireHandle(fd, &handle);
803 error = handle->node()->Tcflush(queue_selector);
812 int KernelProxy::tcgetattr(int fd, struct termios* termios_p) {
813 ScopedKernelHandle handle;
814 Error error = AcquireHandle(fd, &handle);
820 error = handle->node()->Tcgetattr(termios_p);
829 int KernelProxy::tcsetattr(int fd, int optional_actions,
830 const struct termios *termios_p) {
831 ScopedKernelHandle handle;
832 Error error = AcquireHandle(fd, &handle);
838 error = handle->node()->Tcsetattr(optional_actions, termios_p);
847 int KernelProxy::kill(pid_t pid, int sig) {
848 // Currently we don't even pretend that other processes exist
849 // so we can only send a signal to outselves. For kill(2)
850 // pid 0 means the current process group and -1 means all the
851 // processes we have permission to send signals to.
852 if (pid != getpid() && pid != -1 && pid != 0) {
857 // Raise an event so that select/poll get interrupted.
858 AUTO_LOCK(signal_emitter_->GetLock())
859 signal_emitter_->RaiseEvents_Locked(POLLERR);
862 if (sigwinch_handler_ != SIG_IGN)
863 sigwinch_handler_(SIGWINCH);
877 sighandler_t KernelProxy::sigset(int signum, sighandler_t handler) {
881 sighandler_t old_value = sigwinch_handler_;
882 if (handler == SIG_DFL)
884 sigwinch_handler_ = handler;
903 if (handler == SIG_DFL)
912 #ifdef PROVIDES_SOCKET_API
914 int KernelProxy::select(int nfds, fd_set* readfds, fd_set* writefds,
915 fd_set* exceptfds, struct timeval* timeout) {
917 std::vector<pollfd> pollfds;
919 // Simplify logic, by using an IGNORE set for any undefined set
923 if (NULL == writefds)
925 if (NULL == exceptfds)
928 for (int fd = 0; fd < nfds; fd++) {
930 if (FD_ISSET(fd, readfds))
933 if (FD_ISSET(fd, writefds))
936 if (FD_ISSET(fd, exceptfds))
937 events |= POLLERR | POLLHUP;
942 info.events = events;
943 pollfds.push_back(info);
951 // NULL timeout signals wait forever.
953 if (timeout != NULL) {
954 int64_t ms = timeout->tv_sec * 1000 + ((timeout->tv_usec + 500) / 1000);
956 // If the timeout is invalid or too long (larger than signed 32 bit).
957 if ((timeout->tv_sec < 0) || (timeout->tv_sec >= (INT_MAX / 1000)) ||
958 (timeout->tv_usec < 0) || (timeout->tv_usec >= 1000000) ||
959 (ms < 0) || (ms >= INT_MAX)) {
964 ms_timeout = static_cast<int>(ms);
967 int result = poll(&pollfds[0], pollfds.size(), ms_timeout);
972 for (size_t index = 0; index < pollfds.size(); index++) {
973 pollfd* info = &pollfds[index];
974 if (info->revents & POLLIN) {
975 FD_SET(info->fd, readfds);
978 if (info->revents & POLLOUT) {
979 FD_SET(info->fd, writefds);
982 if (info->revents & (POLLHUP | POLLERR)) {
983 FD_SET(info->fd, exceptfds);
992 PollInfo() : index(-1) {};
994 std::vector<struct pollfd*> fds;
998 typedef std::map<EventEmitter*, PollInfo> EventPollMap_t;
1000 int KernelProxy::poll(struct pollfd *fds, nfds_t nfds, int timeout) {
1001 EventPollMap_t event_map;
1003 std::vector<EventRequest> requests;
1004 size_t event_cnt = 0;
1006 for (int index = 0; static_cast<nfds_t>(index) < nfds; index++) {
1007 ScopedKernelHandle handle;
1008 struct pollfd* fd_info = &fds[index];
1009 Error err = AcquireHandle(fd_info->fd, &handle);
1011 fd_info->revents = 0;
1013 // If the node isn't open, or somehow invalid, mark it so.
1015 fd_info->revents = POLLNVAL;
1020 // If it's already signaled, then just capture the event
1021 ScopedEventEmitter emitter(handle->node()->GetEventEmitter());
1022 int events = POLLIN | POLLOUT;
1024 events = emitter->GetEventStatus();
1026 if (events & fd_info->events) {
1027 fd_info->revents = events & fd_info->events;
1032 if (NULL == emitter) {
1033 fd_info->revents = POLLNVAL;
1038 // Otherwise try to track it.
1039 PollInfo* info = &event_map[emitter.get()];
1040 if (info->index == -1) {
1041 EventRequest request;
1042 request.emitter = emitter;
1043 request.filter = fd_info->events;
1046 info->index = requests.size();
1047 requests.push_back(request);
1049 info->fds.push_back(fd_info);
1050 requests[info->index].filter |= fd_info->events;
1053 // If nothing is signaled, then we must wait on the event map
1054 if (0 == event_cnt) {
1055 EventListenerPoll wait;
1056 Error err = wait.WaitOnAny(&requests[0], requests.size(), timeout);
1057 if ((err != 0) && (err != ETIMEDOUT)) {
1062 for (size_t rindex = 0; rindex < requests.size(); rindex++) {
1063 EventRequest* request = &requests[rindex];
1064 if (request->events) {
1065 PollInfo* poll_info = &event_map[request->emitter.get()];
1066 for (size_t findex = 0; findex < poll_info->fds.size(); findex++) {
1067 struct pollfd* fd_info = poll_info->fds[findex];
1068 uint32_t events = fd_info->events & request->events;
1070 fd_info->revents = events;
1083 int KernelProxy::accept(int fd, struct sockaddr* addr, socklen_t* len) {
1084 if (NULL == addr || NULL == len) {
1089 ScopedKernelHandle handle;
1090 Error error = AcquireHandle(fd, &handle);
1096 PP_Resource new_sock = 0;
1097 error = handle->Accept(&new_sock, addr, len);
1103 MountNodeSocket* sock = new MountNodeTCP(stream_mount_.get(), new_sock);
1105 // The MountNodeSocket now holds a reference to the new socket
1106 // so we release ours.
1107 ppapi_->ReleaseResource(new_sock);
1108 error = sock->Init(S_IREAD | S_IWRITE);
1114 ScopedMountNode node(sock);
1115 ScopedKernelHandle new_handle(new KernelHandle(stream_mount_, node));
1116 error = sock->Init(O_RDWR);
1122 return AllocateFD(new_handle);
1125 int KernelProxy::bind(int fd, const struct sockaddr* addr, socklen_t len) {
1131 ScopedKernelHandle handle;
1132 if (AcquireSocketHandle(fd, &handle) == -1)
1135 Error err = handle->socket_node()->Bind(addr, len);
1144 int KernelProxy::connect(int fd, const struct sockaddr* addr, socklen_t len) {
1150 ScopedKernelHandle handle;
1151 Error error = AcquireHandle(fd, &handle);
1157 error = handle->Connect(addr, len);
1166 struct hostent* KernelProxy::gethostbyname(const char* name) {
1167 return host_resolver_.gethostbyname(name);
1170 int KernelProxy::getpeername(int fd, struct sockaddr* addr, socklen_t* len) {
1171 if (NULL == addr || NULL == len) {
1176 ScopedKernelHandle handle;
1177 if (AcquireSocketHandle(fd, &handle) == -1)
1180 Error err = handle->socket_node()->GetPeerName(addr, len);
1189 int KernelProxy::getsockname(int fd, struct sockaddr* addr, socklen_t* len) {
1190 if (NULL == addr || NULL == len) {
1195 ScopedKernelHandle handle;
1196 if (AcquireSocketHandle(fd, &handle) == -1)
1199 Error err = handle->socket_node()->GetSockName(addr, len);
1208 int KernelProxy::getsockopt(int fd,
1213 if (NULL == optval || NULL == len) {
1218 ScopedKernelHandle handle;
1219 if (AcquireSocketHandle(fd, &handle) == -1)
1222 Error err = handle->socket_node()->GetSockOpt(lvl, optname, optval, len);
1231 int KernelProxy::listen(int fd, int backlog) {
1232 ScopedKernelHandle handle;
1233 if (AcquireSocketHandle(fd, &handle) == -1)
1236 Error err = handle->socket_node()->Listen(backlog);
1245 ssize_t KernelProxy::recv(int fd,
1254 ScopedKernelHandle handle;
1255 Error error = AcquireHandle(fd, &handle);
1262 error = handle->Recv(buf, len, flags, &out_len);
1268 return static_cast<ssize_t>(out_len);
1271 ssize_t KernelProxy::recvfrom(int fd,
1275 struct sockaddr* addr,
1276 socklen_t* addrlen) {
1277 // According to the manpage, recvfrom with a null addr is identical to recv.
1279 return recv(fd, buf, len, flags);
1282 if (NULL == buf || NULL == addrlen) {
1287 ScopedKernelHandle handle;
1288 Error error = AcquireHandle(fd, &handle);
1295 error = handle->RecvFrom(buf, len, flags, addr, addrlen, &out_len);
1301 return static_cast<ssize_t>(out_len);
1304 ssize_t KernelProxy::recvmsg(int fd, struct msghdr* msg, int flags) {
1310 ScopedKernelHandle handle;
1311 if (AcquireSocketHandle(fd, &handle) == -1)
1318 ssize_t KernelProxy::send(int fd, const void* buf, size_t len, int flags) {
1324 ScopedKernelHandle handle;
1325 Error error = AcquireHandle(fd, &handle);
1332 error = handle->Send(buf, len, flags, &out_len);
1338 return static_cast<ssize_t>(out_len);
1341 ssize_t KernelProxy::sendto(int fd,
1345 const struct sockaddr* addr,
1346 socklen_t addrlen) {
1347 // According to the manpage, sendto with a null addr is identical to send.
1349 return send(fd, buf, len, flags);
1357 ScopedKernelHandle handle;
1358 Error error = AcquireHandle(fd, &handle);
1365 error = handle->SendTo(buf, len, flags, addr, addrlen, &out_len);
1371 return static_cast<ssize_t>(out_len);
1374 ssize_t KernelProxy::sendmsg(int fd, const struct msghdr* msg, int flags) {
1380 ScopedKernelHandle handle;
1381 if (AcquireSocketHandle(fd, &handle) == -1)
1388 int KernelProxy::setsockopt(int fd,
1393 if (NULL == optval) {
1398 ScopedKernelHandle handle;
1399 if (AcquireSocketHandle(fd, &handle) == -1)
1402 Error err = handle->socket_node()->SetSockOpt(lvl, optname, optval, len);
1411 int KernelProxy::shutdown(int fd, int how) {
1412 ScopedKernelHandle handle;
1413 if (AcquireSocketHandle(fd, &handle) == -1)
1416 Error err = handle->socket_node()->Shutdown(how);
1425 int KernelProxy::socket(int domain, int type, int protocol) {
1426 if (AF_INET != domain && AF_INET6 != domain) {
1427 errno = EAFNOSUPPORT;
1431 MountNodeSocket* sock = NULL;
1434 sock = new MountNodeUDP(stream_mount_.get());
1438 sock = new MountNodeTCP(stream_mount_.get());
1442 errno = EPROTONOSUPPORT;
1446 ScopedMountNode node(sock);
1447 Error rtn = sock->Init(S_IREAD | S_IWRITE);
1453 ScopedKernelHandle handle(new KernelHandle(stream_mount_, node));
1454 rtn = handle->Init(O_RDWR);
1460 return AllocateFD(handle);
1463 int KernelProxy::socketpair(int domain, int type, int protocol, int* sv) {
1469 // Catch-22: We don't support AF_UNIX, but any other AF doesn't support
1470 // socket pairs. Thus, this function always fails.
1471 if (AF_UNIX != domain) {
1472 errno = EPROTONOSUPPORT;
1476 if (AF_INET != domain && AF_INET6 != domain) {
1477 errno = EAFNOSUPPORT;
1481 // We cannot reach this point.
1486 int KernelProxy::AcquireSocketHandle(int fd, ScopedKernelHandle* handle) {
1487 Error error = AcquireHandle(fd, handle);
1494 if ((handle->get()->node_->GetType() & S_IFSOCK) == 0) {
1502 #endif // PROVIDES_SOCKET_API
1504 } // namespace_nacl_io