LCOV - code coverage report
Current view: top level - libsystemd/sd-device - device-enumerator.c (source / functions) Hit Total Coverage
Test: systemd_full.info Lines: 338 557 60.7 %
Date: 2019-08-23 13:36:53 Functions: 30 41 73.2 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 272 587 46.3 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: LGPL-2.1+ */
       2                 :            : 
       3                 :            : #include <fcntl.h>
       4                 :            : #include <unistd.h>
       5                 :            : 
       6                 :            : #include "sd-device.h"
       7                 :            : 
       8                 :            : #include "alloc-util.h"
       9                 :            : #include "device-enumerator-private.h"
      10                 :            : #include "device-util.h"
      11                 :            : #include "dirent-util.h"
      12                 :            : #include "fd-util.h"
      13                 :            : #include "set.h"
      14                 :            : #include "sort-util.h"
      15                 :            : #include "string-util.h"
      16                 :            : #include "strv.h"
      17                 :            : 
      18                 :            : #define DEVICE_ENUMERATE_MAX_DEPTH 256
      19                 :            : 
      20                 :            : typedef enum DeviceEnumerationType {
      21                 :            :         DEVICE_ENUMERATION_TYPE_DEVICES,
      22                 :            :         DEVICE_ENUMERATION_TYPE_SUBSYSTEMS,
      23                 :            :         _DEVICE_ENUMERATION_TYPE_MAX,
      24                 :            :         _DEVICE_ENUMERATION_TYPE_INVALID = -1,
      25                 :            : } DeviceEnumerationType;
      26                 :            : 
      27                 :            : struct sd_device_enumerator {
      28                 :            :         unsigned n_ref;
      29                 :            : 
      30                 :            :         DeviceEnumerationType type;
      31                 :            :         sd_device **devices;
      32                 :            :         size_t n_devices, n_allocated, current_device_index;
      33                 :            :         bool scan_uptodate;
      34                 :            : 
      35                 :            :         Set *match_subsystem;
      36                 :            :         Set *nomatch_subsystem;
      37                 :            :         Hashmap *match_sysattr;
      38                 :            :         Hashmap *nomatch_sysattr;
      39                 :            :         Hashmap *match_property;
      40                 :            :         Set *match_sysname;
      41                 :            :         Set *match_tag;
      42                 :            :         Set *match_parent;
      43                 :            :         bool match_allow_uninitialized;
      44                 :            : };
      45                 :            : 
      46                 :        372 : _public_ int sd_device_enumerator_new(sd_device_enumerator **ret) {
      47                 :        372 :         _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *enumerator = NULL;
      48                 :            : 
      49         [ -  + ]:        372 :         assert(ret);
      50                 :            : 
      51                 :        372 :         enumerator = new(sd_device_enumerator, 1);
      52         [ -  + ]:        372 :         if (!enumerator)
      53                 :          0 :                 return -ENOMEM;
      54                 :            : 
      55                 :        372 :         *enumerator = (sd_device_enumerator) {
      56                 :            :                 .n_ref = 1,
      57                 :            :                 .type = _DEVICE_ENUMERATION_TYPE_INVALID,
      58                 :            :         };
      59                 :            : 
      60                 :        372 :         *ret = TAKE_PTR(enumerator);
      61                 :            : 
      62                 :        372 :         return 0;
      63                 :            : }
      64                 :            : 
      65                 :        372 : static sd_device_enumerator *device_enumerator_free(sd_device_enumerator *enumerator) {
      66                 :            :         size_t i;
      67                 :            : 
      68         [ -  + ]:        372 :         assert(enumerator);
      69                 :            : 
      70         [ +  + ]:      20460 :         for (i = 0; i < enumerator->n_devices; i++)
      71                 :      20088 :                 sd_device_unref(enumerator->devices[i]);
      72                 :            : 
      73                 :        372 :         free(enumerator->devices);
      74                 :        372 :         set_free_free(enumerator->match_subsystem);
      75                 :        372 :         set_free_free(enumerator->nomatch_subsystem);
      76                 :        372 :         hashmap_free_free_free(enumerator->match_sysattr);
      77                 :        372 :         hashmap_free_free_free(enumerator->nomatch_sysattr);
      78                 :        372 :         hashmap_free_free_free(enumerator->match_property);
      79                 :        372 :         set_free_free(enumerator->match_sysname);
      80                 :        372 :         set_free_free(enumerator->match_tag);
      81                 :        372 :         set_free_free(enumerator->match_parent);
      82                 :            : 
      83                 :        372 :         return mfree(enumerator);
      84                 :            : }
      85                 :            : 
      86   [ -  +  -  +  :        372 : DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_device_enumerator, sd_device_enumerator, device_enumerator_free);
                   -  + ]
      87                 :            : 
      88                 :        312 : _public_ int sd_device_enumerator_add_match_subsystem(sd_device_enumerator *enumerator, const char *subsystem, int match) {
      89                 :            :         Set **set;
      90                 :            :         int r;
      91                 :            : 
      92   [ -  +  -  + ]:        312 :         assert_return(enumerator, -EINVAL);
      93   [ -  +  -  + ]:        312 :         assert_return(subsystem, -EINVAL);
      94                 :            : 
      95         [ +  + ]:        312 :         if (match)
      96                 :        308 :                 set = &enumerator->match_subsystem;
      97                 :            :         else
      98                 :          4 :                 set = &enumerator->nomatch_subsystem;
      99                 :            : 
     100                 :        312 :         r = set_ensure_allocated(set, NULL);
     101         [ -  + ]:        312 :         if (r < 0)
     102                 :          0 :                 return r;
     103                 :            : 
     104                 :        312 :         r = set_put_strdup(*set, subsystem);
     105         [ -  + ]:        312 :         if (r < 0)
     106                 :          0 :                 return r;
     107                 :            : 
     108                 :        312 :         enumerator->scan_uptodate = false;
     109                 :            : 
     110                 :        312 :         return 0;
     111                 :            : }
     112                 :            : 
     113                 :          0 : _public_ int sd_device_enumerator_add_match_sysattr(sd_device_enumerator *enumerator, const char *_sysattr, const char *_value, int match) {
     114                 :          0 :         _cleanup_free_ char *sysattr = NULL, *value = NULL;
     115                 :            :         Hashmap **hashmap;
     116                 :            :         int r;
     117                 :            : 
     118   [ #  #  #  # ]:          0 :         assert_return(enumerator, -EINVAL);
     119   [ #  #  #  # ]:          0 :         assert_return(_sysattr, -EINVAL);
     120                 :            : 
     121         [ #  # ]:          0 :         if (match)
     122                 :          0 :                 hashmap = &enumerator->match_sysattr;
     123                 :            :         else
     124                 :          0 :                 hashmap = &enumerator->nomatch_sysattr;
     125                 :            : 
     126                 :          0 :         r = hashmap_ensure_allocated(hashmap, NULL);
     127         [ #  # ]:          0 :         if (r < 0)
     128                 :          0 :                 return r;
     129                 :            : 
     130                 :          0 :         sysattr = strdup(_sysattr);
     131         [ #  # ]:          0 :         if (!sysattr)
     132                 :          0 :                 return -ENOMEM;
     133                 :            : 
     134         [ #  # ]:          0 :         if (_value) {
     135                 :          0 :                 value = strdup(_value);
     136         [ #  # ]:          0 :                 if (!value)
     137                 :          0 :                         return -ENOMEM;
     138                 :            :         }
     139                 :            : 
     140                 :          0 :         r = hashmap_put(*hashmap, sysattr, value);
     141         [ #  # ]:          0 :         if (r < 0)
     142                 :          0 :                 return r;
     143                 :            : 
     144                 :          0 :         sysattr = NULL;
     145                 :          0 :         value = NULL;
     146                 :            : 
     147                 :          0 :         enumerator->scan_uptodate = false;
     148                 :            : 
     149                 :          0 :         return 0;
     150                 :            : }
     151                 :            : 
     152                 :          4 : _public_ int sd_device_enumerator_add_match_property(sd_device_enumerator *enumerator, const char *_property, const char *_value) {
     153                 :          4 :         _cleanup_free_ char *property = NULL, *value = NULL;
     154                 :            :         int r;
     155                 :            : 
     156   [ -  +  -  + ]:          4 :         assert_return(enumerator, -EINVAL);
     157   [ -  +  -  + ]:          4 :         assert_return(_property, -EINVAL);
     158                 :            : 
     159                 :          4 :         r = hashmap_ensure_allocated(&enumerator->match_property, NULL);
     160         [ -  + ]:          4 :         if (r < 0)
     161                 :          0 :                 return r;
     162                 :            : 
     163                 :          4 :         property = strdup(_property);
     164         [ -  + ]:          4 :         if (!property)
     165                 :          0 :                 return -ENOMEM;
     166                 :            : 
     167         [ +  - ]:          4 :         if (_value) {
     168                 :          4 :                 value = strdup(_value);
     169         [ -  + ]:          4 :                 if (!value)
     170                 :          0 :                         return -ENOMEM;
     171                 :            :         }
     172                 :            : 
     173                 :          4 :         r = hashmap_put(enumerator->match_property, property, value);
     174         [ -  + ]:          4 :         if (r < 0)
     175                 :          0 :                 return r;
     176                 :            : 
     177                 :          4 :         property = NULL;
     178                 :          4 :         value = NULL;
     179                 :            : 
     180                 :          4 :         enumerator->scan_uptodate = false;
     181                 :            : 
     182                 :          4 :         return 0;
     183                 :            : }
     184                 :            : 
     185                 :          0 : _public_ int sd_device_enumerator_add_match_sysname(sd_device_enumerator *enumerator, const char *sysname) {
     186                 :            :         int r;
     187                 :            : 
     188   [ #  #  #  # ]:          0 :         assert_return(enumerator, -EINVAL);
     189   [ #  #  #  # ]:          0 :         assert_return(sysname, -EINVAL);
     190                 :            : 
     191                 :          0 :         r = set_ensure_allocated(&enumerator->match_sysname, NULL);
     192         [ #  # ]:          0 :         if (r < 0)
     193                 :          0 :                 return r;
     194                 :            : 
     195                 :          0 :         r = set_put_strdup(enumerator->match_sysname, sysname);
     196         [ #  # ]:          0 :         if (r < 0)
     197                 :          0 :                 return r;
     198                 :            : 
     199                 :          0 :         enumerator->scan_uptodate = false;
     200                 :            : 
     201                 :          0 :         return 0;
     202                 :            : }
     203                 :            : 
     204                 :         44 : _public_ int sd_device_enumerator_add_match_tag(sd_device_enumerator *enumerator, const char *tag) {
     205                 :            :         int r;
     206                 :            : 
     207   [ -  +  -  + ]:         44 :         assert_return(enumerator, -EINVAL);
     208   [ -  +  -  + ]:         44 :         assert_return(tag, -EINVAL);
     209                 :            : 
     210                 :         44 :         r = set_ensure_allocated(&enumerator->match_tag, NULL);
     211         [ -  + ]:         44 :         if (r < 0)
     212                 :          0 :                 return r;
     213                 :            : 
     214                 :         44 :         r = set_put_strdup(enumerator->match_tag, tag);
     215         [ -  + ]:         44 :         if (r < 0)
     216                 :          0 :                 return r;
     217                 :            : 
     218                 :         44 :         enumerator->scan_uptodate = false;
     219                 :            : 
     220                 :         44 :         return 0;
     221                 :            : }
     222                 :            : 
     223                 :          0 : static void device_enumerator_clear_match_parent(sd_device_enumerator *enumerator) {
     224         [ #  # ]:          0 :         if (!enumerator)
     225                 :          0 :                 return;
     226                 :            : 
     227                 :          0 :         set_clear_free(enumerator->match_parent);
     228                 :            : }
     229                 :            : 
     230                 :          0 : int device_enumerator_add_match_parent_incremental(sd_device_enumerator *enumerator, sd_device *parent) {
     231                 :            :         const char *path;
     232                 :            :         int r;
     233                 :            : 
     234   [ #  #  #  # ]:          0 :         assert_return(enumerator, -EINVAL);
     235   [ #  #  #  # ]:          0 :         assert_return(parent, -EINVAL);
     236                 :            : 
     237                 :          0 :         r = sd_device_get_syspath(parent, &path);
     238         [ #  # ]:          0 :         if (r < 0)
     239                 :          0 :                 return r;
     240                 :            : 
     241                 :          0 :         r = set_ensure_allocated(&enumerator->match_parent, NULL);
     242         [ #  # ]:          0 :         if (r < 0)
     243                 :          0 :                 return r;
     244                 :            : 
     245                 :          0 :         r = set_put_strdup(enumerator->match_parent, path);
     246         [ #  # ]:          0 :         if (r < 0)
     247                 :          0 :                 return r;
     248                 :            : 
     249                 :          0 :         enumerator->scan_uptodate = false;
     250                 :            : 
     251                 :          0 :         return 0;
     252                 :            : }
     253                 :            : 
     254                 :          0 : _public_ int sd_device_enumerator_add_match_parent(sd_device_enumerator *enumerator, sd_device *parent) {
     255                 :          0 :         device_enumerator_clear_match_parent(enumerator);
     256                 :          0 :         return device_enumerator_add_match_parent_incremental(enumerator, parent);
     257                 :            : }
     258                 :            : 
     259                 :         36 : _public_ int sd_device_enumerator_allow_uninitialized(sd_device_enumerator *enumerator) {
     260   [ -  +  -  + ]:         36 :         assert_return(enumerator, -EINVAL);
     261                 :            : 
     262                 :         36 :         enumerator->match_allow_uninitialized = true;
     263                 :            : 
     264                 :         36 :         enumerator->scan_uptodate = false;
     265                 :            : 
     266                 :         36 :         return 0;
     267                 :            : }
     268                 :            : 
     269                 :          4 : int device_enumerator_add_match_is_initialized(sd_device_enumerator *enumerator) {
     270   [ -  +  -  + ]:          4 :         assert_return(enumerator, -EINVAL);
     271                 :            : 
     272                 :          4 :         enumerator->match_allow_uninitialized = false;
     273                 :            : 
     274                 :          4 :         enumerator->scan_uptodate = false;
     275                 :            : 
     276                 :          4 :         return 0;
     277                 :            : }
     278                 :            : 
     279                 :     136440 : static int device_compare(sd_device * const *_a, sd_device * const *_b) {
     280                 :     136440 :         sd_device *a = *(sd_device **)_a, *b = *(sd_device **)_b;
     281                 :            :         const char *devpath_a, *devpath_b, *sound_a;
     282                 :            :         bool delay_a, delay_b;
     283                 :            :         int r;
     284                 :            : 
     285         [ -  + ]:     136440 :         assert_se(sd_device_get_devpath(a, &devpath_a) >= 0);
     286         [ -  + ]:     136440 :         assert_se(sd_device_get_devpath(b, &devpath_b) >= 0);
     287                 :            : 
     288                 :     136440 :         sound_a = strstr(devpath_a, "/sound/card");
     289         [ +  + ]:     136440 :         if (sound_a) {
     290                 :            :                 /* For sound cards the control device must be enumerated last to
     291                 :            :                  * make sure it's the final device node that gets ACLs applied.
     292                 :            :                  * Applications rely on this fact and use ACL changes on the
     293                 :            :                  * control node as an indicator that the ACL change of the
     294                 :            :                  * entire sound card completed. The kernel makes this guarantee
     295                 :            :                  * when creating those devices, and hence we should too when
     296                 :            :                  * enumerating them. */
     297                 :       4216 :                 sound_a += STRLEN("/sound/card");
     298                 :       4216 :                 sound_a = strchr(sound_a, '/');
     299                 :            : 
     300         [ +  + ]:       4216 :                 if (sound_a) {
     301                 :            :                         unsigned prefix_len;
     302                 :            : 
     303                 :       3708 :                         prefix_len = sound_a - devpath_a;
     304                 :            : 
     305         [ +  + ]:       3708 :                         if (strncmp(devpath_a, devpath_b, prefix_len) == 0) {
     306                 :            :                                 const char *sound_b;
     307                 :            : 
     308                 :       1664 :                                 sound_b = devpath_b + prefix_len;
     309                 :            : 
     310   [ +  +  +  - ]:       1780 :                                 if (startswith(sound_a, "/controlC") &&
     311                 :        116 :                                     !startswith(sound_b, "/contolC"))
     312                 :        116 :                                         return 1;
     313                 :            : 
     314   [ +  -  +  + ]:       3096 :                                 if (!startswith(sound_a, "/controlC") &&
     315                 :       1548 :                                     startswith(sound_b, "/controlC"))
     316                 :         60 :                                         return -1;
     317                 :            :                         }
     318                 :            :                 }
     319                 :            :         }
     320                 :            : 
     321                 :            :         /* md and dm devices are enumerated after all other devices */
     322   [ +  -  +  + ]:     136264 :         delay_a = strstr(devpath_a, "/block/md") || strstr(devpath_a, "/block/dm-");
     323   [ +  -  +  + ]:     136264 :         delay_b = strstr(devpath_b, "/block/md") || strstr(devpath_b, "/block/dm-");
     324         [ +  + ]:     136264 :         r = CMP(delay_a, delay_b);
     325         [ +  + ]:     136264 :         if (r != 0)
     326                 :       1172 :                 return r;
     327                 :            : 
     328                 :     135092 :         return strcmp(devpath_a, devpath_b);
     329                 :            : }
     330                 :            : 
     331                 :      20248 : int device_enumerator_add_device(sd_device_enumerator *enumerator, sd_device *device) {
     332   [ -  +  -  + ]:      20248 :         assert_return(enumerator, -EINVAL);
     333   [ -  +  -  + ]:      20248 :         assert_return(device, -EINVAL);
     334                 :            : 
     335         [ -  + ]:      20248 :         if (!GREEDY_REALLOC(enumerator->devices, enumerator->n_allocated, enumerator->n_devices + 1))
     336                 :          0 :                 return -ENOMEM;
     337                 :            : 
     338                 :      20248 :         enumerator->devices[enumerator->n_devices++] = sd_device_ref(device);
     339                 :            : 
     340                 :      20248 :         return 0;
     341                 :            : }
     342                 :            : 
     343                 :          0 : static bool match_sysattr_value(sd_device *device, const char *sysattr, const char *match_value) {
     344                 :            :         const char *value;
     345                 :            :         int r;
     346                 :            : 
     347         [ #  # ]:          0 :         assert(device);
     348         [ #  # ]:          0 :         assert(sysattr);
     349                 :            : 
     350                 :          0 :         r = sd_device_get_sysattr_value(device, sysattr, &value);
     351         [ #  # ]:          0 :         if (r < 0)
     352                 :          0 :                 return false;
     353                 :            : 
     354         [ #  # ]:          0 :         if (!match_value)
     355                 :          0 :                 return true;
     356                 :            : 
     357         [ #  # ]:          0 :         if (fnmatch(match_value, value, 0) == 0)
     358                 :          0 :                 return true;
     359                 :            : 
     360                 :          0 :         return false;
     361                 :            : }
     362                 :            : 
     363                 :      20212 : static bool match_sysattr(sd_device_enumerator *enumerator, sd_device *device) {
     364                 :            :         const char *sysattr;
     365                 :            :         const char *value;
     366                 :            :         Iterator i;
     367                 :            : 
     368         [ -  + ]:      20212 :         assert(enumerator);
     369         [ -  + ]:      20212 :         assert(device);
     370                 :            : 
     371         [ -  + ]:      20212 :         HASHMAP_FOREACH_KEY(value, sysattr, enumerator->nomatch_sysattr, i)
     372         [ #  # ]:          0 :                 if (match_sysattr_value(device, sysattr, value))
     373                 :          0 :                         return false;
     374                 :            : 
     375         [ -  + ]:      20212 :         HASHMAP_FOREACH_KEY(value, sysattr, enumerator->match_sysattr, i)
     376         [ #  # ]:          0 :                 if (!match_sysattr_value(device, sysattr, value))
     377                 :          0 :                         return false;
     378                 :            : 
     379                 :      20212 :         return true;
     380                 :            : }
     381                 :            : 
     382                 :      23096 : static bool match_property(sd_device_enumerator *enumerator, sd_device *device) {
     383                 :            :         const char *property;
     384                 :            :         const char *value;
     385                 :            :         Iterator i;
     386                 :            : 
     387         [ -  + ]:      23096 :         assert(enumerator);
     388         [ -  + ]:      23096 :         assert(device);
     389                 :            : 
     390         [ +  + ]:      23096 :         if (hashmap_isempty(enumerator->match_property))
     391                 :      20200 :                 return true;
     392                 :            : 
     393         [ +  + ]:       5780 :         HASHMAP_FOREACH_KEY(value, property, enumerator->match_property, i) {
     394                 :            :                 const char *property_dev, *value_dev;
     395                 :            : 
     396         [ +  + ]:      20280 :                 FOREACH_DEVICE_PROPERTY(device, property_dev, value_dev) {
     397         [ +  + ]:      17396 :                         if (fnmatch(property, property_dev, 0) != 0)
     398                 :      17276 :                                 continue;
     399                 :            : 
     400   [ -  +  #  # ]:        120 :                         if (!value && !value_dev)
     401                 :         12 :                                 return true;
     402                 :            : 
     403   [ +  -  -  + ]:        120 :                         if (!value || !value_dev)
     404                 :          0 :                                 continue;
     405                 :            : 
     406         [ +  + ]:        120 :                         if (fnmatch(value, value_dev, 0) == 0)
     407                 :         12 :                                 return true;
     408                 :            :                 }
     409                 :            :         }
     410                 :            : 
     411                 :       2884 :         return false;
     412                 :            : }
     413                 :            : 
     414                 :      20632 : static bool match_tag(sd_device_enumerator *enumerator, sd_device *device) {
     415                 :            :         const char *tag;
     416                 :            :         Iterator i;
     417                 :            : 
     418         [ -  + ]:      20632 :         assert(enumerator);
     419         [ -  + ]:      20632 :         assert(device);
     420                 :            : 
     421         [ -  + ]:      20632 :         SET_FOREACH(tag, enumerator->match_tag, i)
     422         [ #  # ]:          0 :                 if (!sd_device_has_tag(device, tag))
     423                 :          0 :                         return false;
     424                 :            : 
     425                 :      20632 :         return true;
     426                 :            : }
     427                 :            : 
     428                 :      23096 : static bool match_parent(sd_device_enumerator *enumerator, sd_device *device) {
     429                 :            :         const char *syspath_parent, *syspath;
     430                 :            :         Iterator i;
     431                 :            : 
     432         [ -  + ]:      23096 :         assert(enumerator);
     433         [ -  + ]:      23096 :         assert(device);
     434                 :            : 
     435         [ +  - ]:      23096 :         if (set_isempty(enumerator->match_parent))
     436                 :      23096 :                 return true;
     437                 :            : 
     438         [ #  # ]:          0 :         assert_se(sd_device_get_syspath(device, &syspath) >= 0);
     439                 :            : 
     440         [ #  # ]:          0 :         SET_FOREACH(syspath_parent, enumerator->match_parent, i)
     441         [ #  # ]:          0 :                 if (path_startswith(syspath, syspath_parent))
     442                 :          0 :                         return true;
     443                 :            : 
     444                 :          0 :         return false;
     445                 :            : }
     446                 :            : 
     447                 :      23140 : static bool match_sysname(sd_device_enumerator *enumerator, const char *sysname) {
     448                 :            :         const char *sysname_match;
     449                 :            :         Iterator i;
     450                 :            : 
     451         [ -  + ]:      23140 :         assert(enumerator);
     452         [ -  + ]:      23140 :         assert(sysname);
     453                 :            : 
     454         [ +  - ]:      23140 :         if (set_isempty(enumerator->match_sysname))
     455                 :      23140 :                 return true;
     456                 :            : 
     457         [ #  # ]:          0 :         SET_FOREACH(sysname_match, enumerator->match_sysname, i)
     458         [ #  # ]:          0 :                 if (fnmatch(sysname_match, sysname, 0) == 0)
     459                 :          0 :                         return true;
     460                 :            : 
     461                 :          0 :         return false;
     462                 :            : }
     463                 :            : 
     464                 :       2784 : static int enumerator_scan_dir_and_add_devices(sd_device_enumerator *enumerator, const char *basedir, const char *subdir1, const char *subdir2) {
     465                 :       2784 :         _cleanup_closedir_ DIR *dir = NULL;
     466                 :            :         char *path;
     467                 :            :         struct dirent *dent;
     468                 :       2784 :         int r = 0;
     469                 :            : 
     470         [ -  + ]:       2784 :         assert(enumerator);
     471         [ -  + ]:       2784 :         assert(basedir);
     472                 :            : 
     473   [ +  +  +  -  :      19488 :         path = strjoina("/sys/", basedir, "/");
          -  +  -  +  +  
                +  +  - ]
     474                 :            : 
     475         [ +  + ]:       2784 :         if (subdir1)
     476   [ +  +  +  -  :      19376 :                 path = strjoina(path, subdir1, "/");
          -  +  -  +  +  
                +  +  - ]
     477                 :            : 
     478         [ +  + ]:       2784 :         if (subdir2)
     479   [ +  +  +  -  :       8960 :                 path = strjoina(path, subdir2, "/");
          -  +  -  +  +  
                +  +  - ]
     480                 :            : 
     481                 :       2784 :         dir = opendir(path);
     482         [ -  + ]:       2784 :         if (!dir)
     483                 :          0 :                 return -errno;
     484                 :            : 
     485   [ +  +  -  + ]:      29028 :         FOREACH_DIRENT_ALL(dent, dir, return -errno) {
     486         [ +  + ]:      26244 :                 _cleanup_(sd_device_unrefp) sd_device *device = NULL;
     487                 :      26244 :                 char syspath[strlen(path) + 1 + strlen(dent->d_name) + 1];
     488                 :            :                 int initialized, k;
     489                 :            : 
     490         [ +  + ]:      26244 :                 if (dent->d_name[0] == '.')
     491                 :       5568 :                         continue;
     492                 :            : 
     493         [ -  + ]:      20676 :                 if (!match_sysname(enumerator, dent->d_name))
     494                 :          0 :                         continue;
     495                 :            : 
     496                 :      20676 :                 (void) sprintf(syspath, "%s%s", path, dent->d_name);
     497                 :            : 
     498                 :      20676 :                 k = sd_device_new_from_syspath(&device, syspath);
     499         [ +  + ]:      20676 :                 if (k < 0) {
     500         [ -  + ]:         44 :                         if (k != -ENODEV)
     501                 :            :                                 /* this is necessarily racey, so ignore missing devices */
     502                 :          0 :                                 r = k;
     503                 :            : 
     504                 :         44 :                         continue;
     505                 :            :                 }
     506                 :            : 
     507                 :      20632 :                 initialized = sd_device_get_is_initialized(device);
     508         [ -  + ]:      20632 :                 if (initialized < 0) {
     509                 :          0 :                         r = initialized;
     510                 :          0 :                         continue;
     511                 :            :                 }
     512                 :            : 
     513                 :            :                 /*
     514                 :            :                  * All devices with a device node or network interfaces
     515                 :            :                  * possibly need udev to adjust the device node permission
     516                 :            :                  * or context, or rename the interface before it can be
     517                 :            :                  * reliably used from other processes.
     518                 :            :                  *
     519                 :            :                  * For now, we can only check these types of devices, we
     520                 :            :                  * might not store a database, and have no way to find out
     521                 :            :                  * for all other types of devices.
     522                 :            :                  */
     523   [ +  +  +  + ]:      20632 :                 if (!enumerator->match_allow_uninitialized &&
     524         [ +  - ]:       2864 :                     !initialized &&
     525         [ -  + ]:       5728 :                     (sd_device_get_devnum(device, NULL) >= 0 ||
     526                 :       2864 :                      sd_device_get_ifindex(device, NULL) >= 0))
     527                 :          0 :                         continue;
     528                 :            : 
     529         [ -  + ]:      20632 :                 if (!match_parent(enumerator, device))
     530                 :          0 :                         continue;
     531                 :            : 
     532         [ -  + ]:      20632 :                 if (!match_tag(enumerator, device))
     533                 :          0 :                         continue;
     534                 :            : 
     535         [ +  + ]:      20632 :                 if (!match_property(enumerator, device))
     536                 :       2884 :                         continue;
     537                 :            : 
     538         [ -  + ]:      17748 :                 if (!match_sysattr(enumerator, device))
     539                 :          0 :                         continue;
     540                 :            : 
     541                 :      17748 :                 k = device_enumerator_add_device(enumerator, device);
     542         [ -  + ]:      17748 :                 if (k < 0)
     543                 :          0 :                         r = k;
     544                 :            :         }
     545                 :            : 
     546                 :       2784 :         return r;
     547                 :            : }
     548                 :            : 
     549                 :      36744 : static bool match_subsystem(sd_device_enumerator *enumerator, const char *subsystem) {
     550                 :            :         const char *subsystem_match;
     551                 :            :         Iterator i;
     552                 :            : 
     553         [ -  + ]:      36744 :         assert(enumerator);
     554                 :            : 
     555         [ -  + ]:      36744 :         if (!subsystem)
     556                 :          0 :                 return false;
     557                 :            : 
     558         [ +  + ]:      37164 :         SET_FOREACH(subsystem_match, enumerator->nomatch_subsystem, i)
     559         [ +  + ]:        424 :                 if (fnmatch(subsystem_match, subsystem, 0) == 0)
     560                 :          4 :                         return false;
     561                 :            : 
     562         [ +  + ]:      36740 :         if (set_isempty(enumerator->match_subsystem))
     563                 :       4940 :                 return true;
     564                 :            : 
     565         [ +  + ]:      64120 :         SET_FOREACH(subsystem_match, enumerator->match_subsystem, i)
     566         [ +  + ]:      32636 :                 if (fnmatch(subsystem_match, subsystem, 0) == 0)
     567                 :        316 :                         return true;
     568                 :            : 
     569                 :      31484 :         return false;
     570                 :            : }
     571                 :            : 
     572                 :        648 : static int enumerator_scan_dir(sd_device_enumerator *enumerator, const char *basedir, const char *subdir, const char *subsystem) {
     573                 :        648 :         _cleanup_closedir_ DIR *dir = NULL;
     574                 :            :         char *path;
     575                 :            :         struct dirent *dent;
     576                 :        648 :         int r = 0;
     577                 :            : 
     578   [ +  +  +  -  :       3240 :         path = strjoina("/sys/", basedir);
          -  +  -  +  +  
                +  +  - ]
     579                 :            : 
     580                 :        648 :         dir = opendir(path);
     581         [ -  + ]:        648 :         if (!dir)
     582                 :          0 :                 return -errno;
     583                 :            : 
     584         [ -  + ]:        648 :         log_debug("sd-device-enumerator: Scanning %s", path);
     585                 :            : 
     586   [ +  +  -  + ]:      36200 :         FOREACH_DIRENT_ALL(dent, dir, return -errno) {
     587                 :            :                 int k;
     588                 :            : 
     589         [ +  + ]:      35552 :                 if (dent->d_name[0] == '.')
     590                 :       1296 :                         continue;
     591                 :            : 
     592   [ +  +  +  + ]:      34256 :                 if (!match_subsystem(enumerator, subsystem ? : dent->d_name))
     593                 :      31488 :                         continue;
     594                 :            : 
     595                 :       2768 :                 k = enumerator_scan_dir_and_add_devices(enumerator, basedir, dent->d_name, subdir);
     596         [ -  + ]:       2768 :                 if (k < 0)
     597                 :          0 :                         r = k;
     598                 :            :         }
     599                 :            : 
     600                 :        648 :         return r;
     601                 :            : }
     602                 :            : 
     603                 :         44 : static int enumerator_scan_devices_tag(sd_device_enumerator *enumerator, const char *tag) {
     604                 :         44 :         _cleanup_closedir_ DIR *dir = NULL;
     605                 :            :         char *path;
     606                 :            :         struct dirent *dent;
     607                 :         44 :         int r = 0;
     608                 :            : 
     609         [ -  + ]:         44 :         assert(enumerator);
     610         [ -  + ]:         44 :         assert(tag);
     611                 :            : 
     612   [ +  +  +  -  :        220 :         path = strjoina("/run/udev/tags/", tag);
          -  +  -  +  +  
                +  +  - ]
     613                 :            : 
     614                 :         44 :         dir = opendir(path);
     615         [ -  + ]:         44 :         if (!dir) {
     616         [ #  # ]:          0 :                 if (errno != ENOENT)
     617         [ #  # ]:          0 :                         return log_debug_errno(errno, "sd-device-enumerator: Failed to open tags directory %s: %m", path);
     618                 :          0 :                 return 0;
     619                 :            :         }
     620                 :            : 
     621                 :            :         /* TODO: filter away subsystems? */
     622                 :            : 
     623   [ +  +  -  + ]:       2596 :         FOREACH_DIRENT_ALL(dent, dir, return -errno) {
     624         [ +  + ]:       2552 :                 _cleanup_(sd_device_unrefp) sd_device *device = NULL;
     625                 :            :                 const char *subsystem, *sysname;
     626                 :            :                 int k;
     627                 :            : 
     628         [ +  + ]:       2552 :                 if (dent->d_name[0] == '.')
     629                 :         88 :                         continue;
     630                 :            : 
     631                 :       2464 :                 k = sd_device_new_from_device_id(&device, dent->d_name);
     632         [ -  + ]:       2464 :                 if (k < 0) {
     633         [ #  # ]:          0 :                         if (k != -ENODEV)
     634                 :            :                                 /* this is necessarily racy, so ignore missing devices */
     635                 :          0 :                                 r = k;
     636                 :            : 
     637                 :          0 :                         continue;
     638                 :            :                 }
     639                 :            : 
     640                 :       2464 :                 k = sd_device_get_subsystem(device, &subsystem);
     641         [ -  + ]:       2464 :                 if (k < 0) {
     642                 :          0 :                         r = k;
     643                 :          0 :                         continue;
     644                 :            :                 }
     645                 :            : 
     646         [ -  + ]:       2464 :                 if (!match_subsystem(enumerator, subsystem))
     647                 :          0 :                         continue;
     648                 :            : 
     649                 :       2464 :                 k = sd_device_get_sysname(device, &sysname);
     650         [ -  + ]:       2464 :                 if (k < 0) {
     651                 :          0 :                         r = k;
     652                 :          0 :                         continue;
     653                 :            :                 }
     654                 :            : 
     655         [ -  + ]:       2464 :                 if (!match_sysname(enumerator, sysname))
     656                 :          0 :                         continue;
     657                 :            : 
     658         [ -  + ]:       2464 :                 if (!match_parent(enumerator, device))
     659                 :          0 :                         continue;
     660                 :            : 
     661         [ -  + ]:       2464 :                 if (!match_property(enumerator, device))
     662                 :          0 :                         continue;
     663                 :            : 
     664         [ -  + ]:       2464 :                 if (!match_sysattr(enumerator, device))
     665                 :          0 :                         continue;
     666                 :            : 
     667                 :       2464 :                 k = device_enumerator_add_device(enumerator, device);
     668         [ -  + ]:       2464 :                 if (k < 0) {
     669                 :          0 :                         r = k;
     670                 :          0 :                         continue;
     671                 :            :                 }
     672                 :            :         }
     673                 :            : 
     674                 :         44 :         return r;
     675                 :            : }
     676                 :            : 
     677                 :         44 : static int enumerator_scan_devices_tags(sd_device_enumerator *enumerator) {
     678                 :            :         const char *tag;
     679                 :            :         Iterator i;
     680                 :         44 :         int r = 0;
     681                 :            : 
     682         [ -  + ]:         44 :         assert(enumerator);
     683                 :            : 
     684         [ +  + ]:         88 :         SET_FOREACH(tag, enumerator->match_tag, i) {
     685                 :            :                 int k;
     686                 :            : 
     687                 :         44 :                 k = enumerator_scan_devices_tag(enumerator, tag);
     688         [ -  + ]:         44 :                 if (k < 0)
     689                 :          0 :                         r = k;
     690                 :            :         }
     691                 :            : 
     692                 :         44 :         return r;
     693                 :            : }
     694                 :            : 
     695                 :          0 : static int parent_add_child(sd_device_enumerator *enumerator, const char *path) {
     696                 :          0 :         _cleanup_(sd_device_unrefp) sd_device *device = NULL;
     697                 :            :         const char *subsystem, *sysname;
     698                 :            :         int r;
     699                 :            : 
     700                 :          0 :         r = sd_device_new_from_syspath(&device, path);
     701         [ #  # ]:          0 :         if (r == -ENODEV)
     702                 :            :                 /* this is necessarily racy, so ignore missing devices */
     703                 :          0 :                 return 0;
     704         [ #  # ]:          0 :         else if (r < 0)
     705                 :          0 :                 return r;
     706                 :            : 
     707                 :          0 :         r = sd_device_get_subsystem(device, &subsystem);
     708         [ #  # ]:          0 :         if (r == -ENOENT)
     709                 :          0 :                 return 0;
     710         [ #  # ]:          0 :         if (r < 0)
     711                 :          0 :                 return r;
     712                 :            : 
     713         [ #  # ]:          0 :         if (!match_subsystem(enumerator, subsystem))
     714                 :          0 :                 return 0;
     715                 :            : 
     716                 :          0 :         r = sd_device_get_sysname(device, &sysname);
     717         [ #  # ]:          0 :         if (r < 0)
     718                 :          0 :                 return r;
     719                 :            : 
     720         [ #  # ]:          0 :         if (!match_sysname(enumerator, sysname))
     721                 :          0 :                 return 0;
     722                 :            : 
     723         [ #  # ]:          0 :         if (!match_property(enumerator, device))
     724                 :          0 :                 return 0;
     725                 :            : 
     726         [ #  # ]:          0 :         if (!match_sysattr(enumerator, device))
     727                 :          0 :                 return 0;
     728                 :            : 
     729                 :          0 :         r = device_enumerator_add_device(enumerator, device);
     730         [ #  # ]:          0 :         if (r < 0)
     731                 :          0 :                 return r;
     732                 :            : 
     733                 :          0 :         return 1;
     734                 :            : }
     735                 :            : 
     736                 :          0 : static int parent_crawl_children(sd_device_enumerator *enumerator, const char *path, unsigned maxdepth) {
     737                 :          0 :         _cleanup_closedir_ DIR *dir = NULL;
     738                 :            :         struct dirent *dent;
     739                 :          0 :         int r = 0;
     740                 :            : 
     741                 :          0 :         dir = opendir(path);
     742         [ #  # ]:          0 :         if (!dir)
     743         [ #  # ]:          0 :                 return log_debug_errno(errno, "sd-device-enumerator: Failed to open parent directory %s: %m", path);
     744                 :            : 
     745   [ #  #  #  # ]:          0 :         FOREACH_DIRENT_ALL(dent, dir, return -errno) {
     746      [ #  #  # ]:          0 :                 _cleanup_free_ char *child = NULL;
     747                 :            :                 int k;
     748                 :            : 
     749         [ #  # ]:          0 :                 if (dent->d_name[0] == '.')
     750                 :          0 :                         continue;
     751                 :            : 
     752         [ #  # ]:          0 :                 if (dent->d_type != DT_DIR)
     753                 :          0 :                         continue;
     754                 :            : 
     755                 :          0 :                 child = path_join(path, dent->d_name);
     756         [ #  # ]:          0 :                 if (!child)
     757                 :          0 :                         return -ENOMEM;
     758                 :            : 
     759                 :          0 :                 k = parent_add_child(enumerator, child);
     760         [ #  # ]:          0 :                 if (k < 0)
     761                 :          0 :                         r = k;
     762                 :            : 
     763         [ #  # ]:          0 :                 if (maxdepth > 0)
     764                 :          0 :                         parent_crawl_children(enumerator, child, maxdepth - 1);
     765                 :            :                 else
     766         [ #  # ]:          0 :                         log_debug("sd-device-enumerator: Max depth reached, %s: ignoring devices", child);
     767                 :            :         }
     768                 :            : 
     769                 :          0 :         return r;
     770                 :            : }
     771                 :            : 
     772                 :          0 : static int enumerator_scan_devices_children(sd_device_enumerator *enumerator) {
     773                 :            :         const char *path;
     774                 :          0 :         int r = 0, k;
     775                 :            :         Iterator i;
     776                 :            : 
     777         [ #  # ]:          0 :         SET_FOREACH(path, enumerator->match_parent, i) {
     778                 :          0 :                 k = parent_add_child(enumerator, path);
     779         [ #  # ]:          0 :                 if (k < 0)
     780                 :          0 :                         r = k;
     781                 :            : 
     782                 :          0 :                 k = parent_crawl_children(enumerator, path, DEVICE_ENUMERATE_MAX_DEPTH);
     783         [ #  # ]:          0 :                 if (k < 0)
     784                 :          0 :                         r = k;
     785                 :            :         }
     786                 :            : 
     787                 :          0 :         return r;
     788                 :            : }
     789                 :            : 
     790                 :        320 : static int enumerator_scan_devices_all(sd_device_enumerator *enumerator) {
     791                 :        320 :         int r = 0;
     792                 :            : 
     793         [ -  + ]:        320 :         log_debug("sd-device-enumerator: Scan all dirs");
     794                 :            : 
     795         [ -  + ]:        320 :         if (access("/sys/subsystem", F_OK) >= 0) {
     796                 :            :                 /* we have /subsystem/, forget all the old stuff */
     797                 :          0 :                 r = enumerator_scan_dir(enumerator, "subsystem", "devices", NULL);
     798         [ #  # ]:          0 :                 if (r < 0)
     799         [ #  # ]:          0 :                         return log_debug_errno(r, "sd-device-enumerator: Failed to scan /sys/subsystem: %m");
     800                 :            :         } else {
     801                 :            :                 int k;
     802                 :            : 
     803                 :        320 :                 k = enumerator_scan_dir(enumerator, "bus", "devices", NULL);
     804         [ -  + ]:        320 :                 if (k < 0) {
     805         [ #  # ]:          0 :                         log_debug_errno(k, "sd-device-enumerator: Failed to scan /sys/bus: %m");
     806                 :          0 :                         r = k;
     807                 :            :                 }
     808                 :            : 
     809                 :        320 :                 k = enumerator_scan_dir(enumerator, "class", NULL, NULL);
     810         [ -  + ]:        320 :                 if (k < 0) {
     811         [ #  # ]:          0 :                         log_debug_errno(k, "sd-device-enumerator: Failed to scan /sys/class: %m");
     812                 :          0 :                         r = k;
     813                 :            :                 }
     814                 :            :         }
     815                 :            : 
     816                 :        320 :         return r;
     817                 :            : }
     818                 :            : 
     819                 :        372 : static void device_enumerator_dedup_devices(sd_device_enumerator *enumerator) {
     820                 :            :         sd_device **a, **b, **end;
     821                 :            : 
     822         [ -  + ]:        372 :         assert(enumerator);
     823                 :            : 
     824         [ +  + ]:        372 :         if (enumerator->n_devices <= 1)
     825                 :         84 :                 return;
     826                 :            : 
     827                 :        288 :         a = enumerator->devices + 1;
     828                 :        288 :         b = enumerator->devices;
     829                 :        288 :         end = enumerator->devices + enumerator->n_devices;
     830                 :            : 
     831         [ +  + ]:      20128 :         for (; a < end; a++) {
     832                 :            :                 const char *devpath_a, *devpath_b;
     833                 :            : 
     834         [ -  + ]:      19840 :                 assert_se(sd_device_get_devpath(*a, &devpath_a) >= 0);
     835         [ -  + ]:      19840 :                 assert_se(sd_device_get_devpath(*b, &devpath_b) >= 0);
     836                 :            : 
     837         [ +  + ]:      19840 :                 if (path_equal(devpath_a, devpath_b))
     838                 :        160 :                         sd_device_unref(*a);
     839                 :            :                 else
     840                 :      19680 :                         *(++b) = *a;
     841                 :            :         }
     842                 :            : 
     843                 :        288 :         enumerator->n_devices = b - enumerator->devices + 1;
     844                 :            : }
     845                 :            : 
     846                 :        372 : int device_enumerator_scan_devices(sd_device_enumerator *enumerator) {
     847                 :        372 :         int r = 0, k;
     848                 :            :         size_t i;
     849                 :            : 
     850         [ -  + ]:        372 :         assert(enumerator);
     851                 :            : 
     852         [ +  + ]:        372 :         if (enumerator->scan_uptodate &&
     853         [ +  - ]:          8 :             enumerator->type == DEVICE_ENUMERATION_TYPE_DEVICES)
     854                 :          8 :                 return 0;
     855                 :            : 
     856         [ -  + ]:        364 :         for (i = 0; i < enumerator->n_devices; i++)
     857                 :          0 :                 sd_device_unref(enumerator->devices[i]);
     858                 :            : 
     859                 :        364 :         enumerator->n_devices = 0;
     860                 :            : 
     861         [ +  + ]:        364 :         if (!set_isempty(enumerator->match_tag)) {
     862                 :         44 :                 k = enumerator_scan_devices_tags(enumerator);
     863         [ -  + ]:         44 :                 if (k < 0)
     864                 :          0 :                         r = k;
     865         [ -  + ]:        320 :         } else if (enumerator->match_parent) {
     866                 :          0 :                 k = enumerator_scan_devices_children(enumerator);
     867         [ #  # ]:          0 :                 if (k < 0)
     868                 :          0 :                         r = k;
     869                 :            :         } else {
     870                 :        320 :                 k = enumerator_scan_devices_all(enumerator);
     871         [ -  + ]:        320 :                 if (k < 0)
     872                 :          0 :                         r = k;
     873                 :            :         }
     874                 :            : 
     875                 :        364 :         typesafe_qsort(enumerator->devices, enumerator->n_devices, device_compare);
     876                 :        364 :         device_enumerator_dedup_devices(enumerator);
     877                 :            : 
     878                 :        364 :         enumerator->scan_uptodate = true;
     879                 :        364 :         enumerator->type = DEVICE_ENUMERATION_TYPE_DEVICES;
     880                 :            : 
     881                 :        364 :         return r;
     882                 :            : }
     883                 :            : 
     884                 :        340 : _public_ sd_device *sd_device_enumerator_get_device_first(sd_device_enumerator *enumerator) {
     885                 :            :         int r;
     886                 :            : 
     887   [ -  +  -  + ]:        340 :         assert_return(enumerator, NULL);
     888                 :            : 
     889                 :        340 :         r = device_enumerator_scan_devices(enumerator);
     890         [ -  + ]:        340 :         if (r < 0)
     891                 :          0 :                 return NULL;
     892                 :            : 
     893                 :        340 :         enumerator->current_device_index = 0;
     894                 :            : 
     895         [ -  + ]:        340 :         if (enumerator->n_devices == 0)
     896                 :          0 :                 return NULL;
     897                 :            : 
     898                 :        340 :         return enumerator->devices[0];
     899                 :            : }
     900                 :            : 
     901                 :      11032 : _public_ sd_device *sd_device_enumerator_get_device_next(sd_device_enumerator *enumerator) {
     902   [ -  +  -  + ]:      11032 :         assert_return(enumerator, NULL);
     903                 :            : 
     904         [ +  - ]:      11032 :         if (!enumerator->scan_uptodate ||
     905         [ +  - ]:      11032 :             enumerator->type != DEVICE_ENUMERATION_TYPE_DEVICES ||
     906         [ +  + ]:      11032 :             enumerator->current_device_index + 1 >= enumerator->n_devices)
     907                 :        340 :                 return NULL;
     908                 :            : 
     909                 :      10692 :         return enumerator->devices[++enumerator->current_device_index];
     910                 :            : }
     911                 :            : 
     912                 :          8 : int device_enumerator_scan_subsystems(sd_device_enumerator *enumerator) {
     913                 :            :         const char *subsysdir;
     914                 :          8 :         int r = 0, k;
     915                 :            :         size_t i;
     916                 :            : 
     917         [ -  + ]:          8 :         assert(enumerator);
     918                 :            : 
     919         [ -  + ]:          8 :         if (enumerator->scan_uptodate &&
     920         [ #  # ]:          0 :             enumerator->type == DEVICE_ENUMERATION_TYPE_SUBSYSTEMS)
     921                 :          0 :                 return 0;
     922                 :            : 
     923         [ -  + ]:          8 :         for (i = 0; i < enumerator->n_devices; i++)
     924                 :          0 :                 sd_device_unref(enumerator->devices[i]);
     925                 :            : 
     926                 :          8 :         enumerator->n_devices = 0;
     927                 :            : 
     928                 :            :         /* modules */
     929         [ +  - ]:          8 :         if (match_subsystem(enumerator, "module")) {
     930                 :          8 :                 k = enumerator_scan_dir_and_add_devices(enumerator, "module", NULL, NULL);
     931         [ -  + ]:          8 :                 if (k < 0) {
     932         [ #  # ]:          0 :                         log_debug_errno(k, "sd-device-enumerator: Failed to scan modules: %m");
     933                 :          0 :                         r = k;
     934                 :            :                 }
     935                 :            :         }
     936                 :            : 
     937         [ -  + ]:          8 :         if (access("/sys/subsystem", F_OK) >= 0)
     938                 :          0 :                 subsysdir = "subsystem";
     939                 :            :         else
     940                 :          8 :                 subsysdir = "bus";
     941                 :            : 
     942                 :            :         /* subsystems (only buses support coldplug) */
     943         [ +  - ]:          8 :         if (match_subsystem(enumerator, "subsystem")) {
     944                 :          8 :                 k = enumerator_scan_dir_and_add_devices(enumerator, subsysdir, NULL, NULL);
     945         [ -  + ]:          8 :                 if (k < 0) {
     946         [ #  # ]:          0 :                         log_debug_errno(k, "sd-device-enumerator: Failed to scan subsystems: %m");
     947                 :          0 :                         r = k;
     948                 :            :                 }
     949                 :            :         }
     950                 :            : 
     951                 :            :         /* subsystem drivers */
     952         [ +  - ]:          8 :         if (match_subsystem(enumerator, "drivers")) {
     953                 :          8 :                 k = enumerator_scan_dir(enumerator, subsysdir, "drivers", "drivers");
     954         [ -  + ]:          8 :                 if (k < 0) {
     955         [ #  # ]:          0 :                         log_debug_errno(k, "sd-device-enumerator: Failed to scan drivers: %m");
     956                 :          0 :                         r = k;
     957                 :            :                 }
     958                 :            :         }
     959                 :            : 
     960                 :          8 :         typesafe_qsort(enumerator->devices, enumerator->n_devices, device_compare);
     961                 :          8 :         device_enumerator_dedup_devices(enumerator);
     962                 :            : 
     963                 :          8 :         enumerator->scan_uptodate = true;
     964                 :          8 :         enumerator->type = DEVICE_ENUMERATION_TYPE_SUBSYSTEMS;
     965                 :            : 
     966                 :          8 :         return r;
     967                 :            : }
     968                 :            : 
     969                 :          4 : _public_ sd_device *sd_device_enumerator_get_subsystem_first(sd_device_enumerator *enumerator) {
     970                 :            :         int r;
     971                 :            : 
     972   [ -  +  -  + ]:          4 :         assert_return(enumerator, NULL);
     973                 :            : 
     974                 :          4 :         r = device_enumerator_scan_subsystems(enumerator);
     975         [ -  + ]:          4 :         if (r < 0)
     976                 :          0 :                 return NULL;
     977                 :            : 
     978                 :          4 :         enumerator->current_device_index = 0;
     979                 :            : 
     980         [ -  + ]:          4 :         if (enumerator->n_devices == 0)
     981                 :          0 :                 return NULL;
     982                 :            : 
     983                 :          4 :         return enumerator->devices[0];
     984                 :            : }
     985                 :            : 
     986                 :       1544 : _public_ sd_device *sd_device_enumerator_get_subsystem_next(sd_device_enumerator *enumerator) {
     987   [ -  +  -  + ]:       1544 :         assert_return(enumerator, NULL);
     988                 :            : 
     989         [ +  - ]:       1544 :         if (!enumerator->scan_uptodate ||
     990         [ +  - ]:       1544 :             enumerator->type != DEVICE_ENUMERATION_TYPE_SUBSYSTEMS ||
     991         [ +  + ]:       1544 :             enumerator->current_device_index + 1 >= enumerator->n_devices)
     992                 :          4 :                 return NULL;
     993                 :            : 
     994                 :       1540 :         return enumerator->devices[++enumerator->current_device_index];
     995                 :            : }
     996                 :            : 
     997                 :         28 : sd_device *device_enumerator_get_first(sd_device_enumerator *enumerator) {
     998   [ -  +  -  + ]:         28 :         assert_return(enumerator, NULL);
     999                 :            : 
    1000         [ -  + ]:         28 :         if (!enumerator->scan_uptodate)
    1001                 :          0 :                 return NULL;
    1002                 :            : 
    1003                 :         28 :         enumerator->current_device_index = 0;
    1004                 :            : 
    1005         [ -  + ]:         28 :         if (enumerator->n_devices == 0)
    1006                 :          0 :                 return NULL;
    1007                 :            : 
    1008                 :         28 :         return enumerator->devices[0];
    1009                 :            : }
    1010                 :            : 
    1011                 :       7512 : sd_device *device_enumerator_get_next(sd_device_enumerator *enumerator) {
    1012   [ -  +  -  + ]:       7512 :         assert_return(enumerator, NULL);
    1013                 :            : 
    1014         [ +  - ]:       7512 :         if (!enumerator->scan_uptodate ||
    1015         [ +  + ]:       7512 :             enumerator->current_device_index + 1 >= enumerator->n_devices)
    1016                 :         28 :                 return NULL;
    1017                 :            : 
    1018                 :       7484 :         return enumerator->devices[++enumerator->current_device_index];
    1019                 :            : }
    1020                 :            : 
    1021                 :          0 : sd_device **device_enumerator_get_devices(sd_device_enumerator *enumerator, size_t *ret_n_devices) {
    1022         [ #  # ]:          0 :         assert(enumerator);
    1023         [ #  # ]:          0 :         assert(ret_n_devices);
    1024                 :            : 
    1025         [ #  # ]:          0 :         if (!enumerator->scan_uptodate)
    1026                 :          0 :                 return NULL;
    1027                 :            : 
    1028                 :          0 :         *ret_n_devices = enumerator->n_devices;
    1029                 :          0 :         return enumerator->devices;
    1030                 :            : }

Generated by: LCOV version 1.14