LCOV - code coverage report
Current view: top level - basic - blockdev-util.c (source / functions) Hit Total Coverage
Test: systemd_full.info Lines: 0 93 0.0 %
Date: 2019-08-23 13:36:53 Functions: 0 4 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 102 0.0 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: LGPL-2.1+ */
       2                 :            : 
       3                 :            : #include <sys/stat.h>
       4                 :            : #include <sys/statfs.h>
       5                 :            : 
       6                 :            : #include "alloc-util.h"
       7                 :            : #include "blockdev-util.h"
       8                 :            : #include "btrfs-util.h"
       9                 :            : #include "dirent-util.h"
      10                 :            : #include "fd-util.h"
      11                 :            : #include "fileio.h"
      12                 :            : #include "missing.h"
      13                 :            : #include "parse-util.h"
      14                 :            : #include "stat-util.h"
      15                 :            : 
      16                 :          0 : int block_get_whole_disk(dev_t d, dev_t *ret) {
      17                 :          0 :         char p[SYS_BLOCK_PATH_MAX("/partition")];
      18                 :          0 :         _cleanup_free_ char *s = NULL;
      19                 :            :         dev_t devt;
      20                 :            :         int r;
      21                 :            : 
      22         [ #  # ]:          0 :         assert(ret);
      23                 :            : 
      24         [ #  # ]:          0 :         if (major(d) == 0)
      25                 :          0 :                 return -ENODEV;
      26                 :            : 
      27                 :            :         /* If it has a queue this is good enough for us */
      28         [ #  # ]:          0 :         xsprintf_sys_block_path(p, "/queue", d);
      29         [ #  # ]:          0 :         if (access(p, F_OK) >= 0) {
      30                 :          0 :                 *ret = d;
      31                 :          0 :                 return 0;
      32                 :            :         }
      33                 :            : 
      34                 :            :         /* If it is a partition find the originating device */
      35         [ #  # ]:          0 :         xsprintf_sys_block_path(p, "/partition", d);
      36         [ #  # ]:          0 :         if (access(p, F_OK) < 0)
      37                 :          0 :                 return -errno;
      38                 :            : 
      39                 :            :         /* Get parent dev_t */
      40         [ #  # ]:          0 :         xsprintf_sys_block_path(p, "/../dev", d);
      41                 :          0 :         r = read_one_line_file(p, &s);
      42         [ #  # ]:          0 :         if (r < 0)
      43                 :          0 :                 return r;
      44                 :            : 
      45                 :          0 :         r = parse_dev(s, &devt);
      46         [ #  # ]:          0 :         if (r < 0)
      47                 :          0 :                 return r;
      48                 :            : 
      49                 :            :         /* Only return this if it is really good enough for us. */
      50         [ #  # ]:          0 :         xsprintf_sys_block_path(p, "/queue", devt);
      51         [ #  # ]:          0 :         if (access(p, F_OK) < 0)
      52                 :          0 :                 return -errno;
      53                 :            : 
      54                 :          0 :         *ret = devt;
      55                 :          0 :         return 1;
      56                 :            : }
      57                 :            : 
      58                 :          0 : int get_block_device(const char *path, dev_t *dev) {
      59                 :            :         struct stat st;
      60                 :            :         struct statfs sfs;
      61                 :            : 
      62         [ #  # ]:          0 :         assert(path);
      63         [ #  # ]:          0 :         assert(dev);
      64                 :            : 
      65                 :            :         /* Gets the block device directly backing a file system. If
      66                 :            :          * the block device is encrypted, returns the device mapper
      67                 :            :          * block device. */
      68                 :            : 
      69         [ #  # ]:          0 :         if (lstat(path, &st))
      70                 :          0 :                 return -errno;
      71                 :            : 
      72         [ #  # ]:          0 :         if (major(st.st_dev) != 0) {
      73                 :          0 :                 *dev = st.st_dev;
      74                 :          0 :                 return 1;
      75                 :            :         }
      76                 :            : 
      77         [ #  # ]:          0 :         if (statfs(path, &sfs) < 0)
      78                 :          0 :                 return -errno;
      79                 :            : 
      80         [ #  # ]:          0 :         if (F_TYPE_EQUAL(sfs.f_type, BTRFS_SUPER_MAGIC))
      81                 :          0 :                 return btrfs_get_block_device(path, dev);
      82                 :            : 
      83                 :          0 :         *dev = 0;
      84                 :          0 :         return 0;
      85                 :            : }
      86                 :            : 
      87                 :          0 : int block_get_originating(dev_t dt, dev_t *ret) {
      88                 :          0 :         _cleanup_closedir_ DIR *d = NULL;
      89                 :          0 :         _cleanup_free_ char *t = NULL;
      90                 :          0 :         char p[SYS_BLOCK_PATH_MAX("/slaves")];
      91                 :          0 :         struct dirent *de, *found = NULL;
      92                 :            :         const char *q;
      93                 :            :         dev_t devt;
      94                 :            :         int r;
      95                 :            : 
      96                 :            :         /* For the specified block device tries to chase it through the layers, in case LUKS-style DM stacking is used,
      97                 :            :          * trying to find the next underlying layer.  */
      98                 :            : 
      99         [ #  # ]:          0 :         xsprintf_sys_block_path(p, "/slaves", dt);
     100                 :          0 :         d = opendir(p);
     101         [ #  # ]:          0 :         if (!d)
     102                 :          0 :                 return -errno;
     103                 :            : 
     104   [ #  #  #  # ]:          0 :         FOREACH_DIRENT_ALL(de, d, return -errno) {
     105                 :            : 
     106         [ #  # ]:          0 :                 if (dot_or_dot_dot(de->d_name))
     107                 :          0 :                         continue;
     108                 :            : 
     109   [ #  #  #  # ]:          0 :                 if (!IN_SET(de->d_type, DT_LNK, DT_UNKNOWN))
     110                 :          0 :                         continue;
     111                 :            : 
     112         [ #  # ]:          0 :                 if (found) {
     113   [ #  #  #  #  :          0 :                         _cleanup_free_ char *u = NULL, *v = NULL, *a = NULL, *b = NULL;
             #  #  #  # ]
     114                 :            : 
     115                 :            :                         /* We found a device backed by multiple other devices. We don't really support automatic
     116                 :            :                          * discovery on such setups, with the exception of dm-verity partitions. In this case there are
     117                 :            :                          * two backing devices: the data partition and the hash partition. We are fine with such
     118                 :            :                          * setups, however, only if both partitions are on the same physical device. Hence, let's
     119                 :            :                          * verify this. */
     120                 :            : 
     121                 :          0 :                         u = path_join(p, de->d_name, "../dev");
     122         [ #  # ]:          0 :                         if (!u)
     123                 :          0 :                                 return -ENOMEM;
     124                 :            : 
     125                 :          0 :                         v = path_join(p, found->d_name, "../dev");
     126         [ #  # ]:          0 :                         if (!v)
     127                 :          0 :                                 return -ENOMEM;
     128                 :            : 
     129                 :          0 :                         r = read_one_line_file(u, &a);
     130         [ #  # ]:          0 :                         if (r < 0)
     131         [ #  # ]:          0 :                                 return log_debug_errno(r, "Failed to read %s: %m", u);
     132                 :            : 
     133                 :          0 :                         r = read_one_line_file(v, &b);
     134         [ #  # ]:          0 :                         if (r < 0)
     135         [ #  # ]:          0 :                                 return log_debug_errno(r, "Failed to read %s: %m", v);
     136                 :            : 
     137                 :            :                         /* Check if the parent device is the same. If not, then the two backing devices are on
     138                 :            :                          * different physical devices, and we don't support that. */
     139         [ #  # ]:          0 :                         if (!streq(a, b))
     140                 :          0 :                                 return -ENOTUNIQ;
     141                 :            :                 }
     142                 :            : 
     143                 :          0 :                 found = de;
     144                 :            :         }
     145                 :            : 
     146         [ #  # ]:          0 :         if (!found)
     147                 :          0 :                 return -ENOENT;
     148                 :            : 
     149   [ #  #  #  #  :          0 :         q = strjoina(p, "/", found->d_name, "/dev");
          #  #  #  #  #  
                #  #  # ]
     150                 :            : 
     151                 :          0 :         r = read_one_line_file(q, &t);
     152         [ #  # ]:          0 :         if (r < 0)
     153                 :          0 :                 return r;
     154                 :            : 
     155                 :          0 :         r = parse_dev(t, &devt);
     156         [ #  # ]:          0 :         if (r < 0)
     157                 :          0 :                 return -EINVAL;
     158                 :            : 
     159         [ #  # ]:          0 :         if (major(devt) == 0)
     160                 :          0 :                 return -ENOENT;
     161                 :            : 
     162                 :          0 :         *ret = devt;
     163                 :          0 :         return 1;
     164                 :            : }
     165                 :            : 
     166                 :          0 : int get_block_device_harder(const char *path, dev_t *ret) {
     167                 :            :         int r;
     168                 :            : 
     169         [ #  # ]:          0 :         assert(path);
     170         [ #  # ]:          0 :         assert(ret);
     171                 :            : 
     172                 :            :         /* Gets the backing block device for a file system, and handles LUKS encrypted file systems, looking for its
     173                 :            :          * immediate parent, if there is one. */
     174                 :            : 
     175                 :          0 :         r = get_block_device(path, ret);
     176         [ #  # ]:          0 :         if (r <= 0)
     177                 :          0 :                 return r;
     178                 :            : 
     179                 :          0 :         r = block_get_originating(*ret, ret);
     180         [ #  # ]:          0 :         if (r < 0)
     181         [ #  # ]:          0 :                 log_debug_errno(r, "Failed to chase block device '%s', ignoring: %m", path);
     182                 :            : 
     183                 :          0 :         return 1;
     184                 :            : }

Generated by: LCOV version 1.14