int shim_do_pipe2 (int * filedes, int flags) { if (!filedes) return -EINVAL; int ret = 0; struct shim_handle * hdl1 = get_new_handle(); struct shim_handle * hdl2 = get_new_handle(); if (!hdl1 || !hdl2) { ret = -ENOMEM; goto out; } hdl1->type = TYPE_PIPE; set_handle_fs(hdl1, &pipe_builtin_fs); hdl1->flags = O_RDONLY; hdl1->acc_mode = MAY_READ; hdl2->type = TYPE_PIPE; set_handle_fs(hdl2, &pipe_builtin_fs); hdl2->flags = O_WRONLY; hdl2->acc_mode = MAY_WRITE; if ((ret = create_pipes(&hdl1->info.pipe.pipeid, &hdl1->pal_handle, &hdl2->pal_handle, &hdl1->uri, flags)) < 0) goto out; qstrcopy(&hdl2->uri, &hdl2->uri); flags = flags & O_CLOEXEC ? FD_CLOEXEC : 0; int vfd1 = set_new_fd_handle(hdl1, flags, NULL); int vfd2 = set_new_fd_handle(hdl2, flags, NULL); if (vfd1 < 0 || vfd2 < 0) { if (vfd1 >= 0) { struct shim_handle * tmp = detach_fd_handle(vfd1, NULL, NULL); if (tmp) close_handle(tmp); } if (vfd2 >= 0) { struct shim_handle * tmp = detach_fd_handle(vfd2, NULL, NULL); if (tmp) close_handle(tmp); } goto out; } filedes[0] = vfd1; filedes[1] = vfd2; out: if (hdl1) put_handle(hdl1); if (hdl2) put_handle(hdl2); return ret; }
static inline int init_tty_handle (struct shim_handle * hdl, bool write) { struct shim_dentry * dent = NULL; int ret; if ((ret = path_lookupat(NULL, "/dev/tty", LOOKUP_OPEN, &dent)) < 0) return ret; int flags = (write ? O_WRONLY : O_RDONLY)|O_APPEND; struct shim_mount * fs = dent->fs; ret = fs->d_ops->open(hdl, dent, flags); if (ret < 0) return ret; set_handle_fs(hdl, fs); hdl->dentry = dent; hdl->flags = O_RDWR|O_APPEND|0100000; int size; char * path = dentry_get_path(dent, true, &size); if (path) qstrsetstr(&hdl->path, path, size); else qstrsetstr(&hdl->path, "/dev/tty", 8); return 0; }
static inline int init_exec_handle (struct shim_thread * thread) { if (!PAL_CB(executable)) return 0; struct shim_handle * exec = get_new_handle(); if (!exec) return -ENOMEM; set_handle_fs(exec, &chroot_builtin_fs); qstrsetstr(&exec->uri, PAL_CB(executable), strlen(PAL_CB(executable))); exec->type = TYPE_FILE; exec->flags = O_RDONLY; exec->acc_mode = MAY_READ; lock(thread->lock); thread->exec = exec; unlock(thread->lock); return 0; }
int shim_do_socketpair (int domain, int type, int protocol, int * sv) { if (domain != AF_UNIX) return -EAFNOSUPPORT; if (type != SOCK_STREAM) return -EPROTONOSUPPORT; if (!sv) return -EINVAL; int ret = 0; struct shim_handle * hdl1 = get_new_handle(); struct shim_handle * hdl2 = get_new_handle(); if (!hdl1 || !hdl2) { ret = -ENOMEM; goto out; } struct shim_sock_handle * sock1 = &hdl1->info.sock; struct shim_sock_handle * sock2 = &hdl2->info.sock; hdl1->type = TYPE_SOCK; set_handle_fs(hdl1, &socket_builtin_fs); hdl1->flags = O_RDONLY; hdl1->acc_mode = MAY_READ|MAY_WRITE; sock1->domain = domain; sock1->sock_type = type & ~(SOCK_NONBLOCK|SOCK_CLOEXEC); sock1->protocol = protocol; sock1->sock_state = SOCK_ACCEPTED; hdl2->type = TYPE_SOCK; set_handle_fs(hdl2, &socket_builtin_fs); hdl1->flags = O_WRONLY; hdl2->acc_mode = MAY_READ|MAY_WRITE; sock2->domain = domain; sock2->sock_type = type & ~(SOCK_NONBLOCK|SOCK_CLOEXEC); sock2->protocol = protocol; sock2->sock_state = SOCK_CONNECTED; if ((ret = create_pipes(&sock1->addr.un.pipeid, &hdl1->pal_handle, &hdl2->pal_handle, &hdl1->uri, type & SOCK_NONBLOCK ? O_NONBLOCK : 0)) < 0) goto out; sock2->addr.un.pipeid = sock1->addr.un.pipeid; qstrcopy(&hdl2->uri, &hdl1->uri); int flags = type & SOCK_CLOEXEC ? FD_CLOEXEC : 0; int vfd1 = set_new_fd_handle(hdl1, flags, NULL); int vfd2 = set_new_fd_handle(hdl2, flags, NULL); if (vfd1 < 0 || vfd2 < 0) { if (vfd1 >= 0) { struct shim_handle * tmp = detach_fd_handle(vfd1, NULL, NULL); if (tmp) close_handle(tmp); } if (vfd2 >= 0) { struct shim_handle * tmp = detach_fd_handle(vfd2, NULL, NULL); if (tmp) close_handle(tmp); } goto out; } sv[0] = vfd1; sv[1] = vfd2; out: if (hdl1) put_handle(hdl1); if (hdl2) put_handle(hdl2); return ret; }