"Fossies" - the Fresh Open Source Software Archive

Member "ntfs-3g_ntfsprogs-2017.3.23/libfuse-lite/mount_util.c" (23 Mar 2017, 12009 Bytes) of package /linux/misc/ntfs-3g_ntfsprogs-2017.3.23.tgz:


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 and the latest Fossies "Diffs" side-by-side code changes report: 3g_ntfsprogs-2016.2.22_vs_3g_ntfsprogs-2017.3.23.

    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 LGPLv2.
    6     See the file COPYING.LIB.
    7 */
    8 
    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 <paths.h>
   19 #include <sys/stat.h>
   20 #include <sys/wait.h>
   21 #ifdef __SOLARIS__
   22 #else /* __SOLARIS__ */
   23 #include <mntent.h>
   24 #include <sys/mount.h>
   25 #include <sys/param.h>
   26 #endif /* __SOLARIS__ */
   27 
   28 #ifdef __SOLARIS__
   29 
   30 char *mkdtemp(char *template);
   31 
   32 #ifndef _PATH_MOUNTED
   33 #define _PATH_MOUNTED "/etc/mnttab"
   34 #endif /* _PATH_MOUNTED */
   35 
   36 #ifndef IGNORE_MTAB
   37 static int mtab_needs_update(const char *mnt)
   38 {
   39     struct stat stbuf;
   40 
   41     /* If mtab is within new mount, don't touch it */
   42     if (strncmp(mnt, _PATH_MOUNTED, strlen(mnt)) == 0 &&
   43         _PATH_MOUNTED[strlen(mnt)] == '/')
   44         return 0;
   45 
   46     if (lstat(_PATH_MOUNTED, &stbuf) != -1 && S_ISLNK(stbuf.st_mode))
   47         return 0;
   48 
   49     return 1;
   50 }
   51 #endif /* IGNORE_MTAB */
   52 
   53 int fuse_mnt_add_mount(const char *progname, const char *fsname,
   54                        const char *mnt, const char *type, const char *opts)
   55 {
   56     int res;
   57     int status;
   58 
   59 #ifndef IGNORE_MTAB
   60     if (!mtab_needs_update(mnt))
   61         return 0;
   62 #endif /* IGNORE_MTAB */
   63 
   64     res = fork();
   65     if (res == -1) {
   66         fprintf(stderr, "%s: fork: %s\n", progname, strerror(errno));
   67         return -1;
   68     }
   69     if (res == 0) {
   70         char *env = NULL;
   71         char templ[] = "/tmp/fusermountXXXXXX";
   72         char *tmp;
   73 
   74         setuid(geteuid());
   75 
   76         /* 
   77          * hide in a directory, where mount isn't able to resolve
   78          * fsname as a valid path
   79          */
   80         tmp = mkdtemp(templ);
   81         if (!tmp) {
   82             fprintf(stderr, "%s: failed to create temporary directory\n",
   83                     progname);
   84             exit(1);
   85         }
   86         if (chdir(tmp)) {
   87             fprintf(stderr, "%s: failed to chdir to %s: %s\n",
   88                     progname, tmp, strerror(errno));
   89             exit(1);
   90         }
   91         rmdir(tmp);
   92         execle("/sbin/mount", "/sbin/mount", "-F", type, "-o", opts,
   93               fsname, mnt, NULL, &env);
   94         fprintf(stderr, "%s: failed to execute /sbin/mount: %s\n", progname,
   95                 strerror(errno));
   96         exit(1);
   97     }
   98     res = waitpid(res, &status, 0);
   99     if (res == -1) {
  100         fprintf(stderr, "%s: waitpid: %s\n", progname, strerror(errno));
  101         return -1;
  102     }
  103     if (status != 0)
  104         return -1;
  105 
  106     return 0;
  107 }
  108 
  109 int fuse_mnt_umount(const char *progname, const char *mnt, int lazy)
  110 {
  111     int res;
  112     int status;
  113 
  114 #ifndef IGNORE_MTAB
  115     if (!mtab_needs_update(mnt))
  116         return 0;
  117 #endif /* IGNORE_MTAB */
  118 
  119     res = fork();
  120     if (res == -1) {
  121         fprintf(stderr, "%s: fork: %s\n", progname, strerror(errno));
  122         return -1;
  123     }
  124     if (res == 0) {
  125         char *env = NULL;
  126 
  127         setuid(geteuid());
  128         if (lazy) {
  129             execle("/sbin/umount", "/sbin/umount", mnt,
  130                    NULL, &env);
  131         } else {
  132             execle("/sbin/umount", "/sbin/umount", "-f", mnt,
  133                    NULL, &env);
  134         }
  135         fprintf(stderr, "%s: failed to execute /sbin/umount: %s\n", progname,
  136                 strerror(errno));
  137         exit(1);
  138     }
  139     res = waitpid(res, &status, 0);
  140     if (res == -1) {
  141         fprintf(stderr, "%s: waitpid: %s\n", progname, strerror(errno));
  142         return -1;
  143     }
  144     if (status != 0)
  145         return -1;
  146 
  147     return 0;
  148 }
  149 
  150 char *fuse_mnt_resolve_path(const char *progname, const char *orig)
  151 {
  152     char buf[PATH_MAX];
  153     char *copy;
  154     char *dst;
  155     char *end;
  156     char *lastcomp;
  157     const char *toresolv;
  158 
  159     if (!orig[0]) {
  160         fprintf(stderr, "%s: invalid mountpoint '%s'\n", progname, orig);
  161         return NULL;
  162     }
  163 
  164     copy = strdup(orig);
  165     if (copy == NULL) {
  166         fprintf(stderr, "%s: failed to allocate memory\n", progname);
  167         return NULL;
  168     }
  169 
  170     toresolv = copy;
  171     lastcomp = NULL;
  172     for (end = copy + strlen(copy) - 1; end > copy && *end == '/'; end --);
  173     if (end[0] != '/') {
  174         char *tmp;
  175         end[1] = '\0';
  176         tmp = strrchr(copy, '/');
  177         if (tmp == NULL) {
  178             lastcomp = copy;
  179             toresolv = ".";
  180         } else {
  181             lastcomp = tmp + 1;
  182             if (tmp == copy)
  183                 toresolv = "/";
  184         }
  185         if (strcmp(lastcomp, ".") == 0 || strcmp(lastcomp, "..") == 0) {
  186             lastcomp = NULL;
  187             toresolv = copy;
  188         }
  189         else if (tmp)
  190             tmp[0] = '\0';
  191     }
  192     if (realpath(toresolv, buf) == NULL) {
  193         fprintf(stderr, "%s: bad mount point %s: %s\n", progname, orig,
  194                 strerror(errno));
  195         free(copy);
  196         return NULL;
  197     }
  198     if (lastcomp == NULL)
  199         dst = strdup(buf);
  200     else {
  201         dst = (char *) malloc(strlen(buf) + 1 + strlen(lastcomp) + 1);
  202         if (dst) {
  203             unsigned buflen = strlen(buf);
  204             if (buflen && buf[buflen-1] == '/')
  205                 sprintf(dst, "%s%s", buf, lastcomp);
  206             else
  207                 sprintf(dst, "%s/%s", buf, lastcomp);
  208         }
  209     }
  210     free(copy);
  211     if (dst == NULL)
  212         fprintf(stderr, "%s: failed to allocate memory\n", progname);
  213     return dst;
  214 }
  215 
  216 int fuse_mnt_check_empty(const char *progname, const char *mnt,
  217                          mode_t rootmode, off_t rootsize)
  218 {
  219     int isempty = 1;
  220 
  221     if (S_ISDIR(rootmode)) {
  222         struct dirent *ent;
  223         DIR *dp = opendir(mnt);
  224         if (dp == NULL) {
  225             fprintf(stderr, "%s: failed to open mountpoint for reading: %s\n",
  226                     progname, strerror(errno));
  227             return -1;
  228         }
  229         while ((ent = readdir(dp)) != NULL) {
  230             if (strcmp(ent->d_name, ".") != 0 &&
  231                 strcmp(ent->d_name, "..") != 0) {
  232                 isempty = 0;
  233                 break;
  234             }
  235         }
  236         closedir(dp);
  237     } else if (rootsize)
  238         isempty = 0;
  239 
  240     if (!isempty) {
  241         fprintf(stderr, "%s: mountpoint is not empty\n", progname);
  242         fprintf(stderr, "%s: if you are sure this is safe, use the 'nonempty' mount option\n", progname);
  243         return -1;
  244     }
  245     return 0;
  246 }
  247 
  248 int fuse_mnt_check_fuseblk(void)
  249 {
  250     char buf[256];
  251     FILE *f = fopen("/proc/filesystems", "r");
  252     if (!f)
  253         return 1;
  254 
  255     while (fgets(buf, sizeof(buf), f))
  256         if (strstr(buf, "fuseblk\n")) {
  257             fclose(f);
  258             return 1;
  259         }
  260 
  261     fclose(f);
  262     return 0;
  263 }
  264 
  265 #else /* __SOLARIS__ */
  266 
  267 static int mtab_needs_update(const char *mnt)
  268 {
  269     int res;
  270     struct stat stbuf;
  271 
  272     /* If mtab is within new mount, don't touch it */
  273     if (strncmp(mnt, _PATH_MOUNTED, strlen(mnt)) == 0 &&
  274         _PATH_MOUNTED[strlen(mnt)] == '/')
  275         return 0;
  276 
  277     /*
  278      * Skip mtab update if /etc/mtab:
  279      *
  280      *  - doesn't exist,
  281      *  - is a symlink,
  282      *  - is on a read-only filesystem.
  283      */
  284     res = lstat(_PATH_MOUNTED, &stbuf);
  285     if (res == -1) {
  286         if (errno == ENOENT)
  287             return 0;
  288     } else {
  289         if (S_ISLNK(stbuf.st_mode))
  290             return 0;
  291 
  292         res = access(_PATH_MOUNTED, W_OK);
  293         if (res == -1 && errno == EROFS)
  294             return 0;
  295     }
  296 
  297     return 1;
  298 }
  299 
  300 int fuse_mnt_add_mount(const char *progname, const char *fsname,
  301                        const char *mnt, const char *type, const char *opts)
  302 {
  303     int res;
  304 
  305     if (!mtab_needs_update(mnt))
  306         return 0;
  307 
  308     res = fork();
  309     if (res == -1) {
  310         fprintf(stderr, "%s: fork: %s\n", progname, strerror(errno));
  311         return 0;
  312     }
  313     if (res == 0) {
  314         char *env = NULL;
  315         char templ[] = "/tmp/fusermountXXXXXX";
  316         char *tmp;
  317 
  318         if (setuid(geteuid()))
  319             fprintf(stderr, "%s: failed to setuid : %s\n", progname,
  320                              strerror(errno));
  321 
  322         /* 
  323          * hide in a directory, where mount isn't able to resolve
  324          * fsname as a valid path
  325          */
  326         tmp = mkdtemp(templ);
  327         if (!tmp) {
  328             fprintf(stderr, "%s: failed to create temporary directory\n",
  329                     progname);
  330             exit(1);
  331         }
  332         if (chdir(tmp)) {
  333             fprintf(stderr, "%s: failed to chdir to %s: %s\n",
  334                     progname, tmp, strerror(errno));
  335             exit(1);
  336         }
  337         rmdir(tmp);
  338         execle("/bin/mount", "/bin/mount", "-i", "-f", "-t", type, "-o", opts,
  339                fsname, mnt, NULL, &env);
  340         fprintf(stderr, "%s: failed to execute /bin/mount: %s\n", progname,
  341                 strerror(errno));
  342         exit(1);
  343     }
  344     return 0;
  345 }
  346 
  347 int fuse_mnt_umount(const char *progname, const char *mnt, int lazy)
  348 {
  349     int res;
  350     int status;
  351 
  352     if (!mtab_needs_update(mnt)) {
  353         res = umount2(mnt, lazy ? 2 : 0);
  354         if (res == -1)
  355             fprintf(stderr, "%s: failed to unmount %s: %s\n", progname,
  356                     mnt, strerror(errno));
  357         return res;
  358     }
  359 
  360     res = fork();
  361     if (res == -1) {
  362         fprintf(stderr, "%s: fork: %s\n", progname, strerror(errno));
  363         return -1;
  364     }
  365     if (res == 0) {
  366         char *env = NULL;
  367 
  368         if (setuid(geteuid()))
  369             fprintf(stderr, "%s: failed to setuid : %s\n", progname,
  370                          strerror(errno));
  371         if (lazy) {
  372             execle("/bin/umount", "/bin/umount", "-i", mnt, "-l",
  373                    NULL, &env);
  374         } else {
  375             execle("/bin/umount", "/bin/umount", "-i", mnt,
  376                    NULL, &env);
  377         }
  378         fprintf(stderr, "%s: failed to execute /bin/umount: %s\n", progname,
  379                 strerror(errno));
  380         exit(1);
  381     }
  382     res = waitpid(res, &status, 0);
  383     if (res == -1) {
  384         fprintf(stderr, "%s: waitpid: %s\n", progname, strerror(errno));
  385         return -1;
  386     }
  387     if (status != 0)
  388         return -1;
  389 
  390     return 0;
  391 }
  392 
  393 char *fuse_mnt_resolve_path(const char *progname, const char *orig)
  394 {
  395     char buf[PATH_MAX];
  396     char *copy;
  397     char *dst;
  398     char *end;
  399     char *lastcomp;
  400     const char *toresolv;
  401 
  402     if (!orig[0]) {
  403         fprintf(stderr, "%s: invalid mountpoint '%s'\n", progname, orig);
  404         return NULL;
  405     }
  406 
  407     copy = strdup(orig);
  408     if (copy == NULL) {
  409         fprintf(stderr, "%s: failed to allocate memory\n", progname);
  410         return NULL;
  411     }
  412 
  413     toresolv = copy;
  414     lastcomp = NULL;
  415     for (end = copy + strlen(copy) - 1; end > copy && *end == '/'; end --);
  416     if (end[0] != '/') {
  417         char *tmp;
  418         end[1] = '\0';
  419         tmp = strrchr(copy, '/');
  420         if (tmp == NULL) {
  421             lastcomp = copy;
  422             toresolv = ".";
  423         } else {
  424             lastcomp = tmp + 1;
  425             if (tmp == copy)
  426                 toresolv = "/";
  427         }
  428         if (strcmp(lastcomp, ".") == 0 || strcmp(lastcomp, "..") == 0) {
  429             lastcomp = NULL;
  430             toresolv = copy;
  431         }
  432         else if (tmp)
  433             tmp[0] = '\0';
  434     }
  435     if (realpath(toresolv, buf) == NULL) {
  436         fprintf(stderr, "%s: bad mount point %s: %s\n", progname, orig,
  437                 strerror(errno));
  438         free(copy);
  439         return NULL;
  440     }
  441     if (lastcomp == NULL)
  442         dst = strdup(buf);
  443     else {
  444         dst = (char *) malloc(strlen(buf) + 1 + strlen(lastcomp) + 1);
  445         if (dst) {
  446             unsigned buflen = strlen(buf);
  447             if (buflen && buf[buflen-1] == '/')
  448                 sprintf(dst, "%s%s", buf, lastcomp);
  449             else
  450                 sprintf(dst, "%s/%s", buf, lastcomp);
  451         }
  452     }
  453     free(copy);
  454     if (dst == NULL)
  455         fprintf(stderr, "%s: failed to allocate memory\n", progname);
  456     return dst;
  457 }
  458 
  459 int fuse_mnt_check_fuseblk(void)
  460 {
  461     char buf[256];
  462     FILE *f = fopen("/proc/filesystems", "r");
  463     if (!f)
  464         return 1;
  465 
  466     while (fgets(buf, sizeof(buf), f))
  467         if (strstr(buf, "fuseblk\n")) {
  468             fclose(f);
  469             return 1;
  470         }
  471 
  472     fclose(f);
  473     return 0;
  474 }
  475 
  476 #endif /* __SOLARIS__ */