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; }
int shim_do_openat (int dfd, const char * filename, int flags, int mode) { if (!filename || test_user_string(filename)) return -EFAULT; if (*filename == '/') return shim_do_open(filename, flags, mode); struct shim_dentry * dir = NULL; int ret = 0; if ((ret = path_startat(dfd, &dir)) < 0) return ret; struct shim_handle * hdl = get_new_handle(); if (!hdl) { ret = -ENOMEM; goto out; } ret = open_namei(hdl, dir, filename, flags, mode, NULL); if (ret < 0) goto out_hdl; ret = set_new_fd_handle(hdl, flags & O_CLOEXEC ? FD_CLOEXEC : 0, NULL); out_hdl: put_handle(hdl); out: put_dentry(dir); return ret; }
int shim_do_open (const char * file, int flags, mode_t mode) { if (!file || !(*file)) return -EINVAL; struct shim_handle * hdl = get_new_handle(); if (!hdl) return -ENOMEM; int ret = 0; ret = open_namei(hdl, NULL, file, flags, mode, NULL); if (ret < 0) goto out; ret = set_new_fd_handle(hdl, flags & O_CLOEXEC ? FD_CLOEXEC : 0, NULL); out: put_handle(hdl); return ret; }
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; }