This repository is to contain libraries that will let privilege-demanding application...
[vsys-wrappers.git] / fuse / stolen_from_fuse.c.orig
1 #include <assert.h>
2 #include <errno.h>
3 #include <fcntl.h>
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <sys/mount.h>
7 #include <sys/socket.h>
8 #include <sys/un.h>
9 #include "stolen_from_fuse.h"
10
11 // Most of this code is stolen from FUSE 2.7.4
12
13 int rrm_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 rrm_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
94 int rrm_fuse_mnt_umount(const char *progname, const char *mnt, int lazy)
95 {
96         int res;
97         int status;
98         
99         res = umount2(mnt, lazy ? 2 : 0);
100         if (res == -1)
101           fprintf(stderr, "%s: failed to unmount %s: %s\n",
102                   progname, mnt, strerror(errno));
103         return res;
104
105 }
106
107 static int rrm_try_open(const char *dev, char **devp, int silent)
108 {
109         int fd = open(dev, O_RDWR);
110         if (fd != -1) {
111                 *devp = strdup(dev);
112                 if (*devp == NULL) {
113                   fprintf(stderr, "failed to allocate memory\n" );
114                                 
115                         close(fd);
116                         fd = -1;
117                 }
118         } else if (errno == ENODEV ||
119                    errno == ENOENT)/* check for ENOENT too, for the udev case */
120                 return -2;
121         else if (!silent) {
122                 fprintf(stderr, "failed to open %s: %s\n", dev,
123                         strerror(errno));
124         }
125         return fd;
126 }
127
128 static int rrm_try_open_fuse_device(char **devp)
129 {
130         int fd;
131         int err;
132
133         //drop_privs();
134         fd = rrm_try_open(FUSE_DEV_NEW, devp, 0);
135         //restore_privs();
136         if (fd >= 0)
137                 return fd;
138
139         err = fd;
140         fd = rrm_try_open(FUSE_DEV_OLD, devp, 1);
141         if (fd >= 0)
142                 return fd;
143
144         return err;
145 }
146
147 int rrm_open_fuse_device(char **devp)
148 {
149         int fd = rrm_try_open_fuse_device(devp);
150         if (fd >= -1)
151                 return fd;
152
153         fprintf(stderr,
154                 "fuse device not found, try 'modprobe fuse' first\n");
155
156         return -1;
157 }