int close(int fd) { int ret; struct fdtab_entry *e = fdtab_get(fd); if (e->type == FDTAB_TYPE_AVAILABLE) { return -1; } if (e->type == FDTAB_TYPE_LWIP_SOCKET) { if(e->inherited) { // Perform shallow close on lwip so that it will not terminate // the TCP session printf("close: Inherited socket, not closing completely\n"); ret = 0; } else { ret = lwip_close(e->fd); if(ret < 0) { POSIXCOMPAT_DEBUG("[%d]error in lwip_close\n", disp_get_domain_id()); return -1; } } fdtab_free(fd); } else { ret = vfsfd_close(fd); } return ret; }
int close(int fd) { int ret; struct fdtab_entry *e = fdtab_get(fd); if (e->type == FDTAB_TYPE_AVAILABLE) { return -1; } // Might need to remove from epoll list if(e->epoll_fd != -1) { ret = epoll_ctl(e->epoll_fd, EPOLL_CTL_DEL, fd, NULL); assert(ret == 0); } switch(e->type) { case FDTAB_TYPE_LWIP_SOCKET: if (e->inherited) { // Perform shallow close on lwip so that it will not terminate // the TCP session printf("close: Inherited socket, not closing completely\n"); ret = 0; } else { ret = lwip_close(e->fd); if(ret < 0) { POSIXCOMPAT_DEBUG("[%d]error in lwip_close\n", disp_get_domain_id()); return -1; } } fdtab_free(fd); break; case FDTAB_TYPE_PTM: ret = ptm_close(fd); break; case FDTAB_TYPE_PTS: ret = pts_close(fd); break; default: ret = vfsfd_close(fd); } return ret; }
//XXX: flags are ignored... int vfsfd_open(const char *pathname, int flags) { vfs_handle_t vh; errval_t err; char *path = vfs_path_mkabs(pathname); assert(path != NULL); // If O_CREAT was given, we use vfs_create() if(flags & O_CREAT) { // If O_EXCL was also given, we check whether we can open() first if(flags & O_EXCL) { err = vfs_open(path, &vh); if(err_is_ok(err)) { vfs_close(vh); errno = EEXIST; return -1; } assert(err_no(err) == FS_ERR_NOTFOUND); } err = vfs_create(path, &vh); } else { // Regular open() err = vfs_open(path, &vh); } free(path); if (err_is_fail(err)) { VFSFD_DEBUG("open('%s') failed\n", pathname); switch(err_no(err)) { case FS_ERR_NOTFOUND: errno = ENOENT; break; default: #ifdef VFSFD_DEBUG_ENABLED DEBUG_ERR(err, "vfs_open"); #endif break; } return -1; } struct fdtab_entry e = { .type = FDTAB_TYPE_FILE, .handle = vh, .epoll_fd = -1, }; int fd = fdtab_alloc(&e); VFSFD_DEBUG("open(%s) as fd %d\n", pathname, fd); if (fd < 0) { vfs_close(vh); return -1; } else { return fd; } } int vfsfd_read(int fd, void *buf, size_t len) { struct fdtab_entry *e = fdtab_get(fd); size_t retlen = 0; switch(e->type) { case FDTAB_TYPE_FILE: { errval_t err = vfs_read((vfs_handle_t)e->handle, buf, len, &retlen); VFSFD_DEBUG("%d : read(%d, %d) = %lu\n", disp_get_domain_id(), fd, len, retlen); if (err_is_fail(err)) { DEBUG_ERR(err, "error in vfs_read"); return -1; } } break; case FDTAB_TYPE_STDIN: retlen = terminal_read((char *)buf, len); break; case FDTAB_TYPE_STDOUT: case FDTAB_TYPE_STDERR: case FDTAB_TYPE_AVAILABLE: default: return -1; } return retlen; } int vfsfd_write(int fd, const void *buf, size_t len) { struct fdtab_entry *e = fdtab_get(fd); if (e->type == FDTAB_TYPE_AVAILABLE) { return -1; } size_t retlen = 0; switch(e->type) { case FDTAB_TYPE_FILE: { errval_t err = vfs_write((vfs_handle_t)e->handle, buf, len, &retlen); VFSFD_DEBUG("write(%d, %d) = %lu\n", fd, len, retlen); if (err_is_fail(err)) { DEBUG_ERR(err, "error in vfs_write"); return -1; } } break; case FDTAB_TYPE_STDOUT: /* only support writting to terminal */ retlen = terminal_write((const char*) buf, len); break; case FDTAB_TYPE_STDERR: retlen = terminal_write((const char*) buf, len); break; case FDTAB_TYPE_STDIN: case FDTAB_TYPE_AVAILABLE: default: return -1; } return retlen; } int vfsfd_close(int fd) { errval_t err; struct fdtab_entry *e = fdtab_get(fd); if (e->type == FDTAB_TYPE_AVAILABLE) { return -1; } VFSFD_DEBUG("close(%d)\n", fd); switch(e->type) { case FDTAB_TYPE_FILE: err = vfs_close((vfs_handle_t)e->handle); if (err_is_fail(err)) { DEBUG_ERR(err, "error in vfs_close"); return -1; } break; case FDTAB_TYPE_STDIN: case FDTAB_TYPE_STDOUT: case FDTAB_TYPE_STDERR: // XXX: Should call fclose() when closing last FD break; default: return -1; } // end switch fdtab_free(fd); return 0; }
static errval_t get_inherited_fds(void) { errval_t err; /* Map the FD buffer into our address space. * It stays there since the FD data structures will remain in there and be * referenced from the FD table. */ struct capref frame = { .cnode = cnode_task, .slot = TASKCN_SLOT_FDSPAGE, }; void *fdspg; err = vspace_map_one_frame(&fdspg, FDS_SIZE, frame, NULL, NULL); if (err_is_fail(err)) { return err_push(err, SPAWN_ERR_MAP_FDSPG_TO_SELF); } /* Set up to read the table */ char *p = fdspg; printf("fds at: %p\n", p); int num_fds = *((int*)p); printf("num fds: %d\n", num_fds); struct fd_store *fd; p += sizeof(int); fd = (struct fd_store*)p; p += (sizeof(struct fd_store)*num_fds); /* Process all the FDs passed in the buffer */ int i; for (i = 0; i < num_fds; i++, fd++) { /* add each to our fd table - replacing any fds already there */ struct fdtab_entry fde; fde.type = fd->type; fde.handle = fd->handle; if (fdtab_get(fd->num)->type != FDTAB_TYPE_AVAILABLE) { fdtab_free(fd->num); } fdtab_alloc_from(&fde, fd->num); /* print out some info about the FD */ char *s = ""; switch (fd->type) { case FDTAB_TYPE_AVAILABLE: s = "available"; break; case FDTAB_TYPE_FILE: s = "file"; break; case FDTAB_TYPE_UNIX_SOCKET: s = "unix socket"; break; case FDTAB_TYPE_STDIN: s = "stdin"; break; case FDTAB_TYPE_STDOUT: s = "stdout"; break; case FDTAB_TYPE_STDERR: s = "stderr"; break; case FDTAB_TYPE_LWIP_SOCKET: s = "lwip socket"; break; case FDTAB_TYPE_EPOLL_INSTANCE: s = "epoll instance"; break; case FDTAB_TYPE_PTM: s = "pseudo-terminal master"; break; case FDTAB_TYPE_PTS: s = "pseudo-terminal slave"; break; } printf("fd_store %d: num: %d, type: %d:%s handle: %p\n", i, fd->num, fd->type, s, fd->handle); switch (fd->type) { case FDTAB_TYPE_FILE: print_file_fd((void*)(p + (genpaddr_t)fd->handle)); break; case FDTAB_TYPE_UNIX_SOCKET: print_unixsock_fd((void*)(p + (genpaddr_t)fd->handle)); break; default: printf("[no handle data]\n"); break; } } return SYS_ERR_OK; }