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 "base/KernelProxy.h" |
6 #include <assert.h> | 7 #include <assert.h> |
| 8 #ifdef __GLIBC__ |
| 9 #include <netinet/in.h> |
| 10 #else |
| 11 #include "../base/newlib_hacks.h" |
| 12 #endif |
| 13 #include <sys/time.h> |
7 #include <list> | 14 #include <list> |
8 #include <utility> | 15 #include <utility> |
9 #include "../console/ConsoleMount.h" | 16 #include "console/ConsoleMount.h" |
10 #include "../dev/DevMount.h" | 17 #include "dev/DevMount.h" |
11 #include "KernelProxy.h" | |
12 #include "MountManager.h" | 18 #include "MountManager.h" |
| 19 #include "net/BaseSocketSubSystem.h" |
| 20 #include "net/SocketSubSystem.h" |
| 21 #include "util/DebugPrint.h" |
13 | 22 |
14 static pthread_once_t kp_once_ = PTHREAD_ONCE_INIT; | 23 static pthread_once_t kp_once_ = PTHREAD_ONCE_INIT; |
15 KernelProxy *KernelProxy::kp_instance_; | 24 KernelProxy *KernelProxy::kp_instance_; |
16 | 25 |
17 #ifndef MAXPATHLEN | 26 #ifndef MAXPATHLEN |
18 #define MAXPATHLEN 256 | 27 #define MAXPATHLEN 256 |
19 #endif | 28 #endif |
20 | 29 |
| 30 static const int64_t kMicrosecondsPerSecond = 1000 * 1000; |
| 31 static const int64_t kNanosecondsPerMicrosecond = 1000; |
| 32 |
21 KernelProxy::KernelProxy() { | 33 KernelProxy::KernelProxy() { |
22 if (pthread_mutex_init(&kp_lock_, NULL)) assert(0); | 34 if (pthread_mutex_init(&kp_lock_, NULL)) assert(0); |
23 cwd_ = Path("/"); | 35 cwd_ = Path("/"); |
24 mm_.Init(); | 36 mm_.Init(); |
25 | 37 |
26 // Setup file descriptors 0, 1, and 2 for STDIN, STDOUT, and STDERR | 38 // Setup file descriptors 0, 1, and 2 for STDIN, STDOUT, and STDERR |
27 int ret = mkdir("/dev", 0777); | 39 int ret = mkdir("/dev", 0777); |
28 assert(ret == 0); | 40 assert(ret == 0); |
29 DevMount* dev_mount = new DevMount(); | 41 DevMount* dev_mount = new DevMount(); |
30 ret = mm_.AddMount(dev_mount, "/dev"); | 42 ret = mm_.AddMount(dev_mount, "/dev"); |
31 assert(ret == 0); | 43 assert(ret == 0); |
32 ret = mkdir("/dev/fd", 0777); | 44 ret = mkdir("/dev/fd", 0777); |
33 assert(ret == 0); | 45 assert(ret == 0); |
34 ConsoleMount *console_mount = new ConsoleMount(); | 46 ConsoleMount *console_mount = new ConsoleMount(); |
35 ret = mm_.AddMount(console_mount, "/dev/fd"); | 47 ret = mm_.AddMount(console_mount, "/dev/fd"); |
36 assert(ret == 0); | 48 assert(ret == 0); |
37 int fd = open("/dev/fd/0", O_CREAT | O_RDWR, 0); | 49 int fd = open("/dev/fd/0", O_CREAT | O_RDWR, 0); |
38 assert(fd == 0); | 50 assert(fd == 0); |
39 fd = open("/dev/fd/1", O_CREAT | O_RDWR, 0); | 51 fd = open("/dev/fd/1", O_CREAT | O_RDWR, 0); |
40 assert(fd == 1); | 52 assert(fd == 1); |
41 fd = open("/dev/fd/2", O_CREAT | O_RDWR, 0); | 53 fd = open("/dev/fd/2", O_CREAT | O_RDWR, 0); |
42 assert(fd == 2); | 54 assert(fd == 2); |
43 } | 55 } |
44 | 56 |
| 57 void KernelProxy::SetSocketSubSystem(BaseSocketSubSystem* bss) { |
| 58 socket_subsystem_ = bss; |
| 59 } |
| 60 |
| 61 void KernelProxy::RemoveSocket(int fd) { |
| 62 this->close(fd); |
| 63 } |
| 64 |
| 65 int KernelProxy::AddSocket(Socket* stream) { |
| 66 SimpleAutoLock lock(&kp_lock_); |
| 67 |
| 68 // Setup file handle. |
| 69 int handle_slot = open_files_.Alloc(); |
| 70 int fd = fds_.Alloc(); |
| 71 FileDescriptor* file = fds_.At(fd); |
| 72 file->handle = handle_slot; |
| 73 FileHandle* handle = open_files_.At(handle_slot); |
| 74 |
| 75 // init should be safe because we have the kernel proxy lock |
| 76 if (pthread_mutex_init(&handle->lock, NULL)) assert(0); |
| 77 |
| 78 handle->mount = (Mount*) NULL; |
| 79 handle->stream = (Socket*) NULL; |
| 80 handle->use_count = 1; |
| 81 |
| 82 return fd; |
| 83 } |
| 84 |
45 KernelProxy *KernelProxy::KPInstance() { | 85 KernelProxy *KernelProxy::KPInstance() { |
46 pthread_once(&kp_once_, Instantiate); | 86 pthread_once(&kp_once_, Instantiate); |
47 return kp_instance_; | 87 return kp_instance_; |
48 } | 88 } |
49 | 89 |
50 void KernelProxy::Instantiate() { | 90 void KernelProxy::Instantiate() { |
51 assert(!kp_instance_); | 91 assert(!kp_instance_); |
52 kp_instance_ = new KernelProxy(); | 92 kp_instance_ = new KernelProxy(); |
53 } | 93 } |
54 | 94 |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
170 } | 210 } |
171 } | 211 } |
172 | 212 |
173 mount->Ref(st.st_ino); | 213 mount->Ref(st.st_ino); |
174 mount->Ref(); | 214 mount->Ref(); |
175 // Setup file handle. | 215 // Setup file handle. |
176 int handle_slot = open_files_.Alloc(); | 216 int handle_slot = open_files_.Alloc(); |
177 int fd = fds_.Alloc(); | 217 int fd = fds_.Alloc(); |
178 FileDescriptor* file = fds_.At(fd); | 218 FileDescriptor* file = fds_.At(fd); |
179 file->handle = handle_slot; | 219 file->handle = handle_slot; |
180 FileHandle *handle = open_files_.At(handle_slot); | 220 FileHandle* handle = open_files_.At(handle_slot); |
181 | 221 |
182 // init should be safe because we have the kernel proxy lock | 222 // init should be safe because we have the kernel proxy lock |
183 if (pthread_mutex_init(&handle->lock, NULL)) assert(0); | 223 if (pthread_mutex_init(&handle->lock, NULL)) assert(0); |
184 | 224 |
185 handle->mount = mount; | 225 handle->mount = mount; |
| 226 handle->stream = NULL; |
186 handle->node = st.st_ino; | 227 handle->node = st.st_ino; |
187 handle->flags = flags; | 228 handle->flags = flags; |
188 handle->use_count = 1; | 229 handle->use_count = 1; |
189 | 230 |
190 if (flags & O_APPEND) { | 231 if (flags & O_APPEND) { |
191 handle->offset = st.st_size; | 232 handle->offset = st.st_size; |
192 } else { | 233 } else { |
193 handle->offset = 0; | 234 handle->offset = 0; |
194 } | 235 } |
195 | 236 |
196 return fd; | 237 return fd; |
197 } | 238 } |
198 | 239 |
| 240 static __thread struct hostent* ghn_res = NULL; |
| 241 static __thread char** ghn_addr_list = NULL; |
| 242 static __thread char* ghn_item = NULL; |
| 243 |
| 244 struct hostent* KernelProxy::gethostbyname(const char* name) { |
| 245 struct hostent *res = ghn_res == NULL |
| 246 ? (ghn_res = (struct hostent*) malloc(sizeof(struct hostent))) |
| 247 : ghn_res; |
| 248 if (!res) return NULL; |
| 249 res->h_addr_list = ghn_addr_list == NULL |
| 250 ? (ghn_addr_list = (char**) malloc(sizeof(char*) * 2)) |
| 251 : ghn_addr_list; |
| 252 if (!res->h_addr_list) return NULL; |
| 253 res->h_addr_list[0] = ghn_item == NULL |
| 254 ? (ghn_item = (char*) malloc(sizeof(long int))) |
| 255 : ghn_item; |
| 256 if (!res->h_addr_list[0]) return NULL; |
| 257 *((long int*)res->h_addr_list[0]) = socket_subsystem_->gethostbyname(name); |
| 258 res->h_addr_list[1] = NULL; |
| 259 res->h_length = sizeof(long int); |
| 260 return res; |
| 261 } |
| 262 |
| 263 int KernelProxy::getaddrinfo(const char* hostname, const char* servname, |
| 264 const struct addrinfo* hints, struct addrinfo** res) { |
| 265 dbgprintf("getaddrinfo: %s %s\n", |
| 266 hostname ? hostname : "", servname ? servname : ""); |
| 267 return socket_subsystem_->getaddrinfo( |
| 268 hostname, servname, hints, res); |
| 269 } |
| 270 |
| 271 void KernelProxy::freeaddrinfo(struct addrinfo* ai) { |
| 272 dbgprintf("freeaddrinfo\n"); |
| 273 return socket_subsystem_->freeaddrinfo(ai); |
| 274 } |
| 275 |
| 276 int KernelProxy::getnameinfo(const struct sockaddr *sa, socklen_t salen, |
| 277 char *host, socklen_t hostlen, |
| 278 char *serv, socklen_t servlen, unsigned int flags) { |
| 279 dbgprintf("getnameinfo\n"); |
| 280 return socket_subsystem_->getnameinfo( |
| 281 sa, salen, host, hostlen, serv, servlen, flags); |
| 282 } |
| 283 |
199 int KernelProxy::open(const std::string& path, int flags, mode_t mode) { | 284 int KernelProxy::open(const std::string& path, int flags, mode_t mode) { |
200 if (path.empty()) { | 285 if (path.empty()) { |
201 errno = EINVAL; | 286 errno = EINVAL; |
202 return -1; | 287 return -1; |
203 } | 288 } |
204 | 289 |
205 Path p(path); | 290 Path p(path); |
206 if (path[0] != '/') { | 291 if (path[0] != '/') { |
207 p = Path(cwd_.FormulatePath() + "/" + path); | 292 p = Path(cwd_.FormulatePath() + "/" + path); |
208 } | 293 } |
209 | 294 |
210 std::pair<Mount *, std::string> m_and_p = | 295 std::pair<Mount *, std::string> m_and_p = |
211 mm_.GetMount(p.FormulatePath()); | 296 mm_.GetMount(p.FormulatePath()); |
212 | 297 |
213 if (!(m_and_p.first)) { | 298 if (!(m_and_p.first)) { |
214 errno = ENOENT; | 299 errno = ENOENT; |
215 return -1; | 300 return -1; |
216 } | 301 } |
217 | 302 |
218 return OpenHandle(m_and_p.first, m_and_p.second, flags, mode); | 303 return OpenHandle(m_and_p.first, m_and_p.second, flags, mode); |
219 } | 304 } |
220 | 305 |
221 int KernelProxy::close(int fd) { | 306 int KernelProxy::close(int fd) { |
222 SimpleAutoLock lock(&kp_lock_); | 307 SimpleAutoLock* lock = new SimpleAutoLock(&kp_lock_); |
223 | 308 |
224 FileDescriptor* file = fds_.At(fd); | 309 FileDescriptor* file = fds_.At(fd); |
225 if (file == NULL) { | 310 if (file == NULL) { |
226 errno = EBADF; | 311 errno = EBADF; |
227 return -1; | 312 return -1; |
228 } | 313 } |
229 int h = file->handle; | 314 int h = file->handle; |
230 fds_.Free(fd); | 315 fds_.Free(fd); |
231 FileHandle *handle = open_files_.At(h); | 316 FileHandle* handle = open_files_.At(h); |
232 if (handle == NULL) { | 317 if (handle == NULL) { |
233 errno = EBADF; | 318 errno = EBADF; |
234 return -1; | 319 return -1; |
235 } | 320 } |
236 handle->use_count--; | 321 handle->use_count--; |
237 ino_t node = handle->node; | 322 ino_t node = handle->node; |
238 Mount *mount = handle->mount; | 323 if (handle->mount) { |
239 if (handle->use_count <= 0) { | 324 Mount* mount = handle->mount; |
240 open_files_.Free(h); | 325 if (handle->use_count <= 0) { |
241 mount->Unref(node); | 326 open_files_.Free(h); |
| 327 mount->Unref(node); |
| 328 } |
| 329 mount->Unref(); |
| 330 } else { |
| 331 Socket* stream = handle->stream; |
| 332 delete lock; |
| 333 socket_subsystem_->close(stream); |
| 334 SimpleAutoLock lock(&kp_lock_); |
| 335 if (handle->use_count <= 0) { |
| 336 open_files_.Free(h); |
| 337 } |
| 338 return 0; |
242 } | 339 } |
243 mount->Unref(); | 340 delete lock; |
244 return 0; | 341 return 0; |
245 } | 342 } |
246 | 343 |
247 ssize_t KernelProxy::read(int fd, void *buf, size_t count) { | 344 ssize_t KernelProxy::read(int fd, void *buf, size_t count) { |
248 FileHandle *handle; | 345 FileHandle* handle; |
249 // check if fd is valid and handle exists | 346 // check if fd is valid and handle exists |
250 if (!(handle = GetFileHandle(fd))) { | 347 if (!(handle = GetFileHandle(fd))) { |
251 errno = EBADF; | 348 errno = EBADF; |
252 return -1; | 349 return -1; |
253 } | 350 } |
254 | 351 |
255 SimpleAutoLock(&handle->lock); | 352 if (handle->mount) { |
| 353 SimpleAutoLock(&handle->lock); |
| 354 // Check that this file handle can be read from. |
| 355 if ((handle->flags & O_ACCMODE) == O_WRONLY || |
| 356 is_dir(handle->mount, handle->node)) { |
| 357 errno = EBADF; |
| 358 return -1; |
| 359 } |
256 | 360 |
257 // Check that this file handle can be read from. | 361 ssize_t n = handle->mount->Read(handle->node, handle->offset, buf, count); |
258 if ((handle->flags & O_ACCMODE) == O_WRONLY || | 362 if (n > 0) { |
259 is_dir(handle->mount, handle->node)) { | 363 handle->offset += n; |
260 errno = EBADF; | 364 } |
261 return -1; | 365 return n; |
| 366 } else if (handle->stream) { |
| 367 // TODO(vissi): more elaborate implementation |
| 368 return recv(fd, buf, count, 0); |
262 } | 369 } |
263 | 370 errno = EBADF; |
264 ssize_t n = handle->mount->Read(handle->node, handle->offset, buf, count); | 371 return -1; |
265 if (n > 0) { | |
266 handle->offset += n; | |
267 } | |
268 return n; | |
269 } | 372 } |
270 | 373 |
271 ssize_t KernelProxy::write(int fd, const void *buf, size_t count) { | 374 ssize_t KernelProxy::write(int fd, const void *buf, size_t count) { |
272 FileHandle *handle; | 375 FileHandle* handle; |
273 | 376 |
274 // check if fd is valid and handle exists | 377 // check if fd is valid and handle exists |
275 if (!(handle = GetFileHandle(fd))) { | 378 if (!(handle = GetFileHandle(fd))) { |
276 errno = EBADF; | 379 errno = EBADF; |
277 return -1; | 380 return -1; |
278 } | 381 } |
279 | 382 |
280 SimpleAutoLock(&handle->lock); | 383 if (handle->mount) { |
| 384 SimpleAutoLock(&handle->lock); |
| 385 // Check that this file handle can be written to. |
| 386 if ((handle->flags & O_ACCMODE) == O_RDONLY || |
| 387 is_dir(handle->mount, handle->node)) { |
| 388 errno = EBADF; |
| 389 return -1; |
| 390 } |
281 | 391 |
282 // Check that this file handle can be written to. | 392 ssize_t n = handle->mount->Write(handle->node, handle->offset, buf, count); |
283 if ((handle->flags & O_ACCMODE) == O_RDONLY || | 393 |
284 is_dir(handle->mount, handle->node)) { | 394 if (n > 0) { |
285 errno = EBADF; | 395 handle->offset += n; |
286 return -1; | 396 } |
| 397 return n; |
| 398 } else if (handle->stream) { |
| 399 // TODO(vissi): more elaborate implementation |
| 400 return send(fd, buf, count, 0); |
287 } | 401 } |
288 | 402 errno = EBADF; |
289 ssize_t n = handle->mount->Write(handle->node, handle->offset, buf, count); | 403 return -1; |
290 | |
291 if (n > 0) { | |
292 handle->offset += n; | |
293 } | |
294 return n; | |
295 } | 404 } |
296 | 405 |
297 int KernelProxy::fstat(int fd, struct stat *buf) { | 406 int KernelProxy::fstat(int fd, struct stat *buf) { |
298 FileHandle *handle; | 407 FileHandle* handle; |
299 | 408 |
300 // check if fd is valid and handle exists | 409 // check if fd is valid and handle exists |
301 if (!(handle = GetFileHandle(fd))) { | 410 if (!(handle = GetFileHandle(fd))) { |
302 errno = EBADF; | 411 errno = EBADF; |
303 return -1; | 412 return -1; |
304 } | 413 } |
305 SimpleAutoLock(&handle->lock); | 414 SimpleAutoLock(&handle->lock); |
306 return handle->mount->Stat(handle->node, buf); | 415 return handle->mount->Stat(handle->node, buf); |
307 } | 416 } |
308 | 417 |
309 int KernelProxy::ioctl(int fd, unsigned long request) { | 418 int KernelProxy::ioctl(int fd, unsigned long request) { |
310 errno = ENOSYS; | 419 errno = ENOSYS; |
311 fprintf(stderr, "ioctl has not been implemented!\n"); | 420 fprintf(stderr, "ioctl has not been implemented!\n"); |
312 assert(0); | 421 assert(0); |
313 return -1; | 422 return -1; |
314 } | 423 } |
315 | 424 |
316 int KernelProxy::kill(pid_t pid, int sig) { | 425 int KernelProxy::kill(pid_t pid, int sig) { |
317 errno = ENOSYS; | 426 errno = ENOSYS; |
318 fprintf(stderr, "kill has not been implemented!\n"); | 427 fprintf(stderr, "kill has not been implemented!\n"); |
319 assert(0); | 428 assert(0); |
320 return -1; | 429 return -1; |
321 } | 430 } |
322 | 431 |
323 int KernelProxy::getdents(int fd, void *buf, unsigned int count) { | 432 int KernelProxy::getdents(int fd, void *buf, unsigned int count) { |
324 FileHandle *handle; | 433 FileHandle* handle; |
325 | 434 |
326 // check if fd is valid and handle exists | 435 // check if fd is valid and handle exists |
327 if (!(handle = GetFileHandle(fd))) { | 436 if (!(handle = GetFileHandle(fd))) { |
328 errno = EBADF; | 437 errno = EBADF; |
329 return -1; | 438 return -1; |
330 } | 439 } |
331 | 440 |
332 SimpleAutoLock(&handle->lock); | 441 SimpleAutoLock(&handle->lock); |
333 | 442 |
334 int ret = handle->mount->Getdents(handle->node, handle->offset, | 443 int ret = handle->mount->Getdents(handle->node, handle->offset, |
335 (struct dirent*)buf, count); | 444 (struct dirent*)buf, count); |
336 | 445 |
337 if (ret != -1) { | 446 if (ret != -1) { |
338 // TODO(bradnelson): think of a better interface for Mount::Getdents. | 447 // TODO(bradnelson): think of a better interface for Mount::Getdents. |
339 // http://code.google.com/p/naclports/issues/detail?id=18 | 448 // http://code.google.com/p/naclports/issues/detail?id=18 |
340 handle->offset += ret / sizeof(struct dirent); | 449 handle->offset += ret / sizeof(struct dirent); |
341 } | 450 } |
342 return ret; | 451 return ret; |
343 } | 452 } |
344 | 453 |
345 int KernelProxy::fsync(int fd) { | 454 int KernelProxy::fsync(int fd) { |
346 FileHandle *handle; | 455 FileHandle* handle; |
347 | 456 |
348 if (!(handle = GetFileHandle(fd))) { | 457 if (!(handle = GetFileHandle(fd))) { |
349 errno = EBADF; | 458 errno = EBADF; |
350 return -1; | 459 return -1; |
351 } | 460 } |
352 SimpleAutoLock(&handle->lock); | 461 SimpleAutoLock(&handle->lock); |
353 return handle->mount->Fsync(handle->node); | 462 return handle->mount->Fsync(handle->node); |
354 } | 463 } |
355 | 464 |
356 int KernelProxy::isatty(int fd) { | 465 int KernelProxy::isatty(int fd) { |
357 FileHandle *handle; | 466 FileHandle* handle; |
358 | 467 |
359 if (!(handle = GetFileHandle(fd))) { | 468 if (!(handle = GetFileHandle(fd))) { |
360 errno = EBADF; | 469 errno = EBADF; |
361 return 0; | 470 return 0; |
362 } | 471 } |
363 SimpleAutoLock(&handle->lock); | |
364 return handle->mount->Isatty(handle->node); | 472 return handle->mount->Isatty(handle->node); |
365 } | 473 } |
366 | 474 |
| 475 int KernelProxy::dup2(int fd, int newfd) { |
| 476 SimpleAutoLock lock(&kp_lock_); |
| 477 int handle_slot = fds_.At(fd)->handle; |
| 478 if (fds_.AllocAt(fd) != fd) return -1; |
| 479 FileDescriptor* file = fds_.At(newfd); |
| 480 file->handle = handle_slot; |
| 481 return 0; |
| 482 } |
| 483 |
| 484 int KernelProxy::IsReady(int nfds, fd_set* fds, |
| 485 bool (Socket::*is_ready)(), bool apply) { |
| 486 if (!fds) |
| 487 return 0; |
| 488 |
| 489 int nset = 0; |
| 490 for (int i = 0; i < nfds; i++) { |
| 491 if (FD_ISSET(i, fds)) { |
| 492 Socket* stream = GetFileHandle(i) > 0 ? |
| 493 GetFileHandle(i)->stream : NULL; |
| 494 if (!stream) |
| 495 return -1; |
| 496 if ((stream->*is_ready)()) { |
| 497 if (!apply) |
| 498 return 1; |
| 499 else |
| 500 nset++; |
| 501 } else { |
| 502 if (apply) |
| 503 FD_CLR(i, fds); |
| 504 } |
| 505 } |
| 506 } |
| 507 return nset; |
| 508 } |
| 509 |
367 int KernelProxy::dup(int oldfd) { | 510 int KernelProxy::dup(int oldfd) { |
368 SimpleAutoLock lock(&kp_lock_); | 511 SimpleAutoLock lock(&kp_lock_); |
369 | 512 |
| 513 FileHandle* fh = GetFileHandle(oldfd); |
| 514 if (!fh) { |
| 515 errno = EBADF; |
| 516 return -1; |
| 517 } |
| 518 if (fh->mount == NULL) { |
| 519 Socket* stream = GetFileHandle(oldfd) > 0 |
| 520 ? GetFileHandle(oldfd)->stream : NULL; |
| 521 if (!stream) |
| 522 return EBADF; |
| 523 SimpleAutoLock lock(&kp_lock_); |
| 524 int handle_slot = fds_.At(oldfd)->handle; |
| 525 int newfd = fds_.Alloc(); |
| 526 FileDescriptor* file = fds_.At(newfd); |
| 527 file->handle = handle_slot; |
| 528 return newfd; |
| 529 } |
370 FileDescriptor* oldfile = fds_.At(oldfd); | 530 FileDescriptor* oldfile = fds_.At(oldfd); |
371 if (oldfile == NULL) { | 531 if (oldfile == NULL) { |
372 errno = EBADF; | 532 errno = EBADF; |
373 return -1; | 533 return -1; |
374 } | 534 } |
375 int newfd = fds_.Alloc(); | 535 int newfd = fds_.Alloc(); |
376 FileDescriptor *newfile = fds_.At(newfd); | 536 FileDescriptor *newfile = fds_.At(newfd); |
377 int h = oldfile->handle; | 537 int h = oldfile->handle; |
378 newfile->handle = h; | 538 newfile->handle = h; |
379 FileHandle *handle = open_files_.At(h); | 539 FileHandle* handle = open_files_.At(h); |
380 // init should be safe because we have the kernel proxy lock | 540 // init should be safe because we have the kernel proxy lock |
381 if (pthread_mutex_init(&handle->lock, NULL)) assert(0); | 541 if (pthread_mutex_init(&handle->lock, NULL)) assert(0); |
382 | 542 |
383 if (handle == NULL) { | 543 if (handle == NULL) { |
384 errno = EBADF; | 544 errno = EBADF; |
385 return -1; | 545 return -1; |
386 } | 546 } |
387 ++handle->use_count; | 547 ++handle->use_count; |
388 handle->mount->Ref(handle->node); | 548 handle->mount->Ref(handle->node); |
389 handle->mount->Ref(); | 549 handle->mount->Ref(); |
390 return newfd; | 550 return newfd; |
391 } | 551 } |
392 | 552 |
393 off_t KernelProxy::lseek(int fd, off_t offset, int whence) { | 553 off_t KernelProxy::lseek(int fd, off_t offset, int whence) { |
394 FileHandle *handle; | 554 FileHandle* handle; |
395 // check if fd is valid and handle exists | 555 // check if fd is valid and handle exists |
396 if (!(handle = GetFileHandle(fd))) { | 556 if (!(handle = GetFileHandle(fd))) { |
397 errno = EBADF; | 557 errno = EBADF; |
398 return -1; | 558 return -1; |
399 } | 559 } |
400 | 560 |
401 SimpleAutoLock(&handle->lock); | 561 SimpleAutoLock(&handle->lock); |
402 | 562 |
403 off_t next; | 563 off_t next; |
404 ssize_t len; | 564 ssize_t len; |
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
611 ((amode & X_OK) && !(mode & X_OK))) { | 771 ((amode & X_OK) && !(mode & X_OK))) { |
612 errno = EACCES; | 772 errno = EACCES; |
613 return -1; | 773 return -1; |
614 } | 774 } |
615 } | 775 } |
616 // By now we have checked access permissions for | 776 // By now we have checked access permissions for |
617 // each component of the path. | 777 // each component of the path. |
618 return 0; | 778 return 0; |
619 } | 779 } |
620 | 780 |
621 KernelProxy::FileHandle *KernelProxy::GetFileHandle(int fd) { | 781 KernelProxy::FileHandle* KernelProxy::GetFileHandle(int fd) { |
622 SimpleAutoLock lock(&kp_lock_); | 782 SimpleAutoLock lock(&kp_lock_); |
623 FileDescriptor *file = fds_.At(fd); | 783 FileDescriptor *file = fds_.At(fd); |
624 if (!file) { | 784 if (!file) { |
625 return NULL; | 785 return NULL; |
626 } | 786 } |
627 return open_files_.At(file->handle); | 787 return open_files_.At(file->handle); |
628 } | 788 } |
629 | 789 |
630 int KernelProxy::mkdir(const std::string& path, mode_t mode) { | 790 int KernelProxy::mkdir(const std::string& path, mode_t mode) { |
631 if (path.empty()) { | 791 if (path.empty()) { |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
667 | 827 |
668 // Check if a mount is mounted on abs_path or on a subdirectory of abs_path | 828 // Check if a mount is mounted on abs_path or on a subdirectory of abs_path |
669 if (mm_.InMountRootPath(abs_path)) { | 829 if (mm_.InMountRootPath(abs_path)) { |
670 errno = EBUSY; | 830 errno = EBUSY; |
671 return -1; | 831 return -1; |
672 } | 832 } |
673 | 833 |
674 return mount->Rmdir(buf.st_ino); | 834 return mount->Rmdir(buf.st_ino); |
675 } | 835 } |
676 | 836 |
677 #ifdef __GLIBC__ | |
678 int KernelProxy::socket(int domain, int type, int protocol) { | 837 int KernelProxy::socket(int domain, int type, int protocol) { |
679 errno = ENOSYS; | 838 SimpleAutoLock lock(&kp_lock_); |
680 fprintf(stderr, "socket has not been implemented!\n"); | 839 int handle_slot = open_files_.Alloc(); |
681 return -1; | 840 int fd = fds_.Alloc(); |
| 841 FileDescriptor* file = fds_.At(fd); |
| 842 file->handle = handle_slot; |
| 843 FileHandle* handle = open_files_.At(handle_slot); |
| 844 // this means it is a socket (not a mount handle) and it's implementation |
| 845 // determined by handle->stream type is defined later |
| 846 handle->mount = NULL; |
| 847 handle->stream = NULL; |
| 848 handle->use_count = 1; |
| 849 return fd; |
682 } | 850 } |
683 | 851 |
684 int KernelProxy::accept(int sockfd, struct sockaddr *addr, | 852 int KernelProxy::accept(int sockfd, struct sockaddr *addr, |
685 socklen_t* addrlen) { | 853 socklen_t* addrlen) { |
686 errno = ENOSYS; | 854 if (GetFileHandle(sockfd) == 0) |
687 fprintf(stderr, "accept has not been implemented!\n"); | 855 return EBADF; |
688 return -1; | 856 Socket* ret = socket_subsystem_->accept(GetFileHandle(sockfd)->stream, |
| 857 addr, addrlen); |
| 858 if (ret) |
| 859 return AddSocket(ret); |
| 860 else |
| 861 return -1; |
689 } | 862 } |
690 | 863 |
691 int KernelProxy::bind(int sockfd, const struct sockaddr *addr, | 864 int KernelProxy::bind(int sockfd, const struct sockaddr *addr, |
692 socklen_t addrlen) { | 865 socklen_t addrlen) { |
693 errno = ENOSYS; | 866 if (GetFileHandle(sockfd) == 0) |
694 fprintf(stderr, "bind has not been implemented!\n"); | 867 return EBADF; |
695 return -1; | 868 struct sockaddr_in* in_addr = (struct sockaddr_in*)addr; |
| 869 return socket_subsystem_->bind(&(GetFileHandle(sockfd)->stream), |
| 870 addr, addrlen); |
696 } | 871 } |
697 | 872 |
698 int KernelProxy::listen(int sockfd, int backlog) { | 873 int KernelProxy::listen(int sockfd, int backlog) { |
699 errno = ENOSYS; | 874 if (GetFileHandle(sockfd) == 0) |
700 fprintf(stderr, "listen has not been implemented!\n"); | 875 return EBADF; |
701 return -1; | 876 return socket_subsystem_->listen(GetFileHandle(sockfd)->stream, backlog); |
702 } | 877 } |
703 | 878 |
704 int KernelProxy::connect(int sockfd, const struct sockaddr *addr, | 879 int KernelProxy::connect(int sockfd, const struct sockaddr *addr, |
705 socklen_t addrlen) { | 880 socklen_t addrlen) { |
706 errno = ENOSYS; | 881 if (GetFileHandle(sockfd) == 0) |
707 fprintf(stderr, "connect has not been implemented!\n"); | 882 return EBADF; |
708 return -1; | 883 struct sockaddr_in* in_addr = (struct sockaddr_in*)addr; |
| 884 return socket_subsystem_->connect(&(GetFileHandle(sockfd)->stream), |
| 885 addr, addrlen); |
709 } | 886 } |
710 | 887 |
711 int KernelProxy::send(int sockfd, const void *buf, size_t len, int flags) { | 888 int KernelProxy::send(int sockfd, const void *buf, size_t len, int flags) { |
712 errno = ENOSYS; | 889 if (GetFileHandle(sockfd) == 0) |
713 fprintf(stderr, "send has not been implemented!\n"); | 890 return EBADF; |
714 return -1; | 891 size_t nwr; |
| 892 socket_subsystem_->write(GetFileHandle(sockfd)->stream, (const char*)buf, |
| 893 len, &nwr); |
| 894 return nwr; |
715 } | 895 } |
716 | 896 |
717 int KernelProxy::sendmsg(int sockfd, const struct msghdr *msg, int flags) { | 897 int KernelProxy::sendmsg(int sockfd, const struct msghdr *msg, int flags) { |
718 errno = ENOSYS; | 898 errno = ENOSYS; |
719 fprintf(stderr, "sendmsg has not been implemented!\n"); | 899 fprintf(stderr, "sendmsg has not been implemented!\n"); |
720 return -1; | 900 return -1; |
721 } | 901 } |
722 | 902 |
723 int KernelProxy::sendto(int sockfd, const void *buf, size_t len, int flags, | 903 int KernelProxy::sendto(int sockfd, const void *buf, size_t len, int flags, |
724 const struct sockaddr *dest_addr, socklen_t addrlen) { | 904 const struct sockaddr *dest_addr, socklen_t addrlen) { |
725 errno = ENOSYS; | 905 errno = ENOSYS; |
726 fprintf(stderr, "sendto has not been implemented!\n"); | 906 fprintf(stderr, "sendto has not been implemented!\n"); |
727 return -1; | 907 return -1; |
728 } | 908 } |
729 | 909 |
730 int KernelProxy::recv(int sockfd, void *buf, size_t len, int flags) { | 910 int KernelProxy::recv(int sockfd, void *buf, size_t len, int flags) { |
731 errno = ENOSYS; | 911 if (GetFileHandle(sockfd) == 0) |
732 fprintf(stderr, "recv has not been implemented!\n"); | 912 return EBADF; |
733 return -1; | 913 size_t nread; |
| 914 socket_subsystem_->read(GetFileHandle(sockfd)->stream, |
| 915 reinterpret_cast<char*>(buf), len, &nread); |
| 916 return nread; |
734 } | 917 } |
735 | 918 |
736 int KernelProxy::recvmsg(int sockfd, struct msghdr *msg, int flags) { | 919 int KernelProxy::recvmsg(int sockfd, struct msghdr *msg, int flags) { |
737 errno = ENOSYS; | 920 errno = ENOSYS; |
738 fprintf(stderr, "recvmsg has not been implemented!\n"); | 921 fprintf(stderr, "recvmsg has not been implemented!\n"); |
739 return -1; | 922 return -1; |
740 } | 923 } |
741 | 924 |
742 int KernelProxy::recvfrom(int sockfd, void *buf, size_t len, int flags, | 925 int KernelProxy::recvfrom(int sockfd, void *buf, size_t len, int flags, |
743 struct sockaddr *dest_addr, socklen_t* addrlen) { | 926 struct sockaddr *dest_addr, socklen_t* addrlen) { |
744 errno = ENOSYS; | 927 errno = ENOSYS; |
745 fprintf(stderr, "recvfrom has not been implemented!\n"); | 928 fprintf(stderr, "recvfrom has not been implemented!\n"); |
746 return -1; | 929 return -1; |
747 } | 930 } |
748 | 931 |
| 932 #ifndef TIMEVAL_TO_TIMESPEC |
| 933 /* Macros for converting between `struct timeval' and `struct timespec'. */ |
| 934 # define TIMEVAL_TO_TIMESPEC(tv, ts) { \ |
| 935 (ts)->tv_sec = (tv)->tv_sec; \ |
| 936 (ts)->tv_nsec = (tv)->tv_usec * 1000; \ |
| 937 } |
| 938 # define TIMESPEC_TO_TIMEVAL(tv, ts) { \ |
| 939 (tv)->tv_sec = (ts)->tv_sec; \ |
| 940 (tv)->tv_usec = (ts)->tv_nsec / 1000; \ |
| 941 } |
| 942 #endif |
| 943 |
749 int KernelProxy::select(int nfds, fd_set *readfds, fd_set *writefds, | 944 int KernelProxy::select(int nfds, fd_set *readfds, fd_set *writefds, |
750 fd_set* exceptfds, const struct timeval *timeout) { | 945 fd_set* exceptfds, const struct timeval *timeout) { |
751 errno = ENOSYS; | 946 timespec ts_abs; |
752 fprintf(stderr, "select has not been implemented!\n"); | 947 if (timeout) { |
753 return -1; | 948 timespec ts; |
| 949 TIMEVAL_TO_TIMESPEC(timeout, &ts); |
| 950 timeval tv_now; |
| 951 gettimeofday(&tv_now, NULL); |
| 952 int64_t current_time_us = |
| 953 tv_now.tv_sec * kMicrosecondsPerSecond + tv_now.tv_usec; |
| 954 int64_t wakeup_time_us = |
| 955 current_time_us + |
| 956 timeout->tv_sec * kMicrosecondsPerSecond + timeout->tv_usec; |
| 957 ts_abs.tv_sec = wakeup_time_us / kMicrosecondsPerSecond; |
| 958 ts_abs.tv_nsec = |
| 959 (wakeup_time_us - ts_abs.tv_sec * kMicrosecondsPerSecond) * |
| 960 kNanosecondsPerMicrosecond; |
| 961 } |
| 962 |
| 963 while (!(IsReady(nfds, readfds, &Socket::is_read_ready, false) || |
| 964 IsReady(nfds, writefds, &Socket::is_write_ready, false) || |
| 965 IsReady(nfds, exceptfds, &Socket::is_exception, false))) { |
| 966 SimpleAutoLock lock(select_mutex().get()); |
| 967 if (timeout) { |
| 968 if (!timeout->tv_sec && !timeout->tv_usec) |
| 969 break; |
| 970 |
| 971 if (select_cond().timedwait(select_mutex(), &ts_abs)) { |
| 972 if (errno == ETIMEDOUT) |
| 973 break; |
| 974 else |
| 975 return -1; |
| 976 } |
| 977 } else { |
| 978 select_cond().wait(select_mutex()); |
| 979 } |
| 980 } |
| 981 |
| 982 int nread = IsReady(nfds, readfds, &Socket::is_read_ready, true); |
| 983 int nwrite = IsReady(nfds, writefds, &Socket::is_write_ready, true); |
| 984 int nexcpt = IsReady(nfds, exceptfds, &Socket::is_exception, true); |
| 985 if (nread < 0 || nwrite < 0 || nexcpt < 0) { |
| 986 errno = EBADF; |
| 987 return -1; |
| 988 } |
| 989 return nread + nwrite + nexcpt; |
754 } | 990 } |
755 | 991 |
756 int KernelProxy::pselect(int nfds, fd_set *readfds, fd_set *writefds, | 992 int KernelProxy::pselect(int nfds, fd_set *readfds, fd_set *writefds, |
757 fd_set* exceptfds, const struct timeval *timeout, void* sigmask) { | 993 fd_set* exceptfds, const struct timeval *timeout, void* sigmask) { |
758 errno = ENOSYS; | 994 errno = ENOSYS; |
759 fprintf(stderr, "pselect has not been implemented!\n"); | 995 fprintf(stderr, "pselect has not been implemented!\n"); |
760 return -1; | 996 return -1; |
761 } | 997 } |
762 | 998 |
763 int KernelProxy::getpeername(int sockfd, struct sockaddr *addr, | 999 int KernelProxy::getpeername(int sockfd, struct sockaddr *addr, |
(...skipping 18 matching lines...) Expand all Loading... |
782 } | 1018 } |
783 | 1019 |
784 int KernelProxy::setsockopt(int sockfd, int level, int optname, | 1020 int KernelProxy::setsockopt(int sockfd, int level, int optname, |
785 const void *optval, socklen_t optlen) { | 1021 const void *optval, socklen_t optlen) { |
786 errno = ENOSYS; | 1022 errno = ENOSYS; |
787 fprintf(stderr, "setsockopt has not been implemented!\n"); | 1023 fprintf(stderr, "setsockopt has not been implemented!\n"); |
788 return -1; | 1024 return -1; |
789 } | 1025 } |
790 | 1026 |
791 int KernelProxy::shutdown(int sockfd, int how) { | 1027 int KernelProxy::shutdown(int sockfd, int how) { |
792 errno = ENOSYS; | 1028 if (GetFileHandle(sockfd) == 0) |
793 fprintf(stderr, "shutdown has not been implemented!\n"); | 1029 return EBADF; |
794 return -1; | 1030 return socket_subsystem_->shutdown(GetFileHandle(sockfd)->stream, how); |
795 } | |
796 | |
797 int KernelProxy::epoll_create(int size) { | |
798 errno = ENOSYS; | |
799 fprintf(stderr, "epoll_create has not been implemented!\n"); | |
800 return -1; | |
801 } | |
802 | |
803 int KernelProxy::epoll_create1(int flags) { | |
804 errno = ENOSYS; | |
805 fprintf(stderr, "epoll_create1 has not been implemented!\n"); | |
806 return -1; | |
807 } | |
808 | |
809 int KernelProxy::epoll_ctl(int epfd, int op, int fd, | |
810 struct epoll_event *event) { | |
811 errno = ENOSYS; | |
812 fprintf(stderr, "epoll_ctl has not been implemented!\n"); | |
813 return -1; | |
814 } | |
815 | |
816 int KernelProxy::epoll_wait(int epfd, struct epoll_event *events, int maxevents, | |
817 int timeout) { | |
818 errno = ENOSYS; | |
819 fprintf(stderr, "epoll_wait has not been implemented!\n"); | |
820 return -1; | |
821 } | |
822 | |
823 int KernelProxy::epoll_pwait(int epfd, struct epoll_event *events, | |
824 int maxevents, int timeout, const sigset_t *sigmask, size_t sigset_size) { | |
825 errno = ENOSYS; | |
826 fprintf(stderr, "epoll_pwait has not been implemented!\n"); | |
827 return -1; | |
828 } | 1031 } |
829 | 1032 |
830 int KernelProxy::socketpair(int domain, int type, int protocol, int sv[2]) { | 1033 int KernelProxy::socketpair(int domain, int type, int protocol, int sv[2]) { |
831 errno = ENOSYS; | 1034 errno = ENOSYS; |
832 fprintf(stderr, "socketpair has not been implemented!\n"); | 1035 fprintf(stderr, "socketpair has not been implemented!\n"); |
833 return -1; | 1036 return -1; |
834 } | 1037 } |
835 | 1038 |
836 int KernelProxy::poll(struct pollfd *fds, nfds_t nfds, int timeout) { | |
837 errno = ENOSYS; | |
838 fprintf(stderr, "poll has not been implemented!\n"); | |
839 return -1; | |
840 } | |
841 | |
842 int KernelProxy::ppoll(struct pollfd *fds, nfds_t nfds, | |
843 const struct timespec *timeout, | |
844 const sigset_t *sigmask, size_t sigset_size) { | |
845 errno = ENOSYS; | |
846 fprintf(stderr, "ppoll has not been implemented!\n"); | |
847 return -1; | |
848 } | |
849 #endif | |
850 | |
OLD | NEW |