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