Mercurial > hg
changeset 39969:208cb7a9d0fa
rust-chg: add function to send fds via domain socket
As a beginning, I wrote some C.
It's extracted from attachio() of contrib/chg/hgclient.c. Maybe it could
be rewritten in Rust by using the libc (and/or nix) crates, but doing that
wouldn't be trivial as the code depends on CMSG_*() macros. IMO, using C
is better here.
author | Yuya Nishihara <yuya@tcha.org> |
---|---|
date | Mon, 24 Sep 2018 16:14:35 +0900 |
parents | 86acdfe8b018 |
children | a8be2cff613f |
files | rust/chg/build.rs rust/chg/src/sendfds.c |
diffstat | 2 files changed, 59 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rust/chg/build.rs Mon Sep 24 16:14:35 2018 +0900 @@ -0,0 +1,8 @@ +extern crate cc; + +fn main() { + cc::Build::new() + .warnings(true) + .file("src/sendfds.c") + .compile("procutil"); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rust/chg/src/sendfds.c Mon Sep 24 16:14:35 2018 +0900 @@ -0,0 +1,51 @@ +/* + * Utility to send fds via Unix domain socket + * + * Copyright 2011, 2018 Yuya Nishihara <yuya@tcha.org> + * + * This software may be used and distributed according to the terms of the + * GNU General Public License version 2 or any later version. + */ + +#include <errno.h> +#include <stdlib.h> +#include <string.h> +#include <sys/socket.h> +#include <sys/types.h> + +#define MAX_FD_LEN 10 + +/* + * Sends the given fds with 1-byte dummy payload. + * + * Returns the number of bytes sent on success, -1 on error and errno is set + * appropriately. + */ +ssize_t sendfds(int sockfd, const int *fds, size_t fdlen) +{ + char dummy[1] = {0}; + struct iovec iov = {dummy, sizeof(dummy)}; + char fdbuf[CMSG_SPACE(sizeof(fds[0]) * MAX_FD_LEN)]; + struct msghdr msgh; + struct cmsghdr *cmsg; + + /* just use a fixed-size buffer since we'll never send tons of fds */ + if (fdlen > MAX_FD_LEN) { + errno = EINVAL; + return -1; + } + + memset(&msgh, 0, sizeof(msgh)); + msgh.msg_iov = &iov; + msgh.msg_iovlen = 1; + msgh.msg_control = fdbuf; + msgh.msg_controllen = CMSG_SPACE(sizeof(fds[0]) * fdlen); + + cmsg = CMSG_FIRSTHDR(&msgh); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_RIGHTS; + cmsg->cmsg_len = CMSG_LEN(sizeof(fds[0]) * fdlen); + memcpy(CMSG_DATA(cmsg), fds, sizeof(fds[0]) * fdlen); + msgh.msg_controllen = cmsg->cmsg_len; + return sendmsg(sockfd, &msgh, 0); +}