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