[NaCl SDK] Never return st_size == 0 for directory nodes
[chromium-blink-merge.git] / native_client_sdk / src / libraries / nacl_io / kernel_proxy.cc
blobb554ade35226994cee50d28578dfc2fba3e156db
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/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"
48 #ifndef MAXPATHLEN
49 #define MAXPATHLEN 256
50 #endif
52 namespace nacl_io {
54 KernelProxy::KernelProxy()
55 : dev_(0),
56 ppapi_(NULL),
57 exit_callback_(NULL),
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();
69 ++i) {
70 delete i->second;
74 Error KernelProxy::Init(PepperInterface* ppapi) {
75 Error rtn = 0;
76 ppapi_ = ppapi;
77 dev_ = 1;
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);
87 if (rtn != 0)
88 return rtn;
90 ScopedFilesystem fs;
91 rtn = MountInternal("", "/dev", "dev", 0, NULL, false, &fs);
92 if (rtn != 0)
93 return rtn;
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);
99 if (rtn != 0)
100 return rtn;
102 rtn = CreateFsNode(dev_fs_);
103 if (rtn != 0)
104 return rtn;
106 // Open the first three in order to get STDIN, STDOUT, STDERR
107 int fd;
108 fd = open("/dev/stdin", O_RDONLY, 0);
109 if (fd < 0) {
110 LOG_ERROR("failed to open /dev/stdin: %s", strerror(errno));
111 return errno;
113 assert(fd == 0);
115 fd = open("/dev/stdout", O_WRONLY, 0);
116 if (fd < 0) {
117 LOG_ERROR("failed to open /dev/stdout: %s", strerror(errno));
118 return errno;
120 assert(fd == 1);
122 fd = open("/dev/stderr", O_WRONLY, 0);
123 if (fd < 0) {
124 LOG_ERROR("failed to open /dev/sterr: %s", strerror(errno));
125 return errno;
127 assert(fd == 2);
129 #ifdef PROVIDES_SOCKET_API
130 host_resolver_.Init(ppapi_);
131 #endif
133 FsInitArgs args;
134 args.dev = dev_++;
135 args.ppapi = ppapi_;
136 stream_fs_.reset(new StreamFs());
137 int result = stream_fs_->Init(args);
138 if (result != 0) {
139 LOG_ERROR("initializing streamfs failed: %s", strerror(result));
140 return result;
143 return 0;
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())
150 return false;
152 factories_[fs_type] = new FuseFsFactory(fuse_ops);
153 return true;
156 bool KernelProxy::UnregisterFsType(const char* fs_type) {
157 FsFactoryMap_t::iterator iter = factories_.find(fs_type);
158 if (iter == factories_.end())
159 return false;
161 delete iter->second;
162 factories_.erase(iter);
163 return true;
166 void KernelProxy::SetExitCallback(nacl_io_exit_callback_t exit_callback,
167 void* user_data) {
168 exit_callback_ = exit_callback;
169 exit_callback_user_data_ = user_data;
172 void KernelProxy::SetMountCallback(nacl_io_mount_callback_t mount_callback,
173 void* user_data) {
174 mount_callback_ = mount_callback;
175 mount_callback_user_data_ = user_data;
178 int KernelProxy::open_resource(const char* path) {
179 ScopedFilesystem fs;
180 Path rel;
182 Error error = AcquireFsAndRelPath(path, &fs, &rel);
183 if (error) {
184 errno = error;
185 return -1;
188 ScopedNode node;
189 error = fs->OpenResource(rel, &node);
190 if (error) {
191 // OpenResource failed, try Open().
192 error = fs->Open(rel, O_RDONLY, &node);
193 if (error) {
194 errno = error;
195 return -1;
199 ScopedKernelHandle handle(new KernelHandle(fs, node));
200 error = handle->Init(O_RDONLY);
201 if (error) {
202 errno = error;
203 return -1;
206 return AllocateFD(handle, path);
209 int KernelProxy::open(const char* path, int open_flags, mode_t mode) {
210 ScopedFilesystem fs;
211 ScopedNode node;
212 mode_t mask = ~GetUmask() & S_MODEBITS;
214 Error error = AcquireFsAndNode(path, open_flags, mode & mask, &fs, &node);
215 if (error) {
216 errno = error;
217 return -1;
220 ScopedKernelHandle handle(new KernelHandle(fs, node));
221 error = handle->Init(open_flags);
222 if (error) {
223 errno = error;
224 return -1;
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)) {
240 errno = EACCES;
241 return -1;
244 pipefds[0] = AllocateFD(handle0);
245 pipefds[1] = AllocateFD(handle1);
246 return 0;
249 errno = ENOSYS;
250 return -1;
253 int KernelProxy::close(int fd) {
254 ScopedKernelHandle handle;
255 Error error = AcquireHandle(fd, &handle);
256 if (error) {
257 errno = error;
258 return -1;
261 // Remove the FD from the process open file descriptor map
262 FreeFD(fd);
263 return 0;
266 int KernelProxy::dup(int oldfd) {
267 ScopedKernelHandle handle;
268 std::string path;
269 Error error = AcquireHandleAndPath(oldfd, &handle, &path);
270 if (error) {
271 errno = error;
272 return -1;
274 return AllocateFD(handle, path);
277 int KernelProxy::dup2(int oldfd, int newfd) {
278 // If it's the same file handle, just return
279 if (oldfd == newfd)
280 return newfd;
282 if (newfd < 0) {
283 errno = EBADF;
284 return -1;
287 ScopedKernelHandle old_handle;
288 std::string old_path;
289 Error error = AcquireHandleAndPath(oldfd, &old_handle, &old_path);
290 if (error) {
291 errno = error;
292 return -1;
295 FreeAndReassignFD(newfd, old_handle, old_path);
296 return newfd;
299 int KernelProxy::chdir(const char* path) {
300 Error error = SetCWD(path);
301 if (error) {
302 errno = error;
303 return -1;
305 return 0;
308 void KernelProxy::exit(int status) {
309 if (exit_callback_)
310 exit_callback_(status, exit_callback_user_data_);
313 char* KernelProxy::getcwd(char* buf, size_t size) {
314 if (NULL == buf) {
315 errno = EFAULT;
316 return NULL;
319 std::string cwd = GetCWD();
321 // Verify the buffer is large enough
322 if (size <= cwd.size()) {
323 errno = ERANGE;
324 return NULL;
327 strcpy(buf, cwd.c_str());
328 return buf;
331 char* KernelProxy::getwd(char* buf) {
332 if (NULL == buf) {
333 errno = EFAULT;
334 return NULL;
336 return getcwd(buf, MAXPATHLEN);
339 int KernelProxy::chmod(const char* path, mode_t mode) {
340 ScopedFilesystem fs;
341 ScopedNode node;
343 Error error = AcquireFsAndNode(path, O_RDONLY, 0, &fs, &node);
344 if (error) {
345 errno = error;
346 return -1;
349 error = node->Fchmod(mode & S_MODEBITS);
350 if (error) {
351 errno = error;
352 return -1;
355 return 0;
358 int KernelProxy::chown(const char* path, uid_t owner, gid_t group) {
359 return 0;
362 int KernelProxy::fchown(int fd, uid_t owner, gid_t group) {
363 return 0;
366 int KernelProxy::lchown(const char* path, uid_t owner, gid_t group) {
367 return 0;
370 int KernelProxy::mkdir(const char* path, mode_t mode) {
371 ScopedFilesystem fs;
372 Path rel;
374 Error error = AcquireFsAndRelPath(path, &fs, &rel);
375 if (error) {
376 errno = error;
377 return -1;
380 mode_t mask = ~GetUmask() & S_MODEBITS;
381 error = fs->Mkdir(rel, mode & mask);
382 if (error) {
383 errno = error;
384 return -1;
387 return 0;
390 int KernelProxy::rmdir(const char* path) {
391 ScopedFilesystem fs;
392 Path rel;
394 Error error = AcquireFsAndRelPath(path, &fs, &rel);
395 if (error) {
396 errno = error;
397 return -1;
400 error = fs->Rmdir(rel);
401 if (error) {
402 errno = error;
403 return -1;
406 return 0;
409 int KernelProxy::stat(const char* path, struct stat* buf) {
410 ScopedFilesystem fs;
411 ScopedNode node;
413 Error error = AcquireFsAndNode(path, O_RDONLY, 0, &fs, &node);
414 if (error) {
415 errno = error;
416 return -1;
419 error = node->GetStat(buf);
420 if (error) {
421 errno = error;
422 return -1;
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)
431 buf->st_size = 4096;
433 return 0;
436 int KernelProxy::mount(const char* source,
437 const char* target,
438 const char* filesystemtype,
439 unsigned long mountflags,
440 const void* data) {
441 ScopedFilesystem fs;
442 Error error = MountInternal(
443 source, target, filesystemtype, mountflags, data, true, &fs);
444 if (error) {
445 errno = error;
446 return -1;
449 return 0;
452 Error KernelProxy::MountInternal(const char* source,
453 const char* target,
454 const char* filesystemtype,
455 unsigned long mountflags,
456 const void* data,
457 bool create_fs_node,
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);
465 return ENODEV;
468 // Create a map of settings
469 StringMap_t smap;
470 smap["SOURCE"] = source;
472 if (data) {
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();
478 ++it) {
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);
483 smap[key] = val;
484 } else {
485 smap[*it] = "TRUE";
490 FsInitArgs args;
491 args.dev = dev_++;
492 args.string_map = smap;
493 args.ppapi = ppapi_;
495 ScopedFilesystem fs;
496 Error error = factory->second->CreateFilesystem(args, &fs);
497 if (error)
498 return error;
500 error = AttachFsAtPath(fs, abs_path);
501 if (error)
502 return error;
504 if (create_fs_node) {
505 error = CreateFsNode(fs);
506 if (error) {
507 DetachFsAtPath(abs_path, &fs);
508 return error;
512 *out_filesystem = fs;
514 if (mount_callback_) {
515 mount_callback_(source,
516 target,
517 filesystemtype,
518 mountflags,
519 data,
520 fs->dev(),
521 mount_callback_user_data_);
524 return 0;
527 Error KernelProxy::CreateFsNode(const ScopedFilesystem& fs) {
528 assert(dev_fs_);
530 return dev_fs_->CreateFsNode(fs.get());
533 int KernelProxy::umount(const char* path) {
534 ScopedFilesystem fs;
535 Error error = DetachFsAtPath(path, &fs);
536 if (error) {
537 errno = error;
538 return -1;
541 error = dev_fs_->DestroyFsNode(fs.get());
542 if (error) {
543 // Ignore any errors here, just log.
544 LOG_ERROR("Unable to destroy FsNode: %s", strerror(error));
546 return 0;
549 ssize_t KernelProxy::read(int fd, void* buf, size_t nbytes) {
550 ScopedKernelHandle handle;
551 Error error = AcquireHandle(fd, &handle);
552 if (error) {
553 errno = error;
554 return -1;
557 int cnt = 0;
558 error = handle->Read(buf, nbytes, &cnt);
559 if (error) {
560 errno = error;
561 return -1;
564 return cnt;
567 ssize_t KernelProxy::write(int fd, const void* buf, size_t nbytes) {
568 ScopedKernelHandle handle;
569 Error error = AcquireHandle(fd, &handle);
570 if (error) {
571 errno = error;
572 return -1;
575 int cnt = 0;
576 error = handle->Write(buf, nbytes, &cnt);
577 if (error) {
578 errno = error;
579 return -1;
582 return cnt;
585 int KernelProxy::fstat(int fd, struct stat* buf) {
586 ScopedKernelHandle handle;
587 Error error = AcquireHandle(fd, &handle);
588 if (error) {
589 errno = error;
590 return -1;
593 error = handle->node()->GetStat(buf);
594 if (error) {
595 errno = error;
596 return -1;
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)
605 buf->st_size = 4096;
607 return 0;
610 int KernelProxy::getdents(int fd, struct dirent* buf, unsigned int count) {
611 ScopedKernelHandle handle;
612 Error error = AcquireHandle(fd, &handle);
613 if (error) {
614 errno = error;
615 return -1;
618 int cnt = 0;
619 error = handle->GetDents(buf, count, &cnt);
620 if (error)
621 errno = error;
623 return cnt;
626 int KernelProxy::fchdir(int fd) {
627 ScopedKernelHandle handle;
628 std::string path;
629 Error error = AcquireHandleAndPath(fd, &handle, &path);
630 if (error) {
631 errno = error;
632 return -1;
635 if (!handle->node()->IsaDir()) {
636 errno = ENOTDIR;
637 return -1;
640 if (path.empty()) {
641 errno = EBADF;
642 return -1;
645 error = SetCWD(path);
646 if (error) {
647 // errno is return value from SetCWD
648 errno = error;
649 return -1;
651 return 0;
654 int KernelProxy::ftruncate(int fd, off_t length) {
655 ScopedKernelHandle handle;
656 Error error = AcquireHandle(fd, &handle);
657 if (error) {
658 errno = error;
659 return -1;
662 if (handle->OpenMode() == O_RDONLY) {
663 errno = EACCES;
664 return -1;
667 error = handle->node()->FTruncate(length);
668 if (error) {
669 errno = error;
670 return -1;
673 return 0;
676 int KernelProxy::fsync(int fd) {
677 ScopedKernelHandle handle;
678 Error error = AcquireHandle(fd, &handle);
679 if (error) {
680 errno = error;
681 return -1;
684 error = handle->node()->FSync();
685 if (error) {
686 errno = error;
687 return -1;
690 return 0;
693 int KernelProxy::fdatasync(int fd) {
694 errno = ENOSYS;
695 return -1;
698 int KernelProxy::isatty(int fd) {
699 ScopedKernelHandle handle;
700 Error error = AcquireHandle(fd, &handle);
701 if (error) {
702 errno = error;
703 return 0;
706 error = handle->node()->Isatty();
707 if (error) {
708 errno = error;
709 return 0;
712 return 1;
715 int KernelProxy::ioctl(int fd, int request, va_list args) {
716 ScopedKernelHandle handle;
717 Error error = AcquireHandle(fd, &handle);
718 if (error) {
719 errno = error;
720 return -1;
723 error = handle->node()->VIoctl(request, args);
724 if (error) {
725 errno = error;
726 return -1;
729 return 0;
732 int KernelProxy::futimens(int fd, const struct timespec times[2]) {
733 ScopedKernelHandle handle;
734 Error error = AcquireHandle(fd, &handle);
735 if (error) {
736 errno = error;
737 return -1;
740 return FutimensInternal(handle->node(), times);
743 Error KernelProxy::FutimensInternal(const ScopedNode& node,
744 const struct timespec times[2]) {
745 Error error(0);
746 if (times == NULL) {
747 struct timespec now[2];
748 struct timeval tm;
749 error = gettimeofday(&tm, NULL);
750 if (error) {
751 errno = error;
752 return -1;
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);
758 } else {
759 error = node->Futimens(times);
762 if (error) {
763 errno = error;
764 return -1;
767 return 0;
770 off_t KernelProxy::lseek(int fd, off_t offset, int whence) {
771 ScopedKernelHandle handle;
772 Error error = AcquireHandle(fd, &handle);
773 if (error) {
774 errno = error;
775 return -1;
778 off_t new_offset;
779 error = handle->Seek(offset, whence, &new_offset);
780 if (error) {
781 errno = error;
782 return -1;
785 return new_offset;
788 int KernelProxy::unlink(const char* path) {
789 ScopedFilesystem fs;
790 Path rel;
792 Error error = AcquireFsAndRelPath(path, &fs, &rel);
793 if (error) {
794 errno = error;
795 return -1;
798 error = fs->Unlink(rel);
799 if (error) {
800 errno = error;
801 return -1;
804 return 0;
807 int KernelProxy::truncate(const char* path, off_t len) {
808 ScopedFilesystem fs;
809 ScopedNode node;
811 Error error = AcquireFsAndNode(path, O_WRONLY, 0, &fs, &node);
812 if (error) {
813 errno = error;
814 return -1;
817 // Directories cannot be truncated.
818 if (node->IsaDir()) {
819 return EISDIR;
822 if (!node->CanOpen(O_WRONLY)) {
823 errno = EACCES;
824 return -1;
827 error = node->FTruncate(len);
828 if (error) {
829 errno = error;
830 return -1;
833 return 0;
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) {
841 ScopedFilesystem fs;
842 Path rel;
843 Error error = AcquireFsAndRelPath(path, &fs, &rel);
844 if (error) {
845 errno = error;
846 return -1;
849 ScopedFilesystem newfs;
850 Path newrel;
851 error = AcquireFsAndRelPath(newpath, &newfs, &newrel);
852 if (error) {
853 errno = error;
854 return -1;
857 if (newfs.get() != fs.get()) {
858 // Renaming accross mountpoints is not allowed
859 errno = EXDEV;
860 return -1;
863 // They already point to the same path
864 if (rel == newrel)
865 return 0;
867 error = fs->Rename(rel, newrel);
868 if (error) {
869 errno = error;
870 return -1;
873 return 0;
876 int KernelProxy::remove(const char* path) {
877 ScopedFilesystem fs;
878 Path rel;
880 Error error = AcquireFsAndRelPath(path, &fs, &rel);
881 if (error) {
882 errno = error;
883 return -1;
886 error = fs->Remove(rel);
887 if (error) {
888 errno = error;
889 return -1;
892 return 0;
895 int KernelProxy::fchmod(int fd, mode_t mode) {
896 ScopedKernelHandle handle;
897 Error error = AcquireHandle(fd, &handle);
898 if (error) {
899 errno = error;
900 return -1;
903 error = handle->node()->Fchmod(mode & S_MODEBITS);
904 if (error) {
905 errno = error;
906 return -1;
909 return 0;
912 int KernelProxy::fcntl(int fd, int request, va_list args) {
913 Error error = 0;
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.
918 switch (request) {
919 case F_GETFD: {
920 int rtn = -1;
921 error = GetFDFlags(fd, &rtn);
922 if (error) {
923 errno = error;
924 return -1;
926 return rtn;
928 case F_SETFD: {
929 int flags = va_arg(args, int);
930 error = SetFDFlags(fd, flags);
931 if (error) {
932 errno = error;
933 return -1;
935 return 0;
939 ScopedKernelHandle handle;
940 error = AcquireHandle(fd, &handle);
941 if (error) {
942 errno = error;
943 return -1;
946 int rtn = 0;
947 error = handle->VFcntl(request, &rtn, args);
948 if (error) {
949 errno = error;
950 return -1;
953 return rtn;
956 int KernelProxy::access(const char* path, int amode) {
957 struct stat buf;
958 int rtn = stat(path, &buf);
959 if (rtn != 0)
960 return rtn;
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))) {
965 errno = EACCES;
966 return -1;
969 return 0;
972 int KernelProxy::readlink(const char* path, char* buf, size_t count) {
973 LOG_TRACE("readlink is not implemented.");
974 errno = EINVAL;
975 return -1;
978 int KernelProxy::utimens(const char* path, const struct timespec times[2]) {
979 ScopedFilesystem fs;
980 ScopedNode node;
982 Error error = AcquireFsAndNode(path, O_WRONLY, 0, &fs, &node);
983 if (error) {
984 errno = error;
985 return -1;
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.");
994 errno = EINVAL;
995 return -1;
998 int KernelProxy::symlink(const char* oldpath, const char* newpath) {
999 LOG_TRACE("symlink is not implemented.");
1000 errno = EINVAL;
1001 return -1;
1004 void* KernelProxy::mmap(void* addr,
1005 size_t length,
1006 int prot,
1007 int flags,
1008 int fd,
1009 size_t offset) {
1010 // We shouldn't be getting anonymous mmaps here.
1011 assert((flags & MAP_ANONYMOUS) == 0);
1012 assert(fd != -1);
1014 ScopedKernelHandle handle;
1015 Error error = AcquireHandle(fd, &handle);
1016 if (error) {
1017 errno = error;
1018 return MAP_FAILED;
1021 void* new_addr;
1022 error = handle->node()->MMap(addr, length, prot, flags, offset, &new_addr);
1023 if (error) {
1024 errno = error;
1025 return MAP_FAILED;
1028 return 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
1054 // allowed.
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
1062 // free().
1063 return 0;
1066 int KernelProxy::tcflush(int fd, int queue_selector) {
1067 ScopedKernelHandle handle;
1068 Error error = AcquireHandle(fd, &handle);
1069 if (error) {
1070 errno = error;
1071 return -1;
1074 error = handle->node()->Tcflush(queue_selector);
1075 if (error) {
1076 errno = error;
1077 return -1;
1080 return 0;
1083 int KernelProxy::tcgetattr(int fd, struct termios* termios_p) {
1084 ScopedKernelHandle handle;
1085 Error error = AcquireHandle(fd, &handle);
1086 if (error) {
1087 errno = error;
1088 return -1;
1091 error = handle->node()->Tcgetattr(termios_p);
1092 if (error) {
1093 errno = error;
1094 return -1;
1097 return 0;
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);
1105 if (error) {
1106 errno = error;
1107 return -1;
1110 error = handle->node()->Tcsetattr(optional_actions, termios_p);
1111 if (error) {
1112 errno = error;
1113 return -1;
1116 return 0;
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) {
1125 errno = ESRCH;
1126 return -1;
1129 // Raise an event so that select/poll get interrupted.
1130 AUTO_LOCK(signal_emitter_->GetLock())
1131 signal_emitter_->RaiseEvents_Locked(POLLERR);
1132 switch (sig) {
1133 case SIGWINCH:
1134 if (sigwinch_handler_.sa_handler != SIG_IGN &&
1135 sigwinch_handler_.sa_handler != SIG_DFL) {
1136 sigwinch_handler_.sa_handler(SIGWINCH);
1138 break;
1140 case SIGUSR1:
1141 case SIGUSR2:
1142 break;
1144 default:
1145 LOG_TRACE("Unsupported signal: %d", sig);
1146 errno = EINVAL;
1147 return -1;
1149 return 0;
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
1158 errno = EINVAL;
1159 return -1;
1161 #endif
1163 switch (signum) {
1164 // Handled signals.
1165 case SIGWINCH: {
1166 if (oaction)
1167 *oaction = sigwinch_handler_;
1168 if (action) {
1169 sigwinch_handler_ = *action;
1171 return 0;
1174 // Known signals
1175 case SIGHUP:
1176 case SIGINT:
1177 case SIGPIPE:
1178 #if defined(SIGPOLL)
1179 case SIGPOLL:
1180 #endif
1181 case SIGPROF:
1182 case SIGTERM:
1183 case SIGCHLD:
1184 case SIGURG:
1185 case SIGFPE:
1186 case SIGILL:
1187 case SIGQUIT:
1188 case SIGSEGV:
1189 case SIGTRAP:
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);
1194 errno = EINVAL;
1195 return -1;
1198 if (oaction) {
1199 memset(oaction, 0, sizeof(*oaction));
1200 oaction->sa_handler = SIG_DFL;
1202 return 0;
1204 // KILL and STOP cannot be handled
1205 case SIGKILL:
1206 case SIGSTOP:
1207 LOG_TRACE("sigaction on SIGKILL/SIGSTOP not supported.");
1208 errno = EINVAL;
1209 return -1;
1212 // Unknown signum
1213 errno = EINVAL;
1214 return -1;
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,
1224 fd_set* readfds,
1225 fd_set* writefds,
1226 fd_set* exceptfds,
1227 struct timeval* timeout) {
1228 std::vector<pollfd> pollfds;
1230 for (int fd = 0; fd < nfds; fd++) {
1231 int events = 0;
1232 if (readfds && FD_ISSET(fd, readfds)) {
1233 events |= POLLIN;
1234 FD_CLR(fd, readfds);
1237 if (writefds && FD_ISSET(fd, writefds)) {
1238 events |= POLLOUT;
1239 FD_CLR(fd, writefds);
1242 if (exceptfds && FD_ISSET(fd, exceptfds)) {
1243 events |= POLLERR | POLLHUP;
1244 FD_CLR(fd, exceptfds);
1247 if (events) {
1248 pollfd info;
1249 info.fd = fd;
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) ||
1263 (ms >= INT_MAX)) {
1264 LOG_TRACE("Invalid timeout: tv_sec=%" PRIi64 " tv_usec=%ld.",
1265 timeout->tv_sec,
1266 timeout->tv_usec);
1267 errno = EINVAL;
1268 return -1;
1271 ms_timeout = static_cast<int>(ms);
1274 int result = poll(&pollfds[0], pollfds.size(), ms_timeout);
1275 if (result == -1)
1276 return -1;
1278 int event_cnt = 0;
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);
1283 event_cnt++;
1285 if (info->revents & POLLOUT) {
1286 FD_SET(info->fd, writefds);
1287 event_cnt++;
1289 if (info->revents & (POLLHUP | POLLERR)) {
1290 FD_SET(info->fd, exceptfds);
1291 event_cnt++;
1295 return event_cnt;
1298 struct PollInfo {
1299 PollInfo() : index(-1) {};
1301 std::vector<struct pollfd*> fds;
1302 int index;
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.
1321 if (err != 0) {
1322 fd_info->revents = POLLNVAL;
1323 event_cnt++;
1324 continue;
1327 // If it's already signaled, then just capture the event
1328 ScopedEventEmitter emitter(handle->node()->GetEventEmitter());
1329 int events = POLLIN | POLLOUT;
1330 if (emitter)
1331 events = emitter->GetEventStatus();
1333 if (events & fd_info->events) {
1334 fd_info->revents = events & fd_info->events;
1335 event_cnt++;
1336 continue;
1339 if (NULL == emitter) {
1340 fd_info->revents = POLLNVAL;
1341 event_cnt++;
1342 continue;
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;
1351 request.events = 0;
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)) {
1365 errno = err;
1366 return -1;
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;
1376 if (events) {
1377 fd_info->revents = events;
1378 event_cnt++;
1385 return event_cnt;
1388 // Socket Functions
1389 int KernelProxy::accept(int fd, struct sockaddr* addr, socklen_t* len) {
1390 ScopedKernelHandle handle;
1391 Error error = AcquireHandle(fd, &handle);
1392 if (error) {
1393 errno = error;
1394 return -1;
1397 PP_Resource new_sock = 0;
1398 error = handle->Accept(&new_sock, addr, len);
1399 if (error != 0) {
1400 errno = error;
1401 return -1;
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);
1410 if (error != 0) {
1411 errno = error;
1412 return -1;
1415 ScopedNode node(sock);
1416 ScopedKernelHandle new_handle(new KernelHandle(stream_fs_, node));
1417 error = new_handle->Init(O_RDWR);
1418 if (error != 0) {
1419 errno = error;
1420 return -1;
1423 return AllocateFD(new_handle);
1426 int KernelProxy::bind(int fd, const struct sockaddr* addr, socklen_t len) {
1427 if (NULL == addr) {
1428 errno = EFAULT;
1429 return -1;
1432 ScopedKernelHandle handle;
1433 if (AcquireSocketHandle(fd, &handle) == -1)
1434 return -1;
1436 Error err = handle->socket_node()->Bind(addr, len);
1437 if (err != 0) {
1438 errno = err;
1439 return -1;
1442 return 0;
1445 int KernelProxy::connect(int fd, const struct sockaddr* addr, socklen_t len) {
1446 if (NULL == addr) {
1447 errno = EFAULT;
1448 return -1;
1451 ScopedKernelHandle handle;
1452 Error error = AcquireHandle(fd, &handle);
1453 if (error) {
1454 errno = error;
1455 return -1;
1458 error = handle->Connect(addr, len);
1459 if (error != 0) {
1460 errno = error;
1461 return -1;
1464 return 0;
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,
1479 socklen_t salen,
1480 char *host,
1481 size_t hostlen,
1482 char *serv,
1483 size_t servlen,
1484 int flags) {
1485 return host_resolver_.getnameinfo(sa, salen, host, hostlen, serv, servlen,
1486 flags);
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) {
1495 errno = EFAULT;
1496 return -1;
1499 ScopedKernelHandle handle;
1500 if (AcquireSocketHandle(fd, &handle) == -1)
1501 return -1;
1503 Error err = handle->socket_node()->GetPeerName(addr, len);
1504 if (err != 0) {
1505 errno = err;
1506 return -1;
1509 return 0;
1512 int KernelProxy::getsockname(int fd, struct sockaddr* addr, socklen_t* len) {
1513 if (NULL == addr || NULL == len) {
1514 errno = EFAULT;
1515 return -1;
1518 ScopedKernelHandle handle;
1519 if (AcquireSocketHandle(fd, &handle) == -1)
1520 return -1;
1522 Error err = handle->socket_node()->GetSockName(addr, len);
1523 if (err != 0) {
1524 errno = err;
1525 return -1;
1528 return 0;
1531 int KernelProxy::getsockopt(int fd,
1532 int lvl,
1533 int optname,
1534 void* optval,
1535 socklen_t* len) {
1536 if (NULL == optval || NULL == len) {
1537 errno = EFAULT;
1538 return -1;
1541 ScopedKernelHandle handle;
1542 if (AcquireSocketHandle(fd, &handle) == -1)
1543 return -1;
1545 Error err = handle->socket_node()->GetSockOpt(lvl, optname, optval, len);
1546 if (err != 0) {
1547 errno = err;
1548 return -1;
1551 return 0;
1554 int KernelProxy::listen(int fd, int backlog) {
1555 ScopedKernelHandle handle;
1556 if (AcquireSocketHandle(fd, &handle) == -1)
1557 return -1;
1559 Error err = handle->socket_node()->Listen(backlog);
1560 if (err != 0) {
1561 errno = err;
1562 return -1;
1565 return 0;
1568 ssize_t KernelProxy::recv(int fd, void* buf, size_t len, int flags) {
1569 if (NULL == buf) {
1570 errno = EFAULT;
1571 return -1;
1574 ScopedKernelHandle handle;
1575 Error error = AcquireHandle(fd, &handle);
1576 if (error) {
1577 errno = error;
1578 return -1;
1581 int out_len = 0;
1582 error = handle->Recv(buf, len, flags, &out_len);
1583 if (error != 0) {
1584 errno = error;
1585 return -1;
1588 return static_cast<ssize_t>(out_len);
1591 ssize_t KernelProxy::recvfrom(int fd,
1592 void* buf,
1593 size_t len,
1594 int flags,
1595 struct sockaddr* addr,
1596 socklen_t* addrlen) {
1597 // According to the manpage, recvfrom with a null addr is identical to recv.
1598 if (NULL == addr) {
1599 return recv(fd, buf, len, flags);
1602 if (NULL == buf || NULL == addrlen) {
1603 errno = EFAULT;
1604 return -1;
1607 ScopedKernelHandle handle;
1608 Error error = AcquireHandle(fd, &handle);
1609 if (error) {
1610 errno = error;
1611 return -1;
1614 int out_len = 0;
1615 error = handle->RecvFrom(buf, len, flags, addr, addrlen, &out_len);
1616 if (error != 0) {
1617 errno = error;
1618 return -1;
1621 return static_cast<ssize_t>(out_len);
1624 ssize_t KernelProxy::recvmsg(int fd, struct msghdr* msg, int flags) {
1625 if (NULL == msg) {
1626 errno = EFAULT;
1627 return -1;
1630 ScopedKernelHandle handle;
1631 if (AcquireSocketHandle(fd, &handle) == -1)
1632 return -1;
1634 errno = EOPNOTSUPP;
1635 return -1;
1638 ssize_t KernelProxy::send(int fd, const void* buf, size_t len, int flags) {
1639 if (NULL == buf) {
1640 errno = EFAULT;
1641 return -1;
1644 ScopedKernelHandle handle;
1645 Error error = AcquireHandle(fd, &handle);
1646 if (error) {
1647 errno = error;
1648 return -1;
1651 int out_len = 0;
1652 error = handle->Send(buf, len, flags, &out_len);
1653 if (error != 0) {
1654 errno = error;
1655 return -1;
1658 return static_cast<ssize_t>(out_len);
1661 ssize_t KernelProxy::sendto(int fd,
1662 const void* buf,
1663 size_t len,
1664 int flags,
1665 const struct sockaddr* addr,
1666 socklen_t addrlen) {
1667 // According to the manpage, sendto with a null addr is identical to send.
1668 if (NULL == addr) {
1669 return send(fd, buf, len, flags);
1672 if (NULL == buf) {
1673 errno = EFAULT;
1674 return -1;
1677 ScopedKernelHandle handle;
1678 Error error = AcquireHandle(fd, &handle);
1679 if (error) {
1680 errno = error;
1681 return -1;
1684 int out_len = 0;
1685 error = handle->SendTo(buf, len, flags, addr, addrlen, &out_len);
1686 if (error != 0) {
1687 errno = error;
1688 return -1;
1691 return static_cast<ssize_t>(out_len);
1694 ssize_t KernelProxy::sendmsg(int fd, const struct msghdr* msg, int flags) {
1695 if (NULL == msg) {
1696 errno = EFAULT;
1697 return -1;
1700 ScopedKernelHandle handle;
1701 if (AcquireSocketHandle(fd, &handle) == -1)
1702 return -1;
1704 errno = EOPNOTSUPP;
1705 return -1;
1708 int KernelProxy::setsockopt(int fd,
1709 int lvl,
1710 int optname,
1711 const void* optval,
1712 socklen_t len) {
1713 if (NULL == optval) {
1714 errno = EFAULT;
1715 return -1;
1718 ScopedKernelHandle handle;
1719 if (AcquireSocketHandle(fd, &handle) == -1)
1720 return -1;
1722 Error err = handle->socket_node()->SetSockOpt(lvl, optname, optval, len);
1723 if (err != 0) {
1724 errno = err;
1725 return -1;
1728 return 0;
1731 int KernelProxy::shutdown(int fd, int how) {
1732 ScopedKernelHandle handle;
1733 if (AcquireSocketHandle(fd, &handle) == -1)
1734 return -1;
1736 Error err = handle->socket_node()->Shutdown(how);
1737 if (err != 0) {
1738 errno = err;
1739 return -1;
1742 return 0;
1745 int KernelProxy::socket(int domain, int type, int protocol) {
1746 if (AF_INET != domain && AF_INET6 != domain) {
1747 errno = EAFNOSUPPORT;
1748 return -1;
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
1757 // O_CLOEXEC.
1758 // TODO(sbc): remove this guard once it gets added.
1759 open_flags |= O_CLOEXEC;
1760 #endif
1761 type &= ~SOCK_CLOEXEC;
1763 #endif
1765 #if defined(SOCK_NONBLOCK)
1766 if (type & SOCK_NONBLOCK) {
1767 open_flags |= O_NONBLOCK;
1768 type &= ~SOCK_NONBLOCK;
1770 #endif
1772 SocketNode* sock = NULL;
1773 switch (type) {
1774 case SOCK_DGRAM:
1775 sock = new UdpNode(stream_fs_.get());
1776 break;
1778 case SOCK_STREAM:
1779 sock = new TcpNode(stream_fs_.get());
1780 break;
1782 case SOCK_SEQPACKET:
1783 case SOCK_RDM:
1784 case SOCK_RAW:
1785 errno = EPROTONOSUPPORT;
1786 return -1;
1788 default:
1789 errno = EINVAL;
1790 return -1;
1793 ScopedNode node(sock);
1794 Error rtn = sock->Init(O_RDWR);
1795 if (rtn != 0) {
1796 errno = rtn;
1797 return -1;
1800 ScopedKernelHandle handle(new KernelHandle(stream_fs_, node));
1801 rtn = handle->Init(open_flags);
1802 if (rtn != 0) {
1803 errno = rtn;
1804 return -1;
1807 return AllocateFD(handle);
1810 int KernelProxy::socketpair(int domain, int type, int protocol, int* sv) {
1811 if (NULL == sv) {
1812 errno = EFAULT;
1813 return -1;
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;
1820 return -1;
1823 if (AF_INET != domain && AF_INET6 != domain) {
1824 errno = EAFNOSUPPORT;
1825 return -1;
1828 // We cannot reach this point.
1829 errno = ENOSYS;
1830 return -1;
1833 int KernelProxy::AcquireSocketHandle(int fd, ScopedKernelHandle* handle) {
1834 Error error = AcquireHandle(fd, handle);
1836 if (error) {
1837 errno = error;
1838 return -1;
1841 if ((handle->get()->node_->GetType() & S_IFSOCK) == 0) {
1842 errno = ENOTSOCK;
1843 return -1;
1846 return 0;
1849 #endif // PROVIDES_SOCKET_API
1851 } // namespace_nacl_io