blob: 787c4489d3ee57e236a455349e977104b8731a64 [file] [log] [blame]
Miklos Szeredi0f48a262002-12-05 14:23:01 +00001/*
2 FUSE: Filesystem in Userspace
Miklos Szeredi149f6072005-01-10 12:29:28 +00003 Copyright (C) 2001-2005 Miklos Szeredi <miklos@szeredi.hu>
Miklos Szeredi0f48a262002-12-05 14:23:01 +00004
5 This program can be distributed under the terms of the GNU LGPL.
6 See the file COPYING.LIB.
7*/
8
9#include "fuse.h"
Miklos Szeredi0b6a0ad2004-12-04 00:40:50 +000010#include "fuse_compat.h"
Miklos Szeredi0f48a262002-12-05 14:23:01 +000011
12#include <stdio.h>
13#include <stdlib.h>
14#include <unistd.h>
15#include <fcntl.h>
16#include <errno.h>
17#include <sys/socket.h>
18#include <sys/un.h>
19#include <sys/wait.h>
20
21#define FUSERMOUNT_PROG "fusermount"
22#define FUSE_COMMFD_ENV "_FUSE_COMMFD"
23
24
25/* return value:
26 * >= 0 => fd
27 * -1 => error
28 */
29static int receive_fd(int fd)
30{
31 struct msghdr msg;
32 struct iovec iov;
33 char buf[1];
34 int rv;
35 int connfd = -1;
36 char ccmsg[CMSG_SPACE(sizeof(connfd))];
37 struct cmsghdr *cmsg;
38
39 iov.iov_base = buf;
40 iov.iov_len = 1;
41
42 msg.msg_name = 0;
43 msg.msg_namelen = 0;
44 msg.msg_iov = &iov;
45 msg.msg_iovlen = 1;
46 /* old BSD implementations should use msg_accrights instead of
47 * msg_control; the interface is different. */
48 msg.msg_control = ccmsg;
49 msg.msg_controllen = sizeof(ccmsg);
50
51 while(((rv = recvmsg(fd, &msg, 0)) == -1) && errno == EINTR);
52 if (rv == -1) {
53 perror("recvmsg");
54 return -1;
55 }
56 if(!rv) {
57 /* EOF */
58 return -1;
59 }
Miklos Szeredie5183742005-02-02 11:14:04 +000060
Miklos Szeredi0f48a262002-12-05 14:23:01 +000061 cmsg = CMSG_FIRSTHDR(&msg);
62 if (!cmsg->cmsg_type == SCM_RIGHTS) {
63 fprintf(stderr, "got control message of unknown type %d\n",
64 cmsg->cmsg_type);
65 return -1;
66 }
67 return *(int*)CMSG_DATA(cmsg);
68}
69
70void fuse_unmount(const char *mountpoint)
71{
72 const char *mountprog = FUSERMOUNT_PROG;
Miklos Szeredi832ee442005-11-18 21:02:36 +000073 int pid;
Miklos Szeredie5183742005-02-02 11:14:04 +000074
Miklos Szeredi832ee442005-11-18 21:02:36 +000075#ifdef HAVE_FORK
76 pid = fork();
77#else
78 pid = vfork();
79#endif
80 if(pid == -1)
81 return;
Miklos Szeredie5183742005-02-02 11:14:04 +000082
Miklos Szeredi832ee442005-11-18 21:02:36 +000083 if(pid == 0) {
84 const char *argv[32];
85 int a = 0;
86
87 argv[a++] = mountprog;
88 argv[a++] = "-u";
89 argv[a++] = "-q";
90 argv[a++] = "-z";
91 argv[a++] = "--";
92 argv[a++] = mountpoint;
93 argv[a++] = NULL;
94
95 execvp(mountprog, (char **) argv);
96 exit(1);
97 }
98 waitpid(pid, NULL, 0);
Miklos Szeredi0f48a262002-12-05 14:23:01 +000099}
100
Miklos Szeredibd7661b2004-07-23 17:16:29 +0000101int fuse_mount(const char *mountpoint, const char *opts)
Miklos Szeredi0f48a262002-12-05 14:23:01 +0000102{
103 const char *mountprog = FUSERMOUNT_PROG;
104 int fds[2], pid;
105 int res;
106 int rv;
107
Miklos Szeredibcc53852005-11-10 09:54:41 +0000108 if (!mountpoint) {
109 fprintf(stderr, "fuse: missing mountpoint\n");
110 return -1;
111 }
112
Miklos Szeredi0f48a262002-12-05 14:23:01 +0000113 res = socketpair(PF_UNIX, SOCK_STREAM, 0, fds);
114 if(res == -1) {
115 perror("fuse: socketpair() failed");
116 return -1;
117 }
118
Miklos Szeredi35200932005-09-28 14:50:49 +0000119#ifdef HAVE_FORK
Miklos Szeredi0f48a262002-12-05 14:23:01 +0000120 pid = fork();
Miklos Szeredia25d4c22004-11-23 22:32:16 +0000121#else
122 pid = vfork();
123#endif
Miklos Szeredi0f48a262002-12-05 14:23:01 +0000124 if(pid == -1) {
125 perror("fuse: fork() failed");
126 close(fds[0]);
127 close(fds[1]);
128 return -1;
129 }
130
131 if(pid == 0) {
132 char env[10];
Miklos Szeredi9b813af2005-07-21 07:59:37 +0000133 const char *argv[32];
134 int a = 0;
Miklos Szeredif6e0ec62005-08-03 09:11:06 +0000135
Miklos Szeredi9b813af2005-07-21 07:59:37 +0000136 argv[a++] = mountprog;
137 if (opts) {
138 argv[a++] = "-o";
139 argv[a++] = opts;
140 }
141 argv[a++] = "--";
142 argv[a++] = mountpoint;
143 argv[a++] = NULL;
Miklos Szeredi0f48a262002-12-05 14:23:01 +0000144
145 close(fds[1]);
146 fcntl(fds[0], F_SETFD, 0);
147 snprintf(env, sizeof(env), "%i", fds[0]);
148 setenv(FUSE_COMMFD_ENV, env, 1);
Miklos Szeredibd7661b2004-07-23 17:16:29 +0000149 execvp(mountprog, (char **) argv);
Miklos Szeredi0f48a262002-12-05 14:23:01 +0000150 perror("fuse: failed to exec fusermount");
151 exit(1);
152 }
153
154 close(fds[0]);
155 rv = receive_fd(fds[1]);
156 close(fds[1]);
157 waitpid(pid, NULL, 0); /* bury zombie */
158
159 return rv;
160}
Miklos Szeredi0b6a0ad2004-12-04 00:40:50 +0000161
Miklos Szeredif458b8c2004-12-07 16:46:42 +0000162int fuse_mount_compat1(const char *mountpoint, const char *args[])
Miklos Szeredi0b6a0ad2004-12-04 00:40:50 +0000163{
164 /* just ignore mount args for now */
165 (void) args;
166 return fuse_mount(mountpoint, NULL);
167}