view rust/chg/src/sendfds.c @ 42977:699102b10530

histedit: sniff-test for untracked file conflicts before prompting for rules This bug is as old as histedit, which is more than 10 years! I'm a little sad about the extra calculations here that we're just going to throw out, but I don't see any better way to look for untracked file conflicts and I want the bug fixed. Differential Revision: https://phab.mercurial-scm.org/D6882
author Augie Fackler <augie@google.com>
date Wed, 25 Sep 2019 13:50:48 -0400
parents 208cb7a9d0fa
children
line wrap: on
line source

/*
 * 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);
}