LCOV - code coverage report
Current view: top level - libsystemd/sd-device - sd-device.c (source / functions) Hit Total Coverage
Test: systemd_full.info Lines: 797 1091 73.1 %
Date: 2019-08-23 13:36:53 Functions: 56 63 88.9 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 613 1255 48.8 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: LGPL-2.1+ */
       2                 :            : 
       3                 :            : #include <ctype.h>
       4                 :            : #include <net/if.h>
       5                 :            : #include <sys/ioctl.h>
       6                 :            : #include <sys/types.h>
       7                 :            : 
       8                 :            : #include "sd-device.h"
       9                 :            : 
      10                 :            : #include "alloc-util.h"
      11                 :            : #include "device-internal.h"
      12                 :            : #include "device-private.h"
      13                 :            : #include "device-util.h"
      14                 :            : #include "dirent-util.h"
      15                 :            : #include "fd-util.h"
      16                 :            : #include "fileio.h"
      17                 :            : #include "fs-util.h"
      18                 :            : #include "hashmap.h"
      19                 :            : #include "macro.h"
      20                 :            : #include "parse-util.h"
      21                 :            : #include "path-util.h"
      22                 :            : #include "set.h"
      23                 :            : #include "socket-util.h"
      24                 :            : #include "stat-util.h"
      25                 :            : #include "stdio-util.h"
      26                 :            : #include "string-util.h"
      27                 :            : #include "strv.h"
      28                 :            : #include "strxcpyx.h"
      29                 :            : #include "util.h"
      30                 :            : 
      31                 :      31328 : int device_new_aux(sd_device **ret) {
      32                 :            :         sd_device *device;
      33                 :            : 
      34         [ -  + ]:      31328 :         assert(ret);
      35                 :            : 
      36                 :      31328 :         device = new(sd_device, 1);
      37         [ -  + ]:      31328 :         if (!device)
      38                 :          0 :                 return -ENOMEM;
      39                 :            : 
      40                 :      31328 :         *device = (sd_device) {
      41                 :            :                 .n_ref = 1,
      42                 :            :                 .watch_handle = -1,
      43                 :            :                 .devmode = (mode_t) -1,
      44                 :            :                 .devuid = (uid_t) -1,
      45                 :            :                 .devgid = (gid_t) -1,
      46                 :            :                 .action = _DEVICE_ACTION_INVALID,
      47                 :            :         };
      48                 :            : 
      49                 :      31328 :         *ret = device;
      50                 :      31328 :         return 0;
      51                 :            : }
      52                 :            : 
      53                 :      31328 : static sd_device *device_free(sd_device *device) {
      54         [ -  + ]:      31328 :         assert(device);
      55                 :            : 
      56                 :      31328 :         sd_device_unref(device->parent);
      57                 :      31328 :         free(device->syspath);
      58                 :      31328 :         free(device->sysname);
      59                 :      31328 :         free(device->devtype);
      60                 :      31328 :         free(device->devname);
      61                 :      31328 :         free(device->subsystem);
      62                 :      31328 :         free(device->driver_subsystem);
      63                 :      31328 :         free(device->driver);
      64                 :      31328 :         free(device->id_filename);
      65                 :      31328 :         free(device->properties_strv);
      66                 :      31328 :         free(device->properties_nulstr);
      67                 :            : 
      68                 :      31328 :         ordered_hashmap_free_free_free(device->properties);
      69                 :      31328 :         ordered_hashmap_free_free_free(device->properties_db);
      70                 :      31328 :         hashmap_free_free_free(device->sysattr_values);
      71                 :      31328 :         set_free_free(device->sysattrs);
      72                 :      31328 :         set_free_free(device->tags);
      73                 :      31328 :         set_free_free(device->devlinks);
      74                 :            : 
      75                 :      31328 :         return mfree(device);
      76                 :            : }
      77                 :            : 
      78   [ +  +  -  +  :     124008 : DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_device, sd_device, device_free);
                   +  + ]
      79                 :            : 
      80                 :     219540 : int device_add_property_aux(sd_device *device, const char *_key, const char *_value, bool db) {
      81                 :            :         OrderedHashmap **properties;
      82                 :            : 
      83         [ -  + ]:     219540 :         assert(device);
      84         [ -  + ]:     219540 :         assert(_key);
      85                 :            : 
      86         [ +  + ]:     219540 :         if (db)
      87                 :      49244 :                 properties = &device->properties_db;
      88                 :            :         else
      89                 :     170296 :                 properties = &device->properties;
      90                 :            : 
      91         [ +  + ]:     219540 :         if (_value) {
      92   [ +  -  +  -  :     218228 :                 _cleanup_free_ char *key = NULL, *value = NULL, *old_key = NULL, *old_value = NULL;
             +  -  +  - ]
      93                 :            :                 int r;
      94                 :            : 
      95                 :     218228 :                 r = ordered_hashmap_ensure_allocated(properties, &string_hash_ops);
      96         [ -  + ]:     218228 :                 if (r < 0)
      97                 :          0 :                         return r;
      98                 :            : 
      99                 :     218228 :                 key = strdup(_key);
     100         [ -  + ]:     218228 :                 if (!key)
     101                 :          0 :                         return -ENOMEM;
     102                 :            : 
     103                 :     218228 :                 value = strdup(_value);
     104         [ -  + ]:     218228 :                 if (!value)
     105                 :          0 :                         return -ENOMEM;
     106                 :            : 
     107                 :     218228 :                 old_value = ordered_hashmap_get2(*properties, key, (void**) &old_key);
     108                 :            : 
     109                 :     218228 :                 r = ordered_hashmap_replace(*properties, key, value);
     110         [ -  + ]:     218228 :                 if (r < 0)
     111                 :          0 :                         return r;
     112                 :            : 
     113                 :     218228 :                 key = NULL;
     114                 :     218228 :                 value = NULL;
     115                 :            :         } else {
     116                 :       1312 :                 _cleanup_free_ char *key = NULL;
     117                 :       2624 :                 _cleanup_free_ char *value = NULL;
     118                 :            : 
     119                 :       1312 :                 value = ordered_hashmap_remove2(*properties, _key, (void**) &key);
     120                 :            :         }
     121                 :            : 
     122         [ +  + ]:     219540 :         if (!db) {
     123                 :     170296 :                 device->properties_generation++;
     124                 :     170296 :                 device->properties_buf_outdated = true;
     125                 :            :         }
     126                 :            : 
     127                 :     219540 :         return 0;
     128                 :            : }
     129                 :            : 
     130                 :     121052 : int device_add_property_internal(sd_device *device, const char *key, const char *value) {
     131                 :     121052 :         return device_add_property_aux(device, key, value, false);
     132                 :            : }
     133                 :            : 
     134                 :      31328 : int device_set_syspath(sd_device *device, const char *_syspath, bool verify) {
     135                 :      31328 :         _cleanup_free_ char *syspath = NULL;
     136                 :            :         const char *devpath;
     137                 :            :         int r;
     138                 :            : 
     139         [ -  + ]:      31328 :         assert(device);
     140         [ -  + ]:      31328 :         assert(_syspath);
     141                 :            : 
     142                 :            :         /* must be a subdirectory of /sys */
     143         [ -  + ]:      31328 :         if (!path_startswith(_syspath, "/sys/"))
     144         [ #  # ]:          0 :                 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
     145                 :            :                                        "sd-device: Syspath '%s' is not a subdirectory of /sys",
     146                 :            :                                        _syspath);
     147                 :            : 
     148         [ +  - ]:      31328 :         if (verify) {
     149                 :      31328 :                 r = chase_symlinks(_syspath, NULL, 0, &syspath);
     150         [ -  + ]:      31328 :                 if (r == -ENOENT)
     151                 :          0 :                         return -ENODEV; /* the device does not exist (any more?) */
     152         [ -  + ]:      31328 :                 if (r < 0)
     153         [ #  # ]:          0 :                         return log_debug_errno(r, "sd-device: Failed to get target of '%s': %m", _syspath);
     154                 :            : 
     155         [ -  + ]:      31328 :                 if (!path_startswith(syspath, "/sys")) {
     156   [ #  #  #  # ]:          0 :                         _cleanup_free_ char *real_sys = NULL, *new_syspath = NULL;
     157                 :            :                         char *p;
     158                 :            : 
     159                 :            :                         /* /sys is a symlink to somewhere sysfs is mounted on? In that case, we convert the path to real sysfs to "/sys". */
     160                 :          0 :                         r = chase_symlinks("/sys", NULL, 0, &real_sys);
     161         [ #  # ]:          0 :                         if (r < 0)
     162         [ #  # ]:          0 :                                 return log_debug_errno(r, "sd-device: Failed to chase symlink /sys: %m");
     163                 :            : 
     164                 :          0 :                         p = path_startswith(syspath, real_sys);
     165         [ #  # ]:          0 :                         if (!p)
     166         [ #  # ]:          0 :                                 return log_debug_errno(SYNTHETIC_ERRNO(ENODEV),
     167                 :            :                                                        "sd-device: Canonicalized path '%s' does not starts with sysfs mount point '%s'",
     168                 :            :                                                        syspath, real_sys);
     169                 :            : 
     170                 :          0 :                         new_syspath = path_join("/sys", p);
     171         [ #  # ]:          0 :                         if (!new_syspath)
     172                 :          0 :                                 return -ENOMEM;
     173                 :            : 
     174                 :          0 :                         free_and_replace(syspath, new_syspath);
     175                 :          0 :                         path_simplify(syspath, false);
     176                 :            :                 }
     177                 :            : 
     178         [ +  + ]:      31328 :                 if (path_startswith(syspath,  "/sys/devices/")) {
     179                 :            :                         char *path;
     180                 :            : 
     181                 :            :                         /* all 'devices' require an 'uevent' file */
     182   [ +  +  +  -  :     132760 :                         path = strjoina(syspath, "/uevent");
          -  +  -  +  +  
                +  +  - ]
     183                 :      26552 :                         r = access(path, F_OK);
     184         [ +  + ]:      26552 :                         if (r < 0) {
     185         [ +  - ]:         12 :                                 if (errno == ENOENT)
     186                 :            :                                         /* this is not a valid device */
     187                 :         12 :                                         return -ENODEV;
     188                 :            : 
     189         [ #  # ]:          0 :                                 return log_debug_errno(errno, "sd-device: %s does not have an uevent file: %m", syspath);
     190                 :            :                         }
     191                 :            :                 } else {
     192                 :            :                         /* everything else just needs to be a directory */
     193         [ +  + ]:       4776 :                         if (!is_dir(syspath, false))
     194                 :         44 :                                 return -ENODEV;
     195                 :            :                 }
     196                 :            :         } else {
     197                 :          0 :                 syspath = strdup(_syspath);
     198         [ #  # ]:          0 :                 if (!syspath)
     199                 :          0 :                         return -ENOMEM;
     200                 :            :         }
     201                 :            : 
     202                 :      31272 :         devpath = syspath + STRLEN("/sys");
     203                 :            : 
     204         [ -  + ]:      31272 :         if (devpath[0] == '\0')
     205                 :            :                 /* '/sys' alone is not a valid device path */
     206                 :          0 :                 return -ENODEV;
     207                 :            : 
     208                 :      31272 :         r = device_add_property_internal(device, "DEVPATH", devpath);
     209         [ -  + ]:      31272 :         if (r < 0)
     210                 :          0 :                 return r;
     211                 :            : 
     212                 :      31272 :         free_and_replace(device->syspath, syspath);
     213                 :      31272 :         device->devpath = devpath;
     214                 :      31272 :         return 0;
     215                 :            : }
     216                 :            : 
     217                 :      31328 : _public_ int sd_device_new_from_syspath(sd_device **ret, const char *syspath) {
     218                 :      31328 :         _cleanup_(sd_device_unrefp) sd_device *device = NULL;
     219                 :            :         int r;
     220                 :            : 
     221   [ -  +  -  + ]:      31328 :         assert_return(ret, -EINVAL);
     222   [ -  +  -  + ]:      31328 :         assert_return(syspath, -EINVAL);
     223                 :            : 
     224                 :      31328 :         r = device_new_aux(&device);
     225         [ -  + ]:      31328 :         if (r < 0)
     226                 :          0 :                 return r;
     227                 :            : 
     228                 :      31328 :         r = device_set_syspath(device, syspath, true);
     229         [ +  + ]:      31328 :         if (r < 0)
     230                 :         56 :                 return r;
     231                 :            : 
     232                 :      31272 :         *ret = TAKE_PTR(device);
     233                 :      31272 :         return 0;
     234                 :            : }
     235                 :            : 
     236                 :       2424 : _public_ int sd_device_new_from_devnum(sd_device **ret, char type, dev_t devnum) {
     237                 :            :         char *syspath;
     238                 :            :         char id[DECIMAL_STR_MAX(unsigned) * 2 + 1];
     239                 :            : 
     240   [ -  +  -  + ]:       2424 :         assert_return(ret, -EINVAL);
     241   [ +  -  -  +  :       2424 :         assert_return(IN_SET(type, 'b', 'c'), -EINVAL);
                   -  + ]
     242                 :            : 
     243                 :            :         /* use /sys/dev/{block,char}/<maj>:<min> link */
     244         [ -  + ]:       2424 :         xsprintf(id, "%u:%u", major(devnum), minor(devnum));
     245                 :            : 
     246   [ +  +  +  +  :      21816 :         syspath = strjoina("/sys/dev/", (type == 'b' ? "block" : "char"), "/", id);
          +  -  -  +  -  
             +  +  +  +  
                      - ]
     247                 :            : 
     248                 :       2424 :         return sd_device_new_from_syspath(ret, syspath);
     249                 :            : }
     250                 :            : 
     251                 :        652 : _public_ int sd_device_new_from_subsystem_sysname(sd_device **ret, const char *subsystem, const char *sysname) {
     252                 :            :         char *name, *syspath;
     253                 :        652 :         size_t len = 0;
     254                 :            : 
     255   [ -  +  -  + ]:        652 :         assert_return(ret, -EINVAL);
     256   [ -  +  -  + ]:        652 :         assert_return(subsystem, -EINVAL);
     257   [ -  +  -  + ]:        652 :         assert_return(sysname, -EINVAL);
     258                 :            : 
     259         [ +  + ]:        652 :         if (streq(subsystem, "subsystem")) {
     260   [ +  +  +  -  :         20 :                 syspath = strjoina("/sys/subsystem/", sysname);
          -  +  -  +  +  
                +  +  - ]
     261         [ -  + ]:          4 :                 if (access(syspath, F_OK) >= 0)
     262                 :          0 :                         return sd_device_new_from_syspath(ret, syspath);
     263                 :            : 
     264   [ +  +  +  -  :         20 :                 syspath = strjoina("/sys/bus/", sysname);
          -  +  -  +  +  
                +  +  - ]
     265         [ +  - ]:          4 :                 if (access(syspath, F_OK) >= 0)
     266                 :          4 :                         return sd_device_new_from_syspath(ret, syspath);
     267                 :            : 
     268   [ #  #  #  #  :          0 :                 syspath = strjoina("/sys/class/", sysname);
          #  #  #  #  #  
                #  #  # ]
     269         [ #  # ]:          0 :                 if (access(syspath, F_OK) >= 0)
     270                 :          0 :                         return sd_device_new_from_syspath(ret, syspath);
     271         [ +  + ]:        648 :         } else  if (streq(subsystem, "module")) {
     272   [ +  +  +  -  :        460 :                 syspath = strjoina("/sys/module/", sysname);
          -  +  -  +  +  
                +  +  - ]
     273         [ +  - ]:         92 :                 if (access(syspath, F_OK) >= 0)
     274                 :         92 :                         return sd_device_new_from_syspath(ret, syspath);
     275         [ +  + ]:        556 :         } else if (streq(subsystem, "drivers")) {
     276                 :            :                 char subsys[PATH_MAX];
     277                 :            :                 char *driver;
     278                 :            : 
     279                 :          4 :                 strscpy(subsys, sizeof(subsys), sysname);
     280                 :          4 :                 driver = strchr(subsys, ':');
     281         [ +  - ]:          4 :                 if (driver) {
     282                 :          4 :                         driver[0] = '\0';
     283                 :          4 :                         driver++;
     284                 :            : 
     285   [ +  +  +  -  :         36 :                         syspath = strjoina("/sys/subsystem/", subsys, "/drivers/", driver);
          -  +  -  +  +  
                +  +  - ]
     286         [ -  + ]:          4 :                         if (access(syspath, F_OK) >= 0)
     287                 :          4 :                                 return sd_device_new_from_syspath(ret, syspath);
     288                 :            : 
     289   [ +  +  +  -  :         36 :                         syspath = strjoina("/sys/bus/", subsys, "/drivers/", driver);
          -  +  -  +  +  
                +  +  - ]
     290         [ +  - ]:          4 :                         if (access(syspath, F_OK) >= 0)
     291                 :          4 :                                 return sd_device_new_from_syspath(ret, syspath);
     292                 :            :                 }
     293                 :            :         }
     294                 :            : 
     295                 :            :         /* translate sysname back to sysfs filename */
     296                 :        552 :         name = strdupa(sysname);
     297         [ +  + ]:       4756 :         while (name[len] != '\0') {
     298         [ -  + ]:       4204 :                 if (name[len] == '/')
     299                 :          0 :                         name[len] = '!';
     300                 :            : 
     301                 :       4204 :                 len++;
     302                 :            :         }
     303                 :            : 
     304   [ +  +  +  -  :       4968 :         syspath = strjoina("/sys/subsystem/", subsystem, "/devices/", name);
          -  +  -  +  +  
                +  +  - ]
     305         [ -  + ]:        552 :         if (access(syspath, F_OK) >= 0)
     306                 :          0 :                 return sd_device_new_from_syspath(ret, syspath);
     307                 :            : 
     308   [ +  +  +  -  :       4968 :         syspath = strjoina("/sys/bus/", subsystem, "/devices/", name);
          -  +  -  +  +  
                +  +  - ]
     309         [ -  + ]:        552 :         if (access(syspath, F_OK) >= 0)
     310                 :          0 :                 return sd_device_new_from_syspath(ret, syspath);
     311                 :            : 
     312   [ +  +  +  -  :       4968 :         syspath = strjoina("/sys/class/", subsystem, "/", name);
          -  +  -  +  +  
                +  +  - ]
     313         [ +  + ]:        552 :         if (access(syspath, F_OK) >= 0)
     314                 :        548 :                 return sd_device_new_from_syspath(ret, syspath);
     315                 :            : 
     316   [ +  +  +  -  :         36 :         syspath = strjoina("/sys/firmware/", subsystem, "/", sysname);
          -  +  -  +  +  
                +  +  - ]
     317         [ -  + ]:          4 :         if (access(syspath, F_OK) >= 0)
     318                 :          0 :                 return sd_device_new_from_syspath(ret, syspath);
     319                 :            : 
     320                 :          4 :         return -ENODEV;
     321                 :            : }
     322                 :            : 
     323                 :       2828 : int device_set_devtype(sd_device *device, const char *_devtype) {
     324                 :       2828 :         _cleanup_free_ char *devtype = NULL;
     325                 :            :         int r;
     326                 :            : 
     327         [ -  + ]:       2828 :         assert(device);
     328         [ -  + ]:       2828 :         assert(_devtype);
     329                 :            : 
     330                 :       2828 :         devtype = strdup(_devtype);
     331         [ -  + ]:       2828 :         if (!devtype)
     332                 :          0 :                 return -ENOMEM;
     333                 :            : 
     334                 :       2828 :         r = device_add_property_internal(device, "DEVTYPE", devtype);
     335         [ -  + ]:       2828 :         if (r < 0)
     336                 :          0 :                 return r;
     337                 :            : 
     338                 :       2828 :         free_and_replace(device->devtype, devtype);
     339                 :            : 
     340                 :       2828 :         return 0;
     341                 :            : }
     342                 :            : 
     343                 :        500 : int device_set_ifindex(sd_device *device, const char *_ifindex) {
     344                 :            :         int ifindex, r;
     345                 :            : 
     346         [ -  + ]:        500 :         assert(device);
     347         [ -  + ]:        500 :         assert(_ifindex);
     348                 :            : 
     349                 :        500 :         r = parse_ifindex(_ifindex, &ifindex);
     350         [ -  + ]:        500 :         if (r < 0)
     351                 :          0 :                 return r;
     352                 :            : 
     353                 :        500 :         r = device_add_property_internal(device, "IFINDEX", _ifindex);
     354         [ -  + ]:        500 :         if (r < 0)
     355                 :          0 :                 return r;
     356                 :            : 
     357                 :        500 :         device->ifindex = ifindex;
     358                 :            : 
     359                 :        500 :         return 0;
     360                 :            : }
     361                 :            : 
     362                 :       8240 : int device_set_devname(sd_device *device, const char *_devname) {
     363                 :       8240 :         _cleanup_free_ char *devname = NULL;
     364                 :            :         int r;
     365                 :            : 
     366         [ -  + ]:       8240 :         assert(device);
     367         [ -  + ]:       8240 :         assert(_devname);
     368                 :            : 
     369         [ +  - ]:       8240 :         if (_devname[0] != '/') {
     370                 :       8240 :                 r = asprintf(&devname, "/dev/%s", _devname);
     371         [ -  + ]:       8240 :                 if (r < 0)
     372                 :          0 :                         return -ENOMEM;
     373                 :            :         } else {
     374                 :          0 :                 devname = strdup(_devname);
     375         [ #  # ]:          0 :                 if (!devname)
     376                 :          0 :                         return -ENOMEM;
     377                 :            :         }
     378                 :            : 
     379                 :       8240 :         r = device_add_property_internal(device, "DEVNAME", devname);
     380         [ -  + ]:       8240 :         if (r < 0)
     381                 :          0 :                 return r;
     382                 :            : 
     383                 :       8240 :         free_and_replace(device->devname, devname);
     384                 :            : 
     385                 :       8240 :         return 0;
     386                 :            : }
     387                 :            : 
     388                 :        252 : int device_set_devmode(sd_device *device, const char *_devmode) {
     389                 :            :         unsigned devmode;
     390                 :            :         int r;
     391                 :            : 
     392         [ -  + ]:        252 :         assert(device);
     393         [ -  + ]:        252 :         assert(_devmode);
     394                 :            : 
     395                 :        252 :         r = safe_atou(_devmode, &devmode);
     396         [ -  + ]:        252 :         if (r < 0)
     397                 :          0 :                 return r;
     398                 :            : 
     399         [ -  + ]:        252 :         if (devmode > 07777)
     400                 :          0 :                 return -EINVAL;
     401                 :            : 
     402                 :        252 :         r = device_add_property_internal(device, "DEVMODE", _devmode);
     403         [ -  + ]:        252 :         if (r < 0)
     404                 :          0 :                 return r;
     405                 :            : 
     406                 :        252 :         device->devmode = devmode;
     407                 :            : 
     408                 :        252 :         return 0;
     409                 :            : }
     410                 :            : 
     411                 :       8240 : int device_set_devnum(sd_device *device, const char *major, const char *minor) {
     412                 :       8240 :         unsigned maj = 0, min = 0;
     413                 :            :         int r;
     414                 :            : 
     415         [ -  + ]:       8240 :         assert(device);
     416         [ -  + ]:       8240 :         assert(major);
     417                 :            : 
     418                 :       8240 :         r = safe_atou(major, &maj);
     419         [ -  + ]:       8240 :         if (r < 0)
     420                 :          0 :                 return r;
     421         [ -  + ]:       8240 :         if (!maj)
     422                 :          0 :                 return 0;
     423                 :            : 
     424         [ +  - ]:       8240 :         if (minor) {
     425                 :       8240 :                 r = safe_atou(minor, &min);
     426         [ -  + ]:       8240 :                 if (r < 0)
     427                 :          0 :                         return r;
     428                 :            :         }
     429                 :            : 
     430                 :       8240 :         r = device_add_property_internal(device, "MAJOR", major);
     431         [ -  + ]:       8240 :         if (r < 0)
     432                 :          0 :                 return r;
     433                 :            : 
     434         [ +  - ]:       8240 :         if (minor) {
     435                 :       8240 :                 r = device_add_property_internal(device, "MINOR", minor);
     436         [ -  + ]:       8240 :                 if (r < 0)
     437                 :          0 :                         return r;
     438                 :            :         }
     439                 :            : 
     440                 :       8240 :         device->devnum = makedev(maj, min);
     441                 :            : 
     442                 :       8240 :         return 0;
     443                 :            : }
     444                 :            : 
     445                 :      44556 : static int handle_uevent_line(sd_device *device, const char *key, const char *value, const char **major, const char **minor) {
     446                 :            :         int r;
     447                 :            : 
     448         [ -  + ]:      44556 :         assert(device);
     449         [ -  + ]:      44556 :         assert(key);
     450         [ -  + ]:      44556 :         assert(value);
     451         [ -  + ]:      44556 :         assert(major);
     452         [ -  + ]:      44556 :         assert(minor);
     453                 :            : 
     454         [ +  + ]:      44556 :         if (streq(key, "DEVTYPE")) {
     455                 :       2828 :                 r = device_set_devtype(device, value);
     456         [ -  + ]:       2828 :                 if (r < 0)
     457                 :          0 :                         return r;
     458         [ +  + ]:      41728 :         } else if (streq(key, "IFINDEX")) {
     459                 :        500 :                 r = device_set_ifindex(device, value);
     460         [ -  + ]:        500 :                 if (r < 0)
     461                 :          0 :                         return r;
     462         [ +  + ]:      41228 :         } else if (streq(key, "DEVNAME")) {
     463                 :       8240 :                 r = device_set_devname(device, value);
     464         [ -  + ]:       8240 :                 if (r < 0)
     465                 :          0 :                         return r;
     466         [ +  + ]:      32988 :         } else if (streq(key, "DEVMODE")) {
     467                 :        252 :                 r = device_set_devmode(device, value);
     468         [ -  + ]:        252 :                 if (r < 0)
     469                 :          0 :                         return r;
     470         [ +  + ]:      32736 :         } else if (streq(key, "MAJOR"))
     471                 :       8240 :                 *major = value;
     472         [ +  + ]:      24496 :         else if (streq(key, "MINOR"))
     473                 :       8240 :                 *minor = value;
     474                 :            :         else {
     475                 :      16256 :                 r = device_add_property_internal(device, key, value);
     476         [ -  + ]:      16256 :                 if (r < 0)
     477                 :          0 :                         return r;
     478                 :            :         }
     479                 :            : 
     480                 :      44556 :         return 0;
     481                 :            : }
     482                 :            : 
     483                 :     125004 : int device_read_uevent_file(sd_device *device) {
     484                 :     125004 :         _cleanup_free_ char *uevent = NULL;
     485                 :     125004 :         const char *syspath, *key = NULL, *value = NULL, *major = NULL, *minor = NULL;
     486                 :            :         char *path;
     487                 :            :         size_t uevent_len;
     488                 :            :         unsigned i;
     489                 :            :         int r;
     490                 :            : 
     491                 :            :         enum {
     492                 :            :                 PRE_KEY,
     493                 :            :                 KEY,
     494                 :            :                 PRE_VALUE,
     495                 :            :                 VALUE,
     496                 :            :                 INVALID_LINE,
     497                 :     125004 :         } state = PRE_KEY;
     498                 :            : 
     499         [ -  + ]:     125004 :         assert(device);
     500                 :            : 
     501   [ +  +  -  + ]:     125004 :         if (device->uevent_loaded || device->sealed)
     502                 :     101312 :                 return 0;
     503                 :            : 
     504                 :      23692 :         r = sd_device_get_syspath(device, &syspath);
     505         [ -  + ]:      23692 :         if (r < 0)
     506                 :          0 :                 return r;
     507                 :            : 
     508   [ +  +  +  -  :     118460 :         path = strjoina(syspath, "/uevent");
          -  +  -  +  +  
                +  +  - ]
     509                 :            : 
     510                 :      23692 :         r = read_full_file(path, &uevent, &uevent_len);
     511         [ +  + ]:      23692 :         if (r == -EACCES) {
     512                 :            :                 /* empty uevent files may be write-only */
     513                 :       3188 :                 device->uevent_loaded = true;
     514                 :       3188 :                 return 0;
     515                 :            :         }
     516         [ -  + ]:      20504 :         if (r == -ENOENT)
     517                 :            :                 /* some devices may not have uevent files, see set_syspath() */
     518                 :          0 :                 return 0;
     519         [ -  + ]:      20504 :         if (r < 0)
     520   [ #  #  #  #  :          0 :                 return log_device_debug_errno(device, r, "sd-device: Failed to read uevent file '%s': %m", path);
                   #  # ]
     521                 :            : 
     522                 :      20504 :         device->uevent_loaded = true;
     523                 :            : 
     524         [ +  + ]:     814012 :         for (i = 0; i < uevent_len; i++)
     525   [ +  +  +  +  :     793508 :                 switch (state) {
                      - ]
     526                 :      44700 :                 case PRE_KEY:
     527         [ +  + ]:      44700 :                         if (!strchr(NEWLINE, uevent[i])) {
     528                 :      44556 :                                 key = &uevent[i];
     529                 :            : 
     530                 :      44556 :                                 state = KEY;
     531                 :            :                         }
     532                 :            : 
     533                 :      44700 :                         break;
     534                 :     297684 :                 case KEY:
     535         [ +  + ]:     297684 :                         if (uevent[i] == '=') {
     536                 :      44556 :                                 uevent[i] = '\0';
     537                 :            : 
     538                 :      44556 :                                 state = PRE_VALUE;
     539         [ -  + ]:     253128 :                         } else if (strchr(NEWLINE, uevent[i])) {
     540                 :          0 :                                 uevent[i] = '\0';
     541   [ #  #  #  #  :          0 :                                 log_device_debug(device, "sd-device: Invalid uevent line '%s', ignoring", key);
                   #  # ]
     542                 :            : 
     543                 :          0 :                                 state = PRE_KEY;
     544                 :            :                         }
     545                 :            : 
     546                 :     297684 :                         break;
     547                 :      44556 :                 case PRE_VALUE:
     548                 :      44556 :                         value = &uevent[i];
     549                 :      44556 :                         state = VALUE;
     550                 :            : 
     551                 :            :                         _fallthrough_; /* to handle empty property */
     552                 :     451124 :                 case VALUE:
     553         [ +  + ]:     451124 :                         if (strchr(NEWLINE, uevent[i])) {
     554                 :      44556 :                                 uevent[i] = '\0';
     555                 :            : 
     556                 :      44556 :                                 r = handle_uevent_line(device, key, value, &major, &minor);
     557         [ -  + ]:      44556 :                                 if (r < 0)
     558   [ #  #  #  #  :          0 :                                         log_device_debug_errno(device, r, "sd-device: Failed to handle uevent entry '%s=%s', ignoring: %m", key, value);
                   #  # ]
     559                 :            : 
     560                 :      44556 :                                 state = PRE_KEY;
     561                 :            :                         }
     562                 :            : 
     563                 :     451124 :                         break;
     564                 :          0 :                 default:
     565                 :          0 :                         assert_not_reached("Invalid state when parsing uevent file");
     566                 :            :                 }
     567                 :            : 
     568         [ +  + ]:      20504 :         if (major) {
     569                 :       8240 :                 r = device_set_devnum(device, major, minor);
     570         [ -  + ]:       8240 :                 if (r < 0)
     571   [ #  #  #  #  :          0 :                         log_device_debug_errno(device, r, "sd-device: Failed to set 'MAJOR=%s' or 'MINOR=%s' from '%s', ignoring: %m", major, minor, path);
                   #  # ]
     572                 :            :         }
     573                 :            : 
     574                 :      20504 :         return 0;
     575                 :            : }
     576                 :            : 
     577                 :      23012 : _public_ int sd_device_get_ifindex(sd_device *device, int *ifindex) {
     578                 :            :         int r;
     579                 :            : 
     580   [ -  +  -  + ]:      23012 :         assert_return(device, -EINVAL);
     581                 :            : 
     582                 :      23012 :         r = device_read_uevent_file(device);
     583         [ -  + ]:      23012 :         if (r < 0)
     584                 :          0 :                 return r;
     585                 :            : 
     586         [ +  + ]:      23012 :         if (device->ifindex <= 0)
     587                 :      22188 :                 return -ENOENT;
     588                 :            : 
     589         [ +  - ]:        824 :         if (ifindex)
     590                 :        824 :                 *ifindex = device->ifindex;
     591                 :            : 
     592                 :        824 :         return 0;
     593                 :            : }
     594                 :            : 
     595                 :       2520 : _public_ int sd_device_new_from_device_id(sd_device **ret, const char *id) {
     596                 :            :         int r;
     597                 :            : 
     598   [ -  +  -  + ]:       2520 :         assert_return(ret, -EINVAL);
     599   [ -  +  -  + ]:       2520 :         assert_return(id, -EINVAL);
     600                 :            : 
     601   [ +  +  +  - ]:       2520 :         switch (id[0]) {
     602                 :       1892 :         case 'b':
     603                 :            :         case 'c': {
     604                 :            :                 dev_t devt;
     605                 :            : 
     606         [ -  + ]:       1892 :                 if (isempty(id))
     607                 :          0 :                         return -EINVAL;
     608                 :            : 
     609                 :       1892 :                 r = parse_dev(id + 1, &devt);
     610         [ -  + ]:       1892 :                 if (r < 0)
     611                 :          0 :                         return r;
     612                 :            : 
     613                 :       1892 :                 return sd_device_new_from_devnum(ret, id[0], devt);
     614                 :            :         }
     615                 :            : 
     616                 :        320 :         case 'n': {
     617                 :        320 :                 _cleanup_(sd_device_unrefp) sd_device *device = NULL;
     618                 :        320 :                 _cleanup_close_ int sk = -1;
     619                 :        320 :                 struct ifreq ifr = {};
     620                 :            :                 int ifindex;
     621                 :            : 
     622                 :        320 :                 r = parse_ifindex(&id[1], &ifr.ifr_ifindex);
     623         [ -  + ]:        320 :                 if (r < 0)
     624                 :          0 :                         return r;
     625                 :            : 
     626                 :        320 :                 sk = socket_ioctl_fd();
     627         [ -  + ]:        320 :                 if (sk < 0)
     628                 :          0 :                         return sk;
     629                 :            : 
     630                 :        320 :                 r = ioctl(sk, SIOCGIFNAME, &ifr);
     631         [ +  + ]:        320 :                 if (r < 0)
     632                 :         28 :                         return -errno;
     633                 :            : 
     634                 :        292 :                 r = sd_device_new_from_subsystem_sysname(&device, "net", ifr.ifr_name);
     635         [ -  + ]:        292 :                 if (r < 0)
     636                 :          0 :                         return r;
     637                 :            : 
     638                 :        292 :                 r = sd_device_get_ifindex(device, &ifindex);
     639         [ -  + ]:        292 :                 if (r < 0)
     640                 :          0 :                         return r;
     641                 :            : 
     642                 :            :                 /* this is racey, so we might end up with the wrong device */
     643         [ -  + ]:        292 :                 if (ifr.ifr_ifindex != ifindex)
     644                 :          0 :                         return -ENODEV;
     645                 :            : 
     646                 :        292 :                 *ret = TAKE_PTR(device);
     647                 :        292 :                 return 0;
     648                 :            :         }
     649                 :            : 
     650                 :        308 :         case '+': {
     651                 :            :                 char subsys[PATH_MAX];
     652                 :            :                 char *sysname;
     653                 :            : 
     654                 :        308 :                 (void) strscpy(subsys, sizeof(subsys), id + 1);
     655                 :        308 :                 sysname = strchr(subsys, ':');
     656         [ -  + ]:        308 :                 if (!sysname)
     657                 :          0 :                         return -EINVAL;
     658                 :            : 
     659                 :        308 :                 sysname[0] = '\0';
     660                 :        308 :                 sysname++;
     661                 :            : 
     662                 :        308 :                 return sd_device_new_from_subsystem_sysname(ret, subsys, sysname);
     663                 :            :         }
     664                 :            : 
     665                 :          0 :         default:
     666                 :          0 :                 return -EINVAL;
     667                 :            :         }
     668                 :            : }
     669                 :            : 
     670                 :     109224 : _public_ int sd_device_get_syspath(sd_device *device, const char **ret) {
     671   [ -  +  -  + ]:     109224 :         assert_return(device, -EINVAL);
     672   [ -  +  -  + ]:     109224 :         assert_return(ret, -EINVAL);
     673                 :            : 
     674         [ -  + ]:     109224 :         assert(path_startswith(device->syspath, "/sys/"));
     675                 :            : 
     676                 :     109224 :         *ret = device->syspath;
     677                 :            : 
     678                 :     109224 :         return 0;
     679                 :            : }
     680                 :            : 
     681                 :          4 : static int device_new_from_child(sd_device **ret, sd_device *child) {
     682                 :          4 :         _cleanup_free_ char *path = NULL;
     683                 :            :         const char *subdir, *syspath;
     684                 :            :         int r;
     685                 :            : 
     686         [ -  + ]:          4 :         assert(ret);
     687         [ -  + ]:          4 :         assert(child);
     688                 :            : 
     689                 :          4 :         r = sd_device_get_syspath(child, &syspath);
     690         [ -  + ]:          4 :         if (r < 0)
     691                 :          0 :                 return r;
     692                 :            : 
     693                 :          4 :         path = strdup(syspath);
     694         [ -  + ]:          4 :         if (!path)
     695                 :          0 :                 return -ENOMEM;
     696                 :          4 :         subdir = path + STRLEN("/sys");
     697                 :            : 
     698                 :         12 :         for (;;) {
     699                 :            :                 char *pos;
     700                 :            : 
     701                 :         16 :                 pos = strrchr(subdir, '/');
     702   [ +  -  +  + ]:         16 :                 if (!pos || pos < subdir + 2)
     703                 :            :                         break;
     704                 :            : 
     705                 :         12 :                 *pos = '\0';
     706                 :            : 
     707                 :         12 :                 r = sd_device_new_from_syspath(ret, path);
     708         [ +  - ]:         12 :                 if (r < 0)
     709                 :         12 :                         continue;
     710                 :            : 
     711                 :          0 :                 return 0;
     712                 :            :         }
     713                 :            : 
     714                 :          4 :         return -ENODEV;
     715                 :            : }
     716                 :            : 
     717                 :          4 : _public_ int sd_device_get_parent(sd_device *child, sd_device **ret) {
     718                 :            : 
     719   [ -  +  -  + ]:          4 :         assert_return(ret, -EINVAL);
     720   [ -  +  -  + ]:          4 :         assert_return(child, -EINVAL);
     721                 :            : 
     722         [ +  - ]:          4 :         if (!child->parent_set) {
     723                 :          4 :                 child->parent_set = true;
     724                 :            : 
     725                 :          4 :                 (void) device_new_from_child(&child->parent, child);
     726                 :            :         }
     727                 :            : 
     728         [ +  - ]:          4 :         if (!child->parent)
     729                 :          4 :                 return -ENOENT;
     730                 :            : 
     731                 :          0 :         *ret = child->parent;
     732                 :          0 :         return 0;
     733                 :            : }
     734                 :            : 
     735                 :      30940 : int device_set_subsystem(sd_device *device, const char *_subsystem) {
     736                 :      30940 :         _cleanup_free_ char *subsystem = NULL;
     737                 :            :         int r;
     738                 :            : 
     739         [ -  + ]:      30940 :         assert(device);
     740         [ -  + ]:      30940 :         assert(_subsystem);
     741                 :            : 
     742                 :      30940 :         subsystem = strdup(_subsystem);
     743         [ -  + ]:      30940 :         if (!subsystem)
     744                 :          0 :                 return -ENOMEM;
     745                 :            : 
     746                 :      30940 :         r = device_add_property_internal(device, "SUBSYSTEM", subsystem);
     747         [ -  + ]:      30940 :         if (r < 0)
     748                 :          0 :                 return r;
     749                 :            : 
     750                 :      30940 :         device->subsystem_set = true;
     751                 :      30940 :         return free_and_replace(device->subsystem, subsystem);
     752                 :            : }
     753                 :            : 
     754                 :       1648 : static int device_set_drivers_subsystem(sd_device *device, const char *_subsystem) {
     755                 :       1648 :         _cleanup_free_ char *subsystem = NULL;
     756                 :            :         int r;
     757                 :            : 
     758         [ -  + ]:       1648 :         assert(device);
     759         [ -  + ]:       1648 :         assert(_subsystem);
     760         [ -  + ]:       1648 :         assert(*_subsystem);
     761                 :            : 
     762                 :       1648 :         subsystem = strdup(_subsystem);
     763         [ -  + ]:       1648 :         if (!subsystem)
     764                 :          0 :                 return -ENOMEM;
     765                 :            : 
     766                 :       1648 :         r = device_set_subsystem(device, "drivers");
     767         [ -  + ]:       1648 :         if (r < 0)
     768                 :          0 :                 return r;
     769                 :            : 
     770                 :       1648 :         return free_and_replace(device->driver_subsystem, subsystem);
     771                 :            : }
     772                 :            : 
     773                 :      40692 : _public_ int sd_device_get_subsystem(sd_device *device, const char **ret) {
     774                 :      40692 :         const char *syspath, *drivers = NULL;
     775                 :            :         int r;
     776                 :            : 
     777   [ -  +  -  + ]:      40692 :         assert_return(ret, -EINVAL);
     778   [ -  +  -  + ]:      40692 :         assert_return(device, -EINVAL);
     779                 :            : 
     780                 :      40692 :         r = sd_device_get_syspath(device, &syspath);
     781         [ -  + ]:      40692 :         if (r < 0)
     782                 :          0 :                 return r;
     783                 :            : 
     784         [ +  + ]:      40692 :         if (!device->subsystem_set) {
     785         [ +  - ]:      30940 :                 _cleanup_free_ char *subsystem = NULL;
     786                 :            :                 char *path;
     787                 :            : 
     788                 :            :                 /* read 'subsystem' link */
     789   [ +  +  +  -  :     154700 :                 path = strjoina(syspath, "/subsystem");
          -  +  -  +  +  
                +  +  - ]
     790                 :      30940 :                 r = readlink_value(path, &subsystem);
     791         [ +  + ]:      30940 :                 if (r >= 0)
     792                 :      26208 :                         r = device_set_subsystem(device, subsystem);
     793                 :            :                 /* use implicit names */
     794         [ +  + ]:       4732 :                 else if (path_startswith(device->devpath, "/module/"))
     795                 :       2576 :                         r = device_set_subsystem(device, "module");
     796   [ +  +  +  - ]:       2664 :                 else if (!(drivers = strstr(syspath, "/drivers/")) &&
     797                 :        508 :                          PATH_STARTSWITH_SET(device->devpath, "/subsystem/",
     798                 :            :                                                               "/class/",
     799                 :            :                                                               "/bus/"))
     800                 :        508 :                         r = device_set_subsystem(device, "subsystem");
     801   [ +  +  -  + ]:      30940 :                 if (r < 0 && r != -ENOENT)
     802   [ #  #  #  #  :          0 :                         return log_device_debug_errno(device, r, "sd-device: Failed to set subsystem for %s: %m", device->devpath);
                   #  # ]
     803                 :            : 
     804                 :      30940 :                 device->subsystem_set = true;
     805         [ -  + ]:       9752 :         } else if (!device->driver_subsystem_set)
     806                 :          0 :                 drivers = strstr(syspath, "/drivers/");
     807                 :            : 
     808         [ +  + ]:      40692 :         if (!device->driver_subsystem_set) {
     809         [ +  + ]:      30940 :                 if (drivers) {
     810         [ +  - ]:       1648 :                         _cleanup_free_ char *subpath = NULL;
     811                 :            : 
     812                 :       1648 :                         subpath = strndup(syspath, drivers - syspath);
     813         [ -  + ]:       1648 :                         if (!subpath)
     814                 :          0 :                                 r = -ENOMEM;
     815                 :            :                         else {
     816                 :            :                                 const char *subsys;
     817                 :            : 
     818                 :       1648 :                                 subsys = strrchr(subpath, '/');
     819         [ -  + ]:       1648 :                                 if (!subsys)
     820                 :          0 :                                         r = -EINVAL;
     821                 :            :                                 else
     822                 :       1648 :                                         r = device_set_drivers_subsystem(device, subsys + 1);
     823                 :            :                         }
     824   [ -  +  #  # ]:       1648 :                         if (r < 0 && r != -ENOENT)
     825   [ #  #  #  #  :          0 :                                 return log_device_debug_errno(device, r, "sd-device: Failed to set subsystem for driver %s: %m", device->devpath);
                   #  # ]
     826                 :            :                 }
     827                 :            : 
     828                 :      30940 :                 device->driver_subsystem_set = true;
     829                 :            :         }
     830                 :            : 
     831         [ -  + ]:      40692 :         if (!device->subsystem)
     832                 :          0 :                 return -ENOENT;
     833                 :            : 
     834                 :      40692 :         *ret = device->subsystem;
     835                 :      40692 :         return 0;
     836                 :            : }
     837                 :            : 
     838                 :       4440 : _public_ int sd_device_get_devtype(sd_device *device, const char **devtype) {
     839                 :            :         int r;
     840                 :            : 
     841         [ -  + ]:       4440 :         assert(devtype);
     842         [ -  + ]:       4440 :         assert(device);
     843                 :            : 
     844                 :       4440 :         r = device_read_uevent_file(device);
     845         [ -  + ]:       4440 :         if (r < 0)
     846                 :          0 :                 return r;
     847                 :            : 
     848         [ +  + ]:       4440 :         if (!device->devtype)
     849                 :       4144 :                 return -ENOENT;
     850                 :            : 
     851                 :        296 :         *devtype = device->devtype;
     852                 :            : 
     853                 :        296 :         return 0;
     854                 :            : }
     855                 :            : 
     856                 :          0 : _public_ int sd_device_get_parent_with_subsystem_devtype(sd_device *child, const char *subsystem, const char *devtype, sd_device **ret) {
     857                 :          0 :         sd_device *parent = NULL;
     858                 :            :         int r;
     859                 :            : 
     860   [ #  #  #  # ]:          0 :         assert_return(child, -EINVAL);
     861   [ #  #  #  # ]:          0 :         assert_return(subsystem, -EINVAL);
     862                 :            : 
     863                 :          0 :         r = sd_device_get_parent(child, &parent);
     864         [ #  # ]:          0 :         while (r >= 0) {
     865                 :          0 :                 const char *parent_subsystem = NULL;
     866                 :          0 :                 const char *parent_devtype = NULL;
     867                 :            : 
     868                 :          0 :                 (void) sd_device_get_subsystem(parent, &parent_subsystem);
     869         [ #  # ]:          0 :                 if (streq_ptr(parent_subsystem, subsystem)) {
     870         [ #  # ]:          0 :                         if (!devtype)
     871                 :          0 :                                 break;
     872                 :            : 
     873                 :          0 :                         (void) sd_device_get_devtype(parent, &parent_devtype);
     874         [ #  # ]:          0 :                         if (streq_ptr(parent_devtype, devtype))
     875                 :          0 :                                 break;
     876                 :            :                 }
     877                 :          0 :                 r = sd_device_get_parent(parent, &parent);
     878                 :            :         }
     879                 :            : 
     880         [ #  # ]:          0 :         if (r < 0)
     881                 :          0 :                 return r;
     882                 :            : 
     883                 :          0 :         *ret = parent;
     884                 :          0 :         return 0;
     885                 :            : }
     886                 :            : 
     887                 :      33056 : _public_ int sd_device_get_devnum(sd_device *device, dev_t *devnum) {
     888                 :            :         int r;
     889                 :            : 
     890   [ -  +  -  + ]:      33056 :         assert_return(device, -EINVAL);
     891                 :            : 
     892                 :      33056 :         r = device_read_uevent_file(device);
     893         [ -  + ]:      33056 :         if (r < 0)
     894                 :          0 :                 return r;
     895                 :            : 
     896         [ +  + ]:      33056 :         if (major(device->devnum) <= 0)
     897                 :      22352 :                 return -ENOENT;
     898                 :            : 
     899         [ +  - ]:      10704 :         if (devnum)
     900                 :      10704 :                 *devnum = device->devnum;
     901                 :            : 
     902                 :      10704 :         return 0;
     903                 :            : }
     904                 :            : 
     905                 :        348 : int device_set_driver(sd_device *device, const char *_driver) {
     906                 :        348 :         _cleanup_free_ char *driver = NULL;
     907                 :            :         int r;
     908                 :            : 
     909         [ -  + ]:        348 :         assert(device);
     910         [ -  + ]:        348 :         assert(_driver);
     911                 :            : 
     912                 :        348 :         driver = strdup(_driver);
     913         [ -  + ]:        348 :         if (!driver)
     914                 :          0 :                 return -ENOMEM;
     915                 :            : 
     916                 :        348 :         r = device_add_property_internal(device, "DRIVER", driver);
     917         [ -  + ]:        348 :         if (r < 0)
     918                 :          0 :                 return r;
     919                 :            : 
     920                 :        348 :         device->driver_set = true;
     921                 :        348 :         return free_and_replace(device->driver, driver);
     922                 :            : }
     923                 :            : 
     924                 :       4432 : _public_ int sd_device_get_driver(sd_device *device, const char **ret) {
     925   [ -  +  -  + ]:       4432 :         assert_return(device, -EINVAL);
     926   [ -  +  -  + ]:       4432 :         assert_return(ret, -EINVAL);
     927                 :            : 
     928         [ +  + ]:       4432 :         if (!device->driver_set) {
     929         [ +  - ]:       4428 :                 _cleanup_free_ char *driver = NULL;
     930                 :            :                 const char *syspath;
     931                 :            :                 char *path;
     932                 :            :                 int r;
     933                 :            : 
     934                 :       4428 :                 r = sd_device_get_syspath(device, &syspath);
     935         [ -  + ]:       4428 :                 if (r < 0)
     936                 :          0 :                         return r;
     937                 :            : 
     938   [ +  +  +  -  :      22140 :                 path = strjoina(syspath, "/driver");
          -  +  -  +  +  
                +  +  - ]
     939                 :       4428 :                 r = readlink_value(path, &driver);
     940         [ +  + ]:       4428 :                 if (r >= 0) {
     941                 :        348 :                         r = device_set_driver(device, driver);
     942         [ -  + ]:        348 :                         if (r < 0)
     943   [ #  #  #  #  :          0 :                                 return log_device_debug_errno(device, r, "sd-device: Failed to set driver for %s: %m", device->devpath);
                   #  # ]
     944         [ +  - ]:       4080 :                 } else if (r == -ENOENT)
     945                 :       4080 :                         device->driver_set = true;
     946                 :            :                 else
     947   [ #  #  #  #  :          0 :                         return log_device_debug_errno(device, r, "sd-device: Failed to set driver for %s: %m", device->devpath);
                   #  # ]
     948                 :            :         }
     949                 :            : 
     950         [ +  + ]:       4432 :         if (!device->driver)
     951                 :       4084 :                 return -ENOENT;
     952                 :            : 
     953                 :        348 :         *ret = device->driver;
     954                 :        348 :         return 0;
     955                 :            : }
     956                 :            : 
     957                 :     316992 : _public_ int sd_device_get_devpath(sd_device *device, const char **devpath) {
     958   [ -  +  -  + ]:     316992 :         assert_return(device, -EINVAL);
     959   [ -  +  -  + ]:     316992 :         assert_return(devpath, -EINVAL);
     960                 :            : 
     961         [ -  + ]:     316992 :         assert(device->devpath);
     962         [ -  + ]:     316992 :         assert(device->devpath[0] == '/');
     963                 :            : 
     964                 :     316992 :         *devpath = device->devpath;
     965                 :     316992 :         return 0;
     966                 :            : }
     967                 :            : 
     968                 :       7072 : _public_ int sd_device_get_devname(sd_device *device, const char **devname) {
     969                 :            :         int r;
     970                 :            : 
     971   [ -  +  -  + ]:       7072 :         assert_return(device, -EINVAL);
     972   [ -  +  -  + ]:       7072 :         assert_return(devname, -EINVAL);
     973                 :            : 
     974                 :       7072 :         r = device_read_uevent_file(device);
     975         [ -  + ]:       7072 :         if (r < 0)
     976                 :          0 :                 return r;
     977                 :            : 
     978         [ +  + ]:       7072 :         if (!device->devname)
     979                 :       4036 :                 return -ENOENT;
     980                 :            : 
     981         [ -  + ]:       3036 :         assert(path_startswith(device->devname, "/dev/"));
     982                 :            : 
     983                 :       3036 :         *devname = device->devname;
     984                 :       3036 :         return 0;
     985                 :            : }
     986                 :            : 
     987                 :       6892 : static int device_set_sysname(sd_device *device) {
     988                 :       6892 :         _cleanup_free_ char *sysname = NULL;
     989                 :       6892 :         const char *sysnum = NULL;
     990                 :            :         const char *pos;
     991                 :       6892 :         size_t len = 0;
     992                 :            : 
     993         [ -  + ]:       6892 :         if (!device->devpath)
     994                 :          0 :                 return -EINVAL;
     995                 :            : 
     996                 :       6892 :         pos = strrchr(device->devpath, '/');
     997         [ -  + ]:       6892 :         if (!pos)
     998                 :          0 :                 return -EINVAL;
     999                 :       6892 :         pos++;
    1000                 :            : 
    1001                 :            :         /* devpath is not a root directory */
    1002   [ +  -  -  + ]:       6892 :         if (*pos == '\0' || pos <= device->devpath)
    1003                 :          0 :                 return -EINVAL;
    1004                 :            : 
    1005                 :       6892 :         sysname = strdup(pos);
    1006         [ -  + ]:       6892 :         if (!sysname)
    1007                 :          0 :                 return -ENOMEM;
    1008                 :            : 
    1009                 :            :         /* some devices have '!' in their name, change that to '/' */
    1010         [ +  + ]:      61708 :         while (sysname[len] != '\0') {
    1011         [ -  + ]:      54816 :                 if (sysname[len] == '!')
    1012                 :          0 :                         sysname[len] = '/';
    1013                 :            : 
    1014                 :      54816 :                 len++;
    1015                 :            :         }
    1016                 :            : 
    1017                 :            :         /* trailing number */
    1018   [ +  +  +  + ]:      14052 :         while (len > 0 && isdigit(sysname[--len]))
    1019                 :       7160 :                 sysnum = &sysname[len];
    1020                 :            : 
    1021         [ +  + ]:       6892 :         if (len == 0)
    1022                 :         28 :                 sysnum = NULL;
    1023                 :            : 
    1024                 :       6892 :         device->sysname_set = true;
    1025                 :       6892 :         device->sysnum = sysnum;
    1026                 :       6892 :         return free_and_replace(device->sysname, sysname);
    1027                 :            : }
    1028                 :            : 
    1029                 :       6896 : _public_ int sd_device_get_sysname(sd_device *device, const char **ret) {
    1030                 :            :         int r;
    1031                 :            : 
    1032   [ -  +  -  + ]:       6896 :         assert_return(device, -EINVAL);
    1033   [ -  +  -  + ]:       6896 :         assert_return(ret, -EINVAL);
    1034                 :            : 
    1035         [ +  + ]:       6896 :         if (!device->sysname_set) {
    1036                 :       6892 :                 r = device_set_sysname(device);
    1037         [ -  + ]:       6892 :                 if (r < 0)
    1038                 :          0 :                         return r;
    1039                 :            :         }
    1040                 :            : 
    1041   [ -  +  -  + ]:       6896 :         assert_return(device->sysname, -ENOENT);
    1042                 :            : 
    1043                 :       6896 :         *ret = device->sysname;
    1044                 :       6896 :         return 0;
    1045                 :            : }
    1046                 :            : 
    1047                 :       4432 : _public_ int sd_device_get_sysnum(sd_device *device, const char **ret) {
    1048                 :            :         int r;
    1049                 :            : 
    1050   [ -  +  -  + ]:       4432 :         assert_return(device, -EINVAL);
    1051   [ -  +  -  + ]:       4432 :         assert_return(ret, -EINVAL);
    1052                 :            : 
    1053         [ -  + ]:       4432 :         if (!device->sysname_set) {
    1054                 :          0 :                 r = device_set_sysname(device);
    1055         [ #  # ]:          0 :                 if (r < 0)
    1056                 :          0 :                         return r;
    1057                 :            :         }
    1058                 :            : 
    1059         [ +  + ]:       4432 :         if (!device->sysnum)
    1060                 :       1996 :                 return -ENOENT;
    1061                 :            : 
    1062                 :       2436 :         *ret = device->sysnum;
    1063                 :       2436 :         return 0;
    1064                 :            : }
    1065                 :            : 
    1066                 :       6216 : static bool is_valid_tag(const char *tag) {
    1067         [ -  + ]:       6216 :         assert(tag);
    1068                 :            : 
    1069   [ +  -  +  - ]:       6216 :         return !strchr(tag, ':') && !strchr(tag, ' ');
    1070                 :            : }
    1071                 :            : 
    1072                 :       6216 : int device_add_tag(sd_device *device, const char *tag) {
    1073                 :            :         int r;
    1074                 :            : 
    1075         [ -  + ]:       6216 :         assert(device);
    1076         [ -  + ]:       6216 :         assert(tag);
    1077                 :            : 
    1078         [ -  + ]:       6216 :         if (!is_valid_tag(tag))
    1079                 :          0 :                 return -EINVAL;
    1080                 :            : 
    1081                 :       6216 :         r = set_ensure_allocated(&device->tags, &string_hash_ops);
    1082         [ -  + ]:       6216 :         if (r < 0)
    1083                 :          0 :                 return r;
    1084                 :            : 
    1085                 :       6216 :         r = set_put_strdup(device->tags, tag);
    1086         [ -  + ]:       6216 :         if (r < 0)
    1087                 :          0 :                 return r;
    1088                 :            : 
    1089                 :       6216 :         device->tags_generation++;
    1090                 :       6216 :         device->property_tags_outdated = true;
    1091                 :            : 
    1092                 :       6216 :         return 0;
    1093                 :            : }
    1094                 :            : 
    1095                 :       3648 : int device_add_devlink(sd_device *device, const char *devlink) {
    1096                 :            :         int r;
    1097                 :            : 
    1098         [ -  + ]:       3648 :         assert(device);
    1099         [ -  + ]:       3648 :         assert(devlink);
    1100                 :            : 
    1101                 :       3648 :         r = set_ensure_allocated(&device->devlinks, &string_hash_ops);
    1102         [ -  + ]:       3648 :         if (r < 0)
    1103                 :          0 :                 return r;
    1104                 :            : 
    1105                 :       3648 :         r = set_put_strdup(device->devlinks, devlink);
    1106         [ -  + ]:       3648 :         if (r < 0)
    1107                 :          0 :                 return r;
    1108                 :            : 
    1109                 :       3648 :         device->devlinks_generation++;
    1110                 :       3648 :         device->property_devlinks_outdated = true;
    1111                 :            : 
    1112                 :       3648 :         return 0;
    1113                 :            : }
    1114                 :            : 
    1115                 :      49244 : static int device_add_property_internal_from_string(sd_device *device, const char *str) {
    1116                 :      49244 :         _cleanup_free_ char *key = NULL;
    1117                 :            :         char *value;
    1118                 :            :         int r;
    1119                 :            : 
    1120         [ -  + ]:      49244 :         assert(device);
    1121         [ -  + ]:      49244 :         assert(str);
    1122                 :            : 
    1123                 :      49244 :         key = strdup(str);
    1124         [ -  + ]:      49244 :         if (!key)
    1125                 :          0 :                 return -ENOMEM;
    1126                 :            : 
    1127                 :      49244 :         value = strchr(key, '=');
    1128         [ -  + ]:      49244 :         if (!value)
    1129                 :          0 :                 return -EINVAL;
    1130                 :            : 
    1131                 :      49244 :         *value = '\0';
    1132                 :            : 
    1133         [ +  + ]:      49244 :         if (isempty(++value))
    1134                 :        656 :                 value = NULL;
    1135                 :            : 
    1136                 :            :         /* Add the property to both sd_device::properties and sd_device::properties_db,
    1137                 :            :          * as this is called by only handle_db_line(). */
    1138                 :      49244 :         r = device_add_property_aux(device, key, value, false);
    1139         [ -  + ]:      49244 :         if (r < 0)
    1140                 :          0 :                 return r;
    1141                 :            : 
    1142                 :      49244 :         return device_add_property_aux(device, key, value, true);
    1143                 :            : }
    1144                 :            : 
    1145                 :       9676 : int device_set_usec_initialized(sd_device *device, usec_t when) {
    1146                 :            :         char s[DECIMAL_STR_MAX(usec_t)];
    1147                 :            :         int r;
    1148                 :            : 
    1149         [ -  + ]:       9676 :         assert(device);
    1150                 :            : 
    1151         [ -  + ]:       9676 :         xsprintf(s, USEC_FMT, when);
    1152                 :            : 
    1153                 :       9676 :         r = device_add_property_internal(device, "USEC_INITIALIZED", s);
    1154         [ -  + ]:       9676 :         if (r < 0)
    1155                 :          0 :                 return r;
    1156                 :            : 
    1157                 :       9676 :         device->usec_initialized = when;
    1158                 :       9676 :         return 0;
    1159                 :            : }
    1160                 :            : 
    1161                 :      69712 : static int handle_db_line(sd_device *device, char key, const char *value) {
    1162                 :            :         char *path;
    1163                 :            :         int r;
    1164                 :            : 
    1165         [ -  + ]:      69712 :         assert(device);
    1166         [ -  + ]:      69712 :         assert(value);
    1167                 :            : 
    1168   [ +  +  +  +  :      69712 :         switch (key) {
                +  +  - ]
    1169                 :       6216 :         case 'G':
    1170                 :       6216 :                 r = device_add_tag(device, value);
    1171         [ -  + ]:       6216 :                 if (r < 0)
    1172                 :          0 :                         return r;
    1173                 :            : 
    1174                 :       6216 :                 break;
    1175                 :       3648 :         case 'S':
    1176   [ +  +  +  -  :      18240 :                 path = strjoina("/dev/", value);
          -  +  -  +  +  
                +  +  - ]
    1177                 :       3648 :                 r = device_add_devlink(device, path);
    1178         [ -  + ]:       3648 :                 if (r < 0)
    1179                 :          0 :                         return r;
    1180                 :            : 
    1181                 :       3648 :                 break;
    1182                 :      49244 :         case 'E':
    1183                 :      49244 :                 r = device_add_property_internal_from_string(device, value);
    1184         [ -  + ]:      49244 :                 if (r < 0)
    1185                 :          0 :                         return r;
    1186                 :            : 
    1187                 :      49244 :                 break;
    1188                 :       9676 :         case 'I': {
    1189                 :            :                 usec_t t;
    1190                 :            : 
    1191                 :       9676 :                 r = safe_atou64(value, &t);
    1192         [ -  + ]:       9676 :                 if (r < 0)
    1193                 :          0 :                         return r;
    1194                 :            : 
    1195                 :       9676 :                 r = device_set_usec_initialized(device, t);
    1196         [ -  + ]:       9676 :                 if (r < 0)
    1197                 :          0 :                         return r;
    1198                 :            : 
    1199                 :       9676 :                 break;
    1200                 :            :         }
    1201                 :         24 :         case 'L':
    1202                 :         24 :                 r = safe_atoi(value, &device->devlink_priority);
    1203         [ -  + ]:         24 :                 if (r < 0)
    1204                 :          0 :                         return r;
    1205                 :            : 
    1206                 :         24 :                 break;
    1207                 :        904 :         case 'W':
    1208                 :        904 :                 r = safe_atoi(value, &device->watch_handle);
    1209         [ -  + ]:        904 :                 if (r < 0)
    1210                 :          0 :                         return r;
    1211                 :            : 
    1212                 :        904 :                 break;
    1213                 :          0 :         default:
    1214   [ #  #  #  #  :          0 :                 log_device_debug(device, "sd-device: Unknown key '%c' in device db, ignoring", key);
                   #  # ]
    1215                 :            :         }
    1216                 :            : 
    1217                 :      69712 :         return 0;
    1218                 :            : }
    1219                 :            : 
    1220                 :      34756 : int device_get_id_filename(sd_device *device, const char **ret) {
    1221         [ -  + ]:      34756 :         assert(device);
    1222         [ -  + ]:      34756 :         assert(ret);
    1223                 :            : 
    1224         [ +  + ]:      34756 :         if (!device->id_filename) {
    1225         [ +  - ]:      23428 :                 _cleanup_free_ char *id = NULL;
    1226                 :            :                 const char *subsystem;
    1227                 :            :                 dev_t devnum;
    1228                 :            :                 int ifindex, r;
    1229                 :            : 
    1230                 :      23428 :                 r = sd_device_get_subsystem(device, &subsystem);
    1231         [ -  + ]:      23428 :                 if (r < 0)
    1232                 :          0 :                         return r;
    1233                 :            : 
    1234         [ +  + ]:      23428 :                 if (sd_device_get_devnum(device, &devnum) >= 0) {
    1235         [ -  + ]:       7976 :                         assert(subsystem);
    1236                 :            : 
    1237                 :            :                         /* use dev_t — b259:131072, c254:0 */
    1238                 :       7976 :                         r = asprintf(&id, "%c%u:%u",
    1239         [ +  + ]:       7976 :                                      streq(subsystem, "block") ? 'b' : 'c',
    1240                 :            :                                      major(devnum), minor(devnum));
    1241         [ -  + ]:       7976 :                         if (r < 0)
    1242                 :          0 :                                 return -ENOMEM;
    1243         [ +  + ]:      15452 :                 } else if (sd_device_get_ifindex(device, &ifindex) >= 0) {
    1244                 :            :                         /* use netdev ifindex — n3 */
    1245                 :        500 :                         r = asprintf(&id, "n%u", (unsigned) ifindex);
    1246         [ -  + ]:        500 :                         if (r < 0)
    1247                 :          0 :                                 return -ENOMEM;
    1248                 :            :                 } else {
    1249                 :            :                         /* use $subsys:$sysname — pci:0000:00:1f.2
    1250                 :            :                          * sysname() has '!' translated, get it from devpath
    1251                 :            :                          */
    1252                 :            :                         const char *sysname;
    1253                 :            : 
    1254                 :      14952 :                         sysname = basename(device->devpath);
    1255         [ -  + ]:      14952 :                         if (!sysname)
    1256                 :          0 :                                 return -EINVAL;
    1257                 :            : 
    1258         [ -  + ]:      14952 :                         if (!subsystem)
    1259                 :          0 :                                 return -EINVAL;
    1260                 :            : 
    1261         [ +  + ]:      14952 :                         if (streq(subsystem, "drivers")) {
    1262                 :            :                                 /* the 'drivers' pseudo-subsystem is special, and needs the real subsystem
    1263                 :            :                                  * encoded as well */
    1264                 :       1100 :                                 r = asprintf(&id, "+drivers:%s:%s", device->driver_subsystem, sysname);
    1265         [ -  + ]:       1100 :                                 if (r < 0)
    1266                 :          0 :                                         return -ENOMEM;
    1267                 :            :                         } else {
    1268                 :      13852 :                                 r = asprintf(&id, "+%s:%s", subsystem, sysname);
    1269         [ -  + ]:      13852 :                                 if (r < 0)
    1270                 :          0 :                                         return -ENOMEM;
    1271                 :            :                         }
    1272                 :            :                 }
    1273                 :            : 
    1274                 :      23428 :                 device->id_filename = TAKE_PTR(id);
    1275                 :            :         }
    1276                 :            : 
    1277                 :      34756 :         *ret = device->id_filename;
    1278                 :      34756 :         return 0;
    1279                 :            : }
    1280                 :            : 
    1281                 :      34756 : int device_read_db_internal_filename(sd_device *device, const char *filename) {
    1282                 :      34756 :         _cleanup_free_ char *db = NULL;
    1283                 :            :         const char *value;
    1284                 :            :         size_t db_len, i;
    1285                 :            :         char key;
    1286                 :            :         int r;
    1287                 :            : 
    1288                 :            :         enum {
    1289                 :            :                 PRE_KEY,
    1290                 :            :                 KEY,
    1291                 :            :                 PRE_VALUE,
    1292                 :            :                 VALUE,
    1293                 :            :                 INVALID_LINE,
    1294                 :      34756 :         } state = PRE_KEY;
    1295                 :            : 
    1296         [ -  + ]:      34756 :         assert(device);
    1297         [ -  + ]:      34756 :         assert(filename);
    1298                 :            : 
    1299                 :      34756 :         r = read_full_file(filename, &db, &db_len);
    1300         [ +  + ]:      34756 :         if (r < 0) {
    1301         [ +  - ]:      23084 :                 if (r == -ENOENT)
    1302                 :      23084 :                         return 0;
    1303                 :            : 
    1304   [ #  #  #  #  :          0 :                 return log_device_debug_errno(device, r, "sd-device: Failed to read db '%s': %m", filename);
                   #  # ]
    1305                 :            :         }
    1306                 :            : 
    1307                 :            :         /* devices with a database entry are initialized */
    1308                 :      11672 :         device->is_initialized = true;
    1309                 :            : 
    1310                 :      11672 :         device->db_loaded = true;
    1311                 :            : 
    1312         [ +  + ]:    1966524 :         for (i = 0; i < db_len; i++) {
    1313   [ +  +  +  -  :    1954852 :                 switch (state) {
                   +  - ]
    1314                 :      69712 :                 case PRE_KEY:
    1315         [ +  - ]:      69712 :                         if (!strchr(NEWLINE, db[i])) {
    1316                 :      69712 :                                 key = db[i];
    1317                 :            : 
    1318                 :      69712 :                                 state = KEY;
    1319                 :            :                         }
    1320                 :            : 
    1321                 :      69712 :                         break;
    1322                 :      69712 :                 case KEY:
    1323         [ -  + ]:      69712 :                         if (db[i] != ':') {
    1324   [ #  #  #  #  :          0 :                                 log_device_debug(device, "sd-device: Invalid db entry with key '%c', ignoring", key);
                   #  # ]
    1325                 :            : 
    1326                 :          0 :                                 state = INVALID_LINE;
    1327                 :            :                         } else {
    1328                 :      69712 :                                 db[i] = '\0';
    1329                 :            : 
    1330                 :      69712 :                                 state = PRE_VALUE;
    1331                 :            :                         }
    1332                 :            : 
    1333                 :      69712 :                         break;
    1334                 :      69712 :                 case PRE_VALUE:
    1335                 :      69712 :                         value = &db[i];
    1336                 :            : 
    1337                 :      69712 :                         state = VALUE;
    1338                 :            : 
    1339                 :      69712 :                         break;
    1340                 :          0 :                 case INVALID_LINE:
    1341         [ #  # ]:          0 :                         if (strchr(NEWLINE, db[i]))
    1342                 :          0 :                                 state = PRE_KEY;
    1343                 :            : 
    1344                 :          0 :                         break;
    1345                 :    1745716 :                 case VALUE:
    1346         [ +  + ]:    1745716 :                         if (strchr(NEWLINE, db[i])) {
    1347                 :      69712 :                                 db[i] = '\0';
    1348                 :      69712 :                                 r = handle_db_line(device, key, value);
    1349         [ -  + ]:      69712 :                                 if (r < 0)
    1350   [ #  #  #  #  :          0 :                                         log_device_debug_errno(device, r, "sd-device: Failed to handle db entry '%c:%s', ignoring: %m", key, value);
                   #  # ]
    1351                 :            : 
    1352                 :      69712 :                                 state = PRE_KEY;
    1353                 :            :                         }
    1354                 :            : 
    1355                 :    1745716 :                         break;
    1356                 :          0 :                 default:
    1357   [ #  #  #  #  :          0 :                         return log_device_debug_errno(device, SYNTHETIC_ERRNO(EINVAL), "sd-device: invalid db syntax.");
                   #  # ]
    1358                 :            :                 }
    1359                 :            :         }
    1360                 :            : 
    1361                 :      11672 :         return 0;
    1362                 :            : }
    1363                 :            : 
    1364                 :      98292 : int device_read_db_internal(sd_device *device, bool force) {
    1365                 :            :         const char *id, *path;
    1366                 :            :         int r;
    1367                 :            : 
    1368         [ -  + ]:      98292 :         assert(device);
    1369                 :            : 
    1370   [ +  +  +  -  :      98292 :         if (device->db_loaded || (!force && device->sealed))
                   -  + ]
    1371                 :      63536 :                 return 0;
    1372                 :            : 
    1373                 :      34756 :         r = device_get_id_filename(device, &id);
    1374         [ -  + ]:      34756 :         if (r < 0)
    1375                 :          0 :                 return r;
    1376                 :            : 
    1377   [ +  +  +  -  :     173780 :         path = strjoina("/run/udev/data/", id);
          -  +  -  +  +  
                +  +  - ]
    1378                 :            : 
    1379                 :      34756 :         return device_read_db_internal_filename(device, path);
    1380                 :            : }
    1381                 :            : 
    1382                 :      25060 : _public_ int sd_device_get_is_initialized(sd_device *device) {
    1383                 :            :         int r;
    1384                 :            : 
    1385   [ -  +  -  + ]:      25060 :         assert_return(device, -EINVAL);
    1386                 :            : 
    1387                 :      25060 :         r = device_read_db(device);
    1388         [ -  + ]:      25060 :         if (r < 0)
    1389                 :          0 :                 return r;
    1390                 :            : 
    1391                 :      25060 :         return device->is_initialized;
    1392                 :            : }
    1393                 :            : 
    1394                 :       1452 : _public_ int sd_device_get_usec_since_initialized(sd_device *device, uint64_t *usec) {
    1395                 :            :         usec_t now_ts;
    1396                 :            :         int r;
    1397                 :            : 
    1398   [ -  +  -  + ]:       1452 :         assert_return(device, -EINVAL);
    1399   [ -  +  -  + ]:       1452 :         assert_return(usec, -EINVAL);
    1400                 :            : 
    1401                 :       1452 :         r = device_read_db(device);
    1402         [ -  + ]:       1452 :         if (r < 0)
    1403                 :          0 :                 return r;
    1404                 :            : 
    1405         [ -  + ]:       1452 :         if (!device->is_initialized)
    1406                 :          0 :                 return -EBUSY;
    1407                 :            : 
    1408         [ +  + ]:       1452 :         if (!device->usec_initialized)
    1409                 :        304 :                 return -ENODATA;
    1410                 :            : 
    1411                 :       1148 :         now_ts = now(clock_boottime_or_monotonic());
    1412                 :            : 
    1413         [ -  + ]:       1148 :         if (now_ts < device->usec_initialized)
    1414                 :          0 :                 return -EIO;
    1415                 :            : 
    1416                 :       1148 :         *usec = now_ts - device->usec_initialized;
    1417                 :       1148 :         return 0;
    1418                 :            : }
    1419                 :            : 
    1420                 :       3628 : _public_ const char *sd_device_get_tag_first(sd_device *device) {
    1421                 :            :         void *v;
    1422                 :            : 
    1423   [ -  +  -  + ]:       3628 :         assert_return(device, NULL);
    1424                 :            : 
    1425                 :       3628 :         (void) device_read_db(device);
    1426                 :            : 
    1427                 :       3628 :         device->tags_iterator_generation = device->tags_generation;
    1428                 :       3628 :         device->tags_iterator = ITERATOR_FIRST;
    1429                 :            : 
    1430                 :       3628 :         (void) set_iterate(device->tags, &device->tags_iterator, &v);
    1431                 :       3628 :         return v;
    1432                 :            : }
    1433                 :            : 
    1434                 :       3948 : _public_ const char *sd_device_get_tag_next(sd_device *device) {
    1435                 :            :         void *v;
    1436                 :            : 
    1437   [ -  +  -  + ]:       3948 :         assert_return(device, NULL);
    1438                 :            : 
    1439                 :       3948 :         (void) device_read_db(device);
    1440                 :            : 
    1441         [ -  + ]:       3948 :         if (device->tags_iterator_generation != device->tags_generation)
    1442                 :          0 :                 return NULL;
    1443                 :            : 
    1444                 :       3948 :         (void) set_iterate(device->tags, &device->tags_iterator, &v);
    1445                 :       3948 :         return v;
    1446                 :            : }
    1447                 :            : 
    1448                 :       2464 : _public_ const char *sd_device_get_devlink_first(sd_device *device) {
    1449                 :            :         void *v;
    1450                 :            : 
    1451   [ -  +  -  + ]:       2464 :         assert_return(device, NULL);
    1452                 :            : 
    1453                 :       2464 :         (void) device_read_db(device);
    1454                 :            : 
    1455                 :       2464 :         device->devlinks_iterator_generation = device->devlinks_generation;
    1456                 :       2464 :         device->devlinks_iterator = ITERATOR_FIRST;
    1457                 :            : 
    1458                 :       2464 :         (void) set_iterate(device->devlinks, &device->devlinks_iterator, &v);
    1459                 :       2464 :         return v;
    1460                 :            : }
    1461                 :            : 
    1462                 :       4316 : _public_ const char *sd_device_get_devlink_next(sd_device *device) {
    1463                 :            :         void *v;
    1464                 :            : 
    1465   [ -  +  -  + ]:       4316 :         assert_return(device, NULL);
    1466                 :            : 
    1467                 :       4316 :         (void) device_read_db(device);
    1468                 :            : 
    1469         [ -  + ]:       4316 :         if (device->devlinks_iterator_generation != device->devlinks_generation)
    1470                 :          0 :                 return NULL;
    1471                 :            : 
    1472                 :       4316 :         (void) set_iterate(device->devlinks, &device->devlinks_iterator, &v);
    1473                 :       4316 :         return v;
    1474                 :            : }
    1475                 :            : 
    1476                 :      57424 : int device_properties_prepare(sd_device *device) {
    1477                 :            :         int r;
    1478                 :            : 
    1479         [ -  + ]:      57424 :         assert(device);
    1480                 :            : 
    1481                 :      57424 :         r = device_read_uevent_file(device);
    1482         [ -  + ]:      57424 :         if (r < 0)
    1483                 :          0 :                 return r;
    1484                 :            : 
    1485                 :      57424 :         r = device_read_db(device);
    1486         [ -  + ]:      57424 :         if (r < 0)
    1487                 :          0 :                 return r;
    1488                 :            : 
    1489         [ +  + ]:      57424 :         if (device->property_devlinks_outdated) {
    1490         [ +  - ]:        632 :                 _cleanup_free_ char *devlinks = NULL;
    1491                 :        632 :                 size_t devlinks_allocated = 0, devlinks_len = 0;
    1492                 :            :                 const char *devlink;
    1493                 :            : 
    1494         [ +  + ]:       3308 :                 for (devlink = sd_device_get_devlink_first(device); devlink; devlink = sd_device_get_devlink_next(device)) {
    1495                 :            :                         char *e;
    1496                 :            : 
    1497         [ -  + ]:       2676 :                         if (!GREEDY_REALLOC(devlinks, devlinks_allocated, devlinks_len + strlen(devlink) + 2))
    1498                 :          0 :                                 return -ENOMEM;
    1499         [ +  + ]:       2676 :                         if (devlinks_len > 0)
    1500                 :       2044 :                                 stpcpy(devlinks + devlinks_len++, " ");
    1501                 :       2676 :                         e = stpcpy(devlinks + devlinks_len, devlink);
    1502                 :       2676 :                         devlinks_len = e - devlinks;
    1503                 :            :                 }
    1504                 :            : 
    1505                 :        632 :                 r = device_add_property_internal(device, "DEVLINKS", devlinks);
    1506         [ -  + ]:        632 :                 if (r < 0)
    1507                 :          0 :                         return r;
    1508                 :            : 
    1509                 :        632 :                 device->property_devlinks_outdated = false;
    1510                 :            :         }
    1511                 :            : 
    1512         [ +  + ]:      57424 :         if (device->property_tags_outdated) {
    1513         [ +  - ]:       3628 :                 _cleanup_free_ char *tags = NULL;
    1514                 :       3628 :                 size_t tags_allocated = 0, tags_len = 0;
    1515                 :            :                 const char *tag;
    1516                 :            : 
    1517         [ -  + ]:       3628 :                 if (!GREEDY_REALLOC(tags, tags_allocated, 2))
    1518                 :          0 :                         return -ENOMEM;
    1519                 :       3628 :                 stpcpy(tags, ":");
    1520                 :       3628 :                 tags_len++;
    1521                 :            : 
    1522         [ +  + ]:       7576 :                 for (tag = sd_device_get_tag_first(device); tag; tag = sd_device_get_tag_next(device)) {
    1523                 :            :                         char *e;
    1524                 :            : 
    1525         [ -  + ]:       3948 :                         if (!GREEDY_REALLOC(tags, tags_allocated, tags_len + strlen(tag) + 2))
    1526                 :          0 :                                 return -ENOMEM;
    1527                 :       3948 :                         e = stpcpy(stpcpy(tags + tags_len, tag), ":");
    1528                 :       3948 :                         tags_len = e - tags;
    1529                 :            :                 }
    1530                 :            : 
    1531                 :       3628 :                 r = device_add_property_internal(device, "TAGS", tags);
    1532         [ -  + ]:       3628 :                 if (r < 0)
    1533                 :          0 :                         return r;
    1534                 :            : 
    1535                 :       3628 :                 device->property_tags_outdated = false;
    1536                 :            :         }
    1537                 :            : 
    1538                 :      57424 :         return 0;
    1539                 :            : }
    1540                 :            : 
    1541                 :       2932 : _public_ const char *sd_device_get_property_first(sd_device *device, const char **_value) {
    1542                 :            :         const char *key;
    1543                 :            :         int r;
    1544                 :            : 
    1545   [ -  +  -  + ]:       2932 :         assert_return(device, NULL);
    1546                 :            : 
    1547                 :       2932 :         r = device_properties_prepare(device);
    1548         [ -  + ]:       2932 :         if (r < 0)
    1549                 :          0 :                 return NULL;
    1550                 :            : 
    1551                 :       2932 :         device->properties_iterator_generation = device->properties_generation;
    1552                 :       2932 :         device->properties_iterator = ITERATOR_FIRST;
    1553                 :            : 
    1554                 :       2932 :         (void) ordered_hashmap_iterate(device->properties, &device->properties_iterator, (void**)_value, (const void**)&key);
    1555                 :       2932 :         return key;
    1556                 :            : }
    1557                 :            : 
    1558                 :      17720 : _public_ const char *sd_device_get_property_next(sd_device *device, const char **_value) {
    1559                 :            :         const char *key;
    1560                 :            :         int r;
    1561                 :            : 
    1562   [ -  +  -  + ]:      17720 :         assert_return(device, NULL);
    1563                 :            : 
    1564                 :      17720 :         r = device_properties_prepare(device);
    1565         [ -  + ]:      17720 :         if (r < 0)
    1566                 :          0 :                 return NULL;
    1567                 :            : 
    1568         [ -  + ]:      17720 :         if (device->properties_iterator_generation != device->properties_generation)
    1569                 :          0 :                 return NULL;
    1570                 :            : 
    1571                 :      17720 :         (void) ordered_hashmap_iterate(device->properties, &device->properties_iterator, (void**)_value, (const void**)&key);
    1572                 :      17720 :         return key;
    1573                 :            : }
    1574                 :            : 
    1575                 :          0 : static int device_sysattrs_read_all(sd_device *device) {
    1576                 :          0 :         _cleanup_closedir_ DIR *dir = NULL;
    1577                 :            :         const char *syspath;
    1578                 :            :         struct dirent *dent;
    1579                 :            :         int r;
    1580                 :            : 
    1581         [ #  # ]:          0 :         assert(device);
    1582                 :            : 
    1583         [ #  # ]:          0 :         if (device->sysattrs_read)
    1584                 :          0 :                 return 0;
    1585                 :            : 
    1586                 :          0 :         r = sd_device_get_syspath(device, &syspath);
    1587         [ #  # ]:          0 :         if (r < 0)
    1588                 :          0 :                 return r;
    1589                 :            : 
    1590                 :          0 :         dir = opendir(syspath);
    1591         [ #  # ]:          0 :         if (!dir)
    1592                 :          0 :                 return -errno;
    1593                 :            : 
    1594                 :          0 :         r = set_ensure_allocated(&device->sysattrs, &string_hash_ops);
    1595         [ #  # ]:          0 :         if (r < 0)
    1596                 :          0 :                 return r;
    1597                 :            : 
    1598   [ #  #  #  # ]:          0 :         FOREACH_DIRENT_ALL(dent, dir, return -errno) {
    1599      [ #  #  # ]:          0 :                 _cleanup_free_ char *path = NULL;
    1600                 :            :                 struct stat statbuf;
    1601                 :            : 
    1602                 :            :                 /* only handle symlinks and regular files */
    1603   [ #  #  #  # ]:          0 :                 if (!IN_SET(dent->d_type, DT_LNK, DT_REG))
    1604                 :          0 :                         continue;
    1605                 :            : 
    1606                 :          0 :                 path = path_join(syspath, dent->d_name);
    1607         [ #  # ]:          0 :                 if (!path)
    1608                 :          0 :                         return -ENOMEM;
    1609                 :            : 
    1610         [ #  # ]:          0 :                 if (lstat(path, &statbuf) != 0)
    1611                 :          0 :                         continue;
    1612                 :            : 
    1613         [ #  # ]:          0 :                 if (!(statbuf.st_mode & S_IRUSR))
    1614                 :          0 :                         continue;
    1615                 :            : 
    1616                 :          0 :                 r = set_put_strdup(device->sysattrs, dent->d_name);
    1617         [ #  # ]:          0 :                 if (r < 0)
    1618                 :          0 :                         return r;
    1619                 :            :         }
    1620                 :            : 
    1621                 :          0 :         device->sysattrs_read = true;
    1622                 :            : 
    1623                 :          0 :         return 0;
    1624                 :            : }
    1625                 :            : 
    1626                 :          0 : _public_ const char *sd_device_get_sysattr_first(sd_device *device) {
    1627                 :            :         void *v;
    1628                 :            :         int r;
    1629                 :            : 
    1630   [ #  #  #  # ]:          0 :         assert_return(device, NULL);
    1631                 :            : 
    1632         [ #  # ]:          0 :         if (!device->sysattrs_read) {
    1633                 :          0 :                 r = device_sysattrs_read_all(device);
    1634         [ #  # ]:          0 :                 if (r < 0) {
    1635                 :          0 :                         errno = -r;
    1636                 :          0 :                         return NULL;
    1637                 :            :                 }
    1638                 :            :         }
    1639                 :            : 
    1640                 :          0 :         device->sysattrs_iterator = ITERATOR_FIRST;
    1641                 :            : 
    1642                 :          0 :         (void) set_iterate(device->sysattrs, &device->sysattrs_iterator, &v);
    1643                 :          0 :         return v;
    1644                 :            : }
    1645                 :            : 
    1646                 :          0 : _public_ const char *sd_device_get_sysattr_next(sd_device *device) {
    1647                 :            :         void *v;
    1648                 :            : 
    1649   [ #  #  #  # ]:          0 :         assert_return(device, NULL);
    1650                 :            : 
    1651         [ #  # ]:          0 :         if (!device->sysattrs_read)
    1652                 :          0 :                 return NULL;
    1653                 :            : 
    1654                 :          0 :         (void) set_iterate(device->sysattrs, &device->sysattrs_iterator, &v);
    1655                 :          0 :         return v;
    1656                 :            : }
    1657                 :            : 
    1658                 :          0 : _public_ int sd_device_has_tag(sd_device *device, const char *tag) {
    1659   [ #  #  #  # ]:          0 :         assert_return(device, -EINVAL);
    1660   [ #  #  #  # ]:          0 :         assert_return(tag, -EINVAL);
    1661                 :            : 
    1662                 :          0 :         (void) device_read_db(device);
    1663                 :            : 
    1664                 :          0 :         return !!set_contains(device->tags, tag);
    1665                 :            : }
    1666                 :            : 
    1667                 :      36772 : _public_ int sd_device_get_property_value(sd_device *device, const char *key, const char **_value) {
    1668                 :            :         char *value;
    1669                 :            :         int r;
    1670                 :            : 
    1671   [ -  +  -  + ]:      36772 :         assert_return(device, -EINVAL);
    1672   [ -  +  -  + ]:      36772 :         assert_return(key, -EINVAL);
    1673                 :            : 
    1674                 :      36772 :         r = device_properties_prepare(device);
    1675         [ -  + ]:      36772 :         if (r < 0)
    1676                 :          0 :                 return r;
    1677                 :            : 
    1678                 :      36772 :         value = ordered_hashmap_get(device->properties, key);
    1679         [ +  + ]:      36772 :         if (!value)
    1680                 :      33956 :                 return -ENOENT;
    1681                 :            : 
    1682         [ +  - ]:       2816 :         if (_value)
    1683                 :       2816 :                 *_value = value;
    1684                 :       2816 :         return 0;
    1685                 :            : }
    1686                 :            : 
    1687                 :            : /* replaces the value if it already exists */
    1688                 :       4428 : static int device_add_sysattr_value(sd_device *device, const char *_key, char *value) {
    1689                 :       4428 :         _cleanup_free_ char *key = NULL;
    1690                 :       4428 :         _cleanup_free_ char *value_old = NULL;
    1691                 :            :         int r;
    1692                 :            : 
    1693         [ -  + ]:       4428 :         assert(device);
    1694         [ -  + ]:       4428 :         assert(_key);
    1695                 :            : 
    1696                 :       4428 :         r = hashmap_ensure_allocated(&device->sysattr_values, &string_hash_ops);
    1697         [ -  + ]:       4428 :         if (r < 0)
    1698                 :          0 :                 return r;
    1699                 :            : 
    1700                 :       4428 :         value_old = hashmap_remove2(device->sysattr_values, _key, (void **)&key);
    1701         [ +  - ]:       4428 :         if (!key) {
    1702                 :       4428 :                 key = strdup(_key);
    1703         [ -  + ]:       4428 :                 if (!key)
    1704                 :          0 :                         return -ENOMEM;
    1705                 :            :         }
    1706                 :            : 
    1707                 :       4428 :         r = hashmap_put(device->sysattr_values, key, value);
    1708         [ -  + ]:       4428 :         if (r < 0)
    1709                 :          0 :                 return r;
    1710                 :       4428 :         TAKE_PTR(key);
    1711                 :            : 
    1712                 :       4428 :         return 0;
    1713                 :            : }
    1714                 :            : 
    1715                 :       4448 : static int device_get_sysattr_value(sd_device *device, const char *_key, const char **_value) {
    1716                 :       4448 :         const char *key = NULL, *value;
    1717                 :            : 
    1718         [ -  + ]:       4448 :         assert(device);
    1719         [ -  + ]:       4448 :         assert(_key);
    1720                 :            : 
    1721                 :       4448 :         value = hashmap_get2(device->sysattr_values, _key, (void **) &key);
    1722         [ +  + ]:       4448 :         if (!key)
    1723                 :       4444 :                 return -ENOENT;
    1724                 :            : 
    1725         [ +  - ]:          4 :         if (_value)
    1726                 :          4 :                 *_value = value;
    1727                 :          4 :         return 0;
    1728                 :            : }
    1729                 :            : 
    1730                 :            : /* We cache all sysattr lookups. If an attribute does not exist, it is stored
    1731                 :            :  * with a NULL value in the cache, otherwise the returned string is stored */
    1732                 :       4448 : _public_ int sd_device_get_sysattr_value(sd_device *device, const char *sysattr, const char **_value) {
    1733                 :       4448 :         _cleanup_free_ char *value = NULL;
    1734                 :       4448 :         const char *path, *syspath, *cached_value = NULL;
    1735                 :            :         struct stat statbuf;
    1736                 :            :         int r;
    1737                 :            : 
    1738   [ -  +  -  + ]:       4448 :         assert_return(device, -EINVAL);
    1739   [ -  +  -  + ]:       4448 :         assert_return(sysattr, -EINVAL);
    1740                 :            : 
    1741                 :            :         /* look for possibly already cached result */
    1742                 :       4448 :         r = device_get_sysattr_value(device, sysattr, &cached_value);
    1743         [ +  + ]:       4448 :         if (r != -ENOENT) {
    1744         [ -  + ]:          4 :                 if (r < 0)
    1745                 :          0 :                         return r;
    1746                 :            : 
    1747         [ -  + ]:          4 :                 if (!cached_value)
    1748                 :            :                         /* we looked up the sysattr before and it did not exist */
    1749                 :          0 :                         return -ENOENT;
    1750                 :            : 
    1751         [ +  - ]:          4 :                 if (_value)
    1752                 :          4 :                         *_value = cached_value;
    1753                 :            : 
    1754                 :          4 :                 return 0;
    1755                 :            :         }
    1756                 :            : 
    1757                 :       4444 :         r = sd_device_get_syspath(device, &syspath);
    1758         [ -  + ]:       4444 :         if (r < 0)
    1759                 :          0 :                 return r;
    1760                 :            : 
    1761   [ -  +  #  #  :       4444 :         path = prefix_roota(syspath, sysattr);
          -  +  -  +  -  
          +  +  -  -  +  
                   +  - ]
    1762                 :       4444 :         r = lstat(path, &statbuf);
    1763         [ +  + ]:       4444 :         if (r < 0) {
    1764                 :            :                 /* remember that we could not access the sysattr */
    1765                 :       4392 :                 r = device_add_sysattr_value(device, sysattr, NULL);
    1766         [ -  + ]:       4392 :                 if (r < 0)
    1767                 :          0 :                         return r;
    1768                 :            : 
    1769                 :       4392 :                 return -ENOENT;
    1770         [ -  + ]:         52 :         } else if (S_ISLNK(statbuf.st_mode)) {
    1771                 :            :                 /* Some core links return only the last element of the target path,
    1772                 :            :                  * these are just values, the paths should not be exposed. */
    1773         [ #  # ]:          0 :                 if (STR_IN_SET(sysattr, "driver", "subsystem", "module")) {
    1774                 :          0 :                         r = readlink_value(path, &value);
    1775         [ #  # ]:          0 :                         if (r < 0)
    1776                 :          0 :                                 return r;
    1777                 :            :                 } else
    1778                 :          0 :                         return -EINVAL;
    1779         [ -  + ]:         52 :         } else if (S_ISDIR(statbuf.st_mode)) {
    1780                 :            :                 /* skip directories */
    1781                 :          0 :                 return -EINVAL;
    1782         [ -  + ]:         52 :         } else if (!(statbuf.st_mode & S_IRUSR)) {
    1783                 :            :                 /* skip non-readable files */
    1784                 :          0 :                 return -EPERM;
    1785                 :            :         } else {
    1786                 :            :                 size_t size;
    1787                 :            : 
    1788                 :            :                 /* read attribute value */
    1789                 :         52 :                 r = read_full_file(path, &value, &size);
    1790         [ +  + ]:         52 :                 if (r < 0)
    1791                 :         16 :                         return r;
    1792                 :            : 
    1793                 :            :                 /* drop trailing newlines */
    1794   [ +  -  +  + ]:         72 :                 while (size > 0 && value[--size] == '\n')
    1795                 :         36 :                         value[size] = '\0';
    1796                 :            :         }
    1797                 :            : 
    1798                 :         36 :         r = device_add_sysattr_value(device, sysattr, value);
    1799         [ -  + ]:         36 :         if (r < 0)
    1800                 :          0 :                 return r;
    1801                 :            : 
    1802                 :         36 :         *_value = TAKE_PTR(value);
    1803                 :            : 
    1804                 :         36 :         return 0;
    1805                 :            : }
    1806                 :            : 
    1807                 :          0 : static void device_remove_sysattr_value(sd_device *device, const char *_key) {
    1808                 :          0 :         _cleanup_free_ char *key = NULL;
    1809                 :            : 
    1810         [ #  # ]:          0 :         assert(device);
    1811         [ #  # ]:          0 :         assert(_key);
    1812                 :            : 
    1813                 :          0 :         free(hashmap_remove2(device->sysattr_values, _key, (void **) &key));
    1814                 :          0 : }
    1815                 :            : 
    1816                 :            : /* set the attribute and save it in the cache. If a NULL value is passed the
    1817                 :            :  * attribute is cleared from the cache */
    1818                 :          0 : _public_ int sd_device_set_sysattr_value(sd_device *device, const char *sysattr, const char *_value) {
    1819                 :          0 :         _cleanup_free_ char *value = NULL;
    1820                 :            :         const char *syspath, *path;
    1821                 :            :         size_t len;
    1822                 :            :         int r;
    1823                 :            : 
    1824   [ #  #  #  # ]:          0 :         assert_return(device, -EINVAL);
    1825   [ #  #  #  # ]:          0 :         assert_return(sysattr, -EINVAL);
    1826                 :            : 
    1827         [ #  # ]:          0 :         if (!_value) {
    1828                 :          0 :                 device_remove_sysattr_value(device, sysattr);
    1829                 :          0 :                 return 0;
    1830                 :            :         }
    1831                 :            : 
    1832                 :          0 :         r = sd_device_get_syspath(device, &syspath);
    1833         [ #  # ]:          0 :         if (r < 0)
    1834                 :          0 :                 return r;
    1835                 :            : 
    1836   [ #  #  #  #  :          0 :         path = prefix_roota(syspath, sysattr);
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
    1837                 :            : 
    1838                 :          0 :         len = strlen(_value);
    1839                 :            : 
    1840                 :            :         /* drop trailing newlines */
    1841   [ #  #  #  # ]:          0 :         while (len > 0 && _value[len - 1] == '\n')
    1842                 :          0 :                 len --;
    1843                 :            : 
    1844                 :            :         /* value length is limited to 4k */
    1845         [ #  # ]:          0 :         if (len > 4096)
    1846                 :          0 :                 return -EINVAL;
    1847                 :            : 
    1848                 :          0 :         value = strndup(_value, len);
    1849         [ #  # ]:          0 :         if (!value)
    1850                 :          0 :                 return -ENOMEM;
    1851                 :            : 
    1852                 :          0 :         r = write_string_file(path, value, WRITE_STRING_FILE_DISABLE_BUFFER | WRITE_STRING_FILE_NOFOLLOW);
    1853         [ #  # ]:          0 :         if (r < 0) {
    1854         [ #  # ]:          0 :                 if (r == -ELOOP)
    1855                 :          0 :                         return -EINVAL;
    1856         [ #  # ]:          0 :                 if (r == -EISDIR)
    1857                 :          0 :                         return r;
    1858                 :            : 
    1859                 :          0 :                 r = free_and_strdup(&value, "");
    1860         [ #  # ]:          0 :                 if (r < 0)
    1861                 :          0 :                         return r;
    1862                 :            : 
    1863                 :          0 :                 r = device_add_sysattr_value(device, sysattr, value);
    1864         [ #  # ]:          0 :                 if (r < 0)
    1865                 :          0 :                         return r;
    1866                 :          0 :                 TAKE_PTR(value);
    1867                 :            : 
    1868                 :          0 :                 return -ENXIO;
    1869                 :            :         }
    1870                 :            : 
    1871                 :          0 :         r = device_add_sysattr_value(device, sysattr, value);
    1872         [ #  # ]:          0 :         if (r < 0)
    1873                 :          0 :                 return r;
    1874                 :          0 :         TAKE_PTR(value);
    1875                 :            : 
    1876                 :          0 :         return 0;
    1877                 :            : }

Generated by: LCOV version 1.14