LCOV - code coverage report
Current view: top level - shared - fstab-util.c (source / functions) Hit Total Coverage
Test: main_coverage.info Lines: 96 148 64.9 %
Date: 2019-08-22 15:41:25 Functions: 5 8 62.5 %

          Line data    Source code
       1             : /* SPDX-License-Identifier: LGPL-2.1+ */
       2             : 
       3             : #include <errno.h>
       4             : #include <mntent.h>
       5             : #include <stdio.h>
       6             : #include <stdlib.h>
       7             : #include <string.h>
       8             : 
       9             : #include "alloc-util.h"
      10             : #include "device-nodes.h"
      11             : #include "fstab-util.h"
      12             : #include "macro.h"
      13             : #include "mount-util.h"
      14             : #include "nulstr-util.h"
      15             : #include "parse-util.h"
      16             : #include "path-util.h"
      17             : #include "string-util.h"
      18             : #include "strv.h"
      19             : 
      20           0 : int fstab_has_fstype(const char *fstype) {
      21           0 :         _cleanup_endmntent_ FILE *f = NULL;
      22             :         struct mntent *m;
      23             : 
      24           0 :         f = setmntent("/etc/fstab", "re");
      25           0 :         if (!f)
      26           0 :                 return errno == ENOENT ? false : -errno;
      27             : 
      28             :         for (;;) {
      29           0 :                 errno = 0;
      30           0 :                 m = getmntent(f);
      31           0 :                 if (!m)
      32           0 :                         return errno != 0 ? -errno : false;
      33             : 
      34           0 :                 if (streq(m->mnt_type, fstype))
      35           0 :                         return true;
      36             :         }
      37             :         return false;
      38             : }
      39             : 
      40           0 : int fstab_is_mount_point(const char *mount) {
      41           0 :         _cleanup_endmntent_ FILE *f = NULL;
      42             :         struct mntent *m;
      43             : 
      44           0 :         f = setmntent("/etc/fstab", "re");
      45           0 :         if (!f)
      46           0 :                 return errno == ENOENT ? false : -errno;
      47             : 
      48             :         for (;;) {
      49           0 :                 errno = 0;
      50           0 :                 m = getmntent(f);
      51           0 :                 if (!m)
      52           0 :                         return errno != 0 ? -errno : false;
      53             : 
      54           0 :                 if (path_equal(m->mnt_dir, mount))
      55           0 :                         return true;
      56             :         }
      57             :         return false;
      58             : }
      59             : 
      60         304 : int fstab_filter_options(const char *opts, const char *names,
      61             :                          const char **namefound, char **value, char **filtered) {
      62         304 :         const char *name, *n = NULL, *x;
      63         304 :         _cleanup_strv_free_ char **stor = NULL;
      64         304 :         _cleanup_free_ char *v = NULL, **strv = NULL;
      65             : 
      66         304 :         assert(names && *names);
      67             : 
      68         304 :         if (!opts)
      69           2 :                 goto answer;
      70             : 
      71             :         /* If !value and !filtered, this function is not allowed to fail. */
      72             : 
      73         302 :         if (!filtered) {
      74             :                 const char *word, *state;
      75             :                 size_t l;
      76             : 
      77        1212 :                 FOREACH_WORD_SEPARATOR(word, l, opts, ",", state)
      78        2686 :                         NULSTR_FOREACH(name, names) {
      79        1742 :                                 if (l < strlen(name))
      80         505 :                                         continue;
      81        1237 :                                 if (!strneq(word, name, strlen(name)))
      82        1152 :                                         continue;
      83             : 
      84             :                                 /* we know that the string is NUL
      85             :                                  * terminated, so *x is valid */
      86          85 :                                 x = word + strlen(name);
      87          85 :                                 if (IN_SET(*x, '\0', '=', ',')) {
      88          79 :                                         n = name;
      89          79 :                                         if (value) {
      90           5 :                                                 free(v);
      91           5 :                                                 if (IN_SET(*x, '\0', ','))
      92           1 :                                                         v = NULL;
      93             :                                                 else {
      94           4 :                                                         assert(*x == '=');
      95           4 :                                                         x++;
      96           4 :                                                         v = strndup(x, l - strlen(name) - 1);
      97           4 :                                                         if (!v)
      98           0 :                                                                 return -ENOMEM;
      99             :                                                 }
     100             :                                         }
     101             :                                 }
     102             :                         }
     103             :         } else {
     104             :                 char **t, **s;
     105             : 
     106          34 :                 stor = strv_split(opts, ",");
     107          34 :                 if (!stor)
     108           0 :                         return -ENOMEM;
     109          34 :                 strv = memdup(stor, sizeof(char*) * (strv_length(stor) + 1));
     110          34 :                 if (!strv)
     111           0 :                         return -ENOMEM;
     112             : 
     113          98 :                 for (s = t = strv; *s; s++) {
     114         144 :                         NULSTR_FOREACH(name, names) {
     115         110 :                                 x = startswith(*s, name);
     116         110 :                                 if (x && IN_SET(*x, '\0', '='))
     117          30 :                                         goto found;
     118             :                         }
     119             : 
     120          34 :                         *t = *s;
     121          34 :                         t++;
     122          34 :                         continue;
     123          30 :                 found:
     124             :                         /* Keep the last occurrence found */
     125          30 :                         n = name;
     126          30 :                         if (value) {
     127          30 :                                 free(v);
     128          30 :                                 if (*x == '\0')
     129          11 :                                         v = NULL;
     130             :                                 else {
     131          19 :                                         assert(*x == '=');
     132          19 :                                         x++;
     133          19 :                                         v = strdup(x);
     134          19 :                                         if (!v)
     135           0 :                                                 return -ENOMEM;
     136             :                                 }
     137             :                         }
     138             :                 }
     139          34 :                 *t = NULL;
     140             :         }
     141             : 
     142         304 : answer:
     143         304 :         if (namefound)
     144          91 :                 *namefound = n;
     145         304 :         if (filtered) {
     146             :                 char *f;
     147             : 
     148          35 :                 f = strv_join(strv, ",");
     149          35 :                 if (!f)
     150           0 :                         return -ENOMEM;
     151             : 
     152          35 :                 *filtered = f;
     153             :         }
     154         304 :         if (value)
     155          39 :                 *value = TAKE_PTR(v);
     156             : 
     157         304 :         return !!n;
     158             : }
     159             : 
     160           0 : int fstab_extract_values(const char *opts, const char *name, char ***values) {
     161           0 :         _cleanup_strv_free_ char **optsv = NULL, **res = NULL;
     162             :         char **s;
     163             : 
     164           0 :         assert(opts);
     165           0 :         assert(name);
     166           0 :         assert(values);
     167             : 
     168           0 :         optsv = strv_split(opts, ",");
     169           0 :         if (!optsv)
     170           0 :                 return -ENOMEM;
     171             : 
     172           0 :         STRV_FOREACH(s, optsv) {
     173             :                 char *arg;
     174             :                 int r;
     175             : 
     176           0 :                 arg = startswith(*s, name);
     177           0 :                 if (!arg || *arg != '=')
     178           0 :                         continue;
     179           0 :                 r = strv_extend(&res, arg + 1);
     180           0 :                 if (r < 0)
     181           0 :                         return r;
     182             :         }
     183             : 
     184           0 :         *values = TAKE_PTR(res);
     185             : 
     186           0 :         return !!*values;
     187             : }
     188             : 
     189           4 : int fstab_find_pri(const char *options, int *ret) {
     190           4 :         _cleanup_free_ char *opt = NULL;
     191             :         int r;
     192             :         unsigned pri;
     193             : 
     194           4 :         assert(ret);
     195             : 
     196           4 :         r = fstab_filter_options(options, "pri\0", NULL, &opt, NULL);
     197           4 :         if (r < 0)
     198           0 :                 return r;
     199           4 :         if (r == 0 || !opt)
     200           1 :                 return 0;
     201             : 
     202           3 :         r = safe_atou(opt, &pri);
     203           3 :         if (r < 0)
     204           0 :                 return r;
     205             : 
     206           3 :         if ((int) pri < 0)
     207           0 :                 return -ERANGE;
     208             : 
     209           3 :         *ret = (int) pri;
     210           3 :         return 1;
     211             : }
     212             : 
     213           4 : static char *unquote(const char *s, const char* quotes) {
     214             :         size_t l;
     215           4 :         assert(s);
     216             : 
     217             :         /* This is rather stupid, simply removes the heading and
     218             :          * trailing quotes if there is one. Doesn't care about
     219             :          * escaping or anything.
     220             :          *
     221             :          * DON'T USE THIS FOR NEW CODE ANYMORE! */
     222             : 
     223           4 :         l = strlen(s);
     224           4 :         if (l < 2)
     225           0 :                 return strdup(s);
     226             : 
     227           4 :         if (strchr(quotes, s[0]) && s[l-1] == s[0])
     228           0 :                 return strndup(s+1, l-2);
     229             : 
     230           4 :         return strdup(s);
     231             : }
     232             : 
     233           4 : static char *tag_to_udev_node(const char *tagvalue, const char *by) {
     234           4 :         _cleanup_free_ char *t = NULL, *u = NULL;
     235             :         size_t enc_len;
     236             : 
     237           4 :         u = unquote(tagvalue, QUOTES);
     238           4 :         if (!u)
     239           0 :                 return NULL;
     240             : 
     241           4 :         enc_len = strlen(u) * 4 + 1;
     242           4 :         t = new(char, enc_len);
     243           4 :         if (!t)
     244           0 :                 return NULL;
     245             : 
     246           4 :         if (encode_devnode_name(u, t, enc_len) < 0)
     247           0 :                 return NULL;
     248             : 
     249           4 :         return strjoin("/dev/disk/by-", by, "/", t);
     250             : }
     251             : 
     252           6 : char *fstab_node_to_udev_node(const char *p) {
     253           6 :         assert(p);
     254             : 
     255           6 :         if (startswith(p, "LABEL="))
     256           1 :                 return tag_to_udev_node(p+6, "label");
     257             : 
     258           5 :         if (startswith(p, "UUID="))
     259           1 :                 return tag_to_udev_node(p+5, "uuid");
     260             : 
     261           4 :         if (startswith(p, "PARTUUID="))
     262           1 :                 return tag_to_udev_node(p+9, "partuuid");
     263             : 
     264           3 :         if (startswith(p, "PARTLABEL="))
     265           1 :                 return tag_to_udev_node(p+10, "partlabel");
     266             : 
     267           2 :         return strdup(p);
     268             : }

Generated by: LCOV version 1.14