diff options
author | Thomas Haller <thaller@redhat.com> | 2021-02-18 08:13:35 +0100 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2021-02-24 12:48:19 +0100 |
commit | 4d12a6ac3dd48c606ff45a65bf0e8d2fd5655894 (patch) | |
tree | 55a925e255b8edc76421450113618ddb5a94300e /src/libnm-udev-aux | |
parent | 174bd45344b8c1d6f41c2c5541dedbd7731ea485 (diff) | |
download | NetworkManager-4d12a6ac3dd48c606ff45a65bf0e8d2fd5655894.tar.gz |
build: move "shared/nm-{base,udev-aux}" to "src/libnm-{base,udev-aux}"
Diffstat (limited to 'src/libnm-udev-aux')
-rw-r--r-- | src/libnm-udev-aux/meson.build | 15 | ||||
-rw-r--r-- | src/libnm-udev-aux/nm-udev-utils.c | 265 | ||||
-rw-r--r-- | src/libnm-udev-aux/nm-udev-utils.h | 33 |
3 files changed, 313 insertions, 0 deletions
diff --git a/src/libnm-udev-aux/meson.build b/src/libnm-udev-aux/meson.build new file mode 100644 index 0000000000..4577a83a93 --- /dev/null +++ b/src/libnm-udev-aux/meson.build @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later + +libnm_udev_aux = static_library( + 'nm-udev-aux', + sources: 'nm-udev-utils.c', + dependencies: [ + glib_nm_default_dep, + libudev_dep, + ], +) + +libnm_udev_aux_dep = declare_dependency( + include_directories: shared_inc, + link_with: libnm_udev_aux, +) diff --git a/src/libnm-udev-aux/nm-udev-utils.c b/src/libnm-udev-aux/nm-udev-utils.c new file mode 100644 index 0000000000..0b941dff53 --- /dev/null +++ b/src/libnm-udev-aux/nm-udev-utils.c @@ -0,0 +1,265 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2017 Red Hat, Inc. + */ + +#include "nm-glib-aux/nm-default-glib-i18n-lib.h" + +#include "nm-udev-utils.h" + +#include <libudev.h> + +struct _NMPUdevClient { + char ** subsystems; + GSource * watch_source; + struct udev * udev; + struct udev_monitor *monitor; + NMUdevClientEvent event_handler; + gpointer event_user_data; +}; + +/*****************************************************************************/ + +gboolean +nm_udev_utils_property_as_boolean(const char *uproperty) +{ + /* taken from g_udev_device_get_property_as_boolean() */ + + if (uproperty) { + if (strcmp(uproperty, "1") == 0 || g_ascii_strcasecmp(uproperty, "true") == 0) + return TRUE; + } + return FALSE; +} + +const char * +nm_udev_utils_property_decode(const char *uproperty, char **to_free) +{ + const char *p; + char * unescaped = NULL; + char * n = NULL; + + if (!uproperty) { + *to_free = NULL; + return NULL; + } + + p = uproperty; + while (*p) { + int a, b; + + if (p[0] == '\\' && p[1] == 'x' && (a = g_ascii_xdigit_value(p[2])) >= 0 + && (b = g_ascii_xdigit_value(p[3])) >= 0 && (a || b)) { + if (!n) { + gssize l = p - uproperty; + + unescaped = g_malloc(l + strlen(p) + 1 - 3); + memcpy(unescaped, uproperty, l); + n = &unescaped[l]; + } + *n++ = (a << 4) | b; + p += 4; + } else { + if (n) + *n++ = *p; + p++; + } + } + + if (!n) { + *to_free = NULL; + return uproperty; + } + + *n++ = '\0'; + return (*to_free = unescaped); +} + +char * +nm_udev_utils_property_decode_cp(const char *uproperty) +{ + char *cpy; + + uproperty = nm_udev_utils_property_decode(uproperty, &cpy); + return cpy ?: g_strdup(uproperty); +} + +/*****************************************************************************/ + +static void +_subsystem_split(const char * subsystem_full, + const char **out_subsystem, + const char **out_devtype, + char ** to_free) +{ + char *tmp, *s; + + nm_assert(subsystem_full); + nm_assert(out_subsystem); + nm_assert(out_devtype); + nm_assert(to_free); + + s = strstr(subsystem_full, "/"); + if (s) { + tmp = g_strdup(subsystem_full); + s = &tmp[s - subsystem_full]; + *s = '\0'; + *out_subsystem = tmp; + *out_devtype = &s[1]; + *to_free = tmp; + } else { + *out_subsystem = subsystem_full; + *out_devtype = NULL; + *to_free = NULL; + } +} + +static struct udev_enumerate * +nm_udev_utils_enumerate(struct udev *uclient, const char *const *subsystems) +{ + struct udev_enumerate *enumerate; + guint n; + + enumerate = udev_enumerate_new(uclient); + + if (subsystems) { + for (n = 0; subsystems[n]; n++) { + const char * subsystem; + const char * devtype; + gs_free char *to_free = NULL; + + _subsystem_split(subsystems[n], &subsystem, &devtype, &to_free); + + udev_enumerate_add_match_subsystem(enumerate, subsystem); + + if (devtype != NULL) + udev_enumerate_add_match_property(enumerate, "DEVTYPE", devtype); + } + } + + return enumerate; +} + +struct udev * +nm_udev_client_get_udev(NMUdevClient *self) +{ + g_return_val_if_fail(self, NULL); + + return self->udev; +} + +struct udev_enumerate * +nm_udev_client_enumerate_new(NMUdevClient *self) +{ + g_return_val_if_fail(self, NULL); + + return nm_udev_utils_enumerate(self->udev, (const char *const *) self->subsystems); +} + +/*****************************************************************************/ + +static gboolean +monitor_event(int fd, GIOCondition condition, gpointer user_data) +{ + NMUdevClient * self = user_data; + struct udev_device *udevice; + + if (!self->monitor) + goto out; + + udevice = udev_monitor_receive_device(self->monitor); + if (udevice == NULL) + goto out; + + self->event_handler(self, udevice, self->event_user_data); + udev_device_unref(udevice); + +out: + return TRUE; +} + +/** + * nm_udev_client_new: + * @subsystems: the subsystems + * @event_handler: callback for events + * @event_user_data: user-data for @event_handler + * + * Basically, it is g_udev_client_new(), and most notably + * g_udev_client_constructed(). + * + * Returns: a new NMUdevClient instance. + */ +NMUdevClient * +nm_udev_client_new(const char *const *subsystems, + NMUdevClientEvent event_handler, + gpointer event_user_data) +{ + NMUdevClient *self; + guint n; + + self = g_slice_new0(NMUdevClient); + + self->event_handler = event_handler; + self->event_user_data = event_user_data; + self->subsystems = subsystems && subsystems[0] ? g_strdupv((char **) subsystems) : NULL; + + self->udev = udev_new(); + if (!self->udev) + goto fail; + + /* connect to event source */ + if (self->event_handler) { + self->monitor = udev_monitor_new_from_netlink(self->udev, "udev"); + if (!self->monitor) + goto fail; + + if (self->subsystems) { + /* install subsystem filters to only wake up for certain events */ + for (n = 0; self->subsystems[n]; n++) { + gs_free char *to_free = NULL; + const char * subsystem; + const char * devtype; + + _subsystem_split(self->subsystems[n], &subsystem, &devtype, &to_free); + udev_monitor_filter_add_match_subsystem_devtype(self->monitor, subsystem, devtype); + } + + /* listen to events, and buffer them */ + udev_monitor_set_receive_buffer_size(self->monitor, 4 * 1024 * 1024); + udev_monitor_enable_receiving(self->monitor); + + self->watch_source = nm_g_unix_fd_source_new(udev_monitor_get_fd(self->monitor), + G_IO_IN, + G_PRIORITY_DEFAULT, + monitor_event, + self, + NULL); + g_source_attach(self->watch_source, g_main_context_get_thread_default()); + } + } + + return self; + +fail: + return nm_udev_client_destroy(self); +} + +NMUdevClient * +nm_udev_client_destroy(NMUdevClient *self) +{ + if (!self) + return NULL; + + nm_clear_g_source_inst(&self->watch_source); + + udev_monitor_unref(self->monitor); + self->monitor = NULL; + udev_unref(self->udev); + self->udev = NULL; + + g_strfreev(self->subsystems); + + g_slice_free(NMUdevClient, self); + + return NULL; +} diff --git a/src/libnm-udev-aux/nm-udev-utils.h b/src/libnm-udev-aux/nm-udev-utils.h new file mode 100644 index 0000000000..191f9a89a4 --- /dev/null +++ b/src/libnm-udev-aux/nm-udev-utils.h @@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2017 Red Hat, Inc. + */ + +#ifndef __NM_UDEV_UTILS_H__ +#define __NM_UDEV_UTILS_H__ + +struct udev; +struct udev_device; +struct udev_enumerate; + +gboolean nm_udev_utils_property_as_boolean(const char *uproperty); +const char *nm_udev_utils_property_decode(const char *uproperty, char **to_free); +char * nm_udev_utils_property_decode_cp(const char *uproperty); + +typedef struct _NMPUdevClient NMUdevClient; + +typedef void (*NMUdevClientEvent)(NMUdevClient * udev_client, + struct udev_device *udevice, + gpointer event_user_data); + +NMUdevClient *nm_udev_client_new(const char *const *subsystems, + NMUdevClientEvent event_handler, + gpointer event_user_data); + +NMUdevClient *nm_udev_client_destroy(NMUdevClient *self); + +struct udev *nm_udev_client_get_udev(NMUdevClient *self); + +struct udev_enumerate *nm_udev_client_enumerate_new(NMUdevClient *self); + +#endif /* __NM_UDEV_UTILS_H__ */ |