"Fossies" - the Fresh Open Source Software Archive

Member "fuse-3.10.4/doc/html/mount__util_8c_source.html" (9 Jun 2021, 53381 Bytes) of package /linux/misc/fuse-3.10.4.tar.xz:


Caution: In this restricted "Fossies" environment the current HTML page may not be correctly presentated and may have some non-functional links. You can here alternatively try to browse the pure source code or just view or download the uninterpreted raw source code. If the rendering is insufficient you may try to find and view the page on the project site itself.

libfuse
mount_util.c
1 /*
2  FUSE: Filesystem in Userspace
3  Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
4 
5  Architecture-independent mounting code.
6 
7  This program can be distributed under the terms of the GNU LGPLv2.
8  See the file COPYING.LIB.
9 */
10 
11 #include "config.h"
12 #include "mount_util.h"
13 #include <stdio.h>
14 #include <unistd.h>
15 #include <stdlib.h>
16 #include <string.h>
17 #include <signal.h>
18 #include <dirent.h>
19 #include <errno.h>
20 #include <fcntl.h>
21 #include <limits.h>
22 #include <paths.h>
23 #if !defined( __NetBSD__) && !defined(__FreeBSD__) && !defined(__DragonFly__)
24 #include <mntent.h>
25 #else
26 #define IGNORE_MTAB
27 #endif
28 #include <sys/stat.h>
29 #include <sys/wait.h>
30 #include <sys/mount.h>
31 #include <sys/param.h>
32 
33 #if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__)
34 #define umount2(mnt, flags) unmount(mnt, ((flags) == 2) ? MNT_FORCE : 0)
35 #endif
36 
37 #ifdef IGNORE_MTAB
38 #define mtab_needs_update(mnt) 0
39 #else
40 static int mtab_needs_update(const char *mnt)
41 {
42  int res;
43  struct stat stbuf;
44 
45  /* If mtab is within new mount, don't touch it */
46  if (strncmp(mnt, _PATH_MOUNTED, strlen(mnt)) == 0 &&
47  _PATH_MOUNTED[strlen(mnt)] == '/')
48  return 0;
49 
50  /*
51  * Skip mtab update if /etc/mtab:
52  *
53  * - doesn't exist,
54  * - is a symlink,
55  * - is on a read-only filesystem.
56  */
57  res = lstat(_PATH_MOUNTED, &stbuf);
58  if (res == -1) {
59  if (errno == ENOENT)
60  return 0;
61  } else {
62  uid_t ruid;
63  int err;
64 
65  if (S_ISLNK(stbuf.st_mode))
66  return 0;
67 
68  ruid = getuid();
69  if (ruid != 0)
70  setreuid(0, -1);
71 
72  res = access(_PATH_MOUNTED, W_OK);
73  err = (res == -1) ? errno : 0;
74  if (ruid != 0)
75  setreuid(ruid, -1);
76 
77  if (err == EROFS)
78  return 0;
79  }
80 
81  return 1;
82 }
83 #endif /* IGNORE_MTAB */
84 
85 static int add_mount(const char *progname, const char *fsname,
86  const char *mnt, const char *type, const char *opts)
87 {
88  int res;
89  int status;
90  sigset_t blockmask;
91  sigset_t oldmask;
92 
93  sigemptyset(&blockmask);
94  sigaddset(&blockmask, SIGCHLD);
95  res = sigprocmask(SIG_BLOCK, &blockmask, &oldmask);
96  if (res == -1) {
97  fprintf(stderr, "%s: sigprocmask: %s\n", progname, strerror(errno));
98  return -1;
99  }
100 
101  res = fork();
102  if (res == -1) {
103  fprintf(stderr, "%s: fork: %s\n", progname, strerror(errno));
104  goto out_restore;
105  }
106  if (res == 0) {
107  char *env = NULL;
108 
109  sigprocmask(SIG_SETMASK, &oldmask, NULL);
110 
111  if(setuid(geteuid()) == -1) {
112  fprintf(stderr, "%s: setuid: %s\n", progname, strerror(errno));
113  res = -1;
114  goto out_restore;
115  }
116 
117  execle("/bin/mount", "/bin/mount", "--no-canonicalize", "-i",
118  "-f", "-t", type, "-o", opts, fsname, mnt, NULL, &env);
119  fprintf(stderr, "%s: failed to execute /bin/mount: %s\n",
120  progname, strerror(errno));
121  exit(1);
122  }
123  res = waitpid(res, &status, 0);
124  if (res == -1)
125  fprintf(stderr, "%s: waitpid: %s\n", progname, strerror(errno));
126 
127  if (status != 0)
128  res = -1;
129 
130  out_restore:
131  sigprocmask(SIG_SETMASK, &oldmask, NULL);
132 
133  return res;
134 }
135 
136 int fuse_mnt_add_mount(const char *progname, const char *fsname,
137  const char *mnt, const char *type, const char *opts)
138 {
139  if (!mtab_needs_update(mnt))
140  return 0;
141 
142  return add_mount(progname, fsname, mnt, type, opts);
143 }
144 
145 static int exec_umount(const char *progname, const char *rel_mnt, int lazy)
146 {
147  int res;
148  int status;
149  sigset_t blockmask;
150  sigset_t oldmask;
151 
152  sigemptyset(&blockmask);
153  sigaddset(&blockmask, SIGCHLD);
154  res = sigprocmask(SIG_BLOCK, &blockmask, &oldmask);
155  if (res == -1) {
156  fprintf(stderr, "%s: sigprocmask: %s\n", progname, strerror(errno));
157  return -1;
158  }
159 
160  res = fork();
161  if (res == -1) {
162  fprintf(stderr, "%s: fork: %s\n", progname, strerror(errno));
163  goto out_restore;
164  }
165  if (res == 0) {
166  char *env = NULL;
167 
168  sigprocmask(SIG_SETMASK, &oldmask, NULL);
169 
170  if(setuid(geteuid()) == -1) {
171  fprintf(stderr, "%s: setuid: %s\n", progname, strerror(errno));
172  res = -1;
173  goto out_restore;
174  }
175 
176  if (lazy) {
177  execle("/bin/umount", "/bin/umount", "-i", rel_mnt,
178  "-l", NULL, &env);
179  } else {
180  execle("/bin/umount", "/bin/umount", "-i", rel_mnt,
181  NULL, &env);
182  }
183  fprintf(stderr, "%s: failed to execute /bin/umount: %s\n",
184  progname, strerror(errno));
185  exit(1);
186  }
187  res = waitpid(res, &status, 0);
188  if (res == -1)
189  fprintf(stderr, "%s: waitpid: %s\n", progname, strerror(errno));
190 
191  if (status != 0) {
192  res = -1;
193  }
194 
195  out_restore:
196  sigprocmask(SIG_SETMASK, &oldmask, NULL);
197  return res;
198 
199 }
200 
201 int fuse_mnt_umount(const char *progname, const char *abs_mnt,
202  const char *rel_mnt, int lazy)
203 {
204  int res;
205 
206  if (!mtab_needs_update(abs_mnt)) {
207  res = umount2(rel_mnt, lazy ? 2 : 0);
208  if (res == -1)
209  fprintf(stderr, "%s: failed to unmount %s: %s\n",
210  progname, abs_mnt, strerror(errno));
211  return res;
212  }
213 
214  return exec_umount(progname, rel_mnt, lazy);
215 }
216 
217 static int remove_mount(const char *progname, const char *mnt)
218 {
219  int res;
220  int status;
221  sigset_t blockmask;
222  sigset_t oldmask;
223 
224  sigemptyset(&blockmask);
225  sigaddset(&blockmask, SIGCHLD);
226  res = sigprocmask(SIG_BLOCK, &blockmask, &oldmask);
227  if (res == -1) {
228  fprintf(stderr, "%s: sigprocmask: %s\n", progname, strerror(errno));
229  return -1;
230  }
231 
232  res = fork();
233  if (res == -1) {
234  fprintf(stderr, "%s: fork: %s\n", progname, strerror(errno));
235  goto out_restore;
236  }
237  if (res == 0) {
238  char *env = NULL;
239 
240  sigprocmask(SIG_SETMASK, &oldmask, NULL);
241 
242  if(setuid(geteuid()) == -1) {
243  fprintf(stderr, "%s: setuid: %s\n", progname, strerror(errno));
244  res = -1;
245  goto out_restore;
246  }
247 
248  execle("/bin/umount", "/bin/umount", "--no-canonicalize", "-i",
249  "--fake", mnt, NULL, &env);
250  fprintf(stderr, "%s: failed to execute /bin/umount: %s\n",
251  progname, strerror(errno));
252  exit(1);
253  }
254  res = waitpid(res, &status, 0);
255  if (res == -1)
256  fprintf(stderr, "%s: waitpid: %s\n", progname, strerror(errno));
257 
258  if (status != 0)
259  res = -1;
260 
261  out_restore:
262  sigprocmask(SIG_SETMASK, &oldmask, NULL);
263  return res;
264 }
265 
266 int fuse_mnt_remove_mount(const char *progname, const char *mnt)
267 {
268  if (!mtab_needs_update(mnt))
269  return 0;
270 
271  return remove_mount(progname, mnt);
272 }
273 
274 char *fuse_mnt_resolve_path(const char *progname, const char *orig)
275 {
276  char buf[PATH_MAX];
277  char *copy;
278  char *dst;
279  char *end;
280  char *lastcomp;
281  const char *toresolv;
282 
283  if (!orig[0]) {
284  fprintf(stderr, "%s: invalid mountpoint '%s'\n", progname,
285  orig);
286  return NULL;
287  }
288 
289  copy = strdup(orig);
290  if (copy == NULL) {
291  fprintf(stderr, "%s: failed to allocate memory\n", progname);
292  return NULL;
293  }
294 
295  toresolv = copy;
296  lastcomp = NULL;
297  for (end = copy + strlen(copy) - 1; end > copy && *end == '/'; end --);
298  if (end[0] != '/') {
299  char *tmp;
300  end[1] = '\0';
301  tmp = strrchr(copy, '/');
302  if (tmp == NULL) {
303  lastcomp = copy;
304  toresolv = ".";
305  } else {
306  lastcomp = tmp + 1;
307  if (tmp == copy)
308  toresolv = "/";
309  }
310  if (strcmp(lastcomp, ".") == 0 || strcmp(lastcomp, "..") == 0) {
311  lastcomp = NULL;
312  toresolv = copy;
313  }
314  else if (tmp)
315  tmp[0] = '\0';
316  }
317  if (realpath(toresolv, buf) == NULL) {
318  fprintf(stderr, "%s: bad mount point %s: %s\n", progname, orig,
319  strerror(errno));
320  free(copy);
321  return NULL;
322  }
323  if (lastcomp == NULL)
324  dst = strdup(buf);
325  else {
326  dst = (char *) malloc(strlen(buf) + 1 + strlen(lastcomp) + 1);
327  if (dst) {
328  unsigned buflen = strlen(buf);
329  if (buflen && buf[buflen-1] == '/')
330  sprintf(dst, "%s%s", buf, lastcomp);
331  else
332  sprintf(dst, "%s/%s", buf, lastcomp);
333  }
334  }
335  free(copy);
336  if (dst == NULL)
337  fprintf(stderr, "%s: failed to allocate memory\n", progname);
338  return dst;
339 }
340 
341 int fuse_mnt_check_fuseblk(void)
342 {
343  char buf[256];
344  FILE *f = fopen("/proc/filesystems", "r");
345  if (!f)
346  return 1;
347 
348  while (fgets(buf, sizeof(buf), f))
349  if (strstr(buf, "fuseblk\n")) {
350  fclose(f);
351  return 1;
352  }
353 
354  fclose(f);
355  return 0;
356 }
357 
358 int fuse_mnt_parse_fuse_fd(const char *mountpoint)
359 {
360  int fd = -1;
361  int len = 0;
362 
363  if (sscanf(mountpoint, "/dev/fd/%u%n", &fd, &len) == 1 &&
364  len == strlen(mountpoint)) {
365  return fd;
366  }
367 
368  return -1;
369 }