"Fossies" - the Fresh Open Source Software Archive

Member "fuse-3.2.3/lib/mount_util.c" (11 May 2018, 7541 Bytes) of package /linux/misc/fuse-3.2.3.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "mount_util.c" see the Fossies "Dox" file reference documentation.

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