int fcntl(int fd, int cmd, ...) { int ret; va_list args; union { int i; } uargs; if (!idesc_index_valid(fd) || (NULL == index_descriptor_get(fd))) { return SET_ERRNO(EBADF); } /* Fcntl works in two steps: * 1. Make general commands like F_SETFD, F_GETFD. * 2. If fd has some internal fcntl(), it will be called. * Otherwise result of point 1 will be returned. */ switch (cmd) { case F_DUPFD: va_start(args, cmd); uargs.i = va_arg(args, int); va_end(args); ret = idesc_index_valid(uargs.i) ? index_descriptor_dupfd(fd, uargs.i) : -EBADF; break; case F_GETFL: return index_descriptor_flags_get(fd); case F_SETFL: va_start(args, cmd); index_descriptor_flags_set(fd, va_arg(args, int)); va_end(args); return 0; case F_GETFD: /* only for CLOEXEC flag */ return index_descritor_cloexec_get(fd); case F_SETFD: /* only for CLOEXEC flag */ va_start(args, cmd); index_descriptor_cloexec_set(fd, va_arg(args, int)); va_end(args); return 0; default: va_start(args, cmd); ret = index_descriptor_fcntl(fd, cmd, va_arg(args, void *)); va_end(args); break; } if (ret < 0) { return SET_ERRNO(-ret); } return 0; }
int ioctl(int fd, int request, ...) { void *data; va_list args; int rc; if (!idesc_index_valid(fd)) { return SET_ERRNO(EBADF); } switch (request) { case FIONBIO: va_start(args, request); rc = io_fionbio(fd, args); va_end(args); break; case FIONREAD: rc = index_descriptor_status(fd, POLLIN); if (rc < 0) { rc = SET_ERRNO(-rc); } break; default: va_start(args, request); data = va_arg(args, void*); va_end(args); rc = index_descriptor_ioctl(fd, request, data); if (rc < 0) { rc = SET_ERRNO(-rc); } break; } return rc; }
static int fds_setup(struct idesc_poll_table *pt, struct pollfd fds[], nfds_t nfds) { int i = 0, j = 0; int cnt = 0; assert(pt->size <= nfds); for (j = 0; (j < nfds) && (i < pt->size); j++) { if (!idesc_index_valid(fds[j].fd)) { continue; } if (pt->idesc_poll[i].fd != fds[j].fd) { // continue search corresponding descriptor in fds. cnt++; // TODO continue; } if (pt->idesc_poll[i].o_poll_mask) { cnt++; fds[j].revents = (short) pt->idesc_poll[i].o_poll_mask; } i++; } return cnt; }
static int table_prepare(struct idesc_poll_table *pt, struct pollfd fds[], nfds_t nfds) { int i; struct idesc *idesc; int cnt = 0; int poll_mask; for (i = 0; i < nfds; ++i) { fds[i].revents = 0; if (!idesc_index_valid(fds[i].fd)) { continue; } idesc = index_descriptor_get(fds[i].fd); if (idesc == NULL) { fds[i].revents |= POLLNVAL; // pt->idesc_poll[cnt].idesc = NULL; pt->idesc_poll[cnt].fd = -1; cnt++; continue; } poll_mask = 0; if ((fds[i].events & POLLIN) && (idesc->idesc_amode & FS_MAY_READ)) { poll_mask |= POLLIN; } if ((fds[i].events & POLLOUT) && (idesc->idesc_amode & FS_MAY_WRITE)) { poll_mask |= POLLOUT; } if ((fds[i].events & POLLERR)) { poll_mask |= POLLERR; } if (poll_mask) { // pt->idesc_poll[cnt].idesc = idesc; pt->idesc_poll[cnt].i_poll_mask = poll_mask; pt->idesc_poll[cnt].o_poll_mask = 0; pt->idesc_poll[cnt].fd = fds[i].fd; cnt++; } } pt->size = cnt; return cnt; }
ssize_t write(int fd, const void *buf, size_t nbyte) { ssize_t ret; struct idesc *idesc; if (!idesc_index_valid(fd) || (NULL == (idesc = index_descriptor_get(fd))) || (!(idesc->idesc_amode & FS_MAY_WRITE))) { return SET_ERRNO(EBADF); } assert(idesc->idesc_ops != NULL); ret = idesc->idesc_ops->write(idesc, buf, nbyte); if (ret < 0) { return SET_ERRNO(-ret); } return ret; }
int fgetxattr(int fd, const char *name, void *value, size_t size) { struct idesc *idesc; int res; if (!idesc_index_valid(fd) || (NULL == (idesc = index_descriptor_get(fd)))) { return SET_ERRNO(EBADF); } if (0 > (res = security_xattr_idesc_get(idesc, name, value, size))) { return SET_ERRNO(EACCES); } if (0 > (res = idesc_getxattr(idesc, name, value, size))) { return SET_ERRNO(-res); } return res; }
int flistxattr(int fd, char *list, size_t size) { struct idesc *idesc; int res; if (!idesc_index_valid(fd) || (NULL == (idesc = index_descriptor_get(fd)))) { return SET_ERRNO(EBADF); } if (0 > (res = security_xattr_idesc_list(idesc, list, size))) { return SET_ERRNO(EACCES); } if (0 > (res = idesc_listxattr(idesc, list, size))) { return SET_ERRNO(-res); } return res; }
int ftruncate(int fd, off_t length) { struct idesc *idesc; int ret; if (!idesc_index_valid(fd) || (NULL == (idesc = index_descriptor_get(fd))) || (idesc->idesc_ops != &idesc_file_ops)) { return SET_ERRNO(EBADF); } if (!(idesc->idesc_amode & S_IROTH)) { return SET_ERRNO(EINVAL); } ret = kftruncate(member_cast_out(idesc, struct file_desc, idesc), length); if (ret < 0) { return SET_ERRNO(-ret); } return ret; }