blob: f7a5299949639ab8cfaa349fe07ac7b9a58f8225 [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;
73 char umount_cmd[1024];
Miklos Szeredie5183742005-02-02 11:14:04 +000074
Miklos Szeredi9b813af2005-07-21 07:59:37 +000075 snprintf(umount_cmd, sizeof(umount_cmd) - 1, "%s -u -q -z -- %s",
76 mountprog, mountpoint);
Miklos Szeredie5183742005-02-02 11:14:04 +000077
Miklos Szeredi0f48a262002-12-05 14:23:01 +000078 umount_cmd[sizeof(umount_cmd) - 1] = '\0';
79 system(umount_cmd);
80}
81
Miklos Szeredibd7661b2004-07-23 17:16:29 +000082int fuse_mount(const char *mountpoint, const char *opts)
Miklos Szeredi0f48a262002-12-05 14:23:01 +000083{
84 const char *mountprog = FUSERMOUNT_PROG;
85 int fds[2], pid;
86 int res;
87 int rv;
88
89 res = socketpair(PF_UNIX, SOCK_STREAM, 0, fds);
90 if(res == -1) {
91 perror("fuse: socketpair() failed");
92 return -1;
93 }
94
Miklos Szeredi35200932005-09-28 14:50:49 +000095#ifdef HAVE_FORK
Miklos Szeredi0f48a262002-12-05 14:23:01 +000096 pid = fork();
Miklos Szeredia25d4c22004-11-23 22:32:16 +000097#else
98 pid = vfork();
99#endif
Miklos Szeredi0f48a262002-12-05 14:23:01 +0000100 if(pid == -1) {
101 perror("fuse: fork() failed");
102 close(fds[0]);
103 close(fds[1]);
104 return -1;
105 }
106
107 if(pid == 0) {
108 char env[10];
Miklos Szeredi9b813af2005-07-21 07:59:37 +0000109 const char *argv[32];
110 int a = 0;
Miklos Szeredif6e0ec62005-08-03 09:11:06 +0000111
Miklos Szeredi9b813af2005-07-21 07:59:37 +0000112 argv[a++] = mountprog;
113 if (opts) {
114 argv[a++] = "-o";
115 argv[a++] = opts;
116 }
117 argv[a++] = "--";
118 argv[a++] = mountpoint;
119 argv[a++] = NULL;
Miklos Szeredi0f48a262002-12-05 14:23:01 +0000120
121 close(fds[1]);
122 fcntl(fds[0], F_SETFD, 0);
123 snprintf(env, sizeof(env), "%i", fds[0]);
124 setenv(FUSE_COMMFD_ENV, env, 1);
Miklos Szeredibd7661b2004-07-23 17:16:29 +0000125 execvp(mountprog, (char **) argv);
Miklos Szeredi0f48a262002-12-05 14:23:01 +0000126 perror("fuse: failed to exec fusermount");
127 exit(1);
128 }
129
130 close(fds[0]);
131 rv = receive_fd(fds[1]);
132 close(fds[1]);
133 waitpid(pid, NULL, 0); /* bury zombie */
134
135 return rv;
136}
Miklos Szeredi0b6a0ad2004-12-04 00:40:50 +0000137
Miklos Szeredif458b8c2004-12-07 16:46:42 +0000138int fuse_mount_compat1(const char *mountpoint, const char *args[])
Miklos Szeredi0b6a0ad2004-12-04 00:40:50 +0000139{
140 /* just ignore mount args for now */
141 (void) args;
142 return fuse_mount(mountpoint, NULL);
143}