Allow IPv6 address entry in tools>ping - Loosens valid character check
[tomato/davidwu.git] / release / src / router / ntfs-3g / libfuse-lite / mount_util.c
blob724a042dc5f3497de7d0ff34646360e46f3bfc4a
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 LGPLv2.
6 See the file COPYING.LIB.
7 */
9 #include "config.h"
10 #include "mount_util.h"
11 #include <stdio.h>
12 #include <unistd.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <dirent.h>
16 #include <errno.h>
17 #include <limits.h>
18 #include <sys/stat.h>
19 #include <sys/wait.h>
20 #ifdef __SOLARIS__
21 #else /* __SOLARIS__ */
22 #include <mntent.h>
23 #include <sys/mount.h>
24 #include <sys/param.h>
25 #endif /* __SOLARIS__ */
27 #ifdef __SOLARIS__
29 char *mkdtemp(char *template);
31 #ifndef _PATH_MOUNTED
32 #define _PATH_MOUNTED "/etc/mnttab"
33 #endif /* _PATH_MOUNTED */
35 #ifndef IGNORE_MTAB
36 static int mtab_needs_update(const char *mnt)
38 struct stat stbuf;
40 /* If mtab is within new mount, don't touch it */
41 if (strncmp(mnt, _PATH_MOUNTED, strlen(mnt)) == 0 &&
42 _PATH_MOUNTED[strlen(mnt)] == '/')
43 return 0;
45 if (lstat(_PATH_MOUNTED, &stbuf) != -1 && S_ISLNK(stbuf.st_mode))
46 return 0;
48 return 1;
50 #endif /* IGNORE_MTAB */
52 int fuse_mnt_add_mount(const char *progname, const char *fsname,
53 const char *mnt, const char *type, const char *opts)
55 int res;
56 int status;
58 #ifndef IGNORE_MTAB
59 if (!mtab_needs_update(mnt))
60 return 0;
61 #endif /* IGNORE_MTAB */
63 res = fork();
64 if (res == -1) {
65 fprintf(stderr, "%s: fork: %s\n", progname, strerror(errno));
66 return -1;
68 if (res == 0) {
69 char templ[] = "/tmp/fusermountXXXXXX";
70 char *tmp;
72 setuid(geteuid());
74 /*
75 * hide in a directory, where mount isn't able to resolve
76 * fsname as a valid path
78 tmp = mkdtemp(templ);
79 if (!tmp) {
80 fprintf(stderr, "%s: failed to create temporary directory\n",
81 progname);
82 exit(1);
84 if (chdir(tmp)) {
85 fprintf(stderr, "%s: failed to chdir to %s: %s\n",
86 progname, tmp, strerror(errno));
87 exit(1);
89 rmdir(tmp);
90 execl("/sbin/mount", "/sbin/mount", "-F", type, "-o", opts,
91 fsname, mnt, NULL);
92 fprintf(stderr, "%s: failed to execute /sbin/mount: %s\n", progname,
93 strerror(errno));
94 exit(1);
96 res = waitpid(res, &status, 0);
97 if (res == -1) {
98 fprintf(stderr, "%s: waitpid: %s\n", progname, strerror(errno));
99 return -1;
101 if (status != 0)
102 return -1;
104 return 0;
107 int fuse_mnt_umount(const char *progname, const char *mnt, int lazy)
109 int res;
110 int status;
112 #ifndef IGNORE_MTAB
113 if (!mtab_needs_update(mnt))
114 return 0;
115 #endif /* IGNORE_MTAB */
117 res = fork();
118 if (res == -1) {
119 fprintf(stderr, "%s: fork: %s\n", progname, strerror(errno));
120 return -1;
122 if (res == 0) {
123 setuid(geteuid());
124 execl("/sbin/umount", "/sbin/umount", !lazy ? "-f" : NULL, mnt,
125 NULL);
126 fprintf(stderr, "%s: failed to execute /sbin/umount: %s\n", progname,
127 strerror(errno));
128 exit(1);
130 res = waitpid(res, &status, 0);
131 if (res == -1) {
132 fprintf(stderr, "%s: waitpid: %s\n", progname, strerror(errno));
133 return -1;
135 if (status != 0)
136 return -1;
138 return 0;
141 char *fuse_mnt_resolve_path(const char *progname, const char *orig)
143 char buf[PATH_MAX];
144 char *copy;
145 char *dst;
146 char *end;
147 char *lastcomp;
148 const char *toresolv;
150 if (!orig[0]) {
151 fprintf(stderr, "%s: invalid mountpoint '%s'\n", progname, orig);
152 return NULL;
155 copy = strdup(orig);
156 if (copy == NULL) {
157 fprintf(stderr, "%s: failed to allocate memory\n", progname);
158 return NULL;
161 toresolv = copy;
162 lastcomp = NULL;
163 for (end = copy + strlen(copy) - 1; end > copy && *end == '/'; end --);
164 if (end[0] != '/') {
165 char *tmp;
166 end[1] = '\0';
167 tmp = strrchr(copy, '/');
168 if (tmp == NULL) {
169 lastcomp = copy;
170 toresolv = ".";
171 } else {
172 lastcomp = tmp + 1;
173 if (tmp == copy)
174 toresolv = "/";
176 if (strcmp(lastcomp, ".") == 0 || strcmp(lastcomp, "..") == 0) {
177 lastcomp = NULL;
178 toresolv = copy;
180 else if (tmp)
181 tmp[0] = '\0';
183 if (realpath(toresolv, buf) == NULL) {
184 fprintf(stderr, "%s: bad mount point %s: %s\n", progname, orig,
185 strerror(errno));
186 free(copy);
187 return NULL;
189 if (lastcomp == NULL)
190 dst = strdup(buf);
191 else {
192 dst = (char *) malloc(strlen(buf) + 1 + strlen(lastcomp) + 1);
193 if (dst) {
194 unsigned buflen = strlen(buf);
195 if (buflen && buf[buflen-1] == '/')
196 sprintf(dst, "%s%s", buf, lastcomp);
197 else
198 sprintf(dst, "%s/%s", buf, lastcomp);
201 free(copy);
202 if (dst == NULL)
203 fprintf(stderr, "%s: failed to allocate memory\n", progname);
204 return dst;
207 int fuse_mnt_check_empty(const char *progname, const char *mnt,
208 mode_t rootmode, off_t rootsize)
210 int isempty = 1;
212 if (S_ISDIR(rootmode)) {
213 struct dirent *ent;
214 DIR *dp = opendir(mnt);
215 if (dp == NULL) {
216 fprintf(stderr, "%s: failed to open mountpoint for reading: %s\n",
217 progname, strerror(errno));
218 return -1;
220 while ((ent = readdir(dp)) != NULL) {
221 if (strcmp(ent->d_name, ".") != 0 &&
222 strcmp(ent->d_name, "..") != 0) {
223 isempty = 0;
224 break;
227 closedir(dp);
228 } else if (rootsize)
229 isempty = 0;
231 if (!isempty) {
232 fprintf(stderr, "%s: mountpoint is not empty\n", progname);
233 fprintf(stderr, "%s: if you are sure this is safe, use the 'nonempty' mount option\n", progname);
234 return -1;
236 return 0;
239 int fuse_mnt_check_fuseblk(void)
241 char buf[256];
242 FILE *f = fopen("/proc/filesystems", "r");
243 if (!f)
244 return 1;
246 while (fgets(buf, sizeof(buf), f))
247 if (strstr(buf, "fuseblk\n")) {
248 fclose(f);
249 return 1;
252 fclose(f);
253 return 0;
256 #else /* __SOLARIS__ */
258 static int mtab_needs_update(const char *mnt)
260 int res;
261 struct stat stbuf;
263 /* If mtab is within new mount, don't touch it */
264 if (strncmp(mnt, _PATH_MOUNTED, strlen(mnt)) == 0 &&
265 _PATH_MOUNTED[strlen(mnt)] == '/')
266 return 0;
269 * Skip mtab update if /etc/mtab:
271 * - doesn't exist,
272 * - is a symlink,
273 * - is on a read-only filesystem.
275 res = lstat(_PATH_MOUNTED, &stbuf);
276 if (res == -1) {
277 if (errno == ENOENT)
278 return 0;
279 } else {
280 if (S_ISLNK(stbuf.st_mode))
281 return 0;
283 res = access(_PATH_MOUNTED, W_OK);
284 if (res == -1 && errno == EROFS)
285 return 0;
288 return 1;
291 int fuse_mnt_add_mount(const char *progname, const char *fsname,
292 const char *mnt, const char *type, const char *opts)
294 int res;
296 if (!mtab_needs_update(mnt))
297 return 0;
299 res = fork();
300 if (res == -1) {
301 fprintf(stderr, "%s: fork: %s\n", progname, strerror(errno));
302 return 0;
304 if (res == 0) {
305 char templ[] = "/tmp/fusermountXXXXXX";
306 char *tmp;
308 setuid(geteuid());
311 * hide in a directory, where mount isn't able to resolve
312 * fsname as a valid path
314 tmp = mkdtemp(templ);
315 if (!tmp) {
316 fprintf(stderr, "%s: failed to create temporary directory\n",
317 progname);
318 exit(1);
320 if (chdir(tmp)) {
321 fprintf(stderr, "%s: failed to chdir to %s: %s\n",
322 progname, tmp, strerror(errno));
323 exit(1);
325 rmdir(tmp);
326 execl("/bin/mount", "/bin/mount", "-i", "-f", "-t", type, "-o", opts,
327 fsname, mnt, NULL);
328 fprintf(stderr, "%s: failed to execute /bin/mount: %s\n", progname,
329 strerror(errno));
330 exit(1);
332 return 0;
335 int fuse_mnt_umount(const char *progname, const char *mnt, int lazy)
337 int res;
338 int status;
340 if (!mtab_needs_update(mnt)) {
341 res = umount2(mnt, lazy ? 2 : 0);
342 if (res == -1)
343 fprintf(stderr, "%s: failed to unmount %s: %s\n", progname,
344 mnt, strerror(errno));
345 return res;
348 res = fork();
349 if (res == -1) {
350 fprintf(stderr, "%s: fork: %s\n", progname, strerror(errno));
351 return -1;
353 if (res == 0) {
354 setuid(geteuid());
355 execl("/bin/umount", "/bin/umount", "-i", mnt, lazy ? "-l" : NULL,
356 NULL);
357 fprintf(stderr, "%s: failed to execute /bin/umount: %s\n", progname,
358 strerror(errno));
359 exit(1);
361 res = waitpid(res, &status, 0);
362 if (res == -1) {
363 fprintf(stderr, "%s: waitpid: %s\n", progname, strerror(errno));
364 return -1;
366 if (status != 0)
367 return -1;
369 return 0;
372 char *fuse_mnt_resolve_path(const char *progname, const char *orig)
374 char buf[PATH_MAX];
375 char *copy;
376 char *dst;
377 char *end;
378 char *lastcomp;
379 const char *toresolv;
381 if (!orig[0]) {
382 fprintf(stderr, "%s: invalid mountpoint '%s'\n", progname, orig);
383 return NULL;
386 copy = strdup(orig);
387 if (copy == NULL) {
388 fprintf(stderr, "%s: failed to allocate memory\n", progname);
389 return NULL;
392 toresolv = copy;
393 lastcomp = NULL;
394 for (end = copy + strlen(copy) - 1; end > copy && *end == '/'; end --);
395 if (end[0] != '/') {
396 char *tmp;
397 end[1] = '\0';
398 tmp = strrchr(copy, '/');
399 if (tmp == NULL) {
400 lastcomp = copy;
401 toresolv = ".";
402 } else {
403 lastcomp = tmp + 1;
404 if (tmp == copy)
405 toresolv = "/";
407 if (strcmp(lastcomp, ".") == 0 || strcmp(lastcomp, "..") == 0) {
408 lastcomp = NULL;
409 toresolv = copy;
411 else if (tmp)
412 tmp[0] = '\0';
414 if (realpath(toresolv, buf) == NULL) {
415 fprintf(stderr, "%s: bad mount point %s: %s\n", progname, orig,
416 strerror(errno));
417 free(copy);
418 return NULL;
420 if (lastcomp == NULL)
421 dst = strdup(buf);
422 else {
423 dst = (char *) malloc(strlen(buf) + 1 + strlen(lastcomp) + 1);
424 if (dst) {
425 unsigned buflen = strlen(buf);
426 if (buflen && buf[buflen-1] == '/')
427 sprintf(dst, "%s%s", buf, lastcomp);
428 else
429 sprintf(dst, "%s/%s", buf, lastcomp);
432 free(copy);
433 if (dst == NULL)
434 fprintf(stderr, "%s: failed to allocate memory\n", progname);
435 return dst;
438 int fuse_mnt_check_fuseblk(void)
440 char buf[256];
441 FILE *f = fopen("/proc/filesystems", "r");
442 if (!f)
443 return 1;
445 while (fgets(buf, sizeof(buf), f))
446 if (strstr(buf, "fuseblk\n")) {
447 fclose(f);
448 return 1;
451 fclose(f);
452 return 0;
455 #endif /* __SOLARIS__ */