/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- 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/>.
-***/
#include <dirent.h>
#include <errno.h>
#include "device-enumerator-private.h"
#include "device-util.h"
#include "libudev-device-internal.h"
+#include "libudev-list-internal.h"
/**
* SECTION:libudev-enumerate
*/
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;
* 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);
}
/**
*
* 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:
*
* 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:
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;
}
* 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;
}
/**
* 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;
}
/**
* 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;
}
/**
* 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;
}
/**
* 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;
}
/**
* 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;
}
/**
* 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;
}
/**
* 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;
}
/**
* 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;
}
/**
if (r < 0)
return r;
+ udev_enumerate->devices_uptodate = false;
return 0;
}