Updating trunk VERSION from 2139.0 to 2140.0
[chromium-blink-merge.git] / native_client_sdk / src / libraries / nacl_io / kernel_proxy.cc
blob7574d062a0033fc9059d71bd6b9edc067485a136
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"
7 #include <assert.h>
8 #include <errno.h>
9 #include <fcntl.h>
10 #include <limits.h>
11 #include <poll.h>
12 #include <pthread.h>
13 #include <stdio.h>
14 #include <string.h>
15 #include <sys/time.h>
16 #include <unistd.h>
18 #include <iterator>
19 #include <string>
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"
47 #ifndef MAXPATHLEN
48 #define MAXPATHLEN 256
49 #endif
51 namespace nacl_io {
53 KernelProxy::KernelProxy()
54 : dev_(0),
55 ppapi_(NULL),
56 exit_callback_(NULL),
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();
68 ++i) {
69 delete i->second;
73 Error KernelProxy::Init(PepperInterface* ppapi) {
74 Error rtn = 0;
75 ppapi_ = ppapi;
76 dev_ = 1;
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);
86 if (rtn != 0)
87 assert(false);
89 ScopedFilesystem fs;
90 rtn = MountInternal("", "/dev", "dev", 0, NULL, false, &fs);
91 if (rtn != 0)
92 assert(false);
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);
98 if (rtn != 0)
99 assert(false);
101 rtn = CreateFsNode(dev_fs_);
102 if (rtn != 0)
103 assert(false);
105 // Open the first three in order to get STDIN, STDOUT, STDERR
106 int fd;
107 fd = open("/dev/stdin", O_RDONLY);
108 assert(fd == 0);
109 if (fd < 0)
110 rtn = errno;
112 fd = open("/dev/stdout", O_WRONLY);
113 assert(fd == 1);
114 if (fd < 0)
115 rtn = errno;
117 fd = open("/dev/stderr", O_WRONLY);
118 assert(fd == 2);
119 if (fd < 0)
120 rtn = errno;
122 #ifdef PROVIDES_SOCKET_API
123 host_resolver_.Init(ppapi_);
124 #endif
126 FsInitArgs args;
127 args.dev = dev_++;
128 args.ppapi = ppapi_;
129 stream_fs_.reset(new StreamFs());
130 int result = stream_fs_->Init(args);
131 if (result != 0) {
132 assert(false);
133 rtn = result;
136 return rtn;
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())
143 return false;
145 factories_[fs_type] = new FuseFsFactory(fuse_ops);
146 return true;
149 bool KernelProxy::UnregisterFsType(const char* fs_type) {
150 FsFactoryMap_t::iterator iter = factories_.find(fs_type);
151 if (iter == factories_.end())
152 return false;
154 delete iter->second;
155 factories_.erase(iter);
156 return true;
159 void KernelProxy::SetExitCallback(nacl_io_exit_callback_t exit_callback,
160 void* user_data) {
161 exit_callback_ = exit_callback;
162 exit_callback_user_data_ = user_data;
165 void KernelProxy::SetMountCallback(nacl_io_mount_callback_t mount_callback,
166 void* user_data) {
167 mount_callback_ = mount_callback;
168 mount_callback_user_data_ = user_data;
171 int KernelProxy::open_resource(const char* path) {
172 ScopedFilesystem fs;
173 Path rel;
175 Error error = AcquireFsAndRelPath(path, &fs, &rel);
176 if (error) {
177 errno = error;
178 return -1;
181 ScopedNode node;
182 error = fs->OpenResource(rel, &node);
183 if (error) {
184 // OpenResource failed, try Open().
185 error = fs->Open(rel, O_RDONLY, &node);
186 if (error) {
187 errno = error;
188 return -1;
192 ScopedKernelHandle handle(new KernelHandle(fs, node));
193 error = handle->Init(O_RDONLY);
194 if (error) {
195 errno = error;
196 return -1;
199 return AllocateFD(handle, path);
202 int KernelProxy::open(const char* path, int open_flags) {
203 ScopedFilesystem fs;
204 ScopedNode node;
206 Error error = AcquireFsAndNode(path, open_flags, &fs, &node);
207 if (error) {
208 errno = error;
209 return -1;
212 ScopedKernelHandle handle(new KernelHandle(fs, node));
213 error = handle->Init(open_flags);
214 if (error) {
215 errno = error;
216 return -1;
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)) {
232 errno = EACCES;
233 return -1;
236 pipefds[0] = AllocateFD(handle0);
237 pipefds[1] = AllocateFD(handle1);
238 return 0;
241 errno = ENOSYS;
242 return -1;
245 int KernelProxy::close(int fd) {
246 ScopedKernelHandle handle;
247 Error error = AcquireHandle(fd, &handle);
248 if (error) {
249 errno = error;
250 return -1;
253 // Remove the FD from the process open file descriptor map
254 FreeFD(fd);
255 return 0;
258 int KernelProxy::dup(int oldfd) {
259 ScopedKernelHandle handle;
260 std::string path;
261 Error error = AcquireHandleAndPath(oldfd, &handle, &path);
262 if (error) {
263 errno = error;
264 return -1;
266 return AllocateFD(handle, path);
269 int KernelProxy::dup2(int oldfd, int newfd) {
270 // If it's the same file handle, just return
271 if (oldfd == newfd)
272 return newfd;
274 ScopedKernelHandle old_handle;
275 std::string old_path;
276 Error error = AcquireHandleAndPath(oldfd, &old_handle, &old_path);
277 if (error) {
278 errno = error;
279 return -1;
282 FreeAndReassignFD(newfd, old_handle, old_path);
283 return newfd;
286 int KernelProxy::chdir(const char* path) {
287 Error error = SetCWD(path);
288 if (error) {
289 errno = error;
290 return -1;
292 return 0;
295 void KernelProxy::exit(int status) {
296 if (exit_callback_)
297 exit_callback_(status, exit_callback_user_data_);
300 char* KernelProxy::getcwd(char* buf, size_t size) {
301 if (NULL == buf) {
302 errno = EFAULT;
303 return NULL;
306 std::string cwd = GetCWD();
308 // Verify the buffer is large enough
309 if (size <= cwd.size()) {
310 errno = ERANGE;
311 return NULL;
314 strcpy(buf, cwd.c_str());
315 return buf;
318 char* KernelProxy::getwd(char* buf) {
319 if (NULL == buf) {
320 errno = EFAULT;
321 return NULL;
323 return getcwd(buf, MAXPATHLEN);
326 int KernelProxy::chmod(const char* path, mode_t mode) {
327 int fd = KernelProxy::open(path, O_RDONLY);
328 if (-1 == fd)
329 return -1;
331 int result = fchmod(fd, mode);
332 close(fd);
333 return result;
336 int KernelProxy::chown(const char* path, uid_t owner, gid_t group) {
337 return 0;
340 int KernelProxy::fchown(int fd, uid_t owner, gid_t group) {
341 return 0;
344 int KernelProxy::lchown(const char* path, uid_t owner, gid_t group) {
345 return 0;
348 int KernelProxy::utime(const char* filename, const struct utimbuf* times) {
349 return 0;
352 int KernelProxy::mkdir(const char* path, mode_t mode) {
353 ScopedFilesystem fs;
354 Path rel;
356 Error error = AcquireFsAndRelPath(path, &fs, &rel);
357 if (error) {
358 errno = error;
359 return -1;
362 error = fs->Mkdir(rel, mode);
363 if (error) {
364 errno = error;
365 return -1;
368 return 0;
371 int KernelProxy::rmdir(const char* path) {
372 ScopedFilesystem fs;
373 Path rel;
375 Error error = AcquireFsAndRelPath(path, &fs, &rel);
376 if (error) {
377 errno = error;
378 return -1;
381 error = fs->Rmdir(rel);
382 if (error) {
383 errno = error;
384 return -1;
387 return 0;
390 int KernelProxy::stat(const char* path, struct stat* buf) {
391 int fd = open(path, O_RDONLY);
392 if (-1 == fd)
393 return -1;
395 int result = fstat(fd, buf);
396 close(fd);
397 return result;
400 int KernelProxy::mount(const char* source,
401 const char* target,
402 const char* filesystemtype,
403 unsigned long mountflags,
404 const void* data) {
405 ScopedFilesystem fs;
406 Error error = MountInternal(
407 source, target, filesystemtype, mountflags, data, true, &fs);
408 if (error) {
409 errno = error;
410 return -1;
413 return 0;
416 Error KernelProxy::MountInternal(const char* source,
417 const char* target,
418 const char* filesystemtype,
419 unsigned long mountflags,
420 const void* data,
421 bool create_fs_node,
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);
429 return ENODEV;
432 // Create a map of settings
433 StringMap_t smap;
434 smap["SOURCE"] = source;
436 if (data) {
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();
442 ++it) {
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);
447 smap[key] = val;
448 } else {
449 smap[*it] = "TRUE";
454 FsInitArgs args;
455 args.dev = dev_++;
456 args.string_map = smap;
457 args.ppapi = ppapi_;
459 ScopedFilesystem fs;
460 Error error = factory->second->CreateFilesystem(args, &fs);
461 if (error)
462 return error;
464 error = AttachFsAtPath(fs, abs_path);
465 if (error)
466 return error;
468 if (create_fs_node) {
469 error = CreateFsNode(fs);
470 if (error) {
471 DetachFsAtPath(abs_path, &fs);
472 return error;
476 *out_filesystem = fs;
478 if (mount_callback_) {
479 mount_callback_(source,
480 target,
481 filesystemtype,
482 mountflags,
483 data,
484 fs->dev(),
485 mount_callback_user_data_);
488 return 0;
491 Error KernelProxy::CreateFsNode(const ScopedFilesystem& fs) {
492 assert(dev_fs_);
494 return dev_fs_->CreateFsNode(fs.get());
497 int KernelProxy::umount(const char* path) {
498 ScopedFilesystem fs;
499 Error error = DetachFsAtPath(path, &fs);
500 if (error) {
501 errno = error;
502 return -1;
505 error = dev_fs_->DestroyFsNode(fs.get());
506 if (error) {
507 // Ignore any errors here, just log.
508 LOG_ERROR("Unable to destroy FsNode: %s", strerror(error));
510 return 0;
513 ssize_t KernelProxy::read(int fd, void* buf, size_t nbytes) {
514 ScopedKernelHandle handle;
515 Error error = AcquireHandle(fd, &handle);
516 if (error) {
517 errno = error;
518 return -1;
521 int cnt = 0;
522 error = handle->Read(buf, nbytes, &cnt);
523 if (error) {
524 errno = error;
525 return -1;
528 return cnt;
531 ssize_t KernelProxy::write(int fd, const void* buf, size_t nbytes) {
532 ScopedKernelHandle handle;
533 Error error = AcquireHandle(fd, &handle);
534 if (error) {
535 errno = error;
536 return -1;
539 int cnt = 0;
540 error = handle->Write(buf, nbytes, &cnt);
541 if (error) {
542 errno = error;
543 return -1;
546 return cnt;
549 int KernelProxy::fstat(int fd, struct stat* buf) {
550 ScopedKernelHandle handle;
551 Error error = AcquireHandle(fd, &handle);
552 if (error) {
553 errno = error;
554 return -1;
557 error = handle->node()->GetStat(buf);
558 if (error) {
559 errno = error;
560 return -1;
563 return 0;
566 int KernelProxy::getdents(int fd, void* buf, unsigned int count) {
567 ScopedKernelHandle handle;
568 Error error = AcquireHandle(fd, &handle);
569 if (error) {
570 errno = error;
571 return -1;
574 int cnt = 0;
575 error = handle->GetDents(static_cast<dirent*>(buf), count, &cnt);
576 if (error)
577 errno = error;
579 return cnt;
582 int KernelProxy::fchdir(int fd) {
583 ScopedKernelHandle handle;
584 std::string path;
585 Error error = AcquireHandleAndPath(fd, &handle, &path);
586 if (error) {
587 errno = error;
588 return -1;
591 if (!handle->node()->IsaDir()) {
592 errno = ENOTDIR;
593 return -1;
596 if (path.empty()) {
597 errno = EBADF;
598 return -1;
601 error = SetCWD(path);
602 if (error) {
603 // errno is return value from SetCWD
604 errno = error;
605 return -1;
607 return 0;
610 int KernelProxy::ftruncate(int fd, off_t length) {
611 ScopedKernelHandle handle;
612 Error error = AcquireHandle(fd, &handle);
613 if (error) {
614 errno = error;
615 return -1;
618 error = handle->node()->FTruncate(length);
619 if (error) {
620 errno = error;
621 return -1;
624 return 0;
627 int KernelProxy::fsync(int fd) {
628 ScopedKernelHandle handle;
629 Error error = AcquireHandle(fd, &handle);
630 if (error) {
631 errno = error;
632 return -1;
635 error = handle->node()->FSync();
636 if (error) {
637 errno = error;
638 return -1;
641 return 0;
644 int KernelProxy::fdatasync(int fd) {
645 errno = ENOSYS;
646 return -1;
649 int KernelProxy::isatty(int fd) {
650 ScopedKernelHandle handle;
651 Error error = AcquireHandle(fd, &handle);
652 if (error) {
653 errno = error;
654 return 0;
657 error = handle->node()->Isatty();
658 if (error) {
659 errno = error;
660 return 0;
663 return 1;
666 int KernelProxy::ioctl(int fd, int request, va_list args) {
667 ScopedKernelHandle handle;
668 Error error = AcquireHandle(fd, &handle);
669 if (error) {
670 errno = error;
671 return -1;
674 error = handle->node()->VIoctl(request, args);
675 if (error) {
676 errno = error;
677 return -1;
680 return 0;
683 off_t KernelProxy::lseek(int fd, off_t offset, int whence) {
684 ScopedKernelHandle handle;
685 Error error = AcquireHandle(fd, &handle);
686 if (error) {
687 errno = error;
688 return -1;
691 off_t new_offset;
692 error = handle->Seek(offset, whence, &new_offset);
693 if (error) {
694 errno = error;
695 return -1;
698 return new_offset;
701 int KernelProxy::unlink(const char* path) {
702 ScopedFilesystem fs;
703 Path rel;
705 Error error = AcquireFsAndRelPath(path, &fs, &rel);
706 if (error) {
707 errno = error;
708 return -1;
711 error = fs->Unlink(rel);
712 if (error) {
713 errno = error;
714 return -1;
717 return 0;
720 int KernelProxy::truncate(const char* path, off_t len) {
721 int fd = KernelProxy::open(path, O_WRONLY);
722 if (-1 == fd)
723 return -1;
725 int result = ftruncate(fd, len);
726 close(fd);
727 return result;
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) {
735 ScopedFilesystem fs;
736 Path rel;
737 Error error = AcquireFsAndRelPath(path, &fs, &rel);
738 if (error) {
739 errno = error;
740 return -1;
743 ScopedFilesystem newfs;
744 Path newrel;
745 error = AcquireFsAndRelPath(newpath, &newfs, &newrel);
746 if (error) {
747 errno = error;
748 return -1;
751 if (newfs.get() != fs.get()) {
752 // Renaming accross mountpoints is not allowed
753 errno = EXDEV;
754 return -1;
757 // They already point to the same path
758 if (rel == newrel)
759 return 0;
761 error = fs->Rename(rel, newrel);
762 if (error) {
763 errno = error;
764 return -1;
767 return 0;
770 int KernelProxy::remove(const char* path) {
771 ScopedFilesystem fs;
772 Path rel;
774 Error error = AcquireFsAndRelPath(path, &fs, &rel);
775 if (error) {
776 errno = error;
777 return -1;
780 error = fs->Remove(rel);
781 if (error) {
782 errno = error;
783 return -1;
786 return 0;
789 // TODO(noelallen): Needs implementation.
790 int KernelProxy::fchmod(int fd, int mode) {
791 ScopedKernelHandle handle;
792 Error error = AcquireHandle(fd, &handle);
793 if (error) {
794 errno = error;
795 return -1;
798 return 0;
801 int KernelProxy::fcntl(int fd, int request, va_list args) {
802 Error error = 0;
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.
807 switch (request) {
808 case F_GETFD: {
809 int rtn = -1;
810 error = GetFDFlags(fd, &rtn);
811 if (error) {
812 errno = error;
813 return -1;
815 return rtn;
817 case F_SETFD: {
818 int flags = va_arg(args, int);
819 error = SetFDFlags(fd, flags);
820 if (error) {
821 errno = error;
822 return -1;
824 return 0;
828 ScopedKernelHandle handle;
829 error = AcquireHandle(fd, &handle);
830 if (error) {
831 errno = error;
832 return -1;
835 int rtn = 0;
836 error = handle->VFcntl(request, &rtn, args);
837 if (error) {
838 errno = error;
839 return -1;
842 return rtn;
845 int KernelProxy::access(const char* path, int amode) {
846 ScopedFilesystem fs;
847 Path rel;
849 Error error = AcquireFsAndRelPath(path, &fs, &rel);
850 if (error) {
851 errno = error;
852 return -1;
855 error = fs->Access(rel, amode);
856 if (error) {
857 errno = error;
858 return -1;
860 return 0;
863 int KernelProxy::readlink(const char* path, char* buf, size_t count) {
864 LOG_TRACE("readlink is not implemented.");
865 errno = EINVAL;
866 return -1;
869 int KernelProxy::utimes(const char* filename, const struct timeval times[2]) {
870 LOG_TRACE("utimes is not implemented.");
871 errno = EINVAL;
872 return -1;
875 // TODO(noelallen): Needs implementation.
876 int KernelProxy::link(const char* oldpath, const char* newpath) {
877 LOG_TRACE("link is not implemented.");
878 errno = EINVAL;
879 return -1;
882 int KernelProxy::symlink(const char* oldpath, const char* newpath) {
883 LOG_TRACE("symlink is not implemented.");
884 errno = EINVAL;
885 return -1;
888 void* KernelProxy::mmap(void* addr,
889 size_t length,
890 int prot,
891 int flags,
892 int fd,
893 size_t offset) {
894 // We shouldn't be getting anonymous mmaps here.
895 assert((flags & MAP_ANONYMOUS) == 0);
896 assert(fd != -1);
898 ScopedKernelHandle handle;
899 Error error = AcquireHandle(fd, &handle);
900 if (error) {
901 errno = error;
902 return MAP_FAILED;
905 void* new_addr;
906 error = handle->node()->MMap(addr, length, prot, flags, offset, &new_addr);
907 if (error) {
908 errno = error;
909 return MAP_FAILED;
912 return 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
938 // allowed.
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
946 // free().
947 return 0;
950 int KernelProxy::tcflush(int fd, int queue_selector) {
951 ScopedKernelHandle handle;
952 Error error = AcquireHandle(fd, &handle);
953 if (error) {
954 errno = error;
955 return -1;
958 error = handle->node()->Tcflush(queue_selector);
959 if (error) {
960 errno = error;
961 return -1;
964 return 0;
967 int KernelProxy::tcgetattr(int fd, struct termios* termios_p) {
968 ScopedKernelHandle handle;
969 Error error = AcquireHandle(fd, &handle);
970 if (error) {
971 errno = error;
972 return -1;
975 error = handle->node()->Tcgetattr(termios_p);
976 if (error) {
977 errno = error;
978 return -1;
981 return 0;
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);
989 if (error) {
990 errno = error;
991 return -1;
994 error = handle->node()->Tcsetattr(optional_actions, termios_p);
995 if (error) {
996 errno = error;
997 return -1;
1000 return 0;
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) {
1009 errno = ESRCH;
1010 return -1;
1013 // Raise an event so that select/poll get interrupted.
1014 AUTO_LOCK(signal_emitter_->GetLock())
1015 signal_emitter_->RaiseEvents_Locked(POLLERR);
1016 switch (sig) {
1017 case SIGWINCH:
1018 if (sigwinch_handler_.sa_handler != SIG_IGN &&
1019 sigwinch_handler_.sa_handler != SIG_DFL) {
1020 sigwinch_handler_.sa_handler(SIGWINCH);
1022 break;
1024 case SIGUSR1:
1025 case SIGUSR2:
1026 break;
1028 default:
1029 LOG_TRACE("Unsupported signal: %d", sig);
1030 errno = EINVAL;
1031 return -1;
1033 return 0;
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
1041 errno = EINVAL;
1042 return -1;
1045 switch (signum) {
1046 // Handled signals.
1047 case SIGWINCH: {
1048 if (oaction)
1049 *oaction = sigwinch_handler_;
1050 if (action) {
1051 sigwinch_handler_ = *action;
1053 return 0;
1056 // Known signals
1057 case SIGHUP:
1058 case SIGINT:
1059 case SIGPIPE:
1060 case SIGPOLL:
1061 case SIGPROF:
1062 case SIGTERM:
1063 case SIGCHLD:
1064 case SIGURG:
1065 case SIGFPE:
1066 case SIGILL:
1067 case SIGQUIT:
1068 case SIGSEGV:
1069 case SIGTRAP:
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);
1074 errno = EINVAL;
1075 return -1;
1078 if (oaction) {
1079 memset(oaction, 0, sizeof(*oaction));
1080 oaction->sa_handler = SIG_DFL;
1082 return 0;
1084 // KILL and STOP cannot be handled
1085 case SIGKILL:
1086 case SIGSTOP:
1087 LOG_TRACE("sigaction on SIGKILL/SIGSTOP not supported.");
1088 errno = EINVAL;
1089 return -1;
1092 // Unknown signum
1093 errno = EINVAL;
1094 return -1;
1097 #ifdef PROVIDES_SOCKET_API
1099 int KernelProxy::select(int nfds,
1100 fd_set* readfds,
1101 fd_set* writefds,
1102 fd_set* exceptfds,
1103 struct timeval* timeout) {
1104 std::vector<pollfd> pollfds;
1106 for (int fd = 0; fd < nfds; fd++) {
1107 int events = 0;
1108 if (readfds && FD_ISSET(fd, readfds)) {
1109 events |= POLLIN;
1110 FD_CLR(fd, readfds);
1113 if (writefds && FD_ISSET(fd, writefds)) {
1114 events |= POLLOUT;
1115 FD_CLR(fd, writefds);
1118 if (exceptfds && FD_ISSET(fd, exceptfds)) {
1119 events |= POLLERR | POLLHUP;
1120 FD_CLR(fd, exceptfds);
1123 if (events) {
1124 pollfd info;
1125 info.fd = fd;
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) ||
1139 (ms >= INT_MAX)) {
1140 LOG_TRACE("Invalid timeout: tv_sec=%d tv_usec=%d.",
1141 timeout->tv_sec,
1142 timeout->tv_usec);
1143 errno = EINVAL;
1144 return -1;
1147 ms_timeout = static_cast<int>(ms);
1150 int result = poll(&pollfds[0], pollfds.size(), ms_timeout);
1151 if (result == -1)
1152 return -1;
1154 int event_cnt = 0;
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);
1159 event_cnt++;
1161 if (info->revents & POLLOUT) {
1162 FD_SET(info->fd, writefds);
1163 event_cnt++;
1165 if (info->revents & (POLLHUP | POLLERR)) {
1166 FD_SET(info->fd, exceptfds);
1167 event_cnt++;
1171 return event_cnt;
1174 struct PollInfo {
1175 PollInfo() : index(-1) {};
1177 std::vector<struct pollfd*> fds;
1178 int index;
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.
1197 if (err != 0) {
1198 fd_info->revents = POLLNVAL;
1199 event_cnt++;
1200 continue;
1203 // If it's already signaled, then just capture the event
1204 ScopedEventEmitter emitter(handle->node()->GetEventEmitter());
1205 int events = POLLIN | POLLOUT;
1206 if (emitter)
1207 events = emitter->GetEventStatus();
1209 if (events & fd_info->events) {
1210 fd_info->revents = events & fd_info->events;
1211 event_cnt++;
1212 continue;
1215 if (NULL == emitter) {
1216 fd_info->revents = POLLNVAL;
1217 event_cnt++;
1218 continue;
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;
1227 request.events = 0;
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)) {
1241 errno = err;
1242 return -1;
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;
1252 if (events) {
1253 fd_info->revents = events;
1254 event_cnt++;
1261 return event_cnt;
1264 // Socket Functions
1265 int KernelProxy::accept(int fd, struct sockaddr* addr, socklen_t* len) {
1266 if (NULL == addr || NULL == len) {
1267 errno = EFAULT;
1268 return -1;
1271 ScopedKernelHandle handle;
1272 Error error = AcquireHandle(fd, &handle);
1273 if (error) {
1274 errno = error;
1275 return -1;
1278 PP_Resource new_sock = 0;
1279 error = handle->Accept(&new_sock, addr, len);
1280 if (error != 0) {
1281 errno = error;
1282 return -1;
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);
1291 if (error != 0) {
1292 errno = error;
1293 return -1;
1296 ScopedNode node(sock);
1297 ScopedKernelHandle new_handle(new KernelHandle(stream_fs_, node));
1298 error = new_handle->Init(O_RDWR);
1299 if (error != 0) {
1300 errno = error;
1301 return -1;
1304 return AllocateFD(new_handle);
1307 int KernelProxy::bind(int fd, const struct sockaddr* addr, socklen_t len) {
1308 if (NULL == addr) {
1309 errno = EFAULT;
1310 return -1;
1313 ScopedKernelHandle handle;
1314 if (AcquireSocketHandle(fd, &handle) == -1)
1315 return -1;
1317 Error err = handle->socket_node()->Bind(addr, len);
1318 if (err != 0) {
1319 errno = err;
1320 return -1;
1323 return 0;
1326 int KernelProxy::connect(int fd, const struct sockaddr* addr, socklen_t len) {
1327 if (NULL == addr) {
1328 errno = EFAULT;
1329 return -1;
1332 ScopedKernelHandle handle;
1333 Error error = AcquireHandle(fd, &handle);
1334 if (error) {
1335 errno = error;
1336 return -1;
1339 error = handle->Connect(addr, len);
1340 if (error != 0) {
1341 errno = error;
1342 return -1;
1345 return 0;
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) {
1365 errno = EFAULT;
1366 return -1;
1369 ScopedKernelHandle handle;
1370 if (AcquireSocketHandle(fd, &handle) == -1)
1371 return -1;
1373 Error err = handle->socket_node()->GetPeerName(addr, len);
1374 if (err != 0) {
1375 errno = err;
1376 return -1;
1379 return 0;
1382 int KernelProxy::getsockname(int fd, struct sockaddr* addr, socklen_t* len) {
1383 if (NULL == addr || NULL == len) {
1384 errno = EFAULT;
1385 return -1;
1388 ScopedKernelHandle handle;
1389 if (AcquireSocketHandle(fd, &handle) == -1)
1390 return -1;
1392 Error err = handle->socket_node()->GetSockName(addr, len);
1393 if (err != 0) {
1394 errno = err;
1395 return -1;
1398 return 0;
1401 int KernelProxy::getsockopt(int fd,
1402 int lvl,
1403 int optname,
1404 void* optval,
1405 socklen_t* len) {
1406 if (NULL == optval || NULL == len) {
1407 errno = EFAULT;
1408 return -1;
1411 ScopedKernelHandle handle;
1412 if (AcquireSocketHandle(fd, &handle) == -1)
1413 return -1;
1415 Error err = handle->socket_node()->GetSockOpt(lvl, optname, optval, len);
1416 if (err != 0) {
1417 errno = err;
1418 return -1;
1421 return 0;
1424 int KernelProxy::listen(int fd, int backlog) {
1425 ScopedKernelHandle handle;
1426 if (AcquireSocketHandle(fd, &handle) == -1)
1427 return -1;
1429 Error err = handle->socket_node()->Listen(backlog);
1430 if (err != 0) {
1431 errno = err;
1432 return -1;
1435 return 0;
1438 ssize_t KernelProxy::recv(int fd, void* buf, size_t len, int flags) {
1439 if (NULL == buf) {
1440 errno = EFAULT;
1441 return -1;
1444 ScopedKernelHandle handle;
1445 Error error = AcquireHandle(fd, &handle);
1446 if (error) {
1447 errno = error;
1448 return -1;
1451 int out_len = 0;
1452 error = handle->Recv(buf, len, flags, &out_len);
1453 if (error != 0) {
1454 errno = error;
1455 return -1;
1458 return static_cast<ssize_t>(out_len);
1461 ssize_t KernelProxy::recvfrom(int fd,
1462 void* buf,
1463 size_t len,
1464 int flags,
1465 struct sockaddr* addr,
1466 socklen_t* addrlen) {
1467 // According to the manpage, recvfrom with a null addr is identical to recv.
1468 if (NULL == addr) {
1469 return recv(fd, buf, len, flags);
1472 if (NULL == buf || NULL == addrlen) {
1473 errno = EFAULT;
1474 return -1;
1477 ScopedKernelHandle handle;
1478 Error error = AcquireHandle(fd, &handle);
1479 if (error) {
1480 errno = error;
1481 return -1;
1484 int out_len = 0;
1485 error = handle->RecvFrom(buf, len, flags, addr, addrlen, &out_len);
1486 if (error != 0) {
1487 errno = error;
1488 return -1;
1491 return static_cast<ssize_t>(out_len);
1494 ssize_t KernelProxy::recvmsg(int fd, struct msghdr* msg, int flags) {
1495 if (NULL == msg) {
1496 errno = EFAULT;
1497 return -1;
1500 ScopedKernelHandle handle;
1501 if (AcquireSocketHandle(fd, &handle) == -1)
1502 return -1;
1504 errno = EOPNOTSUPP;
1505 return -1;
1508 ssize_t KernelProxy::send(int fd, const void* buf, size_t len, int flags) {
1509 if (NULL == buf) {
1510 errno = EFAULT;
1511 return -1;
1514 ScopedKernelHandle handle;
1515 Error error = AcquireHandle(fd, &handle);
1516 if (error) {
1517 errno = error;
1518 return -1;
1521 int out_len = 0;
1522 error = handle->Send(buf, len, flags, &out_len);
1523 if (error != 0) {
1524 errno = error;
1525 return -1;
1528 return static_cast<ssize_t>(out_len);
1531 ssize_t KernelProxy::sendto(int fd,
1532 const void* buf,
1533 size_t len,
1534 int flags,
1535 const struct sockaddr* addr,
1536 socklen_t addrlen) {
1537 // According to the manpage, sendto with a null addr is identical to send.
1538 if (NULL == addr) {
1539 return send(fd, buf, len, flags);
1542 if (NULL == buf) {
1543 errno = EFAULT;
1544 return -1;
1547 ScopedKernelHandle handle;
1548 Error error = AcquireHandle(fd, &handle);
1549 if (error) {
1550 errno = error;
1551 return -1;
1554 int out_len = 0;
1555 error = handle->SendTo(buf, len, flags, addr, addrlen, &out_len);
1556 if (error != 0) {
1557 errno = error;
1558 return -1;
1561 return static_cast<ssize_t>(out_len);
1564 ssize_t KernelProxy::sendmsg(int fd, const struct msghdr* msg, int flags) {
1565 if (NULL == msg) {
1566 errno = EFAULT;
1567 return -1;
1570 ScopedKernelHandle handle;
1571 if (AcquireSocketHandle(fd, &handle) == -1)
1572 return -1;
1574 errno = EOPNOTSUPP;
1575 return -1;
1578 int KernelProxy::setsockopt(int fd,
1579 int lvl,
1580 int optname,
1581 const void* optval,
1582 socklen_t len) {
1583 if (NULL == optval) {
1584 errno = EFAULT;
1585 return -1;
1588 ScopedKernelHandle handle;
1589 if (AcquireSocketHandle(fd, &handle) == -1)
1590 return -1;
1592 Error err = handle->socket_node()->SetSockOpt(lvl, optname, optval, len);
1593 if (err != 0) {
1594 errno = err;
1595 return -1;
1598 return 0;
1601 int KernelProxy::shutdown(int fd, int how) {
1602 ScopedKernelHandle handle;
1603 if (AcquireSocketHandle(fd, &handle) == -1)
1604 return -1;
1606 Error err = handle->socket_node()->Shutdown(how);
1607 if (err != 0) {
1608 errno = err;
1609 return -1;
1612 return 0;
1615 int KernelProxy::socket(int domain, int type, int protocol) {
1616 if (AF_INET != domain && AF_INET6 != domain) {
1617 errno = EAFNOSUPPORT;
1618 return -1;
1621 int open_flags = O_RDWR;
1623 if (type & SOCK_CLOEXEC) {
1624 #ifdef O_CLOEXEC
1625 // The NaCl newlib version of fcntl.h doesn't currently define
1626 // O_CLOEXEC.
1627 // TODO(sbc): remove this guard once it gets added.
1628 open_flags |= O_CLOEXEC;
1629 #endif
1630 type &= ~SOCK_CLOEXEC;
1633 if (type & SOCK_NONBLOCK) {
1634 open_flags |= O_NONBLOCK;
1635 type &= ~SOCK_NONBLOCK;
1638 SocketNode* sock = NULL;
1639 switch (type) {
1640 case SOCK_DGRAM:
1641 sock = new UdpNode(stream_fs_.get());
1642 break;
1644 case SOCK_STREAM:
1645 sock = new TcpNode(stream_fs_.get());
1646 break;
1648 case SOCK_SEQPACKET:
1649 case SOCK_RDM:
1650 case SOCK_RAW:
1651 errno = EPROTONOSUPPORT;
1652 return -1;
1654 default:
1655 errno = EINVAL;
1656 return -1;
1659 ScopedNode node(sock);
1660 Error rtn = sock->Init(O_RDWR);
1661 if (rtn != 0) {
1662 errno = rtn;
1663 return -1;
1666 ScopedKernelHandle handle(new KernelHandle(stream_fs_, node));
1667 rtn = handle->Init(open_flags);
1668 if (rtn != 0) {
1669 errno = rtn;
1670 return -1;
1673 return AllocateFD(handle);
1676 int KernelProxy::socketpair(int domain, int type, int protocol, int* sv) {
1677 if (NULL == sv) {
1678 errno = EFAULT;
1679 return -1;
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;
1686 return -1;
1689 if (AF_INET != domain && AF_INET6 != domain) {
1690 errno = EAFNOSUPPORT;
1691 return -1;
1694 // We cannot reach this point.
1695 errno = ENOSYS;
1696 return -1;
1699 int KernelProxy::AcquireSocketHandle(int fd, ScopedKernelHandle* handle) {
1700 Error error = AcquireHandle(fd, handle);
1702 if (error) {
1703 errno = error;
1704 return -1;
1707 if ((handle->get()->node_->GetType() & S_IFSOCK) == 0) {
1708 errno = ENOTSOCK;
1709 return -1;
1712 return 0;
1715 #endif // PROVIDES_SOCKET_API
1717 } // namespace_nacl_io