File Coverage

c/fdpass.c
Criterion Covered Total %
statement 45 46 97.8
branch 11 16 68.7
condition n/a
subroutine n/a
pod n/a
total 56 62 90.3


line stmt bran cond sub pod time code
1             /* File descriptor passing based on
2             * https://manned.org/man.c2c6968a/cmsg.3 */
3              
4 2           static ssize_t fufdpass_send(int socket, int fd, const char *buf, size_t buflen) {
5             union {
6             char buf[CMSG_SPACE(sizeof(int))];
7             struct cmsghdr align;
8 2           } cmsgbuf = {};
9              
10             struct iovec iov;
11 2           iov.iov_base = (char *)buf;
12 2           iov.iov_len = buflen;
13              
14             struct msghdr msg;
15 2           msg.msg_name = NULL;
16 2           msg.msg_namelen = 0;
17 2           msg.msg_iov = &iov;
18 2           msg.msg_iovlen = 1;
19 2           msg.msg_control = cmsgbuf.buf;
20 2           msg.msg_controllen = sizeof(cmsgbuf.buf);
21 2           msg.msg_flags = 0;
22              
23 2 50         struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
24 2           cmsg->cmsg_level = SOL_SOCKET;
25 2           cmsg->cmsg_type = SCM_RIGHTS;
26 2           cmsg->cmsg_len = CMSG_LEN(sizeof(int));
27 2           memcpy(CMSG_DATA(cmsg), &fd, sizeof(int));
28              
29 2           return sendmsg(socket, &msg, 0);
30             }
31              
32 4           static int fufdpass_recv(pTHX_ I32 ax, int socket, size_t len) {
33 4 50         if (GIMME_V != G_LIST)
34 0           fu_confess("Invalid use of fdpass_recv() in scalar context");
35              
36             union {
37             char buf[CMSG_SPACE(sizeof(int))];
38             struct cmsghdr align;
39             } cmsgbuf;
40              
41 4           SV *buf = sv_2mortal(newSV(len));
42 4           SvPOK_only(buf);
43             struct iovec iov;
44 4           iov.iov_base = SvPVX(buf);
45 4           iov.iov_len = len;
46              
47             struct msghdr msg;
48 4           msg.msg_name = NULL;
49 4           msg.msg_namelen = 0;
50 4           msg.msg_iov = &iov;
51 4           msg.msg_iovlen = 1;
52 4           msg.msg_control = cmsgbuf.buf;
53 4           msg.msg_controllen = sizeof(cmsgbuf.buf);
54 4           msg.msg_flags = 0;
55              
56 4           ssize_t r = recvmsg(socket, &msg, MSG_CMSG_CLOEXEC);
57 4 100         if (r < 0) {
58 1           ST(0) = &PL_sv_undef;
59 1           ST(1) = &PL_sv_undef;
60 1           return 2;
61             }
62              
63 3 100         struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
64 3 100         if (cmsg == NULL || cmsg->cmsg_level != SOL_SOCKET
    50          
65 1 50         || cmsg->cmsg_type != SCM_RIGHTS || cmsg->cmsg_len != CMSG_LEN(sizeof(int))) {
    50          
66 2           ST(0) = &PL_sv_undef;
67             } else {
68             int fd;
69 1           memcpy(&fd, CMSG_DATA(cmsg), sizeof(int));
70 1           ST(0) = sv_2mortal(newSViv(fd));
71             }
72              
73 3           SvCUR_set(buf, r);
74 3           SvPVX(buf)[r] = 0;
75 3           ST(1) = buf;
76 3           return 2;
77             }