libudev-monitor: introduce udev_monitor_send_sd_device()

And use it in udev_monitor_send_device().
This commit is contained in:
Yu Watanabe 2018-08-24 17:05:22 +09:00
parent 23c457a7fb
commit a9808d8445
1 changed files with 40 additions and 22 deletions

View File

@ -659,11 +659,11 @@ _public_ struct udev_device *udev_monitor_receive_device(struct udev_monitor *ud
return udev_device_new(udev_monitor->udev, device);
}
int udev_monitor_send_device(struct udev_monitor *udev_monitor,
struct udev_monitor *destination, struct udev_device *udev_device)
{
const char *buf, *val;
ssize_t blen, count;
static int udev_monitor_send_sd_device(
struct udev_monitor *udev_monitor,
struct udev_monitor *destination,
sd_device *device) {
struct udev_monitor_netlink_header nlh = {
.prefix = "libudev",
.magic = htobe32(UDEV_MONITOR_MAGIC),
@ -676,27 +676,37 @@ int udev_monitor_send_device(struct udev_monitor *udev_monitor,
.msg_iov = iov,
.msg_iovlen = 2,
};
struct udev_list_entry *list_entry;
uint64_t tag_bloom_bits;
const char *buf, *val;
ssize_t count;
size_t blen;
int r;
blen = udev_device_get_properties_monitor_buf(udev_device, &buf);
assert(udev_monitor);
assert(device);
r = device_get_properties_nulstr(device, (const uint8_t **) &buf, &blen);
if (r < 0)
return log_debug_errno(r, "Failed to get device properties: %m");
if (blen < 32) {
log_debug("device buffer is too small to contain a valid device");
log_debug("Device buffer is too small to contain a valid device");
return -EINVAL;
}
/* fill in versioned header */
val = udev_device_get_subsystem(udev_device);
r = sd_device_get_subsystem(device, &val);
if (r < 0)
return log_debug_errno(r, "Failed to get device subsystem: %m");
nlh.filter_subsystem_hash = htobe32(util_string_hash32(val));
val = udev_device_get_devtype(udev_device);
if (val != NULL)
if (sd_device_get_devtype(device, &val) >= 0 && val)
nlh.filter_devtype_hash = htobe32(util_string_hash32(val));
/* add tag bloom filter */
tag_bloom_bits = 0;
udev_list_entry_foreach(list_entry, udev_device_get_tags_list_entry(udev_device))
tag_bloom_bits |= util_string_bloom64(udev_list_entry_get_name(list_entry));
FOREACH_DEVICE_TAG(device, val)
tag_bloom_bits |= util_string_bloom64(val);
if (tag_bloom_bits > 0) {
nlh.filter_tag_bloom_hi = htobe32(tag_bloom_bits >> 32);
nlh.filter_tag_bloom_lo = htobe32(tag_bloom_bits & 0xffffffff);
@ -705,8 +715,10 @@ int udev_monitor_send_device(struct udev_monitor *udev_monitor,
/* add properties list */
nlh.properties_off = iov[0].iov_len;
nlh.properties_len = blen;
iov[1].iov_base = (char *)buf;
iov[1].iov_len = blen;
iov[1] = (struct iovec) {
.iov_base = (char*) buf,
.iov_len = blen,
};
/*
* Use custom address for target, or the default one.
@ -714,24 +726,30 @@ int udev_monitor_send_device(struct udev_monitor *udev_monitor,
* If we send to a multicast group, we will get
* ECONNREFUSED, which is expected.
*/
if (destination)
smsg.msg_name = &destination->snl;
else
smsg.msg_name = &udev_monitor->snl_destination;
smsg.msg_name = destination ? &destination->snl : &udev_monitor->snl_destination;
smsg.msg_namelen = sizeof(struct sockaddr_nl);
count = sendmsg(udev_monitor->sock, &smsg, 0);
if (count < 0) {
if (!destination && errno == ECONNREFUSED) {
log_debug("passed device to netlink monitor %p", udev_monitor);
log_debug("Passed device to netlink monitor %p", udev_monitor);
return 0;
} else
return -errno;
return log_debug_errno(errno, "Failed to send device to netlink monitor %p", udev_monitor);
}
log_debug("passed %zi byte device to netlink monitor %p", count, udev_monitor);
log_debug("Passed %zi byte device to netlink monitor %p", count, udev_monitor);
return count;
}
int udev_monitor_send_device(
struct udev_monitor *udev_monitor,
struct udev_monitor *destination,
struct udev_device *udev_device) {
assert(udev_device);
return udev_monitor_send_sd_device(udev_monitor, destination, udev_device->device);
}
/**
* udev_monitor_filter_add_match_subsystem_devtype:
* @udev_monitor: the monitor