chiark / gitweb /
hashmap: fix iterators to not skip entries
[elogind.git] / src / libelogind / sd-device / sd-device.c
index 9dcb1a892bc46a13758d957083416c8cc24fa1fb..b274f710935841f027c94c45d5dcf04dc9a58373 100644 (file)
@@ -158,15 +158,21 @@ int device_set_syspath(sd_device *device, const char *_syspath, bool verify) {
 
         if (verify) {
                 r = readlink_and_canonicalize(_syspath, &syspath);
-                if (r == -EINVAL) {
+                if (r == -ENOENT)
+                        /* the device does not exist (any more?) */
+                        return -ENODEV;
+                else if (r == -EINVAL) {
                         /* not a symlink */
                         syspath = canonicalize_file_name(_syspath);
                         if (!syspath) {
+                                if (errno == ENOENT)
+                                        /* the device does not exist (any more?) */
+                                        return -ENODEV;
+
                                 log_debug("sd-device: could not canonicalize '%s': %m", _syspath);
                                 return -errno;
                         }
-                /* ignore errors due to the link not being a symlink */
-                } else if (r < 0 && r != -EINVAL) {
+                } else if (r < 0) {
                         log_debug("sd-device: could not get target of '%s': %s", _syspath, strerror(-r));
                         return r;
                 }
@@ -178,15 +184,17 @@ int device_set_syspath(sd_device *device, const char *_syspath, bool verify) {
                         path = strjoina(syspath, "/uevent");
                         r = access(path, F_OK);
                         if (r < 0) {
+                                if (errno == ENOENT)
+                                        /* this is not a valid device */
+                                        return -ENODEV;
+
                                 log_debug("sd-device: %s does not have an uevent file: %m", syspath);
                                 return -errno;
                         }
                 } else {
                         /* everything else just just needs to be a directory */
-                        if (!is_dir(syspath, false)) {
-                                log_debug("sd-device: %s is not a directory", syspath);
-                                return -EINVAL;
-                        }
+                        if (!is_dir(syspath, false))
+                                return -ENODEV;
                 }
         } else {
                 syspath = strdup(_syspath);
@@ -301,7 +309,7 @@ _public_ int sd_device_new_from_subsystem_sysname(sd_device **ret, const char *s
                         return sd_device_new_from_syspath(ret, syspath);
         }
 
-        return -ENOENT;
+        return -ENODEV;
 }
 
 int device_set_devtype(sd_device *device, const char *_devtype) {
@@ -492,6 +500,8 @@ int device_read_uevent_file(sd_device *device) {
         if (device->uevent_loaded || device->sealed)
                 return 0;
 
+        device->uevent_loaded = true;
+
         r = sd_device_get_syspath(device, &syspath);
         if (r < 0)
                 return r;
@@ -502,6 +512,9 @@ int device_read_uevent_file(sd_device *device) {
         if (r == -EACCES)
                 /* empty uevent files may be write-only */
                 return 0;
+        else if (r == -ENOENT)
+                /* some devices may not have uevent files, see set_syspath() */
+                return 0;
         else if (r < 0) {
                 log_debug("sd-device: failed to read uevent file '%s': %s", path, strerror(-r));
                 return r;
@@ -559,8 +572,6 @@ int device_read_uevent_file(sd_device *device) {
                         log_debug("sd-device: could not set 'MAJOR=%s' or 'MINOR=%s' from '%s': %s", major, minor, path, strerror(-r));
         }
 
-        device->uevent_loaded = true;
-
         return 0;
 }
 
@@ -627,7 +638,7 @@ _public_ int sd_device_new_from_device_id(sd_device **ret, const char *id) {
                 if (r < 0)
                         return r;
 
-                /* this si racey, so we might end up with the wrong device */
+                /* this is racey, so we might end up with the wrong device */
                 if (ifr.ifr_ifindex != ifindex)
                         return -ENODEV;
 
@@ -700,7 +711,7 @@ static int device_new_from_child(sd_device **ret, sd_device *child) {
                 return 0;
         }
 
-        return -ENOENT;
+        return -ENODEV;
 }
 
 _public_ int sd_device_get_parent(sd_device *child, sd_device **ret) {
@@ -774,7 +785,7 @@ _public_ int sd_device_get_subsystem(sd_device *device, const char **ret) {
                          path_startswith(device->devpath, "/class/") ||
                          path_startswith(device->devpath, "/bus/"))
                         r = device_set_subsystem(device, "subsystem");
-                if (r < 0)
+                if (r < 0 && r != -ENOENT)
                         return log_debug_errno(r, "sd-device: could not set subsystem for %s: %m", device->devpath);
 
                 device->subsystem_set = true;
@@ -890,8 +901,11 @@ _public_ int sd_device_get_driver(sd_device *device, const char **ret) {
                 if (r >= 0) {
                         r = device_set_driver(device, driver);
                         if (r < 0)
-                                return r;
-                }
+                                return log_debug_errno(r, "sd-device: could not set driver for %s: %m", device->devpath);
+                } else if (r == -ENOENT)
+                        device->driver_set = true;
+                else
+                        return log_debug_errno(r, "sd-device: could not set driver for %s: %m", device->devpath);
         }
 
         *ret = device->driver;
@@ -1177,17 +1191,19 @@ int device_get_id_filename(sd_device *device, const char **ret) {
                         return r;
 
                 if (major(devnum) > 0) {
+                        assert(subsystem);
+
                         /* use dev_t -- b259:131072, c254:0 */
                         r = asprintf(&id, "%c%u:%u",
                                      streq(subsystem, "block") ? 'b' : 'c',
                                      major(devnum), minor(devnum));
                         if (r < 0)
-                                return -errno;
+                                return -ENOMEM;
                 } else if (ifindex > 0) {
                         /* use netdev ifindex -- n3 */
                         r = asprintf(&id, "n%u", ifindex);
                         if (r < 0)
-                                return -errno;
+                                return -ENOMEM;
                 } else {
                         /* use $subsys:$sysname -- pci:0000:00:1f.2
                          * sysname() has '!' translated, get it from devpath
@@ -1198,9 +1214,12 @@ int device_get_id_filename(sd_device *device, const char **ret) {
                         if (!sysname)
                                 return -EINVAL;
 
+                        if (!subsystem)
+                                return -EINVAL;
+
                         r = asprintf(&id, "+%s:%s", subsystem, sysname);
                         if (r < 0)
-                                return -errno;
+                                return -ENOMEM;
                 }
 
                 device->id_filename = id;
@@ -1212,7 +1231,7 @@ int device_get_id_filename(sd_device *device, const char **ret) {
         return 0;
 }
 
-static int device_read_db(sd_device *device) {
+int device_read_db_aux(sd_device *device, bool force) {
         _cleanup_free_ char *db = NULL;
         char *path;
         const char *id, *value;
@@ -1229,9 +1248,11 @@ static int device_read_db(sd_device *device) {
                 INVALID_LINE,
         } state = PRE_KEY;
 
-        if (device->db_loaded || device->sealed)
+        if (device->db_loaded || (!force && device->sealed))
                 return 0;
 
+        device->db_loaded = true;
+
         r = device_get_id_filename(device, &id);
         if (r < 0)
                 return r;
@@ -1249,7 +1270,7 @@ static int device_read_db(sd_device *device) {
         }
 
         /* devices with a database entry are initialized */
-        device->is_initialized = true;;
+        device->is_initialized = true;
 
         for (i = 0; i < db_len; i++) {
                 switch (state) {
@@ -1300,11 +1321,13 @@ static int device_read_db(sd_device *device) {
                 }
         }
 
-        device->db_loaded = true;
-
         return 0;
 }
 
+static int device_read_db(sd_device *device) {
+        return device_read_db_aux(device, false);
+}
+
 _public_ int sd_device_get_is_initialized(sd_device *device, int *initialized) {
         int r;
 
@@ -1348,6 +1371,8 @@ _public_ int sd_device_get_usec_since_initialized(sd_device *device, uint64_t *u
 }
 
 _public_ const char *sd_device_get_tag_first(sd_device *device) {
+        void *v;
+
         assert_return(device, NULL);
 
         (void) device_read_db(device);
@@ -1355,10 +1380,13 @@ _public_ const char *sd_device_get_tag_first(sd_device *device) {
         device->tags_iterator_generation = device->tags_generation;
         device->tags_iterator = ITERATOR_FIRST;
 
-        return set_iterate(device->tags, &device->tags_iterator);
+        set_iterate(device->tags, &device->tags_iterator, &v);
+        return v;
 }
 
 _public_ const char *sd_device_get_tag_next(sd_device *device) {
+        void *v;
+
         assert_return(device, NULL);
 
         (void) device_read_db(device);
@@ -1366,10 +1394,13 @@ _public_ const char *sd_device_get_tag_next(sd_device *device) {
         if (device->tags_iterator_generation != device->tags_generation)
                 return NULL;
 
-        return set_iterate(device->tags, &device->tags_iterator);
+        set_iterate(device->tags, &device->tags_iterator, &v);
+        return v;
 }
 
 _public_ const char *sd_device_get_devlink_first(sd_device *device) {
+        void *v;
+
         assert_return(device, NULL);
 
         (void) device_read_db(device);
@@ -1377,10 +1408,13 @@ _public_ const char *sd_device_get_devlink_first(sd_device *device) {
         device->devlinks_iterator_generation = device->devlinks_generation;
         device->devlinks_iterator = ITERATOR_FIRST;
 
-        return set_iterate(device->devlinks, &device->devlinks_iterator);
+        set_iterate(device->devlinks, &device->devlinks_iterator, &v);
+        return v;
 }
 
 _public_ const char *sd_device_get_devlink_next(sd_device *device) {
+        void *v;
+
         assert_return(device, NULL);
 
         (void) device_read_db(device);
@@ -1388,7 +1422,8 @@ _public_ const char *sd_device_get_devlink_next(sd_device *device) {
         if (device->devlinks_iterator_generation != device->devlinks_generation)
                 return NULL;
 
-        return set_iterate(device->devlinks, &device->devlinks_iterator);
+        set_iterate(device->devlinks, &device->devlinks_iterator, &v);
+        return v;
 }
 
 static int device_properties_prepare(sd_device *device) {
@@ -1459,7 +1494,7 @@ _public_ const char *sd_device_get_property_first(sd_device *device, const char
         device->properties_iterator_generation = device->properties_generation;
         device->properties_iterator = ITERATOR_FIRST;
 
-        value = ordered_hashmap_iterate(device->properties, &device->properties_iterator, (const void**)&key);
+        ordered_hashmap_iterate(device->properties, &device->properties_iterator, (void**)&value, (const void**)&key);
 
         if (_value)
                 *_value = value;
@@ -1481,7 +1516,7 @@ _public_ const char *sd_device_get_property_next(sd_device *device, const char *
         if (device->properties_iterator_generation != device->properties_generation)
                 return NULL;
 
-        value = ordered_hashmap_iterate(device->properties, &device->properties_iterator, (const void**)&key);
+        ordered_hashmap_iterate(device->properties, &device->properties_iterator, (void**)&value, (const void**)&key);
 
         if (_value)
                 *_value = value;
@@ -1539,6 +1574,7 @@ static int device_sysattrs_read_all(sd_device *device) {
 }
 
 _public_ const char *sd_device_get_sysattr_first(sd_device *device) {
+        void *v;
         int r;
 
         assert_return(device, NULL);
@@ -1553,16 +1589,20 @@ _public_ const char *sd_device_get_sysattr_first(sd_device *device) {
 
         device->sysattrs_iterator = ITERATOR_FIRST;
 
-        return set_iterate(device->sysattrs, &device->sysattrs_iterator);
+        set_iterate(device->sysattrs, &device->sysattrs_iterator, &v);
+        return v;
 }
 
 _public_ const char *sd_device_get_sysattr_next(sd_device *device) {
+        void *v;
+
         assert_return(device, NULL);
 
         if (!device->sysattrs_read)
                 return NULL;
 
-        return set_iterate(device->sysattrs, &device->sysattrs_iterator);
+        set_iterate(device->sysattrs, &device->sysattrs_iterator, &v);
+        return v;
 }
 
 _public_ int sd_device_has_tag(sd_device *device, const char *tag) {