OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (c) 2012 The Native Client Authors. All rights reserved. | 2 * Copyright (c) 2012 The Native Client Authors. All rights reserved. |
3 * Use of this source code is governed by a BSD-style license that can be | 3 * Use of this source code is governed by a BSD-style license that can be |
4 * found in the LICENSE file. | 4 * found in the LICENSE file. |
5 */ | 5 */ |
6 #include <assert.h> | 6 #include <assert.h> |
7 #include <sys/time.h> | |
7 #include <list> | 8 #include <list> |
8 #include <utility> | 9 #include <utility> |
9 #include "../console/ConsoleMount.h" | 10 #include "console/ConsoleMount.h" |
Evgeniy Stepanov
2012/05/23 15:35:13
Why this one without ../, and the two below it wit
vissi
2012/05/25 11:08:50
Now without ..
| |
10 #include "../dev/DevMount.h" | 11 #include "../dev/DevMount.h" |
12 #include "../net/SocketSubSystem.h" | |
11 #include "KernelProxy.h" | 13 #include "KernelProxy.h" |
12 #include "MountManager.h" | 14 #include "MountManager.h" |
15 #include "net/BaseSocketSubSystem.h" | |
16 #include <netinet/in.h> | |
17 #include "util/DebugPrint.h" | |
13 | 18 |
14 static pthread_once_t kp_once_ = PTHREAD_ONCE_INIT; | 19 static pthread_once_t kp_once_ = PTHREAD_ONCE_INIT; |
15 KernelProxy *KernelProxy::kp_instance_; | 20 KernelProxy *KernelProxy::kp_instance_; |
16 | 21 |
17 #ifndef MAXPATHLEN | 22 #ifndef MAXPATHLEN |
18 #define MAXPATHLEN 256 | 23 #define MAXPATHLEN 256 |
19 #endif | 24 #endif |
20 | 25 |
21 KernelProxy::KernelProxy() { | 26 KernelProxy::KernelProxy() { |
22 if (pthread_mutex_init(&kp_lock_, NULL)) assert(0); | 27 if (pthread_mutex_init(&kp_lock_, NULL)) assert(0); |
(...skipping 12 matching lines...) Expand all Loading... | |
35 ret = mm_.AddMount(console_mount, "/dev/fd"); | 40 ret = mm_.AddMount(console_mount, "/dev/fd"); |
36 assert(ret == 0); | 41 assert(ret == 0); |
37 int fd = open("/dev/fd/0", O_CREAT | O_RDWR, 0); | 42 int fd = open("/dev/fd/0", O_CREAT | O_RDWR, 0); |
38 assert(fd == 0); | 43 assert(fd == 0); |
39 fd = open("/dev/fd/1", O_CREAT | O_RDWR, 0); | 44 fd = open("/dev/fd/1", O_CREAT | O_RDWR, 0); |
40 assert(fd == 1); | 45 assert(fd == 1); |
41 fd = open("/dev/fd/2", O_CREAT | O_RDWR, 0); | 46 fd = open("/dev/fd/2", O_CREAT | O_RDWR, 0); |
42 assert(fd == 2); | 47 assert(fd == 2); |
43 } | 48 } |
44 | 49 |
50 void KernelProxy::SetSS(BaseSocketSubSystem* bss) { | |
Evgeniy Stepanov
2012/05/23 15:35:13
A more descriptive setter name pls.
vissi
2012/05/25 11:08:50
Done.
| |
51 ss = bss; | |
52 } | |
53 | |
54 void KernelProxy::RemoveFileStream(int fd) { | |
55 this->close(fd); | |
56 } | |
57 | |
58 int KernelProxy::AddFileStream(FileStream* stream) { | |
59 SimpleAutoLock lock(&kp_lock_); | |
60 | |
61 // Setup file handle. | |
62 int handle_slot = open_files_.Alloc(); | |
63 int fd = fds_.Alloc(); | |
64 FileDescriptor* file = fds_.At(fd); | |
65 file->handle = handle_slot; | |
66 FileHandle* handle = open_files_.At(handle_slot); | |
67 | |
68 // init should be safe because we have the kernel proxy lock | |
69 if (pthread_mutex_init(&handle->lock, NULL)) assert(0); | |
70 | |
71 handle->mount = (Mount*) NULL; | |
72 handle->stream = (FileStream*) NULL; | |
73 handle->use_count = 1; | |
74 | |
75 return fd; | |
76 } | |
77 | |
45 KernelProxy *KernelProxy::KPInstance() { | 78 KernelProxy *KernelProxy::KPInstance() { |
46 pthread_once(&kp_once_, Instantiate); | 79 pthread_once(&kp_once_, Instantiate); |
47 return kp_instance_; | 80 return kp_instance_; |
48 } | 81 } |
49 | 82 |
50 void KernelProxy::Instantiate() { | 83 void KernelProxy::Instantiate() { |
51 assert(!kp_instance_); | 84 assert(!kp_instance_); |
52 kp_instance_ = new KernelProxy(); | 85 kp_instance_ = new KernelProxy(); |
53 } | 86 } |
54 | 87 |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
170 } | 203 } |
171 } | 204 } |
172 | 205 |
173 mount->Ref(st.st_ino); | 206 mount->Ref(st.st_ino); |
174 mount->Ref(); | 207 mount->Ref(); |
175 // Setup file handle. | 208 // Setup file handle. |
176 int handle_slot = open_files_.Alloc(); | 209 int handle_slot = open_files_.Alloc(); |
177 int fd = fds_.Alloc(); | 210 int fd = fds_.Alloc(); |
178 FileDescriptor* file = fds_.At(fd); | 211 FileDescriptor* file = fds_.At(fd); |
179 file->handle = handle_slot; | 212 file->handle = handle_slot; |
180 FileHandle *handle = open_files_.At(handle_slot); | 213 FileHandle* handle = open_files_.At(handle_slot); |
181 | 214 |
182 // init should be safe because we have the kernel proxy lock | 215 // init should be safe because we have the kernel proxy lock |
183 if (pthread_mutex_init(&handle->lock, NULL)) assert(0); | 216 if (pthread_mutex_init(&handle->lock, NULL)) assert(0); |
184 | 217 |
185 handle->mount = mount; | 218 handle->mount = mount; |
219 handle->stream = NULL; | |
186 handle->node = st.st_ino; | 220 handle->node = st.st_ino; |
187 handle->flags = flags; | 221 handle->flags = flags; |
188 handle->use_count = 1; | 222 handle->use_count = 1; |
189 | 223 |
190 if (flags & O_APPEND) { | 224 if (flags & O_APPEND) { |
191 handle->offset = st.st_size; | 225 handle->offset = st.st_size; |
192 } else { | 226 } else { |
193 handle->offset = 0; | 227 handle->offset = 0; |
194 } | 228 } |
195 | 229 |
196 return fd; | 230 return fd; |
197 } | 231 } |
198 | 232 |
233 ino_t KernelProxy::CreateSocket() { | |
234 SimpleAutoLock lock(&kp_lock_); | |
235 int handle_slot = open_files_.Alloc(); | |
236 int fd = fds_.Alloc(); | |
237 FileDescriptor* file = fds_.At(fd); | |
238 file->handle = handle_slot; | |
239 FileHandle *handle = open_files_.At(handle_slot); | |
240 handle->mount = NULL; | |
241 handle->stream = NULL; | |
242 handle->use_count = 1; | |
243 return fd; | |
244 } | |
245 | |
246 struct hostent* KernelProxy::gethostbyname(const char* name) { | |
247 struct hostent *res = (struct hostent*) malloc(sizeof(struct hostent)); | |
248 if (!res) return NULL; | |
249 res->h_addr_list = (char**) malloc(sizeof(char*) * 2); | |
250 if (!res->h_addr_list) return NULL; | |
251 res->h_addr_list[0] = (char*) malloc(sizeof(long int)); | |
252 if (!res->h_addr_list[0]) return NULL; | |
253 *((long int*)res->h_addr_list[0]) = ss->gethostbyname(name); | |
254 res->h_addr_list[1] = NULL; | |
255 res->h_length = sizeof(long int); | |
256 return res; | |
257 } | |
258 | |
199 int KernelProxy::open(const std::string& path, int flags, mode_t mode) { | 259 int KernelProxy::open(const std::string& path, int flags, mode_t mode) { |
200 if (path.empty()) { | 260 if (path.empty()) { |
201 errno = EINVAL; | 261 errno = EINVAL; |
202 return -1; | 262 return -1; |
203 } | 263 } |
204 | 264 |
205 Path p(path); | 265 Path p(path); |
206 if (path[0] != '/') { | 266 if (path[0] != '/') { |
207 p = Path(cwd_.FormulatePath() + "/" + path); | 267 p = Path(cwd_.FormulatePath() + "/" + path); |
208 } | 268 } |
(...skipping 19 matching lines...) Expand all Loading... | |
228 } | 288 } |
229 int h = file->handle; | 289 int h = file->handle; |
230 fds_.Free(fd); | 290 fds_.Free(fd); |
231 FileHandle *handle = open_files_.At(h); | 291 FileHandle *handle = open_files_.At(h); |
232 if (handle == NULL) { | 292 if (handle == NULL) { |
233 errno = EBADF; | 293 errno = EBADF; |
234 return -1; | 294 return -1; |
235 } | 295 } |
236 handle->use_count--; | 296 handle->use_count--; |
237 ino_t node = handle->node; | 297 ino_t node = handle->node; |
238 Mount *mount = handle->mount; | 298 if (handle->mount) { |
239 if (handle->use_count <= 0) { | 299 Mount* mount = handle->mount; |
240 open_files_.Free(h); | 300 if (handle->use_count <= 0) { |
241 mount->Unref(node); | 301 open_files_.Free(h); |
302 mount->Unref(node); | |
303 } | |
304 mount->Unref(); | |
242 } | 305 } |
243 mount->Unref(); | |
244 return 0; | 306 return 0; |
245 } | 307 } |
246 | 308 |
247 ssize_t KernelProxy::read(int fd, void *buf, size_t count) { | 309 ssize_t KernelProxy::read(int fd, void *buf, size_t count) { |
248 FileHandle *handle; | 310 FileHandle *handle; |
249 // check if fd is valid and handle exists | 311 // check if fd is valid and handle exists |
250 if (!(handle = GetFileHandle(fd))) { | 312 if (!(handle = GetFileHandle(fd))) { |
251 errno = EBADF; | 313 errno = EBADF; |
252 return -1; | 314 return -1; |
253 } | 315 } |
(...skipping 357 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
611 ((amode & X_OK) && !(mode & X_OK))) { | 673 ((amode & X_OK) && !(mode & X_OK))) { |
612 errno = EACCES; | 674 errno = EACCES; |
613 return -1; | 675 return -1; |
614 } | 676 } |
615 } | 677 } |
616 // By now we have checked access permissions for | 678 // By now we have checked access permissions for |
617 // each component of the path. | 679 // each component of the path. |
618 return 0; | 680 return 0; |
619 } | 681 } |
620 | 682 |
621 KernelProxy::FileHandle *KernelProxy::GetFileHandle(int fd) { | 683 FileHandle* KernelProxy::GetFileHandle(int fd) { |
622 SimpleAutoLock lock(&kp_lock_); | 684 SimpleAutoLock lock(&kp_lock_); |
623 FileDescriptor *file = fds_.At(fd); | 685 FileDescriptor *file = fds_.At(fd); |
624 if (!file) { | 686 if (!file) { |
625 return NULL; | 687 return NULL; |
626 } | 688 } |
627 return open_files_.At(file->handle); | 689 return open_files_.At(file->handle); |
628 } | 690 } |
629 | 691 |
630 int KernelProxy::mkdir(const std::string& path, mode_t mode) { | 692 int KernelProxy::mkdir(const std::string& path, mode_t mode) { |
631 if (path.empty()) { | 693 if (path.empty()) { |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
669 if (mm_.InMountRootPath(abs_path)) { | 731 if (mm_.InMountRootPath(abs_path)) { |
670 errno = EBUSY; | 732 errno = EBUSY; |
671 return -1; | 733 return -1; |
672 } | 734 } |
673 | 735 |
674 return mount->Rmdir(buf.st_ino); | 736 return mount->Rmdir(buf.st_ino); |
675 } | 737 } |
676 | 738 |
677 #ifdef __GLIBC__ | 739 #ifdef __GLIBC__ |
678 int KernelProxy::socket(int domain, int type, int protocol) { | 740 int KernelProxy::socket(int domain, int type, int protocol) { |
679 errno = ENOSYS; | 741 return ss->socket(domain, type, protocol); |
680 fprintf(stderr, "socket has not been implemented!\n"); | |
681 return -1; | |
682 } | 742 } |
683 | 743 |
684 int KernelProxy::accept(int sockfd, struct sockaddr *addr, | 744 int KernelProxy::accept(int sockfd, struct sockaddr *addr, |
685 socklen_t* addrlen) { | 745 socklen_t* addrlen) { |
686 errno = ENOSYS; | 746 return ss->accept(GetFileHandle(sockfd), addr, addrlen); |
687 fprintf(stderr, "accept has not been implemented!\n"); | |
688 return -1; | |
689 } | 747 } |
690 | 748 |
691 int KernelProxy::bind(int sockfd, const struct sockaddr *addr, | 749 int KernelProxy::bind(int sockfd, const struct sockaddr *addr, |
692 socklen_t addrlen) { | 750 socklen_t addrlen) { |
693 errno = ENOSYS; | 751 struct sockaddr_in* in_addr = (struct sockaddr_in*)addr; |
694 fprintf(stderr, "bind has not been implemented!\n"); | 752 return ss->bind(GetFileHandle(sockfd), in_addr->sin_addr.s_addr, |
695 return -1; | 753 (unsigned short) ntohs(in_addr->sin_port)); |
696 } | 754 } |
697 | 755 |
698 int KernelProxy::listen(int sockfd, int backlog) { | 756 int KernelProxy::listen(int sockfd, int backlog) { |
699 errno = ENOSYS; | 757 return ss->listen(GetFileHandle(sockfd), backlog); |
700 fprintf(stderr, "listen has not been implemented!\n"); | |
701 return -1; | |
702 } | 758 } |
703 | 759 |
704 int KernelProxy::connect(int sockfd, const struct sockaddr *addr, | 760 int KernelProxy::connect(int sockfd, const struct sockaddr *addr, |
705 socklen_t addrlen) { | 761 socklen_t addrlen) { |
706 errno = ENOSYS; | 762 struct sockaddr_in* in_addr = (struct sockaddr_in*)addr; |
707 fprintf(stderr, "connect has not been implemented!\n"); | 763 return ss->connect(GetFileHandle(sockfd), in_addr->sin_addr.s_addr, |
708 return -1; | 764 (unsigned short) ntohs(in_addr->sin_port)); |
709 } | 765 } |
710 | 766 |
711 int KernelProxy::send(int sockfd, const void *buf, size_t len, int flags) { | 767 int KernelProxy::send(int sockfd, const void *buf, size_t len, int flags) { |
712 errno = ENOSYS; | 768 size_t nwr; |
713 fprintf(stderr, "send has not been implemented!\n"); | 769 ss->write(GetFileHandle(sockfd), (const char*)buf, len, &nwr); |
714 return -1; | 770 return nwr; |
715 } | 771 } |
716 | 772 |
717 int KernelProxy::sendmsg(int sockfd, const struct msghdr *msg, int flags) { | 773 int KernelProxy::sendmsg(int sockfd, const struct msghdr *msg, int flags) { |
718 errno = ENOSYS; | 774 errno = ENOSYS; |
719 fprintf(stderr, "sendmsg has not been implemented!\n"); | 775 fprintf(stderr, "sendmsg has not been implemented!\n"); |
720 return -1; | 776 return -1; |
721 } | 777 } |
722 | 778 |
723 int KernelProxy::sendto(int sockfd, const void *buf, size_t len, int flags, | 779 int KernelProxy::sendto(int sockfd, const void *buf, size_t len, int flags, |
724 const struct sockaddr *dest_addr, socklen_t addrlen) { | 780 const struct sockaddr *dest_addr, socklen_t addrlen) { |
725 errno = ENOSYS; | 781 errno = ENOSYS; |
726 fprintf(stderr, "sendto has not been implemented!\n"); | 782 fprintf(stderr, "sendto has not been implemented!\n"); |
727 return -1; | 783 return -1; |
728 } | 784 } |
729 | 785 |
730 int KernelProxy::recv(int sockfd, void *buf, size_t len, int flags) { | 786 int KernelProxy::recv(int sockfd, void *buf, size_t len, int flags) { |
731 errno = ENOSYS; | 787 size_t nread; |
732 fprintf(stderr, "recv has not been implemented!\n"); | 788 ss->read(GetFileHandle(sockfd), reinterpret_cast<char*>(buf), len, &nread); |
733 return -1; | 789 return nread; |
734 } | 790 } |
735 | 791 |
736 int KernelProxy::recvmsg(int sockfd, struct msghdr *msg, int flags) { | 792 int KernelProxy::recvmsg(int sockfd, struct msghdr *msg, int flags) { |
737 errno = ENOSYS; | 793 errno = ENOSYS; |
738 fprintf(stderr, "recvmsg has not been implemented!\n"); | 794 fprintf(stderr, "recvmsg has not been implemented!\n"); |
739 return -1; | 795 return -1; |
740 } | 796 } |
741 | 797 |
742 int KernelProxy::recvfrom(int sockfd, void *buf, size_t len, int flags, | 798 int KernelProxy::recvfrom(int sockfd, void *buf, size_t len, int flags, |
743 struct sockaddr *dest_addr, socklen_t* addrlen) { | 799 struct sockaddr *dest_addr, socklen_t* addrlen) { |
744 errno = ENOSYS; | 800 errno = ENOSYS; |
745 fprintf(stderr, "recvfrom has not been implemented!\n"); | 801 fprintf(stderr, "recvfrom has not been implemented!\n"); |
746 return -1; | 802 return -1; |
747 } | 803 } |
748 | 804 |
749 int KernelProxy::select(int nfds, fd_set *readfds, fd_set *writefds, | 805 int KernelProxy::select(int nfds, fd_set *readfds, fd_set *writefds, |
750 fd_set* exceptfds, const struct timeval *timeout) { | 806 fd_set* exceptfds, const struct timeval *timeout) { |
751 errno = ENOSYS; | 807 dbgprintf("int select() before mutex\n"); |
752 fprintf(stderr, "select has not been implemented!\n"); | 808 Mutex::Lock lock(ss->mutex()); |
753 return -1; | 809 dbgprintf("int select() after mutex\n"); |
810 | |
811 timespec ts_abs; | |
812 if (timeout) { | |
813 timespec ts; | |
814 TIMEVAL_TO_TIMESPEC(timeout, &ts); | |
815 timeval tv_now; | |
816 gettimeofday(&tv_now, NULL); | |
817 int64_t current_time_us = | |
818 tv_now.tv_sec * kMicrosecondsPerSecond + tv_now.tv_usec; | |
819 int64_t wakeup_time_us = | |
820 current_time_us + | |
821 timeout->tv_sec * kMicrosecondsPerSecond + timeout->tv_usec; | |
822 ts_abs.tv_sec = wakeup_time_us / kMicrosecondsPerSecond; | |
823 ts_abs.tv_nsec = | |
824 (wakeup_time_us - ts_abs.tv_sec * kMicrosecondsPerSecond) * | |
825 kNanosecondsPerMicrosecond; | |
826 } | |
827 | |
828 while (!(ss->IsReady(nfds, readfds, &FileStream::is_read_ready, false) || | |
829 ss->IsReady(nfds, writefds, &FileStream::is_write_ready, false) || | |
830 ss->IsReady(nfds, exceptfds, &FileStream::is_exception, false))) { | |
831 if (timeout) { | |
832 if (!timeout->tv_sec && !timeout->tv_usec) | |
833 break; | |
834 | |
835 if (ss->cond().timedwait(ss->mutex(), &ts_abs)) { | |
836 if (errno == ETIMEDOUT) | |
837 break; | |
838 else | |
839 return -1; | |
840 } | |
841 } else { | |
842 ss->cond().wait(ss->mutex()); | |
843 } | |
844 } | |
845 | |
846 int nread = ss->IsReady(nfds, readfds, &FileStream::is_read_ready, true); | |
847 int nwrite = ss->IsReady(nfds, writefds, &FileStream::is_write_ready, true); | |
848 int nexcpt = ss->IsReady(nfds, exceptfds, &FileStream::is_exception, true); | |
849 if (nread < 0 || nwrite < 0 || nexcpt < 0) { | |
850 errno = EBADF; | |
851 return -1; | |
852 } | |
853 return nread + nwrite + nexcpt; | |
754 } | 854 } |
755 | 855 |
756 int KernelProxy::pselect(int nfds, fd_set *readfds, fd_set *writefds, | 856 int KernelProxy::pselect(int nfds, fd_set *readfds, fd_set *writefds, |
757 fd_set* exceptfds, const struct timeval *timeout, void* sigmask) { | 857 fd_set* exceptfds, const struct timeval *timeout, void* sigmask) { |
758 errno = ENOSYS; | 858 errno = ENOSYS; |
759 fprintf(stderr, "pselect has not been implemented!\n"); | 859 fprintf(stderr, "pselect has not been implemented!\n"); |
760 return -1; | 860 return -1; |
761 } | 861 } |
762 | 862 |
763 int KernelProxy::getpeername(int sockfd, struct sockaddr *addr, | 863 int KernelProxy::getpeername(int sockfd, struct sockaddr *addr, |
(...skipping 18 matching lines...) Expand all Loading... | |
782 } | 882 } |
783 | 883 |
784 int KernelProxy::setsockopt(int sockfd, int level, int optname, | 884 int KernelProxy::setsockopt(int sockfd, int level, int optname, |
785 const void *optval, socklen_t optlen) { | 885 const void *optval, socklen_t optlen) { |
786 errno = ENOSYS; | 886 errno = ENOSYS; |
787 fprintf(stderr, "setsockopt has not been implemented!\n"); | 887 fprintf(stderr, "setsockopt has not been implemented!\n"); |
788 return -1; | 888 return -1; |
789 } | 889 } |
790 | 890 |
791 int KernelProxy::shutdown(int sockfd, int how) { | 891 int KernelProxy::shutdown(int sockfd, int how) { |
792 errno = ENOSYS; | 892 return close(sockfd); |
793 fprintf(stderr, "shutdown has not been implemented!\n"); | |
794 return -1; | |
795 } | 893 } |
796 | 894 |
797 int KernelProxy::epoll_create(int size) { | 895 int KernelProxy::epoll_create(int size) { |
798 errno = ENOSYS; | 896 errno = ENOSYS; |
799 fprintf(stderr, "epoll_create has not been implemented!\n"); | 897 fprintf(stderr, "epoll_create has not been implemented!\n"); |
800 return -1; | 898 return -1; |
801 } | 899 } |
802 | 900 |
803 int KernelProxy::epoll_create1(int flags) { | 901 int KernelProxy::epoll_create1(int flags) { |
804 errno = ENOSYS; | 902 errno = ENOSYS; |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
841 | 939 |
842 int KernelProxy::ppoll(struct pollfd *fds, nfds_t nfds, | 940 int KernelProxy::ppoll(struct pollfd *fds, nfds_t nfds, |
843 const struct timespec *timeout, | 941 const struct timespec *timeout, |
844 const sigset_t *sigmask, size_t sigset_size) { | 942 const sigset_t *sigmask, size_t sigset_size) { |
845 errno = ENOSYS; | 943 errno = ENOSYS; |
846 fprintf(stderr, "ppoll has not been implemented!\n"); | 944 fprintf(stderr, "ppoll has not been implemented!\n"); |
847 return -1; | 945 return -1; |
848 } | 946 } |
849 #endif | 947 #endif |
850 | 948 |
OLD | NEW |