]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/libudev/libudev-enumerate.c
Merge pull request #12753 from jrouleau/fix/hibernate-resume-timeout
[thirdparty/systemd.git] / src / libudev / libudev-enumerate.c
index ea80c750c91a9e9ae67d1207b8104b6a45af9884..a8b3f53572413e967e230076c0ce22233adb27d8 100644 (file)
@@ -1,22 +1,4 @@
-/***
-  This file is part of systemd.
-
-  Copyright 2008-2012 Kay Sievers <kay@vrfy.org>
-  Copyright 2015 Tom Gundersen <teg@jklm.no>
-
-  systemd is free software; you can redistribute it and/or modify it
-  under the terms of the GNU Lesser General Public License as published by
-  the Free Software Foundation; either version 2.1 of the License, or
-  (at your option) any later version.
-
-  systemd is distributed in the hope that it will be useful, but
-  WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-  Lesser General Public License for more details.
-
-  You should have received a copy of the GNU Lesser General Public License
-  along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
 
 #include <dirent.h>
 #include <errno.h>
@@ -35,6 +17,7 @@
 #include "device-enumerator-private.h"
 #include "device-util.h"
 #include "libudev-device-internal.h"
+#include "libudev-list-internal.h"
 
 /**
  * SECTION:libudev-enumerate
@@ -51,8 +34,8 @@
  */
 struct udev_enumerate {
         struct udev *udev;
-        int refcount;
-        struct udev_list devices_list;
+        unsigned n_ref;
+        struct udev_list *devices_list;
         bool devices_uptodate:1;
 
         sd_device_enumerator *enumerator;
@@ -67,39 +50,43 @@ struct udev_enumerate {
  * Returns: an enumeration context.
  **/
 _public_ struct udev_enumerate *udev_enumerate_new(struct udev *udev) {
-        _cleanup_free_ struct udev_enumerate *udev_enumerate = NULL;
-        struct udev_enumerate *ret;
+        _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL;
+        _cleanup_(udev_list_freep) struct udev_list *list = NULL;
+        struct udev_enumerate *udev_enumerate;
         int r;
 
-        assert_return_errno(udev, NULL, EINVAL);
+        r = sd_device_enumerator_new(&e);
+        if (r < 0)
+                return_with_errno(NULL, r);
 
-        udev_enumerate = new0(struct udev_enumerate, 1);
-        if (!udev_enumerate) {
-                errno = ENOMEM;
-                return NULL;
-        }
+        r = sd_device_enumerator_allow_uninitialized(e);
+        if (r < 0)
+                return_with_errno(NULL, r);
 
-        r = sd_device_enumerator_new(&udev_enumerate->enumerator);
-        if (r < 0) {
-                errno = -r;
-                return NULL;
-        }
+        list = udev_list_new(false);
+        if (!list)
+                return_with_errno(NULL, ENOMEM);
 
-        r = sd_device_enumerator_allow_uninitialized(udev_enumerate->enumerator);
-        if (r < 0) {
-                errno = -r;
-                return NULL;
-        }
+        udev_enumerate = new(struct udev_enumerate, 1);
+        if (!udev_enumerate)
+                return_with_errno(NULL, ENOMEM);
 
-        udev_enumerate->refcount = 1;
-        udev_enumerate->udev = udev;
+        *udev_enumerate = (struct udev_enumerate) {
+                .udev = udev,
+                .n_ref = 1,
+                .enumerator = TAKE_PTR(e),
+                .devices_list = TAKE_PTR(list),
+        };
 
-        udev_list_init(udev, &udev_enumerate->devices_list, false);
+        return udev_enumerate;
+}
 
-        ret = udev_enumerate;
-        udev_enumerate = NULL;
+static struct udev_enumerate *udev_enumerate_free(struct udev_enumerate *udev_enumerate) {
+        assert(udev_enumerate);
 
-        return ret;
+        udev_list_free(udev_enumerate->devices_list);
+        sd_device_enumerator_unref(udev_enumerate->enumerator);
+        return mfree(udev_enumerate);
 }
 
 /**
@@ -110,12 +97,6 @@ _public_ struct udev_enumerate *udev_enumerate_new(struct udev *udev) {
  *
  * Returns: the passed enumeration context
  **/
-_public_ struct udev_enumerate *udev_enumerate_ref(struct udev_enumerate *udev_enumerate) {
-        if (udev_enumerate)
-                udev_enumerate->refcount++;
-
-        return udev_enumerate;
-}
 
 /**
  * udev_enumerate_unref:
@@ -126,15 +107,7 @@ _public_ struct udev_enumerate *udev_enumerate_ref(struct udev_enumerate *udev_e
  *
  * Returns: #NULL
  **/
-_public_ struct udev_enumerate *udev_enumerate_unref(struct udev_enumerate *udev_enumerate) {
-        if (udev_enumerate && (-- udev_enumerate->refcount) == 0) {
-                udev_list_cleanup(&udev_enumerate->devices_list);
-                sd_device_enumerator_unref(udev_enumerate->enumerator);
-                free(udev_enumerate);
-        }
-
-        return NULL;
-}
+DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(struct udev_enumerate, udev_enumerate, udev_enumerate_free);
 
 /**
  * udev_enumerate_get_udev:
@@ -166,27 +139,26 @@ _public_ struct udev_list_entry *udev_enumerate_get_list_entry(struct udev_enume
         if (!udev_enumerate->devices_uptodate) {
                 sd_device *device;
 
-                udev_list_cleanup(&udev_enumerate->devices_list);
+                udev_list_cleanup(udev_enumerate->devices_list);
 
                 FOREACH_DEVICE_AND_SUBSYSTEM(udev_enumerate->enumerator, device) {
                         const char *syspath;
                         int r;
 
                         r = sd_device_get_syspath(device, &syspath);
-                        if (r < 0) {
-                                errno = -r;
-                                return NULL;
-                        }
+                        if (r < 0)
+                                return_with_errno(NULL, r);
 
-                        udev_list_entry_add(&udev_enumerate->devices_list, syspath, NULL);
+                        if (!udev_list_entry_add(udev_enumerate->devices_list, syspath, NULL))
+                                return_with_errno(NULL, ENOMEM);
                 }
 
                 udev_enumerate->devices_uptodate = true;
         }
 
-        e = udev_list_get_entry(&udev_enumerate->devices_list);
+        e = udev_list_get_entry(udev_enumerate->devices_list);
         if (!e)
-                errno = ENODATA;
+                return_with_errno(NULL, ENODATA);
 
         return e;
 }
@@ -201,12 +173,19 @@ _public_ struct udev_list_entry *udev_enumerate_get_list_entry(struct udev_enume
  * Returns: 0 on success, otherwise a negative error value.
  */
 _public_ int udev_enumerate_add_match_subsystem(struct udev_enumerate *udev_enumerate, const char *subsystem) {
+        int r;
+
         assert_return(udev_enumerate, -EINVAL);
 
         if (!subsystem)
                 return 0;
 
-        return sd_device_enumerator_add_match_subsystem(udev_enumerate->enumerator, subsystem, true);
+        r = sd_device_enumerator_add_match_subsystem(udev_enumerate->enumerator, subsystem, true);
+        if (r < 0)
+                return r;
+
+        udev_enumerate->devices_uptodate = false;
+        return 0;
 }
 
 /**
@@ -219,12 +198,19 @@ _public_ int udev_enumerate_add_match_subsystem(struct udev_enumerate *udev_enum
  * Returns: 0 on success, otherwise a negative error value.
  */
 _public_ int udev_enumerate_add_nomatch_subsystem(struct udev_enumerate *udev_enumerate, const char *subsystem) {
+        int r;
+
         assert_return(udev_enumerate, -EINVAL);
 
         if (!subsystem)
                 return 0;
 
-        return sd_device_enumerator_add_match_subsystem(udev_enumerate->enumerator, subsystem, false);
+        r = sd_device_enumerator_add_match_subsystem(udev_enumerate->enumerator, subsystem, false);
+        if (r < 0)
+                return r;
+
+        udev_enumerate->devices_uptodate = false;
+        return 0;
 }
 
 /**
@@ -238,12 +224,19 @@ _public_ int udev_enumerate_add_nomatch_subsystem(struct udev_enumerate *udev_en
  * Returns: 0 on success, otherwise a negative error value.
  */
 _public_ int udev_enumerate_add_match_sysattr(struct udev_enumerate *udev_enumerate, const char *sysattr, const char *value) {
+        int r;
+
         assert_return(udev_enumerate, -EINVAL);
 
         if (!sysattr)
                 return 0;
 
-        return sd_device_enumerator_add_match_sysattr(udev_enumerate->enumerator, sysattr, value, true);
+        r = sd_device_enumerator_add_match_sysattr(udev_enumerate->enumerator, sysattr, value, true);
+        if (r < 0)
+                return r;
+
+        udev_enumerate->devices_uptodate = false;
+        return 0;
 }
 
 /**
@@ -257,12 +250,19 @@ _public_ int udev_enumerate_add_match_sysattr(struct udev_enumerate *udev_enumer
  * Returns: 0 on success, otherwise a negative error value.
  */
 _public_ int udev_enumerate_add_nomatch_sysattr(struct udev_enumerate *udev_enumerate, const char *sysattr, const char *value) {
+        int r;
+
         assert_return(udev_enumerate, -EINVAL);
 
         if (!sysattr)
                 return 0;
 
-        return sd_device_enumerator_add_match_sysattr(udev_enumerate->enumerator, sysattr, value, false);
+        r = sd_device_enumerator_add_match_sysattr(udev_enumerate->enumerator, sysattr, value, false);
+        if (r < 0)
+                return r;
+
+        udev_enumerate->devices_uptodate = false;
+        return 0;
 }
 
 /**
@@ -276,12 +276,19 @@ _public_ int udev_enumerate_add_nomatch_sysattr(struct udev_enumerate *udev_enum
  * Returns: 0 on success, otherwise a negative error value.
  */
 _public_ int udev_enumerate_add_match_property(struct udev_enumerate *udev_enumerate, const char *property, const char *value) {
+        int r;
+
         assert_return(udev_enumerate, -EINVAL);
 
         if (!property)
                 return 0;
 
-        return sd_device_enumerator_add_match_property(udev_enumerate->enumerator, property, value);
+        r = sd_device_enumerator_add_match_property(udev_enumerate->enumerator, property, value);
+        if (r < 0)
+                return r;
+
+        udev_enumerate->devices_uptodate = false;
+        return 0;
 }
 
 /**
@@ -294,12 +301,19 @@ _public_ int udev_enumerate_add_match_property(struct udev_enumerate *udev_enume
  * Returns: 0 on success, otherwise a negative error value.
  */
 _public_ int udev_enumerate_add_match_tag(struct udev_enumerate *udev_enumerate, const char *tag) {
+        int r;
+
         assert_return(udev_enumerate, -EINVAL);
 
         if (!tag)
                 return 0;
 
-        return sd_device_enumerator_add_match_tag(udev_enumerate->enumerator, tag);
+        r = sd_device_enumerator_add_match_tag(udev_enumerate->enumerator, tag);
+        if (r < 0)
+                return r;
+
+        udev_enumerate->devices_uptodate = false;
+        return 0;
 }
 
 /**
@@ -310,18 +324,22 @@ _public_ int udev_enumerate_add_match_tag(struct udev_enumerate *udev_enumerate,
  * Return the devices on the subtree of one given device. The parent
  * itself is included in the list.
  *
- * A reference for the device is held until the udev_enumerate context
- * is cleaned up.
- *
  * Returns: 0 on success, otherwise a negative error value.
  */
 _public_ int udev_enumerate_add_match_parent(struct udev_enumerate *udev_enumerate, struct udev_device *parent) {
+        int r;
+
         assert_return(udev_enumerate, -EINVAL);
 
         if (!parent)
                 return 0;
 
-        return sd_device_enumerator_add_match_parent(udev_enumerate->enumerator, parent->device);
+        r = sd_device_enumerator_add_match_parent(udev_enumerate->enumerator, udev_device_get_sd_device(parent));
+        if (r < 0)
+                return r;
+
+        udev_enumerate->devices_uptodate = false;
+        return 0;
 }
 
 /**
@@ -343,9 +361,16 @@ _public_ int udev_enumerate_add_match_parent(struct udev_enumerate *udev_enumera
  * Returns: 0 on success, otherwise a negative error value.
  */
 _public_ int udev_enumerate_add_match_is_initialized(struct udev_enumerate *udev_enumerate) {
+        int r;
+
         assert_return(udev_enumerate, -EINVAL);
 
-        return device_enumerator_add_match_is_initialized(udev_enumerate->enumerator);
+        r = device_enumerator_add_match_is_initialized(udev_enumerate->enumerator);
+        if (r < 0)
+                return r;
+
+        udev_enumerate->devices_uptodate = false;
+        return 0;
 }
 
 /**
@@ -358,12 +383,19 @@ _public_ int udev_enumerate_add_match_is_initialized(struct udev_enumerate *udev
  * Returns: 0 on success, otherwise a negative error value.
  */
 _public_ int udev_enumerate_add_match_sysname(struct udev_enumerate *udev_enumerate, const char *sysname) {
+        int r;
+
         assert_return(udev_enumerate, -EINVAL);
 
         if (!sysname)
                 return 0;
 
-        return sd_device_enumerator_add_match_sysname(udev_enumerate->enumerator, sysname);
+        r = sd_device_enumerator_add_match_sysname(udev_enumerate->enumerator, sysname);
+        if (r < 0)
+                return r;
+
+        udev_enumerate->devices_uptodate = false;
+        return 0;
 }
 
 /**
@@ -392,6 +424,7 @@ _public_ int udev_enumerate_add_syspath(struct udev_enumerate *udev_enumerate, c
         if (r < 0)
                 return r;
 
+        udev_enumerate->devices_uptodate = false;
         return 0;
 }