Client-side library for big sockets.
[vsys-wrappers.git] / fuse / fdpass.c
1 // Modified version of library functions in FUSE
2 //
3
4 #include <assert.h>
5 #include <errno.h>
6 #include <fcntl.h>
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <sys/mount.h>
10 #include <sys/socket.h>
11 #include <sys/un.h>
12
13 int send_fd(int sock_fd, int fd)
14 {
15         int retval;
16         struct msghdr msg;
17         struct cmsghdr *p_cmsg;
18         struct iovec vec;
19         size_t cmsgbuf[CMSG_SPACE(sizeof(fd)) / sizeof(size_t)];
20         int *p_fds;
21         char sendchar = 0;
22
23         msg.msg_control = cmsgbuf;
24         msg.msg_controllen = sizeof(cmsgbuf);
25         p_cmsg = CMSG_FIRSTHDR(&msg);
26         p_cmsg->cmsg_level = SOL_SOCKET;
27         p_cmsg->cmsg_type = SCM_RIGHTS;
28         p_cmsg->cmsg_len = CMSG_LEN(sizeof(fd));
29         p_fds = (int *) CMSG_DATA(p_cmsg);
30         *p_fds = fd;
31         msg.msg_controllen = p_cmsg->cmsg_len;
32         msg.msg_name = NULL;
33         msg.msg_namelen = 0;
34         msg.msg_iov = &vec;
35         msg.msg_iovlen = 1;
36         msg.msg_flags = 0;
37         /* "To pass file descriptors or credentials you need to send/read at
38          * least one byte" (man 7 unix) */
39         vec.iov_base = &sendchar;
40         vec.iov_len = sizeof(sendchar);
41         while ((retval = sendmsg(sock_fd, &msg, 0)) == -1 && errno == EINTR);
42         if (retval != 1) {
43                 perror("sending file descriptor");
44                 return -1;
45         }
46         return 0;
47 }
48
49
50 /* return value:
51  * >= 0  => fd
52  * -1    => error
53  */
54 int receive_fd(int fd)
55 {
56         struct msghdr msg;
57         struct iovec iov;
58         char buf[1];
59         int rv;
60         size_t ccmsg[CMSG_SPACE(sizeof(int)) / sizeof(size_t)];
61         struct cmsghdr *cmsg;
62
63         iov.iov_base = buf;
64         iov.iov_len = 1;
65
66         msg.msg_name = 0;
67         msg.msg_namelen = 0;
68         msg.msg_iov = &iov;
69         msg.msg_iovlen = 1;
70         /* old BSD implementations should use msg_accrights instead of
71          * msg_control; the interface is different. */
72         msg.msg_control = ccmsg;
73         msg.msg_controllen = sizeof(ccmsg);
74
75         while(((rv = recvmsg(fd, &msg, 0)) == -1) && errno == EINTR);
76         if (rv == -1) {
77                 perror("recvmsg");
78                 return -1;
79         }
80         if(!rv) {
81                 /* EOF */
82                 return -1;
83         }
84
85         cmsg = CMSG_FIRSTHDR(&msg);
86         if (!cmsg->cmsg_type == SCM_RIGHTS) {
87                 fprintf(stderr, "got control message of unknown type %d\n",
88                         cmsg->cmsg_type);
89                 return -1;
90         }
91         return *(int*)CMSG_DATA(cmsg);
92 }
93