libfuse: fuse-3.2.1/util/mount.fuse.c Source File

libfuse

mount.fuse.c
1 /*
2 FUSE: Filesystem in Userspace
3 Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
4
5 This program can be distributed under the terms of the GNU GPL.
6 See the file COPYING.
7 */
8
9 #include <config.h>
10
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include <unistd.h>
15 #include <errno.h>
16
17 static char *progname;
18
19 static char *xstrdup(const char *s)
20 {
21 char *t = strdup(s);
22 if (!t) {
23 fprintf(stderr, "%s: failed to allocate memory\n", progname);
24 exit(1);
25 }
26 return t;
27 }
28
29 static void *xrealloc(void *oldptr, size_t size)
30 {
31 void *ptr = realloc(oldptr, size);
32 if (!ptr) {
33 fprintf(stderr, "%s: failed to allocate memory\n", progname);
34 exit(1);
35 }
36 return ptr;
37 }
38
39 static void add_arg(char **cmdp, const char *opt)
40 {
41 size_t optlen = strlen(opt);
42 size_t cmdlen = *cmdp ? strlen(*cmdp) : 0;
43 char *cmd = xrealloc(*cmdp, cmdlen + optlen * 4 + 4);
44 char *s;
45 s = cmd + cmdlen;
46 if (*cmdp)
47 *s++ = ' ';
48
49 *s++ = '\'';
50 for (; *opt; opt++) {
51 if (*opt == '\'') {
52 *s++ = '\'';
53 *s++ = '\\';
54 *s++ = '\'';
55 *s++ = '\'';
56 } else
57 *s++ = *opt;
58 }
59 *s++ = '\'';
60 *s = '\0';
61 *cmdp = cmd;
62 }
63
64 static char *add_option(const char *opt, char *options)
65 {
66 int oldlen = options ? strlen(options) : 0;
67
68 options = xrealloc(options, oldlen + 1 + strlen(opt) + 1);
69 if (!oldlen)
70 strcpy(options, opt);
71 else {
72 strcat(options, ",");
73 strcat(options, opt);
74 }
75 return options;
76 }
77
78 int main(int argc, char *argv[])
79 {
80 char *type = NULL;
81 char *source;
82 const char *mountpoint;
83 char *basename;
84 char *options = NULL;
85 char *command = NULL;
86 char *setuid = NULL;
87 int i;
88 int dev = 1;
89 int suid = 1;
90
91 progname = argv[0];
92 basename = strrchr(argv[0], '/');
93 if (basename)
94 basename++;
95 else
96 basename = argv[0];
97
98 if (strncmp(basename, "mount.fuse.", 11) == 0)
99 type = basename + 11;
100 if (strncmp(basename, "mount.fuseblk.", 14) == 0)
101 type = basename + 14;
102
103 if (type && !type[0])
104 type = NULL;
105
106 if (argc < 3) {
107 fprintf(stderr,
108 "usage: %s %s destination [-t type] [-o opt[,opts...]]\n",
109 progname, type ? "source" : "type#[source]");
110 exit(1);
111 }
112
113 source = argv[1];
114 if (!source[0])
115 source = NULL;
116
117 mountpoint = argv[2];
118
119 for (i = 3; i < argc; i++) {
120 if (strcmp(argv[i], "-v") == 0) {
121 continue;
122 } else if (strcmp(argv[i], "-t") == 0) {
123 i++;
124
125 if (i == argc) {
126 fprintf(stderr,
127 "%s: missing argument to option '-t'\n",
128 progname);
129 exit(1);
130 }
131 type = argv[i];
132 if (strncmp(type, "fuse.", 5) == 0)
133 type += 5;
134 else if (strncmp(type, "fuseblk.", 8) == 0)
135 type += 8;
136
137 if (!type[0]) {
138 fprintf(stderr,
139 "%s: empty type given as argument to option '-t'\n",
140 progname);
141 exit(1);
142 }
143 } else if (strcmp(argv[i], "-o") == 0) {
144 char *opts;
145 char *opt;
146 i++;
147 if (i == argc)
148 break;
149
150 opts = xstrdup(argv[i]);
151 opt = strtok(opts, ",");
152 while (opt) {
153 int j;
154 int ignore = 0;
155 const char *ignore_opts[] = { "",
156 "user",
157 "nouser",
158 "users",
159 "auto",
160 "noauto",
161 "_netdev",
162 NULL};
163 if (strncmp(opt, "setuid=", 7) == 0) {
164 setuid = xstrdup(opt + 7);
165 ignore = 1;
166 }
167 for (j = 0; ignore_opts[j]; j++)
168 if (strcmp(opt, ignore_opts[j]) == 0)
169 ignore = 1;
170
171 if (!ignore) {
172 if (strcmp(opt, "nodev") == 0)
173 dev = 0;
174 else if (strcmp(opt, "nosuid") == 0)
175 suid = 0;
176
177 options = add_option(opt, options);
178 }
179 opt = strtok(NULL, ",");
180 }
181 }
182 }
183
184 if (dev)
185 options = add_option("dev", options);
186 if (suid)
187 options = add_option("suid", options);
188
189 if (!type) {
190 if (source) {
191 type = xstrdup(source);
192 source = strchr(type, '#');
193 if (source)
194 *source++ = '\0';
195 if (!type[0]) {
196 fprintf(stderr, "%s: empty filesystem type\n",
197 progname);
198 exit(1);
199 }
200 } else {
201 fprintf(stderr, "%s: empty source\n", progname);
202 exit(1);
203 }
204 }
205
206 add_arg(&command, type);
207 if (source)
208 add_arg(&command, source);
209 add_arg(&command, mountpoint);
210 if (options) {
211 add_arg(&command, "-o");
212 add_arg(&command, options);
213 }
214
215 if (setuid && setuid[0]) {
216 char *sucommand = command;
217 command = NULL;
218 add_arg(&command, "su");
219 add_arg(&command, "-");
220 add_arg(&command, setuid);
221 add_arg(&command, "-c");
222 add_arg(&command, sucommand);
223 } else if (!getenv("HOME")) {
224 /* Hack to make filesystems work in the boot environment */
225 setenv("HOME", "/root", 0);
226 }
227
228 execl("/bin/sh", "/bin/sh", "-c", command, NULL);
229 fprintf(stderr, "%s: failed to execute /bin/sh: %s\n", progname,
230 strerror(errno));
231 return 1;
232 }