diff options
Diffstat (limited to 'src')
139 files changed, 1696 insertions, 3827 deletions
diff --git a/src/console/consoled-manager.c b/src/console/consoled-manager.c index b288239cae..e560dcf524 100644 --- a/src/console/consoled-manager.c +++ b/src/console/consoled-manager.c @@ -21,16 +21,17 @@ #include <errno.h> #include <stdlib.h> -#include "consoled.h" -#include "grdev.h" -#include "idev.h" -#include "log.h" #include "sd-bus.h" #include "sd-event.h" #include "sd-login.h" +#include "log.h" +#include "signal-util.h" +#include "util.h" +#include "consoled.h" +#include "idev.h" +#include "grdev.h" #include "sysview.h" #include "unifont.h" -#include "util.h" int manager_new(Manager **out) { _cleanup_(manager_freep) Manager *m = NULL; diff --git a/src/console/consoled.c b/src/console/consoled.c index 26dd068f5c..9f69e8983f 100644 --- a/src/console/consoled.c +++ b/src/console/consoled.c @@ -21,9 +21,10 @@ #include <errno.h> #include <stdlib.h> -#include "consoled.h" -#include "log.h" #include "sd-daemon.h" +#include "log.h" +#include "signal-util.h" +#include "consoled.h" int main(int argc, char *argv[]) { _cleanup_(manager_freep) Manager *m = NULL; diff --git a/src/core/automount.c b/src/core/automount.c index 13f80c2abd..d847dc1629 100644 --- a/src/core/automount.c +++ b/src/core/automount.c @@ -747,7 +747,7 @@ static int automount_start(Unit *u) { assert(a); assert(a->state == AUTOMOUNT_DEAD || a->state == AUTOMOUNT_FAILED); - if (path_is_mount_point(a->where, false) > 0) { + if (path_is_mount_point(a->where, 0) > 0) { log_unit_error(u, "Path %s is already a mount point, refusing start.", a->where); return -EEXIST; } diff --git a/src/core/busname.c b/src/core/busname.c index 17b85134e8..11f3b98009 100644 --- a/src/core/busname.c +++ b/src/core/busname.c @@ -22,15 +22,16 @@ #include <sys/mman.h> #include "special.h" +#include "formats-util.h" +#include "signal-util.h" #include "bus-kernel.h" #include "bus-internal.h" #include "bus-util.h" -#include "service.h" #include "kdbus.h" #include "bus-policy.h" +#include "service.h" #include "dbus-busname.h" #include "busname.h" -#include "formats-util.h" static const UnitActiveState state_translation_table[_BUSNAME_STATE_MAX] = { [BUSNAME_DEAD] = UNIT_INACTIVE, diff --git a/src/core/dbus-kill.c b/src/core/dbus-kill.c index fb29e147cb..3b8116281c 100644 --- a/src/core/dbus-kill.c +++ b/src/core/dbus-kill.c @@ -19,9 +19,11 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ +#include "signal-util.h" +#include "bus-util.h" + #include "kill.h" #include "dbus-kill.h" -#include "bus-util.h" static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_kill_mode, kill_mode, KillMode); diff --git a/src/core/execute.c b/src/core/execute.c index e88a2dc0ed..4120493bda 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -49,14 +49,13 @@ #include <sys/apparmor.h> #endif +#include "sd-messages.h" #include "rm-rf.h" -#include "execute.h" #include "strv.h" #include "macro.h" #include "capability.h" #include "util.h" #include "log.h" -#include "sd-messages.h" #include "ioprio.h" #include "securebits.h" #include "namespace.h" @@ -79,6 +78,7 @@ #include "formats-util.h" #include "process-util.h" #include "terminal-util.h" +#include "signal-util.h" #ifdef HAVE_APPARMOR #include "apparmor-util.h" @@ -88,6 +88,8 @@ #include "seccomp-util.h" #endif +#include "execute.h" + #define IDLE_TIMEOUT_USEC (5*USEC_PER_SEC) #define IDLE_TIMEOUT2_USEC (1*USEC_PER_SEC) diff --git a/src/core/ima-setup.c b/src/core/ima-setup.c index 7721b3ecaf..4d8b638115 100644 --- a/src/core/ima-setup.c +++ b/src/core/ima-setup.c @@ -24,9 +24,10 @@ #include <unistd.h> #include <errno.h> #include <fcntl.h> +#include <sys/stat.h> +#include <sys/mman.h> #include "ima-setup.h" -#include "copy.h" #include "util.h" #include "log.h" @@ -39,6 +40,8 @@ int ima_setup(void) { #ifdef HAVE_IMA _cleanup_close_ int policyfd = -1, imafd = -1; + struct stat st; + char *policy; if (access(IMA_SECFS_DIR, F_OK) < 0) { log_debug("IMA support is disabled in the kernel, ignoring."); @@ -63,12 +66,20 @@ int ima_setup(void) { return 0; } - r = copy_bytes(policyfd, imafd, (off_t) -1, false); + if (fstat(policyfd, &st) < 0) + return log_error_errno(errno, "Failed to fstat "IMA_POLICY_PATH": %m"); + + policy = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, policyfd, 0); + if (policy == MAP_FAILED) + return log_error_errno(errno, "Failed to mmap "IMA_POLICY_PATH": %m"); + + r = loop_write(imafd, policy, (size_t) st.st_size, false); if (r < 0) log_error_errno(r, "Failed to load the IMA custom policy file "IMA_POLICY_PATH": %m"); else log_info("Successfully loaded the IMA custom policy "IMA_POLICY_PATH"."); + munmap(policy, st.st_size); #endif /* HAVE_IMA */ return r; } diff --git a/src/core/kill.c b/src/core/kill.c index 60a510eae6..2de71c6bf9 100644 --- a/src/core/kill.c +++ b/src/core/kill.c @@ -19,9 +19,9 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ - -#include "kill.h" #include "util.h" +#include "signal-util.h" +#include "kill.h" void kill_context_init(KillContext *c) { assert(c); diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c index 9415e92c90..df5fe6fb32 100644 --- a/src/core/load-fragment.c +++ b/src/core/load-fragment.c @@ -52,6 +52,7 @@ #include "errno-list.h" #include "af-list.h" #include "cap-list.h" +#include "signal-util.h" #include "bus-internal.h" #ifdef HAVE_SECCOMP @@ -609,7 +610,7 @@ int config_parse_exec( else skip = strneq(word, "\\;", MAX(l, 1U)); - r = cunescape_length(word + skip, l - skip, 0, &c); + r = cunescape_length(word + skip, l - skip, UNESCAPE_RELAX, &c); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, "Failed to unescape command line, ignoring: %s", rvalue); r = 0; diff --git a/src/core/machine-id-setup.c b/src/core/machine-id-setup.c index e083c5b347..b3d22840cf 100644 --- a/src/core/machine-id-setup.c +++ b/src/core/machine-id-setup.c @@ -297,7 +297,7 @@ int machine_id_commit(const char *root) { etc_machine_id = path_kill_slashes(x); } - r = path_is_mount_point(etc_machine_id, false); + r = path_is_mount_point(etc_machine_id, 0); if (r < 0) return log_error_errno(r, "Failed to determine whether %s is a mount point: %m", etc_machine_id); if (r == 0) { diff --git a/src/core/main.c b/src/core/main.c index 212ab901b1..674e47e788 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -60,6 +60,10 @@ #include "bus-error.h" #include "bus-util.h" #include "selinux-util.h" +#include "formats-util.h" +#include "process-util.h" +#include "terminal-util.h" +#include "signal-util.h" #include "manager.h" #include "dbus-manager.h" #include "load-fragment.h" @@ -72,9 +76,6 @@ #include "ima-setup.h" #include "smack-setup.h" #include "kmod-setup.h" -#include "formats-util.h" -#include "process-util.h" -#include "terminal-util.h" static enum { ACTION_RUN, diff --git a/src/core/manager.c b/src/core/manager.c index b931b0d71d..a1c54339ea 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -40,8 +40,6 @@ #include "sd-daemon.h" #include "sd-messages.h" -#include "manager.h" -#include "transaction.h" #include "hashmap.h" #include "macro.h" #include "strv.h" @@ -65,14 +63,17 @@ #include "bus-common-errors.h" #include "bus-error.h" #include "bus-util.h" -#include "dbus.h" -#include "dbus-unit.h" -#include "dbus-job.h" -#include "dbus-manager.h" #include "bus-kernel.h" #include "time-util.h" #include "process-util.h" #include "terminal-util.h" +#include "signal-util.h" +#include "dbus.h" +#include "dbus-unit.h" +#include "dbus-job.h" +#include "dbus-manager.h" +#include "manager.h" +#include "transaction.h" /* Initial delay and the interval for printing status messages about running jobs */ #define JOBS_IN_PROGRESS_WAIT_USEC (5*USEC_PER_SEC) @@ -740,9 +741,6 @@ static int manager_setup_kdbus(Manager *m) { if (!is_kdbus_available()) return -ESOCKTNOSUPPORT; - if (m->running_as == MANAGER_SYSTEM && detect_container(NULL) <= 0) - bus_kernel_fix_attach_mask(); - m->kdbus_fd = bus_kernel_create_bus( m->running_as == MANAGER_SYSTEM ? "system" : "user", m->running_as == MANAGER_SYSTEM, &p); diff --git a/src/core/mount-setup.c b/src/core/mount-setup.c index ba96741e95..c35248eeae 100644 --- a/src/core/mount-setup.c +++ b/src/core/mount-setup.c @@ -156,7 +156,7 @@ static int mount_one(const MountPoint *p, bool relabel) { if (relabel) label_fix(p->where, true, true); - r = path_is_mount_point(p->where, true); + r = path_is_mount_point(p->where, AT_SYMLINK_FOLLOW); if (r < 0 && r != -ENOENT) return r; if (r > 0) diff --git a/src/core/mount.c b/src/core/mount.c index ba1dcf1e85..851b41351e 100644 --- a/src/core/mount.c +++ b/src/core/mount.c @@ -1522,6 +1522,9 @@ static int mount_load_proc_self_mountinfo(Manager *m, bool set_flags) { options = mnt_fs_get_options(fs); fstype = mnt_fs_get_fstype(fs); + if (!device || !path) + continue; + if (cunescape(device, UNESCAPE_RELAX, &d) < 0) return log_oom(); diff --git a/src/core/namespace.c b/src/core/namespace.c index 7d0b7e7e84..01a817bf23 100644 --- a/src/core/namespace.c +++ b/src/core/namespace.c @@ -499,7 +499,7 @@ int setup_namespace( if (protect_system != PROTECT_SYSTEM_NO) { const char *usr_dir, *boot_dir, *etc_dir; - usr_dir = prefix_roota(root_directory, "/home"); + usr_dir = prefix_roota(root_directory, "/usr"); boot_dir = prefix_roota(root_directory, "/boot"); boot_dir = strjoina("-", boot_dir); etc_dir = prefix_roota(root_directory, "/etc"); diff --git a/src/core/service.c b/src/core/service.c index 07347b99a4..c7e65772ea 100644 --- a/src/core/service.c +++ b/src/core/service.c @@ -47,6 +47,7 @@ #include "bus-kernel.h" #include "formats-util.h" #include "process-util.h" +#include "signal-util.h" static const UnitActiveState state_translation_table[_SERVICE_STATE_MAX] = { [SERVICE_DEAD] = UNIT_INACTIVE, diff --git a/src/core/socket.c b/src/core/socket.c index 17b8a5059d..fc5eb1464a 100644 --- a/src/core/socket.c +++ b/src/core/socket.c @@ -47,8 +47,9 @@ #include "selinux-util.h" #include "dbus-socket.h" #include "unit.h" -#include "socket.h" #include "formats-util.h" +#include "signal-util.h" +#include "socket.h" static const UnitActiveState state_translation_table[_SOCKET_STATE_MAX] = { [SOCKET_DEAD] = UNIT_INACTIVE, diff --git a/src/efi-boot-generator/efi-boot-generator.c b/src/efi-boot-generator/efi-boot-generator.c index 42b21f57de..e6b15c9bb0 100644 --- a/src/efi-boot-generator/efi-boot-generator.c +++ b/src/efi-boot-generator/efi-boot-generator.c @@ -68,7 +68,7 @@ int main(int argc, char *argv[]) { return EXIT_SUCCESS; } - r = path_is_mount_point("/boot", true); + r = path_is_mount_point("/boot", AT_SYMLINK_FOLLOW); if (r > 0) { log_debug("/boot is already a mount point, exiting."); return EXIT_SUCCESS; diff --git a/src/fsck/fsck.c b/src/fsck/fsck.c index 9bbe9ff673..f0e5c5f239 100644 --- a/src/fsck/fsck.c +++ b/src/fsck/fsck.c @@ -34,6 +34,7 @@ #include "util.h" #include "process-util.h" +#include "signal-util.h" #include "special.h" #include "bus-util.h" #include "bus-error.h" diff --git a/src/gpt-auto-generator/gpt-auto-generator.c b/src/gpt-auto-generator/gpt-auto-generator.c index b192526186..b46e160888 100644 --- a/src/gpt-auto-generator/gpt-auto-generator.c +++ b/src/gpt-auto-generator/gpt-auto-generator.c @@ -297,7 +297,7 @@ static int probe_and_add_mount( assert(where); assert(description); - if (path_is_mount_point(where, true) <= 0 && + if (path_is_mount_point(where, AT_SYMLINK_FOLLOW) <= 0 && dir_is_empty(where) <= 0) { log_debug("%s already populated, ignoring.", where); return 0; diff --git a/src/gudev/.gitignore b/src/gudev/.gitignore deleted file mode 100644 index 4577903c40..0000000000 --- a/src/gudev/.gitignore +++ /dev/null @@ -1,7 +0,0 @@ -gudev-1.0.pc -gudevenumtypes.c -gudevenumtypes.h -gudevmarshal.c -gudevmarshal.h -GUdev-1.0.gir -GUdev-1.0.typelib diff --git a/src/gudev/Makefile b/src/gudev/Makefile deleted file mode 120000 index d0b0e8e008..0000000000 --- a/src/gudev/Makefile +++ /dev/null @@ -1 +0,0 @@ -../Makefile
\ No newline at end of file diff --git a/src/gudev/gjs-example.js b/src/gudev/gjs-example.js deleted file mode 100755 index 5586fd6a61..0000000000 --- a/src/gudev/gjs-example.js +++ /dev/null @@ -1,75 +0,0 @@ -#!/usr/bin/env gjs-console - -// This currently depends on the following patches to gjs -// -// http://bugzilla.gnome.org/show_bug.cgi?id=584558 -// http://bugzilla.gnome.org/show_bug.cgi?id=584560 -// http://bugzilla.gnome.org/show_bug.cgi?id=584568 - -const GUdev = imports.gi.GUdev; -const Mainloop = imports.mainloop; - -function print_device (device) { - print (" subsystem: " + device.get_subsystem ()); - print (" devtype: " + device.get_devtype ()); - print (" name: " + device.get_name ()); - print (" number: " + device.get_number ()); - print (" sysfs_path: " + device.get_sysfs_path ()); - print (" driver: " + device.get_driver ()); - print (" action: " + device.get_action ()); - print (" seqnum: " + device.get_seqnum ()); - print (" device type: " + device.get_device_type ()); - print (" device number: " + device.get_device_number ()); - print (" device file: " + device.get_device_file ()); - print (" device file symlinks: " + device.get_device_file_symlinks ()); - print (" foo: " + device.get_sysfs_attr_as_strv ("stat")); - var keys = device.get_property_keys (); - for (var n = 0; n < keys.length; n++) { - print (" " + keys[n] + "=" + device.get_property (keys[n])); - } -} - -function on_uevent (client, action, device) { - print ("action " + action + " on device " + device.get_sysfs_path()); - print_device (device); - print (""); -} - -var client = new GUdev.Client ({subsystems: ["block", "usb/usb_interface"]}); -client.connect ("uevent", on_uevent); - -var block_devices = client.query_by_subsystem ("block"); -for (var n = 0; n < block_devices.length; n++) { - print ("block device: " + block_devices[n].get_device_file ()); -} - -var d; - -d = client.query_by_device_number (GUdev.DeviceType.BLOCK, 0x0810); -if (d == null) { - print ("query_by_device_number 0x810 -> null"); -} else { - print ("query_by_device_number 0x810 -> " + d.get_device_file ()); - var dd = d.get_parent_with_subsystem ("usb", null); - print_device (dd); - print ("--------------------------------------------------------------------------"); - while (d != null) { - print_device (d); - print (""); - d = d.get_parent (); - } -} - -d = client.query_by_sysfs_path ("/sys/block/sda/sda1"); -print ("query_by_sysfs_path (\"/sys/block/sda1\") -> " + d.get_device_file ()); - -d = client.query_by_subsystem_and_name ("block", "sda2"); -print ("query_by_subsystem_and_name (\"block\", \"sda2\") -> " + d.get_device_file ()); - -d = client.query_by_device_file ("/dev/sda"); -print ("query_by_device_file (\"/dev/sda\") -> " + d.get_device_file ()); - -d = client.query_by_device_file ("/dev/block/8:0"); -print ("query_by_device_file (\"/dev/block/8:0\") -> " + d.get_device_file ()); - -Mainloop.run('udev-example'); diff --git a/src/gudev/gudev-1.0.pc.in b/src/gudev/gudev-1.0.pc.in deleted file mode 100644 index 058262d767..0000000000 --- a/src/gudev/gudev-1.0.pc.in +++ /dev/null @@ -1,11 +0,0 @@ -prefix=@prefix@ -exec_prefix=@exec_prefix@ -libdir=@libdir@ -includedir=@includedir@ - -Name: gudev-1.0 -Description: GObject bindings for libudev -Version: @VERSION@ -Requires: glib-2.0, gobject-2.0 -Libs: -L${libdir} -lgudev-1.0 -Cflags: -I${includedir}/gudev-1.0 diff --git a/src/gudev/gudev.h b/src/gudev/gudev.h deleted file mode 100644 index 1dc42b11b7..0000000000 --- a/src/gudev/gudev.h +++ /dev/null @@ -1,32 +0,0 @@ -/* -*- Mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * - * Copyright (C) 2008 David Zeuthen <davidz@redhat.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef __G_UDEV_H__ -#define __G_UDEV_H__ - -#define _GUDEV_INSIDE_GUDEV_H -#include <gudev/gudevenums.h> -#include <gudev/gudevenumtypes.h> -#include <gudev/gudevtypes.h> -#include <gudev/gudevclient.h> -#include <gudev/gudevdevice.h> -#include <gudev/gudevenumerator.h> -#undef _GUDEV_INSIDE_GUDEV_H - -#endif /* __G_UDEV_H__ */ diff --git a/src/gudev/gudevclient.c b/src/gudev/gudevclient.c deleted file mode 100644 index 8b9516cba8..0000000000 --- a/src/gudev/gudevclient.c +++ /dev/null @@ -1,533 +0,0 @@ -/* -*- Mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * - * Copyright (C) 2008-2010 David Zeuthen <davidz@redhat.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include <stdlib.h> -#include <string.h> -#include <sys/stat.h> - -#include "gudevclient.h" -#include "gudevdevice.h" -#include "gudevmarshal.h" -#include "gudevprivate.h" - -/** - * SECTION:gudevclient - * @short_description: Query devices and listen to uevents - * - * #GUdevClient is used to query information about devices on a Linux - * system from the Linux kernel and the udev device - * manager. - * - * Device information is retrieved from the kernel (through the - * <literal>sysfs</literal> filesystem) and the udev daemon (through a - * <literal>tmpfs</literal> filesystem) and presented through - * #GUdevDevice objects. This means that no blocking IO ever happens - * (in both cases, we are essentially just reading data from kernel - * memory) and as such there are no asynchronous versions of the - * provided methods. - * - * To get #GUdevDevice objects, use - * g_udev_client_query_by_subsystem(), - * g_udev_client_query_by_device_number(), - * g_udev_client_query_by_device_file(), - * g_udev_client_query_by_sysfs_path(), - * g_udev_client_query_by_subsystem_and_name() - * or the #GUdevEnumerator type. - * - * To listen to uevents, connect to the #GUdevClient::uevent signal. - */ - -struct _GUdevClientPrivate -{ - GSource *watch_source; - struct udev *udev; - struct udev_monitor *monitor; - - gchar **subsystems; -}; - -enum -{ - PROP_0, - PROP_SUBSYSTEMS, -}; - -enum -{ - UEVENT_SIGNAL, - LAST_SIGNAL, -}; - -static guint signals[LAST_SIGNAL] = { 0 }; - -G_DEFINE_TYPE (GUdevClient, g_udev_client, G_TYPE_OBJECT) - -/* ---------------------------------------------------------------------------------------------------- */ - -static gboolean -monitor_event (GIOChannel *source, - GIOCondition condition, - gpointer data) -{ - GUdevClient *client = (GUdevClient *) data; - GUdevDevice *device; - struct udev_device *udevice; - - if (client->priv->monitor == NULL) - goto out; - udevice = udev_monitor_receive_device (client->priv->monitor); - if (udevice == NULL) - goto out; - - device = _g_udev_device_new (udevice); - udev_device_unref (udevice); - g_signal_emit (client, - signals[UEVENT_SIGNAL], - 0, - g_udev_device_get_action (device), - device); - g_object_unref (device); - - out: - return TRUE; -} - -static void -g_udev_client_finalize (GObject *object) -{ - GUdevClient *client = G_UDEV_CLIENT (object); - - if (client->priv->watch_source != NULL) - { - g_source_destroy (client->priv->watch_source); - client->priv->watch_source = NULL; - } - - if (client->priv->monitor != NULL) - { - udev_monitor_unref (client->priv->monitor); - client->priv->monitor = NULL; - } - - if (client->priv->udev != NULL) - { - udev_unref (client->priv->udev); - client->priv->udev = NULL; - } - - g_strfreev (client->priv->subsystems); - - if (G_OBJECT_CLASS (g_udev_client_parent_class)->finalize != NULL) - G_OBJECT_CLASS (g_udev_client_parent_class)->finalize (object); -} - -static void -g_udev_client_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - GUdevClient *client = G_UDEV_CLIENT (object); - - switch (prop_id) - { - case PROP_SUBSYSTEMS: - if (client->priv->subsystems != NULL) - g_strfreev (client->priv->subsystems); - client->priv->subsystems = g_strdupv (g_value_get_boxed (value)); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -g_udev_client_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - GUdevClient *client = G_UDEV_CLIENT (object); - - switch (prop_id) - { - case PROP_SUBSYSTEMS: - g_value_set_boxed (value, client->priv->subsystems); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -g_udev_client_constructed (GObject *object) -{ - GUdevClient *client = G_UDEV_CLIENT (object); - GIOChannel *channel; - guint n; - - client->priv->udev = udev_new (); - - /* connect to event source */ - client->priv->monitor = udev_monitor_new_from_netlink (client->priv->udev, "udev"); - - //g_debug ("ss = %p", client->priv->subsystems); - - if (client->priv->subsystems != NULL) - { - /* install subsystem filters to only wake up for certain events */ - for (n = 0; client->priv->subsystems[n] != NULL; n++) - { - gchar *subsystem; - gchar *devtype; - gchar *s; - - subsystem = g_strdup (client->priv->subsystems[n]); - devtype = NULL; - - //g_debug ("s = '%s'", subsystem); - - s = strstr (subsystem, "/"); - if (s != NULL) - { - devtype = s + 1; - *s = '\0'; - } - - if (client->priv->monitor != NULL) - udev_monitor_filter_add_match_subsystem_devtype (client->priv->monitor, subsystem, devtype); - - g_free (subsystem); - } - - /* listen to events, and buffer them */ - if (client->priv->monitor != NULL) - { - udev_monitor_enable_receiving (client->priv->monitor); - channel = g_io_channel_unix_new (udev_monitor_get_fd (client->priv->monitor)); - client->priv->watch_source = g_io_create_watch (channel, G_IO_IN); - g_io_channel_unref (channel); - g_source_set_callback (client->priv->watch_source, (GSourceFunc) monitor_event, client, NULL); - g_source_attach (client->priv->watch_source, g_main_context_get_thread_default ()); - g_source_unref (client->priv->watch_source); - } - else - { - client->priv->watch_source = NULL; - } - } - - if (G_OBJECT_CLASS (g_udev_client_parent_class)->constructed != NULL) - G_OBJECT_CLASS (g_udev_client_parent_class)->constructed (object); -} - - -static void -g_udev_client_class_init (GUdevClientClass *klass) -{ - GObjectClass *gobject_class = (GObjectClass *) klass; - - gobject_class->constructed = g_udev_client_constructed; - gobject_class->set_property = g_udev_client_set_property; - gobject_class->get_property = g_udev_client_get_property; - gobject_class->finalize = g_udev_client_finalize; - - /** - * GUdevClient:subsystems: - * - * The subsystems to listen for uevents on. - * - * To listen for only a specific DEVTYPE for a given SUBSYSTEM, use - * "subsystem/devtype". For example, to only listen for uevents - * where SUBSYSTEM is usb and DEVTYPE is usb_interface, use - * "usb/usb_interface". - * - * If this property is %NULL, then no events will be reported. If - * it's the empty array, events from all subsystems will be - * reported. - */ - g_object_class_install_property (gobject_class, - PROP_SUBSYSTEMS, - g_param_spec_boxed ("subsystems", - "The subsystems to listen for changes on", - "The subsystems to listen for changes on", - G_TYPE_STRV, - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_READWRITE)); - - /** - * GUdevClient::uevent: - * @client: The #GUdevClient receiving the event. - * @action: The action for the uevent e.g. "add", "remove", "change", "move", etc. - * @device: Details about the #GUdevDevice the event is for. - * - * Emitted when @client receives an uevent. - * - * This signal is emitted in the - * <link linkend="g-main-context-push-thread-default">thread-default main loop</link> - * of the thread that @client was created in. - */ - signals[UEVENT_SIGNAL] = g_signal_new ("uevent", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (GUdevClientClass, uevent), - NULL, - NULL, - g_udev_marshal_VOID__STRING_OBJECT, - G_TYPE_NONE, - 2, - G_TYPE_STRING, - G_UDEV_TYPE_DEVICE); - - g_type_class_add_private (klass, sizeof (GUdevClientPrivate)); -} - -static void -g_udev_client_init (GUdevClient *client) -{ - client->priv = G_TYPE_INSTANCE_GET_PRIVATE (client, - G_UDEV_TYPE_CLIENT, - GUdevClientPrivate); -} - -/** - * g_udev_client_new: - * @subsystems: (array zero-terminated=1) (element-type utf8) (transfer none) (allow-none): A %NULL terminated string array of subsystems to listen for uevents on, %NULL to not listen on uevents at all, or an empty array to listen to uevents on all subsystems. See the documentation for the #GUdevClient:subsystems property for details on this parameter. - * - * Constructs a #GUdevClient object that can be used to query - * information about devices. Connect to the #GUdevClient::uevent - * signal to listen for uevents. Note that signals are emitted in the - * <link linkend="g-main-context-push-thread-default">thread-default main loop</link> - * of the thread that you call this constructor from. - * - * Returns: A new #GUdevClient object. Free with g_object_unref(). - */ -GUdevClient * -g_udev_client_new (const gchar * const *subsystems) -{ - return G_UDEV_CLIENT (g_object_new (G_UDEV_TYPE_CLIENT, "subsystems", subsystems, NULL)); -} - -/** - * g_udev_client_query_by_subsystem: - * @client: A #GUdevClient. - * @subsystem: (allow-none): The subsystem to get devices for or %NULL to get all devices. - * - * Gets all devices belonging to @subsystem. - * - * Returns: (nullable) (element-type GUdevDevice) (transfer full): A - * list of #GUdevDevice objects. The caller should free the result by - * using g_object_unref() on each element in the list and then - * g_list_free() on the list. - */ -GList * -g_udev_client_query_by_subsystem (GUdevClient *client, - const gchar *subsystem) -{ - struct udev_enumerate *enumerate; - struct udev_list_entry *l, *devices; - GList *ret; - - g_return_val_if_fail (G_UDEV_IS_CLIENT (client), NULL); - - ret = NULL; - - /* prepare a device scan */ - enumerate = udev_enumerate_new (client->priv->udev); - - /* filter for subsystem */ - if (subsystem != NULL) - udev_enumerate_add_match_subsystem (enumerate, subsystem); - /* retrieve the list */ - udev_enumerate_scan_devices (enumerate); - - /* add devices to the list */ - devices = udev_enumerate_get_list_entry (enumerate); - for (l = devices; l != NULL; l = udev_list_entry_get_next (l)) - { - struct udev_device *udevice; - GUdevDevice *device; - - udevice = udev_device_new_from_syspath (udev_enumerate_get_udev (enumerate), - udev_list_entry_get_name (l)); - if (udevice == NULL) - continue; - device = _g_udev_device_new (udevice); - udev_device_unref (udevice); - ret = g_list_prepend (ret, device); - } - udev_enumerate_unref (enumerate); - - ret = g_list_reverse (ret); - - return ret; -} - -/** - * g_udev_client_query_by_device_number: - * @client: A #GUdevClient. - * @type: A value from the #GUdevDeviceType enumeration. - * @number: A device number. - * - * Looks up a device for a type and device number. - * - * Returns: (nullable) (transfer full): A #GUdevDevice object or %NULL - * if the device was not found. Free with g_object_unref(). - */ -GUdevDevice * -g_udev_client_query_by_device_number (GUdevClient *client, - GUdevDeviceType type, - GUdevDeviceNumber number) -{ - struct udev_device *udevice; - GUdevDevice *device; - - g_return_val_if_fail (G_UDEV_IS_CLIENT (client), NULL); - - device = NULL; - udevice = udev_device_new_from_devnum (client->priv->udev, type, number); - - if (udevice == NULL) - goto out; - - device = _g_udev_device_new (udevice); - udev_device_unref (udevice); - - out: - return device; -} - -/** - * g_udev_client_query_by_device_file: - * @client: A #GUdevClient. - * @device_file: A device file. - * - * Looks up a device for a device file. - * - * Returns: (nullable) (transfer full): A #GUdevDevice object or %NULL - * if the device was not found. Free with g_object_unref(). - */ -GUdevDevice * -g_udev_client_query_by_device_file (GUdevClient *client, - const gchar *device_file) -{ - struct stat stat_buf; - GUdevDevice *device; - - g_return_val_if_fail (G_UDEV_IS_CLIENT (client), NULL); - g_return_val_if_fail (device_file != NULL, NULL); - - device = NULL; - - if (stat (device_file, &stat_buf) != 0) - goto out; - - if (stat_buf.st_rdev == 0) - goto out; - - if (S_ISBLK (stat_buf.st_mode)) - device = g_udev_client_query_by_device_number (client, G_UDEV_DEVICE_TYPE_BLOCK, stat_buf.st_rdev); - else if (S_ISCHR (stat_buf.st_mode)) - device = g_udev_client_query_by_device_number (client, G_UDEV_DEVICE_TYPE_CHAR, stat_buf.st_rdev); - - out: - return device; -} - -/** - * g_udev_client_query_by_sysfs_path: - * @client: A #GUdevClient. - * @sysfs_path: A sysfs path. - * - * Looks up a device for a sysfs path. - * - * Returns: (nullable) (transfer full): A #GUdevDevice object or %NULL - * if the device was not found. Free with g_object_unref(). - */ -GUdevDevice * -g_udev_client_query_by_sysfs_path (GUdevClient *client, - const gchar *sysfs_path) -{ - struct udev_device *udevice; - GUdevDevice *device; - - g_return_val_if_fail (G_UDEV_IS_CLIENT (client), NULL); - g_return_val_if_fail (sysfs_path != NULL, NULL); - - device = NULL; - udevice = udev_device_new_from_syspath (client->priv->udev, sysfs_path); - if (udevice == NULL) - goto out; - - device = _g_udev_device_new (udevice); - udev_device_unref (udevice); - - out: - return device; -} - -/** - * g_udev_client_query_by_subsystem_and_name: - * @client: A #GUdevClient. - * @subsystem: A subsystem name. - * @name: The name of the device. - * - * Looks up a device for a subsystem and name. - * - * Returns: (nullable) (transfer full): A #GUdevDevice object or %NULL - * if the device was not found. Free with g_object_unref(). - */ -GUdevDevice * -g_udev_client_query_by_subsystem_and_name (GUdevClient *client, - const gchar *subsystem, - const gchar *name) -{ - struct udev_device *udevice; - GUdevDevice *device; - - g_return_val_if_fail (G_UDEV_IS_CLIENT (client), NULL); - g_return_val_if_fail (subsystem != NULL, NULL); - g_return_val_if_fail (name != NULL, NULL); - - device = NULL; - udevice = udev_device_new_from_subsystem_sysname (client->priv->udev, subsystem, name); - if (udevice == NULL) - goto out; - - device = _g_udev_device_new (udevice); - udev_device_unref (udevice); - - out: - return device; -} - -struct udev * -_g_udev_client_get_udev (GUdevClient *client) -{ - g_return_val_if_fail (G_UDEV_IS_CLIENT (client), NULL); - return client->priv->udev; -} diff --git a/src/gudev/gudevclient.h b/src/gudev/gudevclient.h deleted file mode 100644 index 23bfce615f..0000000000 --- a/src/gudev/gudevclient.h +++ /dev/null @@ -1,99 +0,0 @@ -/* -*- Mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * - * Copyright (C) 2008 David Zeuthen <davidz@redhat.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#if !defined (_GUDEV_COMPILATION) && !defined(_GUDEV_INSIDE_GUDEV_H) -#error "Only <gudev/gudev.h> can be included directly, this file may disappear or change contents." -#endif - -#ifndef __G_UDEV_CLIENT_H__ -#define __G_UDEV_CLIENT_H__ - -#include <gudev/gudevtypes.h> - -G_BEGIN_DECLS - -#define G_UDEV_TYPE_CLIENT (g_udev_client_get_type ()) -#define G_UDEV_CLIENT(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_UDEV_TYPE_CLIENT, GUdevClient)) -#define G_UDEV_CLIENT_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_UDEV_TYPE_CLIENT, GUdevClientClass)) -#define G_UDEV_IS_CLIENT(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_UDEV_TYPE_CLIENT)) -#define G_UDEV_IS_CLIENT_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_UDEV_TYPE_CLIENT)) -#define G_UDEV_CLIENT_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_UDEV_TYPE_CLIENT, GUdevClientClass)) - -typedef struct _GUdevClientClass GUdevClientClass; -typedef struct _GUdevClientPrivate GUdevClientPrivate; - -/** - * GUdevClient: - * - * The #GUdevClient struct is opaque and should not be accessed directly. - */ -struct _GUdevClient -{ - GObject parent; - - /*< private >*/ - GUdevClientPrivate *priv; -}; - -/** - * GUdevClientClass: - * @parent_class: Parent class. - * @uevent: Signal class handler for the #GUdevClient::uevent signal. - * - * Class structure for #GUdevClient. - */ -struct _GUdevClientClass -{ - GObjectClass parent_class; - - /* signals */ - void (*uevent) (GUdevClient *client, - const gchar *action, - GUdevDevice *device); - - /*< private >*/ - /* Padding for future expansion */ - void (*reserved1) (void); - void (*reserved2) (void); - void (*reserved3) (void); - void (*reserved4) (void); - void (*reserved5) (void); - void (*reserved6) (void); - void (*reserved7) (void); - void (*reserved8) (void); -}; - -GType g_udev_client_get_type (void) G_GNUC_CONST; -GUdevClient *g_udev_client_new (const gchar* const *subsystems); -GList *g_udev_client_query_by_subsystem (GUdevClient *client, - const gchar *subsystem); -GUdevDevice *g_udev_client_query_by_device_number (GUdevClient *client, - GUdevDeviceType type, - GUdevDeviceNumber number); -GUdevDevice *g_udev_client_query_by_device_file (GUdevClient *client, - const gchar *device_file); -GUdevDevice *g_udev_client_query_by_sysfs_path (GUdevClient *client, - const gchar *sysfs_path); -GUdevDevice *g_udev_client_query_by_subsystem_and_name (GUdevClient *client, - const gchar *subsystem, - const gchar *name); - -G_END_DECLS - -#endif /* __G_UDEV_CLIENT_H__ */ diff --git a/src/gudev/gudevdevice.c b/src/gudev/gudevdevice.c deleted file mode 100644 index 28b229b8d8..0000000000 --- a/src/gudev/gudevdevice.c +++ /dev/null @@ -1,1027 +0,0 @@ -/* -*- Mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * - * Copyright (C) 2008 David Zeuthen <davidz@redhat.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include <stdlib.h> -#include <string.h> -#include <sys/stat.h> - -#include "gudevdevice.h" -#include "gudevprivate.h" - -/** - * SECTION:gudevdevice - * @short_description: Get information about a device - * - * The #GUdevDevice class is used to get information about a specific - * device. Note that you cannot instantiate a #GUdevDevice object - * yourself. Instead you must use #GUdevClient to obtain #GUdevDevice - * objects. - * - * To get basic information about a device, use - * g_udev_device_get_subsystem(), g_udev_device_get_devtype(), - * g_udev_device_get_name(), g_udev_device_get_number(), - * g_udev_device_get_sysfs_path(), g_udev_device_get_driver(), - * g_udev_device_get_action(), g_udev_device_get_seqnum(), - * g_udev_device_get_device_type(), g_udev_device_get_device_number(), - * g_udev_device_get_device_file(), - * g_udev_device_get_device_file_symlinks(). - * - * To navigate the device tree, use g_udev_device_get_parent() and - * g_udev_device_get_parent_with_subsystem(). - * - * To access udev properties for the device, use - * g_udev_device_get_property_keys(), - * g_udev_device_has_property(), - * g_udev_device_get_property(), - * g_udev_device_get_property_as_int(), - * g_udev_device_get_property_as_uint64(), - * g_udev_device_get_property_as_double(), - * g_udev_device_get_property_as_boolean() and - * g_udev_device_get_property_as_strv(). - * - * To access sysfs attributes for the device, use - * g_udev_device_get_sysfs_attr_keys(), - * g_udev_device_has_sysfs_attr(), - * g_udev_device_get_sysfs_attr(), - * g_udev_device_get_sysfs_attr_as_int(), - * g_udev_device_get_sysfs_attr_as_uint64(), - * g_udev_device_get_sysfs_attr_as_double(), - * g_udev_device_get_sysfs_attr_as_boolean() and - * g_udev_device_get_sysfs_attr_as_strv(). - * - * Note that all getters on #GUdevDevice are non-reffing – returned - * values are owned by the object, should not be freed and are only - * valid as long as the object is alive. - * - * By design, #GUdevDevice will not react to changes for a device – it - * only contains a snapshot of information when the #GUdevDevice - * object was created. To work with changes, you typically connect to - * the #GUdevClient::uevent signal on a #GUdevClient and get a new - * #GUdevDevice whenever an event happens. - */ - -struct _GUdevDevicePrivate -{ - struct udev_device *udevice; - - /* computed ondemand and cached */ - gchar **device_file_symlinks; - gchar **property_keys; - gchar **sysfs_attr_keys; - gchar **tags; - GHashTable *prop_strvs; - GHashTable *sysfs_attr_strvs; -}; - -G_DEFINE_TYPE (GUdevDevice, g_udev_device, G_TYPE_OBJECT) - -static void -g_udev_device_finalize (GObject *object) -{ - GUdevDevice *device = G_UDEV_DEVICE (object); - - g_strfreev (device->priv->device_file_symlinks); - g_strfreev (device->priv->property_keys); - g_strfreev (device->priv->sysfs_attr_keys); - g_strfreev (device->priv->tags); - - if (device->priv->udevice != NULL) - udev_device_unref (device->priv->udevice); - - if (device->priv->prop_strvs != NULL) - g_hash_table_unref (device->priv->prop_strvs); - - if (device->priv->sysfs_attr_strvs != NULL) - g_hash_table_unref (device->priv->sysfs_attr_strvs); - - if (G_OBJECT_CLASS (g_udev_device_parent_class)->finalize != NULL) - (* G_OBJECT_CLASS (g_udev_device_parent_class)->finalize) (object); -} - -static void -g_udev_device_class_init (GUdevDeviceClass *klass) -{ - GObjectClass *gobject_class = (GObjectClass *) klass; - - gobject_class->finalize = g_udev_device_finalize; - - g_type_class_add_private (klass, sizeof (GUdevDevicePrivate)); -} - -static void -g_udev_device_init (GUdevDevice *device) -{ - device->priv = G_TYPE_INSTANCE_GET_PRIVATE (device, - G_UDEV_TYPE_DEVICE, - GUdevDevicePrivate); -} - - -GUdevDevice * -_g_udev_device_new (struct udev_device *udevice) -{ - GUdevDevice *device; - - device = G_UDEV_DEVICE (g_object_new (G_UDEV_TYPE_DEVICE, NULL)); - device->priv->udevice = udev_device_ref (udevice); - - return device; -} - -/** - * g_udev_device_get_subsystem: - * @device: A #GUdevDevice. - * - * Gets the subsystem for @device. - * - * Returns: The subsystem for @device. - */ -const gchar * -g_udev_device_get_subsystem (GUdevDevice *device) -{ - g_return_val_if_fail (G_UDEV_IS_DEVICE (device), NULL); - return udev_device_get_subsystem (device->priv->udevice); -} - -/** - * g_udev_device_get_devtype: - * @device: A #GUdevDevice. - * - * Gets the device type for @device. - * - * Returns: The devtype for @device. - */ -const gchar * -g_udev_device_get_devtype (GUdevDevice *device) -{ - g_return_val_if_fail (G_UDEV_IS_DEVICE (device), NULL); - return udev_device_get_devtype (device->priv->udevice); -} - -/** - * g_udev_device_get_name: - * @device: A #GUdevDevice. - * - * Gets the name of @device, e.g. "sda3". - * - * Returns: The name of @device. - */ -const gchar * -g_udev_device_get_name (GUdevDevice *device) -{ - g_return_val_if_fail (G_UDEV_IS_DEVICE (device), NULL); - return udev_device_get_sysname (device->priv->udevice); -} - -/** - * g_udev_device_get_number: - * @device: A #GUdevDevice. - * - * Gets the number of @device, e.g. "3" if g_udev_device_get_name() returns "sda3". - * - * Returns: The number of @device. - */ -const gchar * -g_udev_device_get_number (GUdevDevice *device) -{ - g_return_val_if_fail (G_UDEV_IS_DEVICE (device), NULL); - return udev_device_get_sysnum (device->priv->udevice); -} - -/** - * g_udev_device_get_sysfs_path: - * @device: A #GUdevDevice. - * - * Gets the sysfs path for @device. - * - * Returns: The sysfs path for @device. - */ -const gchar * -g_udev_device_get_sysfs_path (GUdevDevice *device) -{ - g_return_val_if_fail (G_UDEV_IS_DEVICE (device), NULL); - return udev_device_get_syspath (device->priv->udevice); -} - -/** - * g_udev_device_get_driver: - * @device: A #GUdevDevice. - * - * Gets the name of the driver used for @device. - * - * Returns: (nullable): The name of the driver for @device or %NULL if - * unknown. - */ -const gchar * -g_udev_device_get_driver (GUdevDevice *device) -{ - g_return_val_if_fail (G_UDEV_IS_DEVICE (device), NULL); - return udev_device_get_driver (device->priv->udevice); -} - -/** - * g_udev_device_get_action: - * @device: A #GUdevDevice. - * - * Gets the most recent action (e.g. "add", "remove", "change", etc.) for @device. - * - * Returns: An action string. - */ -const gchar * -g_udev_device_get_action (GUdevDevice *device) -{ - g_return_val_if_fail (G_UDEV_IS_DEVICE (device), NULL); - return udev_device_get_action (device->priv->udevice); -} - -/** - * g_udev_device_get_seqnum: - * @device: A #GUdevDevice. - * - * Gets the most recent sequence number for @device. - * - * Returns: A sequence number. - */ -guint64 -g_udev_device_get_seqnum (GUdevDevice *device) -{ - g_return_val_if_fail (G_UDEV_IS_DEVICE (device), 0); - return udev_device_get_seqnum (device->priv->udevice); -} - -/** - * g_udev_device_get_device_type: - * @device: A #GUdevDevice. - * - * Gets the type of the device file, if any, for @device. - * - * Returns: The device number for @device or #G_UDEV_DEVICE_TYPE_NONE if the device does not have a device file. - */ -GUdevDeviceType -g_udev_device_get_device_type (GUdevDevice *device) -{ - struct stat stat_buf; - const gchar *device_file; - GUdevDeviceType type; - - g_return_val_if_fail (G_UDEV_IS_DEVICE (device), G_UDEV_DEVICE_TYPE_NONE); - - type = G_UDEV_DEVICE_TYPE_NONE; - - /* TODO: would be better to have support for this in libudev... */ - - device_file = g_udev_device_get_device_file (device); - if (device_file == NULL) - goto out; - - if (stat (device_file, &stat_buf) != 0) - goto out; - - if (S_ISBLK (stat_buf.st_mode)) - type = G_UDEV_DEVICE_TYPE_BLOCK; - else if (S_ISCHR (stat_buf.st_mode)) - type = G_UDEV_DEVICE_TYPE_CHAR; - - out: - return type; -} - -/** - * g_udev_device_get_device_number: - * @device: A #GUdevDevice. - * - * Gets the device number, if any, for @device. - * - * Returns: The device number for @device or 0 if unknown. - */ -GUdevDeviceNumber -g_udev_device_get_device_number (GUdevDevice *device) -{ - g_return_val_if_fail (G_UDEV_IS_DEVICE (device), 0); - return udev_device_get_devnum (device->priv->udevice); -} - -/** - * g_udev_device_get_device_file: - * @device: A #GUdevDevice. - * - * Gets the device file for @device. - * - * Returns: (nullable): The device file for @device or %NULL if no - * device file exists. - */ -const gchar * -g_udev_device_get_device_file (GUdevDevice *device) -{ - g_return_val_if_fail (G_UDEV_IS_DEVICE (device), NULL); - return udev_device_get_devnode (device->priv->udevice); -} - -/** - * g_udev_device_get_device_file_symlinks: - * @device: A #GUdevDevice. - * - * Gets a list of symlinks (in <literal>/dev</literal>) that points to - * the device file for @device. - * - * Returns: (transfer none) (array zero-terminated=1) (element-type utf8): A %NULL terminated string array of symlinks. This array is owned by @device and should not be freed by the caller. - */ -const gchar * const * -g_udev_device_get_device_file_symlinks (GUdevDevice *device) -{ - struct udev_list_entry *l; - GPtrArray *p; - - g_return_val_if_fail (G_UDEV_IS_DEVICE (device), NULL); - - if (device->priv->device_file_symlinks != NULL) - goto out; - - p = g_ptr_array_new (); - for (l = udev_device_get_devlinks_list_entry (device->priv->udevice); l != NULL; l = udev_list_entry_get_next (l)) - { - g_ptr_array_add (p, g_strdup (udev_list_entry_get_name (l))); - } - g_ptr_array_add (p, NULL); - device->priv->device_file_symlinks = (gchar **) g_ptr_array_free (p, FALSE); - - out: - return (const gchar * const *) device->priv->device_file_symlinks; -} - -/* ---------------------------------------------------------------------------------------------------- */ - -/** - * g_udev_device_get_parent: - * @device: A #GUdevDevice. - * - * Gets the immediate parent of @device, if any. - * - * Returns: (nullable) (transfer full): A #GUdevDevice or %NULL if - * @device has no parent. Free with g_object_unref(). - */ -GUdevDevice * -g_udev_device_get_parent (GUdevDevice *device) -{ - GUdevDevice *ret; - struct udev_device *udevice; - - g_return_val_if_fail (G_UDEV_IS_DEVICE (device), NULL); - - ret = NULL; - - udevice = udev_device_get_parent (device->priv->udevice); - if (udevice == NULL) - goto out; - - ret = _g_udev_device_new (udevice); - - out: - return ret; -} - -/** - * g_udev_device_get_parent_with_subsystem: - * @device: A #GUdevDevice. - * @subsystem: The subsystem of the parent to get. - * @devtype: (allow-none): The devtype of the parent to get or %NULL. - * - * Walks up the chain of parents of @device and returns the first - * device encountered where @subsystem and @devtype matches, if any. - * - * Returns: (nullable) (transfer full): A #GUdevDevice or %NULL if - * @device has no parent with @subsystem and @devtype. Free with - * g_object_unref(). - */ -GUdevDevice * -g_udev_device_get_parent_with_subsystem (GUdevDevice *device, - const gchar *subsystem, - const gchar *devtype) -{ - GUdevDevice *ret; - struct udev_device *udevice; - - g_return_val_if_fail (G_UDEV_IS_DEVICE (device), NULL); - g_return_val_if_fail (subsystem != NULL, NULL); - - ret = NULL; - - udevice = udev_device_get_parent_with_subsystem_devtype (device->priv->udevice, - subsystem, - devtype); - if (udevice == NULL) - goto out; - - ret = _g_udev_device_new (udevice); - - out: - return ret; -} - -/* ---------------------------------------------------------------------------------------------------- */ - -/** - * g_udev_device_get_property_keys: - * @device: A #GUdevDevice. - * - * Gets all keys for properties on @device. - * - * Returns: (transfer none) (array zero-terminated=1) (element-type utf8): A %NULL terminated string array of property keys. This array is owned by @device and should not be freed by the caller. - */ -const gchar* const * -g_udev_device_get_property_keys (GUdevDevice *device) -{ - struct udev_list_entry *l; - GPtrArray *p; - - g_return_val_if_fail (G_UDEV_IS_DEVICE (device), NULL); - - if (device->priv->property_keys != NULL) - goto out; - - p = g_ptr_array_new (); - for (l = udev_device_get_properties_list_entry (device->priv->udevice); l != NULL; l = udev_list_entry_get_next (l)) - { - g_ptr_array_add (p, g_strdup (udev_list_entry_get_name (l))); - } - g_ptr_array_add (p, NULL); - device->priv->property_keys = (gchar **) g_ptr_array_free (p, FALSE); - - out: - return (const gchar * const *) device->priv->property_keys; -} - - -/** - * g_udev_device_has_property: - * @device: A #GUdevDevice. - * @key: Name of property. - * - * Check if a the property with the given key exists. - * - * Returns: %TRUE only if the value for @key exist. - */ -gboolean -g_udev_device_has_property (GUdevDevice *device, - const gchar *key) -{ - g_return_val_if_fail (G_UDEV_IS_DEVICE (device), FALSE); - g_return_val_if_fail (key != NULL, FALSE); - return udev_device_get_property_value (device->priv->udevice, key) != NULL; -} - -/** - * g_udev_device_get_property: - * @device: A #GUdevDevice. - * @key: Name of property. - * - * Look up the value for @key on @device. - * - * Returns: (nullable): The value for @key or %NULL if @key doesn't - * exist on @device. Do not free this string, it is owned by @device. - */ -const gchar * -g_udev_device_get_property (GUdevDevice *device, - const gchar *key) -{ - g_return_val_if_fail (G_UDEV_IS_DEVICE (device), NULL); - g_return_val_if_fail (key != NULL, NULL); - return udev_device_get_property_value (device->priv->udevice, key); -} - -/** - * g_udev_device_get_property_as_int: - * @device: A #GUdevDevice. - * @key: Name of property. - * - * Look up the value for @key on @device and convert it to an integer - * using strtol(). - * - * Returns: The value for @key or 0 if @key doesn't exist or - * isn't an integer. - */ -gint -g_udev_device_get_property_as_int (GUdevDevice *device, - const gchar *key) -{ - gint result; - const gchar *s; - - g_return_val_if_fail (G_UDEV_IS_DEVICE (device), 0); - g_return_val_if_fail (key != NULL, 0); - - result = 0; - s = g_udev_device_get_property (device, key); - if (s == NULL) - goto out; - - result = strtol (s, NULL, 0); -out: - return result; -} - -/** - * g_udev_device_get_property_as_uint64: - * @device: A #GUdevDevice. - * @key: Name of property. - * - * Look up the value for @key on @device and convert it to an unsigned - * 64-bit integer using g_ascii_strtoull(). - * - * Returns: The value for @key or 0 if @key doesn't exist or isn't a - * #guint64. - */ -guint64 -g_udev_device_get_property_as_uint64 (GUdevDevice *device, - const gchar *key) -{ - guint64 result; - const gchar *s; - - g_return_val_if_fail (G_UDEV_IS_DEVICE (device), 0); - g_return_val_if_fail (key != NULL, 0); - - result = 0; - s = g_udev_device_get_property (device, key); - if (s == NULL) - goto out; - - result = g_ascii_strtoull (s, NULL, 0); -out: - return result; -} - -/** - * g_udev_device_get_property_as_double: - * @device: A #GUdevDevice. - * @key: Name of property. - * - * Look up the value for @key on @device and convert it to a double - * precision floating point number using strtod(). - * - * Returns: The value for @key or 0.0 if @key doesn't exist or isn't a - * #gdouble. - */ -gdouble -g_udev_device_get_property_as_double (GUdevDevice *device, - const gchar *key) -{ - gdouble result; - const gchar *s; - - g_return_val_if_fail (G_UDEV_IS_DEVICE (device), 0.0); - g_return_val_if_fail (key != NULL, 0.0); - - result = 0.0; - s = g_udev_device_get_property (device, key); - if (s == NULL) - goto out; - - result = strtod (s, NULL); -out: - return result; -} - -/** - * g_udev_device_get_property_as_boolean: - * @device: A #GUdevDevice. - * @key: Name of property. - * - * Look up the value for @key on @device and convert it to an - * boolean. This is done by doing a case-insensitive string comparison - * on the string value against "1" and "true". - * - * Returns: The value for @key or %FALSE if @key doesn't exist or - * isn't a #gboolean. - */ -gboolean -g_udev_device_get_property_as_boolean (GUdevDevice *device, - const gchar *key) -{ - gboolean result; - const gchar *s; - - g_return_val_if_fail (G_UDEV_IS_DEVICE (device), FALSE); - g_return_val_if_fail (key != NULL, FALSE); - - result = FALSE; - s = g_udev_device_get_property (device, key); - if (s == NULL) - goto out; - - if (strcmp (s, "1") == 0 || g_ascii_strcasecmp (s, "true") == 0) - result = TRUE; - out: - return result; -} - -static gchar ** -split_at_whitespace (const gchar *s) -{ - gchar **result; - guint n; - guint m; - - result = g_strsplit_set (s, " \v\t\r\n", 0); - - /* remove empty strings, thanks GLib */ - for (n = 0; result[n] != NULL; n++) - { - if (strlen (result[n]) == 0) - { - g_free (result[n]); - for (m = n; result[m] != NULL; m++) - result[m] = result[m + 1]; - n--; - } - } - - return result; -} - -/** - * g_udev_device_get_property_as_strv: - * @device: A #GUdevDevice. - * @key: Name of property. - * - * Look up the value for @key on @device and return the result of - * splitting it into non-empty tokens split at white space (only space - * (' '), form-feed ('\f'), newline ('\n'), carriage return ('\r'), - * horizontal tab ('\t'), and vertical tab ('\v') are considered; the - * locale is not taken into account). - * - * Returns: (nullable) (transfer none) (array zero-terminated=1) (element-type utf8): - * The value of @key on @device split into tokens or %NULL if @key - * doesn't exist. This array is owned by @device and should not be - * freed by the caller. - */ -const gchar* const * -g_udev_device_get_property_as_strv (GUdevDevice *device, - const gchar *key) -{ - gchar **result; - const gchar *s; - - g_return_val_if_fail (G_UDEV_IS_DEVICE (device), NULL); - g_return_val_if_fail (key != NULL, NULL); - - if (device->priv->prop_strvs != NULL) - { - result = g_hash_table_lookup (device->priv->prop_strvs, key); - if (result != NULL) - goto out; - } - - result = NULL; - s = g_udev_device_get_property (device, key); - if (s == NULL) - goto out; - - result = split_at_whitespace (s); - if (result == NULL) - goto out; - - if (device->priv->prop_strvs == NULL) - device->priv->prop_strvs = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_strfreev); - g_hash_table_insert (device->priv->prop_strvs, g_strdup (key), result); - -out: - return (const gchar* const *) result; -} - -/* ---------------------------------------------------------------------------------------------------- */ - -/** - * g_udev_device_get_sysfs_attr_keys: - * @device: A #GUdevDevice. - * - * Gets all keys for sysfs attributes on @device. - * - * Returns: (transfer none) (array zero-terminated=1) (element-type utf8): A %NULL terminated string array of sysfs attribute keys. This array is owned by @device and should not be freed by the caller. - */ -const gchar * const * -g_udev_device_get_sysfs_attr_keys (GUdevDevice *device) -{ - struct udev_list_entry *l; - GPtrArray *p; - - g_return_val_if_fail (G_UDEV_IS_DEVICE (device), NULL); - - if (device->priv->sysfs_attr_keys != NULL) - goto out; - - p = g_ptr_array_new (); - for (l = udev_device_get_sysattr_list_entry (device->priv->udevice); l != NULL; l = udev_list_entry_get_next (l)) - { - g_ptr_array_add (p, g_strdup (udev_list_entry_get_name (l))); - } - g_ptr_array_add (p, NULL); - device->priv->sysfs_attr_keys = (gchar **) g_ptr_array_free (p, FALSE); - - out: - return (const gchar * const *) device->priv->sysfs_attr_keys; -} - -/** - * g_udev_device_has_sysfs_attr: - * @device: A #GUdevDevice. - * @key: Name of sysfs attribute. - * - * Check if a the sysfs attribute with the given key exists. - * - * Returns: %TRUE only if the value for @key exist. - */ -gboolean -g_udev_device_has_sysfs_attr (GUdevDevice *device, - const gchar *key) -{ - g_return_val_if_fail (G_UDEV_IS_DEVICE (device), FALSE); - g_return_val_if_fail (key != NULL, FALSE); - return udev_device_get_sysattr_value (device->priv->udevice, key) != NULL; -} - -/** - * g_udev_device_get_sysfs_attr: - * @device: A #GUdevDevice. - * @name: Name of the sysfs attribute. - * - * Look up the sysfs attribute with @name on @device. - * - * Returns: (nullable): The value of the sysfs attribute or %NULL if - * there is no such attribute. Do not free this string, it is owned by - * @device. - */ -const gchar * -g_udev_device_get_sysfs_attr (GUdevDevice *device, - const gchar *name) -{ - g_return_val_if_fail (G_UDEV_IS_DEVICE (device), NULL); - g_return_val_if_fail (name != NULL, NULL); - return udev_device_get_sysattr_value (device->priv->udevice, name); -} - -/** - * g_udev_device_get_sysfs_attr_as_int: - * @device: A #GUdevDevice. - * @name: Name of the sysfs attribute. - * - * Look up the sysfs attribute with @name on @device and convert it to an integer - * using strtol(). - * - * Returns: The value of the sysfs attribute or 0 if there is no such - * attribute. - */ -gint -g_udev_device_get_sysfs_attr_as_int (GUdevDevice *device, - const gchar *name) -{ - gint result; - const gchar *s; - - g_return_val_if_fail (G_UDEV_IS_DEVICE (device), 0); - g_return_val_if_fail (name != NULL, 0); - - result = 0; - s = g_udev_device_get_sysfs_attr (device, name); - if (s == NULL) - goto out; - - result = strtol (s, NULL, 0); -out: - return result; -} - -/** - * g_udev_device_get_sysfs_attr_as_uint64: - * @device: A #GUdevDevice. - * @name: Name of the sysfs attribute. - * - * Look up the sysfs attribute with @name on @device and convert it to an unsigned - * 64-bit integer using g_ascii_strtoull(). - * - * Returns: The value of the sysfs attribute or 0 if there is no such - * attribute. - */ -guint64 -g_udev_device_get_sysfs_attr_as_uint64 (GUdevDevice *device, - const gchar *name) -{ - guint64 result; - const gchar *s; - - g_return_val_if_fail (G_UDEV_IS_DEVICE (device), 0); - g_return_val_if_fail (name != NULL, 0); - - result = 0; - s = g_udev_device_get_sysfs_attr (device, name); - if (s == NULL) - goto out; - - result = g_ascii_strtoull (s, NULL, 0); -out: - return result; -} - -/** - * g_udev_device_get_sysfs_attr_as_double: - * @device: A #GUdevDevice. - * @name: Name of the sysfs attribute. - * - * Look up the sysfs attribute with @name on @device and convert it to a double - * precision floating point number using strtod(). - * - * Returns: The value of the sysfs attribute or 0.0 if there is no such - * attribute. - */ -gdouble -g_udev_device_get_sysfs_attr_as_double (GUdevDevice *device, - const gchar *name) -{ - gdouble result; - const gchar *s; - - g_return_val_if_fail (G_UDEV_IS_DEVICE (device), 0.0); - g_return_val_if_fail (name != NULL, 0.0); - - result = 0.0; - s = g_udev_device_get_sysfs_attr (device, name); - if (s == NULL) - goto out; - - result = strtod (s, NULL); -out: - return result; -} - -/** - * g_udev_device_get_sysfs_attr_as_boolean: - * @device: A #GUdevDevice. - * @name: Name of the sysfs attribute. - * - * Look up the sysfs attribute with @name on @device and convert it to an - * boolean. This is done by doing a case-insensitive string comparison - * on the string value against "1" and "true". - * - * Returns: The value of the sysfs attribute or %FALSE if there is no such - * attribute. - */ -gboolean -g_udev_device_get_sysfs_attr_as_boolean (GUdevDevice *device, - const gchar *name) -{ - gboolean result; - const gchar *s; - - g_return_val_if_fail (G_UDEV_IS_DEVICE (device), FALSE); - g_return_val_if_fail (name != NULL, FALSE); - - result = FALSE; - s = g_udev_device_get_sysfs_attr (device, name); - if (s == NULL) - goto out; - - if (strcmp (s, "1") == 0 || g_ascii_strcasecmp (s, "true") == 0) - result = TRUE; - out: - return result; -} - -/** - * g_udev_device_get_sysfs_attr_as_strv: - * @device: A #GUdevDevice. - * @name: Name of the sysfs attribute. - * - * Look up the sysfs attribute with @name on @device and return the result of - * splitting it into non-empty tokens split at white space (only space (' '), - * form-feed ('\f'), newline ('\n'), carriage return ('\r'), horizontal - * tab ('\t'), and vertical tab ('\v') are considered; the locale is - * not taken into account). - * - * Returns: (nullable) (transfer none) (array zero-terminated=1) (element-type utf8): - * The value of the sysfs attribute split into tokens or %NULL if - * there is no such attribute. This array is owned by @device and - * should not be freed by the caller. - */ -const gchar * const * -g_udev_device_get_sysfs_attr_as_strv (GUdevDevice *device, - const gchar *name) -{ - gchar **result; - const gchar *s; - - g_return_val_if_fail (G_UDEV_IS_DEVICE (device), NULL); - g_return_val_if_fail (name != NULL, NULL); - - if (device->priv->sysfs_attr_strvs != NULL) - { - result = g_hash_table_lookup (device->priv->sysfs_attr_strvs, name); - if (result != NULL) - goto out; - } - - result = NULL; - s = g_udev_device_get_sysfs_attr (device, name); - if (s == NULL) - goto out; - - result = split_at_whitespace (s); - if (result == NULL) - goto out; - - if (device->priv->sysfs_attr_strvs == NULL) - device->priv->sysfs_attr_strvs = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_strfreev); - g_hash_table_insert (device->priv->sysfs_attr_strvs, g_strdup (name), result); - -out: - return (const gchar* const *) result; -} - -/** - * g_udev_device_get_tags: - * @device: A #GUdevDevice. - * - * Gets all tags for @device. - * - * Returns: (transfer none) (array zero-terminated=1) (element-type utf8): A %NULL terminated string array of tags. This array is owned by @device and should not be freed by the caller. - * - * Since: 165 - */ -const gchar* const * -g_udev_device_get_tags (GUdevDevice *device) -{ - struct udev_list_entry *l; - GPtrArray *p; - - g_return_val_if_fail (G_UDEV_IS_DEVICE (device), NULL); - - if (device->priv->tags != NULL) - goto out; - - p = g_ptr_array_new (); - for (l = udev_device_get_tags_list_entry (device->priv->udevice); l != NULL; l = udev_list_entry_get_next (l)) - { - g_ptr_array_add (p, g_strdup (udev_list_entry_get_name (l))); - } - g_ptr_array_add (p, NULL); - device->priv->tags = (gchar **) g_ptr_array_free (p, FALSE); - - out: - return (const gchar * const *) device->priv->tags; -} - -/** - * g_udev_device_get_is_initialized: - * @device: A #GUdevDevice. - * - * Gets whether @device has been initialized. - * - * Returns: Whether @device has been initialized. - * - * Since: 165 - */ -gboolean -g_udev_device_get_is_initialized (GUdevDevice *device) -{ - g_return_val_if_fail (G_UDEV_IS_DEVICE (device), FALSE); - return udev_device_get_is_initialized (device->priv->udevice); -} - -/** - * g_udev_device_get_usec_since_initialized: - * @device: A #GUdevDevice. - * - * Gets number of micro-seconds since @device was initialized. - * - * This only works for devices with properties in the udev - * database. All other devices return 0. - * - * Returns: Number of micro-seconds since @device was initialized or 0 if unknown. - * - * Since: 165 - */ -guint64 -g_udev_device_get_usec_since_initialized (GUdevDevice *device) -{ - g_return_val_if_fail (G_UDEV_IS_DEVICE (device), 0); - return udev_device_get_usec_since_initialized (device->priv->udevice); -} diff --git a/src/gudev/gudevdevice.h b/src/gudev/gudevdevice.h deleted file mode 100644 index 72ec180f55..0000000000 --- a/src/gudev/gudevdevice.h +++ /dev/null @@ -1,130 +0,0 @@ -/* -*- Mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * - * Copyright (C) 2008 David Zeuthen <davidz@redhat.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#if !defined (_GUDEV_COMPILATION) && !defined(_GUDEV_INSIDE_GUDEV_H) -#error "Only <gudev/gudev.h> can be included directly, this file may disappear or change contents." -#endif - -#ifndef __G_UDEV_DEVICE_H__ -#define __G_UDEV_DEVICE_H__ - -#include <gudev/gudevtypes.h> - -G_BEGIN_DECLS - -#define G_UDEV_TYPE_DEVICE (g_udev_device_get_type ()) -#define G_UDEV_DEVICE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_UDEV_TYPE_DEVICE, GUdevDevice)) -#define G_UDEV_DEVICE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_UDEV_TYPE_DEVICE, GUdevDeviceClass)) -#define G_UDEV_IS_DEVICE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_UDEV_TYPE_DEVICE)) -#define G_UDEV_IS_DEVICE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_UDEV_TYPE_DEVICE)) -#define G_UDEV_DEVICE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_UDEV_TYPE_DEVICE, GUdevDeviceClass)) - -typedef struct _GUdevDeviceClass GUdevDeviceClass; -typedef struct _GUdevDevicePrivate GUdevDevicePrivate; - -/** - * GUdevDevice: - * - * The #GUdevDevice struct is opaque and should not be accessed directly. - */ -struct _GUdevDevice -{ - GObject parent; - - /*< private >*/ - GUdevDevicePrivate *priv; -}; - -/** - * GUdevDeviceClass: - * @parent_class: Parent class. - * - * Class structure for #GUdevDevice. - */ -struct _GUdevDeviceClass -{ - GObjectClass parent_class; - - /*< private >*/ - /* Padding for future expansion */ - void (*reserved1) (void); - void (*reserved2) (void); - void (*reserved3) (void); - void (*reserved4) (void); - void (*reserved5) (void); - void (*reserved6) (void); - void (*reserved7) (void); - void (*reserved8) (void); -}; - -GType g_udev_device_get_type (void) G_GNUC_CONST; -gboolean g_udev_device_get_is_initialized (GUdevDevice *device); -guint64 g_udev_device_get_usec_since_initialized (GUdevDevice *device); -const gchar *g_udev_device_get_subsystem (GUdevDevice *device); -const gchar *g_udev_device_get_devtype (GUdevDevice *device); -const gchar *g_udev_device_get_name (GUdevDevice *device); -const gchar *g_udev_device_get_number (GUdevDevice *device); -const gchar *g_udev_device_get_sysfs_path (GUdevDevice *device); -const gchar *g_udev_device_get_driver (GUdevDevice *device); -const gchar *g_udev_device_get_action (GUdevDevice *device); -guint64 g_udev_device_get_seqnum (GUdevDevice *device); -GUdevDeviceType g_udev_device_get_device_type (GUdevDevice *device); -GUdevDeviceNumber g_udev_device_get_device_number (GUdevDevice *device); -const gchar *g_udev_device_get_device_file (GUdevDevice *device); -const gchar* const *g_udev_device_get_device_file_symlinks (GUdevDevice *device); -GUdevDevice *g_udev_device_get_parent (GUdevDevice *device); -GUdevDevice *g_udev_device_get_parent_with_subsystem (GUdevDevice *device, - const gchar *subsystem, - const gchar *devtype); -const gchar* const *g_udev_device_get_property_keys (GUdevDevice *device); -gboolean g_udev_device_has_property (GUdevDevice *device, - const gchar *key); -const gchar *g_udev_device_get_property (GUdevDevice *device, - const gchar *key); -gint g_udev_device_get_property_as_int (GUdevDevice *device, - const gchar *key); -guint64 g_udev_device_get_property_as_uint64 (GUdevDevice *device, - const gchar *key); -gdouble g_udev_device_get_property_as_double (GUdevDevice *device, - const gchar *key); -gboolean g_udev_device_get_property_as_boolean (GUdevDevice *device, - const gchar *key); -const gchar* const *g_udev_device_get_property_as_strv (GUdevDevice *device, - const gchar *key); - -const gchar* const *g_udev_device_get_sysfs_attr_keys (GUdevDevice *device); -gboolean g_udev_device_has_sysfs_attr (GUdevDevice *device, - const gchar *key); -const gchar *g_udev_device_get_sysfs_attr (GUdevDevice *device, - const gchar *name); -gint g_udev_device_get_sysfs_attr_as_int (GUdevDevice *device, - const gchar *name); -guint64 g_udev_device_get_sysfs_attr_as_uint64 (GUdevDevice *device, - const gchar *name); -gdouble g_udev_device_get_sysfs_attr_as_double (GUdevDevice *device, - const gchar *name); -gboolean g_udev_device_get_sysfs_attr_as_boolean (GUdevDevice *device, - const gchar *name); -const gchar* const *g_udev_device_get_sysfs_attr_as_strv (GUdevDevice *device, - const gchar *name); -const gchar* const *g_udev_device_get_tags (GUdevDevice *device); - -G_END_DECLS - -#endif /* __G_UDEV_DEVICE_H__ */ diff --git a/src/gudev/gudevenumerator.c b/src/gudev/gudevenumerator.c deleted file mode 100644 index 1fb3098709..0000000000 --- a/src/gudev/gudevenumerator.c +++ /dev/null @@ -1,429 +0,0 @@ -/* -*- Mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * - * Copyright (C) 2008-2010 David Zeuthen <davidz@redhat.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include <stdlib.h> -#include <string.h> - -#include "gudevclient.h" -#include "gudevenumerator.h" -#include "gudevdevice.h" -#include "gudevmarshal.h" -#include "gudevprivate.h" - -/** - * SECTION:gudevenumerator - * @short_description: Lookup and sort devices - * - * #GUdevEnumerator is used to lookup and sort devices. - * - * Since: 165 - */ - -struct _GUdevEnumeratorPrivate -{ - GUdevClient *client; - struct udev_enumerate *e; -}; - -enum -{ - PROP_0, - PROP_CLIENT, -}; - -G_DEFINE_TYPE (GUdevEnumerator, g_udev_enumerator, G_TYPE_OBJECT) - -/* ---------------------------------------------------------------------------------------------------- */ - -static void -g_udev_enumerator_finalize (GObject *object) -{ - GUdevEnumerator *enumerator = G_UDEV_ENUMERATOR (object); - - if (enumerator->priv->client != NULL) - { - g_object_unref (enumerator->priv->client); - enumerator->priv->client = NULL; - } - - if (enumerator->priv->e != NULL) - { - udev_enumerate_unref (enumerator->priv->e); - enumerator->priv->e = NULL; - } - - if (G_OBJECT_CLASS (g_udev_enumerator_parent_class)->finalize != NULL) - G_OBJECT_CLASS (g_udev_enumerator_parent_class)->finalize (object); -} - -static void -g_udev_enumerator_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - GUdevEnumerator *enumerator = G_UDEV_ENUMERATOR (object); - - switch (prop_id) - { - case PROP_CLIENT: - if (enumerator->priv->client != NULL) - g_object_unref (enumerator->priv->client); - enumerator->priv->client = g_value_dup_object (value); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -g_udev_enumerator_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - GUdevEnumerator *enumerator = G_UDEV_ENUMERATOR (object); - - switch (prop_id) - { - case PROP_CLIENT: - g_value_set_object (value, enumerator->priv->client); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -g_udev_enumerator_constructed (GObject *object) -{ - GUdevEnumerator *enumerator = G_UDEV_ENUMERATOR (object); - - g_assert (G_UDEV_IS_CLIENT (enumerator->priv->client)); - - enumerator->priv->e = udev_enumerate_new (_g_udev_client_get_udev (enumerator->priv->client)); - - if (G_OBJECT_CLASS (g_udev_enumerator_parent_class)->constructed != NULL) - G_OBJECT_CLASS (g_udev_enumerator_parent_class)->constructed (object); -} - -static void -g_udev_enumerator_class_init (GUdevEnumeratorClass *klass) -{ - GObjectClass *gobject_class = (GObjectClass *) klass; - - gobject_class->finalize = g_udev_enumerator_finalize; - gobject_class->set_property = g_udev_enumerator_set_property; - gobject_class->get_property = g_udev_enumerator_get_property; - gobject_class->constructed = g_udev_enumerator_constructed; - - /** - * GUdevEnumerator:client: - * - * The #GUdevClient to enumerate devices from. - * - * Since: 165 - */ - g_object_class_install_property (gobject_class, - PROP_CLIENT, - g_param_spec_object ("client", - "The client to enumerate devices from", - "The client to enumerate devices from", - G_UDEV_TYPE_CLIENT, - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_READWRITE)); - - g_type_class_add_private (klass, sizeof (GUdevEnumeratorPrivate)); -} - -static void -g_udev_enumerator_init (GUdevEnumerator *enumerator) -{ - enumerator->priv = G_TYPE_INSTANCE_GET_PRIVATE (enumerator, - G_UDEV_TYPE_ENUMERATOR, - GUdevEnumeratorPrivate); -} - -/** - * g_udev_enumerator_new: - * @client: A #GUdevClient to enumerate devices from. - * - * Constructs a #GUdevEnumerator object that can be used to enumerate - * and sort devices. Use the add_match_*() and add_nomatch_*() methods - * and execute the query to get a list of devices with - * g_udev_enumerator_execute(). - * - * Returns: A new #GUdevEnumerator object. Free with g_object_unref(). - * - * Since: 165 - */ -GUdevEnumerator * -g_udev_enumerator_new (GUdevClient *client) -{ - g_return_val_if_fail (G_UDEV_IS_CLIENT (client), NULL); - return G_UDEV_ENUMERATOR (g_object_new (G_UDEV_TYPE_ENUMERATOR, "client", client, NULL)); -} - - -/** - * g_udev_enumerator_add_match_subsystem: - * @enumerator: A #GUdevEnumerator. - * @subsystem: Wildcard for subsystem name e.g. 'scsi' or 'a*'. - * - * All returned devices will match the given @subsystem. - * - * Returns: (transfer none): The passed in @enumerator. - * - * Since: 165 - */ -GUdevEnumerator * -g_udev_enumerator_add_match_subsystem (GUdevEnumerator *enumerator, - const gchar *subsystem) -{ - g_return_val_if_fail (G_UDEV_IS_ENUMERATOR (enumerator), NULL); - g_return_val_if_fail (subsystem != NULL, NULL); - udev_enumerate_add_match_subsystem (enumerator->priv->e, subsystem); - return enumerator; -} - -/** - * g_udev_enumerator_add_nomatch_subsystem: - * @enumerator: A #GUdevEnumerator. - * @subsystem: Wildcard for subsystem name e.g. 'scsi' or 'a*'. - * - * All returned devices will not match the given @subsystem. - * - * Returns: (transfer none): The passed in @enumerator. - * - * Since: 165 - */ -GUdevEnumerator * -g_udev_enumerator_add_nomatch_subsystem (GUdevEnumerator *enumerator, - const gchar *subsystem) -{ - g_return_val_if_fail (G_UDEV_IS_ENUMERATOR (enumerator), NULL); - g_return_val_if_fail (subsystem != NULL, NULL); - udev_enumerate_add_nomatch_subsystem (enumerator->priv->e, subsystem); - return enumerator; -} - -/** - * g_udev_enumerator_add_match_sysfs_attr: - * @enumerator: A #GUdevEnumerator. - * @name: Wildcard filter for sysfs attribute key. - * @value: Wildcard filter for sysfs attribute value. - * - * All returned devices will have a sysfs attribute matching the given @name and @value. - * - * Returns: (transfer none): The passed in @enumerator. - * - * Since: 165 - */ -GUdevEnumerator * -g_udev_enumerator_add_match_sysfs_attr (GUdevEnumerator *enumerator, - const gchar *name, - const gchar *value) -{ - g_return_val_if_fail (G_UDEV_IS_ENUMERATOR (enumerator), NULL); - g_return_val_if_fail (name != NULL, NULL); - g_return_val_if_fail (value != NULL, NULL); - udev_enumerate_add_match_sysattr (enumerator->priv->e, name, value); - return enumerator; -} - -/** - * g_udev_enumerator_add_nomatch_sysfs_attr: - * @enumerator: A #GUdevEnumerator. - * @name: Wildcard filter for sysfs attribute key. - * @value: Wildcard filter for sysfs attribute value. - * - * All returned devices will not have a sysfs attribute matching the given @name and @value. - * - * Returns: (transfer none): The passed in @enumerator. - * - * Since: 165 - */ -GUdevEnumerator * -g_udev_enumerator_add_nomatch_sysfs_attr (GUdevEnumerator *enumerator, - const gchar *name, - const gchar *value) -{ - g_return_val_if_fail (G_UDEV_IS_ENUMERATOR (enumerator), NULL); - g_return_val_if_fail (name != NULL, NULL); - g_return_val_if_fail (value != NULL, NULL); - udev_enumerate_add_nomatch_sysattr (enumerator->priv->e, name, value); - return enumerator; -} - -/** - * g_udev_enumerator_add_match_property: - * @enumerator: A #GUdevEnumerator. - * @name: Wildcard filter for property name. - * @value: Wildcard filter for property value. - * - * All returned devices will have a property matching the given @name and @value. - * - * Returns: (transfer none): The passed in @enumerator. - * - * Since: 165 - */ -GUdevEnumerator * -g_udev_enumerator_add_match_property (GUdevEnumerator *enumerator, - const gchar *name, - const gchar *value) -{ - g_return_val_if_fail (G_UDEV_IS_ENUMERATOR (enumerator), NULL); - g_return_val_if_fail (name != NULL, NULL); - g_return_val_if_fail (value != NULL, NULL); - udev_enumerate_add_match_property (enumerator->priv->e, name, value); - return enumerator; -} - -/** - * g_udev_enumerator_add_match_name: - * @enumerator: A #GUdevEnumerator. - * @name: Wildcard filter for kernel name e.g. "sda*". - * - * All returned devices will match the given @name. - * - * Returns: (transfer none): The passed in @enumerator. - * - * Since: 165 - */ -GUdevEnumerator * -g_udev_enumerator_add_match_name (GUdevEnumerator *enumerator, - const gchar *name) -{ - g_return_val_if_fail (G_UDEV_IS_ENUMERATOR (enumerator), NULL); - g_return_val_if_fail (name != NULL, NULL); - udev_enumerate_add_match_sysname (enumerator->priv->e, name); - return enumerator; -} - -/** - * g_udev_enumerator_add_sysfs_path: - * @enumerator: A #GUdevEnumerator. - * @sysfs_path: A sysfs path, e.g. "/sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda" - * - * Add a device to the list of devices, to retrieve it back sorted in dependency order. - * - * Returns: (transfer none): The passed in @enumerator. - * - * Since: 165 - */ -GUdevEnumerator * -g_udev_enumerator_add_sysfs_path (GUdevEnumerator *enumerator, - const gchar *sysfs_path) -{ - g_return_val_if_fail (G_UDEV_IS_ENUMERATOR (enumerator), NULL); - g_return_val_if_fail (sysfs_path != NULL, NULL); - udev_enumerate_add_syspath (enumerator->priv->e, sysfs_path); - return enumerator; -} - -/** - * g_udev_enumerator_add_match_tag: - * @enumerator: A #GUdevEnumerator. - * @tag: A udev tag e.g. "udev-acl". - * - * All returned devices will match the given @tag. - * - * Returns: (transfer none): The passed in @enumerator. - * - * Since: 165 - */ -GUdevEnumerator * -g_udev_enumerator_add_match_tag (GUdevEnumerator *enumerator, - const gchar *tag) -{ - g_return_val_if_fail (G_UDEV_IS_ENUMERATOR (enumerator), NULL); - g_return_val_if_fail (tag != NULL, NULL); - udev_enumerate_add_match_tag (enumerator->priv->e, tag); - return enumerator; -} - -/** - * g_udev_enumerator_add_match_is_initialized: - * @enumerator: A #GUdevEnumerator. - * - * All returned devices will be initialized. - * - * Returns: (transfer none): The passed in @enumerator. - * - * Since: 165 - */ -GUdevEnumerator * -g_udev_enumerator_add_match_is_initialized (GUdevEnumerator *enumerator) -{ - g_return_val_if_fail (G_UDEV_IS_ENUMERATOR (enumerator), NULL); - udev_enumerate_add_match_is_initialized (enumerator->priv->e); - return enumerator; -} - -/** - * g_udev_enumerator_execute: - * @enumerator: A #GUdevEnumerator. - * - * Executes the query in @enumerator. - * - * Returns: (element-type GUdevDevice) (transfer full): A list of #GUdevDevice objects. The caller should free the result by using g_object_unref() on each element in the list and then g_list_free() on the list. - * - * Since: 165 - */ -GList * -g_udev_enumerator_execute (GUdevEnumerator *enumerator) -{ - GList *ret; - struct udev_list_entry *l, *devices; - - g_return_val_if_fail (G_UDEV_IS_ENUMERATOR (enumerator), NULL); - - ret = NULL; - - /* retrieve the list */ - udev_enumerate_scan_devices (enumerator->priv->e); - - devices = udev_enumerate_get_list_entry (enumerator->priv->e); - for (l = devices; l != NULL; l = udev_list_entry_get_next (l)) - { - struct udev_device *udevice; - GUdevDevice *device; - - udevice = udev_device_new_from_syspath (udev_enumerate_get_udev (enumerator->priv->e), - udev_list_entry_get_name (l)); - if (udevice == NULL) - continue; - - device = _g_udev_device_new (udevice); - udev_device_unref (udevice); - ret = g_list_prepend (ret, device); - } - - ret = g_list_reverse (ret); - - return ret; -} diff --git a/src/gudev/gudevenumerator.h b/src/gudev/gudevenumerator.h deleted file mode 100644 index e1dbcf1441..0000000000 --- a/src/gudev/gudevenumerator.h +++ /dev/null @@ -1,106 +0,0 @@ -/* -*- Mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * - * Copyright (C) 2008-2010 David Zeuthen <davidz@redhat.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#if !defined (_GUDEV_COMPILATION) && !defined(_GUDEV_INSIDE_GUDEV_H) -#error "Only <gudev/gudev.h> can be included directly, this file may disappear or change contents." -#endif - -#ifndef __G_UDEV_ENUMERATOR_H__ -#define __G_UDEV_ENUMERATOR_H__ - -#include <gudev/gudevtypes.h> - -G_BEGIN_DECLS - -#define G_UDEV_TYPE_ENUMERATOR (g_udev_enumerator_get_type ()) -#define G_UDEV_ENUMERATOR(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_UDEV_TYPE_ENUMERATOR, GUdevEnumerator)) -#define G_UDEV_ENUMERATOR_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_UDEV_TYPE_ENUMERATOR, GUdevEnumeratorClass)) -#define G_UDEV_IS_ENUMERATOR(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_UDEV_TYPE_ENUMERATOR)) -#define G_UDEV_IS_ENUMERATOR_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_UDEV_TYPE_ENUMERATOR)) -#define G_UDEV_ENUMERATOR_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_UDEV_TYPE_ENUMERATOR, GUdevEnumeratorClass)) - -typedef struct _GUdevEnumeratorClass GUdevEnumeratorClass; -typedef struct _GUdevEnumeratorPrivate GUdevEnumeratorPrivate; - -/** - * GUdevEnumerator: - * - * The #GUdevEnumerator struct is opaque and should not be accessed directly. - * - * Since: 165 - */ -struct _GUdevEnumerator -{ - GObject parent; - - /*< private >*/ - GUdevEnumeratorPrivate *priv; -}; - -/** - * GUdevEnumeratorClass: - * @parent_class: Parent class. - * - * Class structure for #GUdevEnumerator. - * - * Since: 165 - */ -struct _GUdevEnumeratorClass -{ - GObjectClass parent_class; - - /*< private >*/ - /* Padding for future expansion */ - void (*reserved1) (void); - void (*reserved2) (void); - void (*reserved3) (void); - void (*reserved4) (void); - void (*reserved5) (void); - void (*reserved6) (void); - void (*reserved7) (void); - void (*reserved8) (void); -}; - -GType g_udev_enumerator_get_type (void) G_GNUC_CONST; -GUdevEnumerator *g_udev_enumerator_new (GUdevClient *client); -GUdevEnumerator *g_udev_enumerator_add_match_subsystem (GUdevEnumerator *enumerator, - const gchar *subsystem); -GUdevEnumerator *g_udev_enumerator_add_nomatch_subsystem (GUdevEnumerator *enumerator, - const gchar *subsystem); -GUdevEnumerator *g_udev_enumerator_add_match_sysfs_attr (GUdevEnumerator *enumerator, - const gchar *name, - const gchar *value); -GUdevEnumerator *g_udev_enumerator_add_nomatch_sysfs_attr (GUdevEnumerator *enumerator, - const gchar *name, - const gchar *value); -GUdevEnumerator *g_udev_enumerator_add_match_property (GUdevEnumerator *enumerator, - const gchar *name, - const gchar *value); -GUdevEnumerator *g_udev_enumerator_add_match_name (GUdevEnumerator *enumerator, - const gchar *name); -GUdevEnumerator *g_udev_enumerator_add_match_tag (GUdevEnumerator *enumerator, - const gchar *tag); -GUdevEnumerator *g_udev_enumerator_add_match_is_initialized (GUdevEnumerator *enumerator); -GUdevEnumerator *g_udev_enumerator_add_sysfs_path (GUdevEnumerator *enumerator, - const gchar *sysfs_path); -GList *g_udev_enumerator_execute (GUdevEnumerator *enumerator); - -G_END_DECLS - -#endif /* __G_UDEV_ENUMERATOR_H__ */ diff --git a/src/gudev/gudevenums.h b/src/gudev/gudevenums.h deleted file mode 100644 index 467e93bd60..0000000000 --- a/src/gudev/gudevenums.h +++ /dev/null @@ -1,48 +0,0 @@ -/* -*- Mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * - * Copyright (C) 2008 David Zeuthen <davidz@redhat.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#if !defined (_GUDEV_COMPILATION) && !defined(_GUDEV_INSIDE_GUDEV_H) -#error "Only <gudev/gudev.h> can be included directly, this file may disappear or change contents." -#endif - -#ifndef __G_UDEV_ENUMS_H__ -#define __G_UDEV_ENUMS_H__ - -#include <glib-object.h> - -G_BEGIN_DECLS - -/** - * GUdevDeviceType: - * @G_UDEV_DEVICE_TYPE_NONE: Device does not have a device file. - * @G_UDEV_DEVICE_TYPE_BLOCK: Device is a block device. - * @G_UDEV_DEVICE_TYPE_CHAR: Device is a character device. - * - * Enumeration used to specify a the type of a device. - */ -typedef enum -{ - G_UDEV_DEVICE_TYPE_NONE = 0, - G_UDEV_DEVICE_TYPE_BLOCK = 'b', - G_UDEV_DEVICE_TYPE_CHAR = 'c', -} GUdevDeviceType; - -G_END_DECLS - -#endif /* __G_UDEV_ENUMS_H__ */ diff --git a/src/gudev/gudevenumtypes.c.template b/src/gudev/gudevenumtypes.c.template deleted file mode 100644 index fc30b39e2e..0000000000 --- a/src/gudev/gudevenumtypes.c.template +++ /dev/null @@ -1,39 +0,0 @@ -/*** BEGIN file-header ***/ -#include <gudev.h> - -/*** END file-header ***/ - -/*** BEGIN file-production ***/ -/* enumerations from "@filename@" */ -/*** END file-production ***/ - -/*** BEGIN value-header ***/ -GType -@enum_name@_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const G@Type@Value values[] = { -/*** END value-header ***/ - -/*** BEGIN value-production ***/ - { @VALUENAME@, "@VALUENAME@", "@valuenick@" }, -/*** END value-production ***/ - -/*** BEGIN value-tail ***/ - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_@type@_register_static (g_intern_static_string ("@EnumName@"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} - -/*** END value-tail ***/ - -/*** BEGIN file-tail ***/ -/*** END file-tail ***/ diff --git a/src/gudev/gudevenumtypes.h.template b/src/gudev/gudevenumtypes.h.template deleted file mode 100644 index d0ab3393e6..0000000000 --- a/src/gudev/gudevenumtypes.h.template +++ /dev/null @@ -1,24 +0,0 @@ -/*** BEGIN file-header ***/ -#ifndef __GUDEV_ENUM_TYPES_H__ -#define __GUDEV_ENUM_TYPES_H__ - -#include <glib-object.h> - -G_BEGIN_DECLS -/*** END file-header ***/ - -/*** BEGIN file-production ***/ - -/* enumerations from "@filename@" */ -/*** END file-production ***/ - -/*** BEGIN value-header ***/ -GType @enum_name@_get_type (void) G_GNUC_CONST; -#define @ENUMPREFIX@_TYPE_@ENUMSHORT@ (@enum_name@_get_type ()) -/*** END value-header ***/ - -/*** BEGIN file-tail ***/ -G_END_DECLS - -#endif /* __GUDEV_ENUM_TYPES_H__ */ -/*** END file-tail ***/ diff --git a/src/gudev/gudevmarshal.list b/src/gudev/gudevmarshal.list deleted file mode 100644 index 7e665999e8..0000000000 --- a/src/gudev/gudevmarshal.list +++ /dev/null @@ -1 +0,0 @@ -VOID:STRING,OBJECT diff --git a/src/gudev/gudevprivate.h b/src/gudev/gudevprivate.h deleted file mode 100644 index 52e272be3d..0000000000 --- a/src/gudev/gudevprivate.h +++ /dev/null @@ -1,40 +0,0 @@ -/* -*- Mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * - * Copyright (C) 2008 David Zeuthen <davidz@redhat.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#if !defined (_GUDEV_COMPILATION) && !defined(_GUDEV_INSIDE_GUDEV_H) -#error "Only <gudev/gudev.h> can be included directly, this file may disappear or change contents." -#endif - -#ifndef __G_UDEV_PRIVATE_H__ -#define __G_UDEV_PRIVATE_H__ - -#include <gudev/gudevtypes.h> - -#include <libudev.h> - -G_BEGIN_DECLS - -GUdevDevice * -_g_udev_device_new (struct udev_device *udevice); - -struct udev *_g_udev_client_get_udev (GUdevClient *client); - -G_END_DECLS - -#endif /* __G_UDEV_PRIVATE_H__ */ diff --git a/src/gudev/gudevtypes.h b/src/gudev/gudevtypes.h deleted file mode 100644 index e2f688ff2d..0000000000 --- a/src/gudev/gudevtypes.h +++ /dev/null @@ -1,50 +0,0 @@ -/* -*- Mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * - * Copyright (C) 2008 David Zeuthen <davidz@redhat.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#if !defined (_GUDEV_COMPILATION) && !defined(_GUDEV_INSIDE_GUDEV_H) -#error "Only <gudev/gudev.h> can be included directly, this file may disappear or change contents." -#endif - -#ifndef __G_UDEV_TYPES_H__ -#define __G_UDEV_TYPES_H__ - -#include <gudev/gudevenums.h> -#include <sys/types.h> - -G_BEGIN_DECLS - -typedef struct _GUdevClient GUdevClient; -typedef struct _GUdevDevice GUdevDevice; -typedef struct _GUdevEnumerator GUdevEnumerator; - -/** - * GUdevDeviceNumber: - * - * Corresponds to the standard #dev_t type as defined by POSIX (Until - * bug 584517 is resolved this work-around is needed). - */ -#ifdef _GUDEV_WORK_AROUND_DEV_T_BUG -typedef guint64 GUdevDeviceNumber; /* __UQUAD_TYPE */ -#else -typedef dev_t GUdevDeviceNumber; -#endif - -G_END_DECLS - -#endif /* __G_UDEV_TYPES_H__ */ diff --git a/src/gudev/libgudev-1.0.sym b/src/gudev/libgudev-1.0.sym deleted file mode 100644 index 0600486e9c..0000000000 --- a/src/gudev/libgudev-1.0.sym +++ /dev/null @@ -1,68 +0,0 @@ -/*** - This file is part of systemd. - - 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. -***/ - -{ -global: - g_udev_client_get_type; - g_udev_client_new; - g_udev_client_query_by_device_file; - g_udev_client_query_by_device_number; - g_udev_client_query_by_subsystem; - g_udev_client_query_by_subsystem_and_name; - g_udev_client_query_by_sysfs_path; - g_udev_device_get_action; - g_udev_device_get_device_file; - g_udev_device_get_device_file_symlinks; - g_udev_device_get_device_number; - g_udev_device_get_device_type; - g_udev_device_get_devtype; - g_udev_device_get_driver; - g_udev_device_get_is_initialized; - g_udev_device_get_name; - g_udev_device_get_number; - g_udev_device_get_parent; - g_udev_device_get_parent_with_subsystem; - g_udev_device_get_property; - g_udev_device_get_property_as_boolean; - g_udev_device_get_property_as_double; - g_udev_device_get_property_as_int; - g_udev_device_get_property_as_strv; - g_udev_device_get_property_as_uint64; - g_udev_device_get_property_keys; - g_udev_device_get_seqnum; - g_udev_device_get_subsystem; - g_udev_device_get_sysfs_attr; - g_udev_device_get_sysfs_attr_as_boolean; - g_udev_device_get_sysfs_attr_as_double; - g_udev_device_get_sysfs_attr_as_int; - g_udev_device_get_sysfs_attr_as_strv; - g_udev_device_get_sysfs_attr_as_uint64; - g_udev_device_get_sysfs_attr_keys; - g_udev_device_get_sysfs_path; - g_udev_device_get_tags; - g_udev_device_get_type; - g_udev_device_get_usec_since_initialized; - g_udev_device_has_property; - g_udev_device_has_sysfs_attr; - g_udev_device_type_get_type; - g_udev_enumerator_add_match_is_initialized; - g_udev_enumerator_add_match_name; - g_udev_enumerator_add_match_property; - g_udev_enumerator_add_match_subsystem; - g_udev_enumerator_add_match_sysfs_attr; - g_udev_enumerator_add_match_tag; - g_udev_enumerator_add_nomatch_subsystem; - g_udev_enumerator_add_nomatch_sysfs_attr; - g_udev_enumerator_add_sysfs_path; - g_udev_enumerator_execute; - g_udev_enumerator_get_type; - g_udev_enumerator_new; -local: - *; -}; diff --git a/src/gudev/seed-example-enum.js b/src/gudev/seed-example-enum.js deleted file mode 100755 index 66206ad806..0000000000 --- a/src/gudev/seed-example-enum.js +++ /dev/null @@ -1,38 +0,0 @@ -#!/usr/bin/env seed - -const GLib = imports.gi.GLib; -const GUdev = imports.gi.GUdev; - -function print_device(device) { - print(" initialized: " + device.get_is_initialized()); - print(" usec since initialized: " + device.get_usec_since_initialized()); - print(" subsystem: " + device.get_subsystem()); - print(" devtype: " + device.get_devtype()); - print(" name: " + device.get_name()); - print(" number: " + device.get_number()); - print(" sysfs_path: " + device.get_sysfs_path()); - print(" driver: " + device.get_driver()); - print(" action: " + device.get_action()); - print(" seqnum: " + device.get_seqnum()); - print(" device type: " + device.get_device_type()); - print(" device number: " + device.get_device_number()); - print(" device file: " + device.get_device_file()); - print(" device file symlinks: " + device.get_device_file_symlinks()); - print(" tags: " + device.get_tags()); - var keys = device.get_property_keys(); - for (var n = 0; n < keys.length; n++) { - print(" " + keys[n] + "=" + device.get_property(keys[n])); - } -} - -var client = new GUdev.Client({subsystems: []}); -var enumerator = new GUdev.Enumerator({client: client}); -enumerator.add_match_subsystem('b*') - -var devices = enumerator.execute(); - -for (var n=0; n < devices.length; n++) { - var device = devices[n]; - print_device(device); - print(""); -} diff --git a/src/gudev/seed-example.js b/src/gudev/seed-example.js deleted file mode 100755 index e2ac324d23..0000000000 --- a/src/gudev/seed-example.js +++ /dev/null @@ -1,72 +0,0 @@ -#!/usr/bin/env seed - -// seed example - -const GLib = imports.gi.GLib; -const GUdev = imports.gi.GUdev; - -function print_device (device) { - print (" subsystem: " + device.get_subsystem ()); - print (" devtype: " + device.get_devtype ()); - print (" name: " + device.get_name ()); - print (" number: " + device.get_number ()); - print (" sysfs_path: " + device.get_sysfs_path ()); - print (" driver: " + device.get_driver ()); - print (" action: " + device.get_action ()); - print (" seqnum: " + device.get_seqnum ()); - print (" device type: " + device.get_device_type ()); - print (" device number: " + device.get_device_number ()); - print (" device file: " + device.get_device_file ()); - print (" device file symlinks: " + device.get_device_file_symlinks ()); - print (" foo: " + device.get_sysfs_attr_as_strv ("stat")); - var keys = device.get_property_keys (); - for (var n = 0; n < keys.length; n++) { - print (" " + keys[n] + "=" + device.get_property (keys[n])); - } -} - -function on_uevent (client, action, device) { - print ("action " + action + " on device " + device.get_sysfs_path()); - print_device (device); - print (""); -} - -var client = new GUdev.Client ({subsystems: ["block", "usb/usb_interface"]}); -client.signal.connect ("uevent", on_uevent); - -var block_devices = client.query_by_subsystem ("block"); -for (var n = 0; n < block_devices.length; n++) { - print ("block device: " + block_devices[n].get_device_file ()); -} - -var d; - -d = client.query_by_device_number (GUdev.DeviceType.BLOCK, 0x0810); -if (d == null) { - print ("query_by_device_number 0x810 -> null"); -} else { - print ("query_by_device_number 0x810 -> " + d.get_device_file ()); - dd = d.get_parent_with_subsystem ("usb", null); - print_device (dd); - print ("--------------------------------------------------------------------------"); - while (d != null) { - print_device (d); - print (""); - d = d.get_parent (); - } -} - -d = client.query_by_sysfs_path ("/sys/block/sda/sda1"); -print ("query_by_sysfs_path (\"/sys/block/sda1\") -> " + d.get_device_file ()); - -d = client.query_by_subsystem_and_name ("block", "sda2"); -print ("query_by_subsystem_and_name (\"block\", \"sda2\") -> " + d.get_device_file ()); - -d = client.query_by_device_file ("/dev/sda"); -print ("query_by_device_file (\"/dev/sda\") -> " + d.get_device_file ()); - -d = client.query_by_device_file ("/dev/block/8:0"); -print ("query_by_device_file (\"/dev/block/8:0\") -> " + d.get_device_file ()); - -var mainloop = GLib.main_loop_new (); -GLib.main_loop_run (mainloop); diff --git a/src/import/export.c b/src/import/export.c index 201c5ab356..d4bc88e010 100644 --- a/src/import/export.c +++ b/src/import/export.c @@ -23,6 +23,7 @@ #include "sd-event.h" #include "event-util.h" +#include "signal-util.h" #include "verbs.h" #include "build.h" #include "machine-image.h" diff --git a/src/import/import-common.c b/src/import/import-common.c index aede2f9b36..9711614000 100644 --- a/src/import/import-common.c +++ b/src/import/import-common.c @@ -26,6 +26,7 @@ #include "util.h" #include "btrfs-util.h" #include "capability.h" +#include "signal-util.h" #include "import-common.h" int import_make_read_only_fd(int fd) { diff --git a/src/import/import.c b/src/import/import.c index f3072b3775..fff5a104b1 100644 --- a/src/import/import.c +++ b/src/import/import.c @@ -25,6 +25,7 @@ #include "event-util.h" #include "verbs.h" #include "build.h" +#include "signal-util.h" #include "machine-image.h" #include "import-util.h" #include "import-tar.h" diff --git a/src/import/importd.c b/src/import/importd.c index 45d1d93343..50566a6e5c 100644 --- a/src/import/importd.c +++ b/src/import/importd.c @@ -34,6 +34,7 @@ #include "path-util.h" #include "import-util.h" #include "process-util.h" +#include "signal-util.h" typedef struct Transfer Transfer; typedef struct Manager Manager; diff --git a/src/import/pull-common.c b/src/import/pull-common.c index 59091ba7cb..d2588d4fa0 100644 --- a/src/import/pull-common.c +++ b/src/import/pull-common.c @@ -30,6 +30,7 @@ #include "pull-job.h" #include "pull-common.h" #include "process-util.h" +#include "signal-util.h" #define FILENAME_ESCAPE "/.#\"\'" diff --git a/src/import/pull.c b/src/import/pull.c index 0f2ad92187..eec4583868 100644 --- a/src/import/pull.c +++ b/src/import/pull.c @@ -25,6 +25,7 @@ #include "event-util.h" #include "verbs.h" #include "build.h" +#include "signal-util.h" #include "machine-image.h" #include "import-util.h" #include "pull-tar.h" diff --git a/src/journal-remote/journal-remote.c b/src/journal-remote/journal-remote.c index f87a939168..911e2a178b 100644 --- a/src/journal-remote/journal-remote.c +++ b/src/journal-remote/journal-remote.c @@ -30,6 +30,7 @@ #include <getopt.h> #include "sd-daemon.h" +#include "signal-util.h" #include "journal-file.h" #include "journald-native.h" #include "socket-util.h" diff --git a/src/journal-remote/journal-upload.c b/src/journal-remote/journal-upload.c index ddbb8731e2..ddb1ef0396 100644 --- a/src/journal-remote/journal-upload.c +++ b/src/journal-remote/journal-upload.c @@ -33,8 +33,9 @@ #include "mkdir.h" #include "conf-parser.h" #include "sigbus.h" -#include "journal-upload.h" #include "formats-util.h" +#include "signal-util.h" +#include "journal-upload.h" #define PRIV_KEY_FILE CERTIFICATE_ROOT "/private/journal-upload.pem" #define CERT_FILE CERTIFICATE_ROOT "/certs/journal-upload.pem" diff --git a/src/journal/coredumpctl.c b/src/journal/coredumpctl.c index bcb0ff9c39..381bf72776 100644 --- a/src/journal/coredumpctl.c +++ b/src/journal/coredumpctl.c @@ -39,6 +39,7 @@ #include "sigbus.h" #include "process-util.h" #include "terminal-util.h" +#include "signal-util.h" static enum { ACTION_NONE, diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c index b3a4b53080..3353024f4e 100644 --- a/src/journal/journald-server.c +++ b/src/journal/journald-server.c @@ -25,6 +25,10 @@ #include <sys/statvfs.h> #include <sys/mman.h> +#ifdef HAVE_SELINUX +#include <selinux/selinux.h> +#endif + #include <libudev.h> #include "sd-journal.h" @@ -43,6 +47,7 @@ #include "formats-util.h" #include "process-util.h" #include "hostname-util.h" +#include "signal-util.h" #include "journal-internal.h" #include "journal-vacuum.h" #include "journal-authenticate.h" @@ -54,10 +59,6 @@ #include "journald-audit.h" #include "journald-server.h" -#ifdef HAVE_SELINUX -#include <selinux/selinux.h> -#endif - #define USER_JOURNALS_MAX 1024 #define DEFAULT_SYNC_INTERVAL_USEC (5*USEC_PER_MINUTE) diff --git a/src/kernel-install/90-loaderentry.install b/src/kernel-install/90-loaderentry.install index d433e00a5c..4c9b1f0327 100644 --- a/src/kernel-install/90-loaderentry.install +++ b/src/kernel-install/90-loaderentry.install @@ -43,14 +43,14 @@ fi declare -a BOOT_OPTIONS if [[ -f /etc/kernel/cmdline ]]; then - readarray -t BOOT_OPTIONS < /etc/kernel/cmdline + read -r -d '' -a BOOT_OPTIONS < /etc/kernel/cmdline fi if ! [[ ${BOOT_OPTIONS[*]} ]]; then - read -a line -r < /proc/cmdline + read -r -d '' -a line < /proc/cmdline for i in "${line[@]}"; do [[ "${i#initrd=*}" != "$i" ]] && continue - BOOT_OPTIONS[${#BOOT_OPTIONS[@]}]="$i" + BOOT_OPTIONS+=("$i") done fi diff --git a/src/libsystemd-terminal/evcat.c b/src/libsystemd-terminal/evcat.c index d274225ed0..bfa166c489 100644 --- a/src/libsystemd-terminal/evcat.c +++ b/src/libsystemd-terminal/evcat.c @@ -35,19 +35,20 @@ #include <stdlib.h> #include <sys/ioctl.h> #include <sys/stat.h> -#include <systemd/sd-bus.h> -#include <systemd/sd-event.h> -#include <systemd/sd-login.h> #include <termios.h> #include <unistd.h> #include <xkbcommon/xkbcommon.h> +#include "sd-bus.h" +#include "sd-event.h" +#include "sd-login.h" #include "build.h" #include "event-util.h" -#include "idev.h" #include "macro.h" +#include "signal-util.h" +#include "util.h" +#include "idev.h" #include "sysview.h" #include "term-internal.h" -#include "util.h" typedef struct Evcat Evcat; diff --git a/src/libsystemd-terminal/grdev-drm.c b/src/libsystemd-terminal/grdev-drm.c index 01a70fd320..4cee95f469 100644 --- a/src/libsystemd-terminal/grdev-drm.c +++ b/src/libsystemd-terminal/grdev-drm.c @@ -27,8 +27,6 @@ #include <sys/ioctl.h> #include <sys/mman.h> #include <sys/types.h> -#include <systemd/sd-bus.h> -#include <systemd/sd-event.h> #include <unistd.h> /* Yuck! DRM headers need system headers included first.. but we have to @@ -37,12 +35,14 @@ #include <drm_fourcc.h> #include <drm_mode.h> -#include "bus-util.h" +#include "sd-bus.h" +#include "sd-event.h" #include "hashmap.h" -#include "grdev.h" -#include "grdev-internal.h" #include "macro.h" #include "util.h" +#include "bus-util.h" +#include "grdev.h" +#include "grdev-internal.h" #define GRDRM_MAX_TRIES (16) diff --git a/src/libsystemd-terminal/grdev-internal.h b/src/libsystemd-terminal/grdev-internal.h index f455dd4172..46d65f0248 100644 --- a/src/libsystemd-terminal/grdev-internal.h +++ b/src/libsystemd-terminal/grdev-internal.h @@ -25,12 +25,12 @@ #include <libudev.h> #include <stdbool.h> #include <stdlib.h> -#include <systemd/sd-bus.h> -#include <systemd/sd-event.h> -#include "grdev.h" +#include "sd-bus.h" +#include "sd-event.h" #include "hashmap.h" #include "list.h" #include "util.h" +#include "grdev.h" typedef struct grdev_tile grdev_tile; typedef struct grdev_display_cache grdev_display_cache; diff --git a/src/libsystemd-terminal/grdev.c b/src/libsystemd-terminal/grdev.c index feed579295..c386e65982 100644 --- a/src/libsystemd-terminal/grdev.c +++ b/src/libsystemd-terminal/grdev.c @@ -22,14 +22,14 @@ #include <libudev.h> #include <stdbool.h> #include <stdlib.h> -#include <systemd/sd-bus.h> -#include <systemd/sd-event.h> -#include "grdev.h" -#include "grdev-internal.h" +#include "sd-bus.h" +#include "sd-event.h" #include "hashmap.h" #include "login-shared.h" #include "macro.h" #include "util.h" +#include "grdev.h" +#include "grdev-internal.h" static void pipe_enable(grdev_pipe *pipe); static void pipe_disable(grdev_pipe *pipe); diff --git a/src/libsystemd-terminal/grdev.h b/src/libsystemd-terminal/grdev.h index db2a508fd8..110d24e6d5 100644 --- a/src/libsystemd-terminal/grdev.h +++ b/src/libsystemd-terminal/grdev.h @@ -56,8 +56,8 @@ #include <libudev.h> #include <stdbool.h> #include <stdlib.h> -#include <systemd/sd-bus.h> -#include <systemd/sd-event.h> +#include "sd-bus.h" +#include "sd-event.h" #include "util.h" typedef struct grdev_fb grdev_fb; diff --git a/src/libsystemd-terminal/idev-evdev.c b/src/libsystemd-terminal/idev-evdev.c index 64e703eb67..f1a18b91d3 100644 --- a/src/libsystemd-terminal/idev-evdev.c +++ b/src/libsystemd-terminal/idev-evdev.c @@ -24,13 +24,13 @@ #include <libudev.h> #include <stdbool.h> #include <stdlib.h> -#include <systemd/sd-bus.h> -#include <systemd/sd-event.h> +#include "sd-bus.h" +#include "sd-event.h" +#include "macro.h" +#include "util.h" #include "bus-util.h" #include "idev.h" #include "idev-internal.h" -#include "macro.h" -#include "util.h" typedef struct idev_evdev idev_evdev; typedef struct unmanaged_evdev unmanaged_evdev; diff --git a/src/libsystemd-terminal/idev-internal.h b/src/libsystemd-terminal/idev-internal.h index a159aef211..a02a16c408 100644 --- a/src/libsystemd-terminal/idev-internal.h +++ b/src/libsystemd-terminal/idev-internal.h @@ -26,13 +26,13 @@ #include <linux/input.h> #include <stdbool.h> #include <stdlib.h> -#include <systemd/sd-bus.h> -#include <systemd/sd-event.h> #include <xkbcommon/xkbcommon.h> +#include "sd-bus.h" +#include "sd-event.h" #include "hashmap.h" -#include "idev.h" #include "list.h" #include "util.h" +#include "idev.h" typedef struct idev_link idev_link; typedef struct idev_device_vtable idev_device_vtable; diff --git a/src/libsystemd-terminal/idev-keyboard.c b/src/libsystemd-terminal/idev-keyboard.c index ef56ee2482..93f49e9458 100644 --- a/src/libsystemd-terminal/idev-keyboard.c +++ b/src/libsystemd-terminal/idev-keyboard.c @@ -21,17 +21,17 @@ #include <stdbool.h> #include <stdlib.h> -#include <systemd/sd-bus.h> -#include <systemd/sd-event.h> #include <xkbcommon/xkbcommon.h> #include <xkbcommon/xkbcommon-compose.h> -#include "bus-util.h" +#include "sd-bus.h" +#include "sd-event.h" #include "hashmap.h" +#include "macro.h" +#include "util.h" +#include "bus-util.h" #include "idev.h" #include "idev-internal.h" -#include "macro.h" #include "term-internal.h" -#include "util.h" typedef struct kbdtbl kbdtbl; typedef struct kbdmap kbdmap; diff --git a/src/libsystemd-terminal/idev.c b/src/libsystemd-terminal/idev.c index 0ba2b28ab7..b187934977 100644 --- a/src/libsystemd-terminal/idev.c +++ b/src/libsystemd-terminal/idev.c @@ -22,14 +22,14 @@ #include <libudev.h> #include <stdbool.h> #include <stdlib.h> -#include <systemd/sd-bus.h> -#include <systemd/sd-event.h> +#include "sd-bus.h" +#include "sd-event.h" #include "hashmap.h" -#include "idev.h" -#include "idev-internal.h" #include "login-shared.h" #include "macro.h" #include "util.h" +#include "idev.h" +#include "idev-internal.h" static void element_open(idev_element *e); static void element_close(idev_element *e); diff --git a/src/libsystemd-terminal/idev.h b/src/libsystemd-terminal/idev.h index 0e846179e6..241677cbbe 100644 --- a/src/libsystemd-terminal/idev.h +++ b/src/libsystemd-terminal/idev.h @@ -28,9 +28,9 @@ #include <libudev.h> #include <linux/input.h> #include <stdbool.h> -#include <systemd/sd-bus.h> -#include <systemd/sd-event.h> #include <xkbcommon/xkbcommon.h> +#include "sd-bus.h" +#include "sd-event.h" typedef struct idev_data idev_data; typedef struct idev_data_evdev idev_data_evdev; diff --git a/src/libsystemd-terminal/modeset.c b/src/libsystemd-terminal/modeset.c index 621d6c4fa3..f3a60e1fb0 100644 --- a/src/libsystemd-terminal/modeset.c +++ b/src/libsystemd-terminal/modeset.c @@ -35,18 +35,18 @@ #include <stdlib.h> #include <sys/ioctl.h> #include <sys/stat.h> -#include <systemd/sd-bus.h> -#include <systemd/sd-event.h> -#include <systemd/sd-login.h> #include <termios.h> #include <unistd.h> - +#include "sd-bus.h" +#include "sd-event.h" +#include "sd-login.h" #include "build.h" -#include "grdev.h" #include "macro.h" -#include "sysview.h" -#include "util.h" #include "random-util.h" +#include "signal-util.h" +#include "util.h" +#include "grdev.h" +#include "sysview.h" typedef struct Modeset Modeset; diff --git a/src/libsystemd-terminal/subterm.c b/src/libsystemd-terminal/subterm.c index 983a2a14ab..d10e2f549f 100644 --- a/src/libsystemd-terminal/subterm.c +++ b/src/libsystemd-terminal/subterm.c @@ -34,13 +34,14 @@ #include <string.h> #include <sys/ioctl.h> #include <termios.h> +#include "sd-event.h" #include "macro.h" #include "pty.h" #include "ring.h" -#include "sd-event.h" -#include "term-internal.h" -#include "util.h" +#include "signal-util.h" #include "utf8.h" +#include "util.h" +#include "term-internal.h" typedef struct Output Output; typedef struct Terminal Terminal; diff --git a/src/libsystemd-terminal/sysview-internal.h b/src/libsystemd-terminal/sysview-internal.h index f1fd4b5f53..251c8d7300 100644 --- a/src/libsystemd-terminal/sysview-internal.h +++ b/src/libsystemd-terminal/sysview-internal.h @@ -25,13 +25,13 @@ #include <libudev.h> #include <stdbool.h> #include <stdlib.h> -#include <systemd/sd-bus.h> -#include <systemd/sd-event.h> +#include "sd-bus.h" +#include "sd-event.h" #include "hashmap.h" #include "list.h" #include "macro.h" -#include "sysview.h" #include "util.h" +#include "sysview.h" /* * Devices diff --git a/src/libsystemd-terminal/sysview.c b/src/libsystemd-terminal/sysview.c index 1e13167a79..2e9b15859a 100644 --- a/src/libsystemd-terminal/sysview.c +++ b/src/libsystemd-terminal/sysview.c @@ -23,15 +23,15 @@ #include <libudev.h> #include <stdbool.h> #include <stdlib.h> -#include <systemd/sd-bus.h> -#include <systemd/sd-event.h> -#include <systemd/sd-login.h> -#include "bus-util.h" +#include "sd-bus.h" +#include "sd-event.h" +#include "sd-login.h" #include "macro.h" -#include "sysview.h" -#include "sysview-internal.h" #include "udev-util.h" #include "util.h" +#include "bus-util.h" +#include "sysview.h" +#include "sysview-internal.h" static int context_raise_session_control(sysview_context *c, sysview_session *session, int error); @@ -196,7 +196,7 @@ int sysview_session_new(sysview_session **out, sysview_seat *seat, const char *n if (r < 0) return r; - session->custom = false;; + session->custom = false; } else { /* * No session name was given. We assume this is an unmanaged diff --git a/src/libsystemd-terminal/sysview.h b/src/libsystemd-terminal/sysview.h index 71e56e7ebf..a5e7a38df3 100644 --- a/src/libsystemd-terminal/sysview.h +++ b/src/libsystemd-terminal/sysview.h @@ -37,8 +37,8 @@ #pragma once #include <stdbool.h> -#include <systemd/sd-bus.h> -#include <systemd/sd-event.h> +#include "sd-bus.h" +#include "sd-event.h" typedef struct sysview_event sysview_event; typedef struct sysview_device sysview_device; diff --git a/src/libsystemd/sd-bus/bus-kernel.c b/src/libsystemd/sd-bus/bus-kernel.c index d5cc8100ce..417e4d5903 100644 --- a/src/libsystemd/sd-bus/bus-kernel.c +++ b/src/libsystemd/sd-bus/bus-kernel.c @@ -1770,32 +1770,6 @@ int bus_kernel_realize_attach_flags(sd_bus *bus) { return 0; } -int bus_kernel_fix_attach_mask(void) { - _cleanup_free_ char *mask = NULL; - uint64_t m = (uint64_t) -1; - char buf[2+16+2]; - int r; - - /* By default we don't want any kdbus metadata fields to be - * suppressed, hence we reset the kernel mask for it to - * (uint64_t) -1. If the module argument was overwritten by - * the kernel cmdline, we leave it as is. */ - - r = get_proc_cmdline_key("kdbus.attach_flags_mask=", &mask); - if (r < 0) - return log_warning_errno(r, "Failed to read kernel command line: %m"); - - if (r == 0) { - sprintf(buf, "0x%" PRIx64 "\n", m); - r = write_string_file("/sys/module/kdbus/parameters/attach_flags_mask", buf); - if (r < 0) - return log_full_errno(IN_SET(r, -ENOENT, -EROFS) ? LOG_DEBUG : LOG_WARNING, r, - "Failed to write kdbus attach mask: %m"); - } - - return 0; -} - int bus_kernel_get_bus_name(sd_bus *bus, char **name) { struct kdbus_cmd_info cmd = { .size = sizeof(struct kdbus_cmd_info), diff --git a/src/libsystemd/sd-bus/bus-kernel.h b/src/libsystemd/sd-bus/bus-kernel.h index b9f31ba790..bb4dff6d82 100644 --- a/src/libsystemd/sd-bus/bus-kernel.h +++ b/src/libsystemd/sd-bus/bus-kernel.h @@ -90,8 +90,6 @@ int bus_kernel_drop_one(int fd); int bus_kernel_realize_attach_flags(sd_bus *bus); -int bus_kernel_fix_attach_mask(void); - int bus_kernel_get_bus_name(sd_bus *bus, char **name); int bus_kernel_cmd_free(sd_bus *bus, uint64_t offset); diff --git a/src/libsystemd/sd-bus/bus-socket.c b/src/libsystemd/sd-bus/bus-socket.c index 881efb176a..4fffc6581d 100644 --- a/src/libsystemd/sd-bus/bus-socket.c +++ b/src/libsystemd/sd-bus/bus-socket.c @@ -24,12 +24,13 @@ #include <unistd.h> #include <poll.h> +#include "sd-daemon.h" #include "util.h" #include "macro.h" #include "missing.h" #include "utf8.h" -#include "sd-daemon.h" #include "formats-util.h" +#include "signal-util.h" #include "sd-bus.h" #include "bus-socket.h" diff --git a/src/libsystemd/sd-bus/bus-util.c b/src/libsystemd/sd-bus/bus-util.c index 5e375af206..99937799b3 100644 --- a/src/libsystemd/sd-bus/bus-util.c +++ b/src/libsystemd/sd-bus/bus-util.c @@ -30,6 +30,7 @@ #include "path-util.h" #include "missing.h" #include "set.h" +#include "signal-util.h" #include "unit-name.h" #include "sd-bus.h" diff --git a/src/libsystemd/sd-bus/kdbus.h b/src/libsystemd/sd-bus/kdbus.h index fc1d77dd7c..00a6e142c9 100644 --- a/src/libsystemd/sd-bus/kdbus.h +++ b/src/libsystemd/sd-bus/kdbus.h @@ -5,8 +5,8 @@ * your option) any later version. */ -#ifndef _KDBUS_UAPI_H_ -#define _KDBUS_UAPI_H_ +#ifndef _UAPI_KDBUS_H_ +#define _UAPI_KDBUS_H_ #include <linux/ioctl.h> #include <linux/types.h> @@ -544,7 +544,7 @@ struct kdbus_msg_info { * reply to this message. The * KDBUS_CMD_SEND ioctl() will block * until the reply is received, and - * offset_reply in struct kdbus_msg will + * reply in struct kdbus_cmd_send will * yield the offset in the sender's pool * where the reply can be found. * This flag is only valid if @@ -976,4 +976,4 @@ enum kdbus_ioctl_type { struct kdbus_cmd_match), }; -#endif /* _KDBUS_UAPI_H_ */ +#endif /* _UAPI_KDBUS_H_ */ diff --git a/src/libsystemd/sd-bus/test-bus-kernel.c b/src/libsystemd/sd-bus/test-bus-kernel.c index 8f4f60b65f..6506eaab2e 100644 --- a/src/libsystemd/sd-bus/test-bus-kernel.c +++ b/src/libsystemd/sd-bus/test-bus-kernel.c @@ -43,8 +43,6 @@ int main(int argc, char *argv[]) { assert_se(asprintf(&name, "deine-mutter-%u", (unsigned) getpid()) >= 0); - bus_kernel_fix_attach_mask(); - bus_ref = bus_kernel_create_bus(name, false, &bus_name); if (bus_ref == -ENOENT) return EXIT_TEST_SKIP; diff --git a/src/libsystemd/sd-device/device-enumerator.c b/src/libsystemd/sd-device/device-enumerator.c index ce4862d7f0..7fd77e9480 100644 --- a/src/libsystemd/sd-device/device-enumerator.c +++ b/src/libsystemd/sd-device/device-enumerator.c @@ -137,7 +137,6 @@ _public_ int sd_device_enumerator_add_match_sysattr(sd_device_enumerator *enumer assert_return(enumerator, -EINVAL); assert_return(_sysattr, -EINVAL); - assert_return(_value, -EINVAL); if (match) hashmap = &enumerator->match_sysattr; @@ -152,9 +151,11 @@ _public_ int sd_device_enumerator_add_match_sysattr(sd_device_enumerator *enumer if (!sysattr) return -ENOMEM; - value = strdup(_value); - if (!value) - return -ENOMEM; + if (_value) { + value = strdup(_value); + if (!value) + return -ENOMEM; + } r = hashmap_put(*hashmap, sysattr, value); if (r < 0) @@ -174,7 +175,6 @@ _public_ int sd_device_enumerator_add_match_property(sd_device_enumerator *enume assert_return(enumerator, -EINVAL); assert_return(_property, -EINVAL); - assert_return(_value, -EINVAL); r = hashmap_ensure_allocated(&enumerator->match_property, NULL); if (r < 0) @@ -184,9 +184,11 @@ _public_ int sd_device_enumerator_add_match_property(sd_device_enumerator *enume if (!property) return -ENOMEM; - value = strdup(_value); - if (!value) - return -ENOMEM; + if (_value) { + value = strdup(_value); + if (!value) + return -ENOMEM; + } r = hashmap_put(enumerator->match_property, property, value); if (r < 0) @@ -367,11 +369,11 @@ static bool match_sysattr(sd_device_enumerator *enumerator, sd_device *device) { assert(enumerator); assert(device); - HASHMAP_FOREACH_KEY(sysattr, value, enumerator->nomatch_sysattr, i) + HASHMAP_FOREACH_KEY(value, sysattr, enumerator->nomatch_sysattr, i) if (match_sysattr_value(device, sysattr, value)) return false; - HASHMAP_FOREACH_KEY(sysattr, value, enumerator->match_sysattr, i) + HASHMAP_FOREACH_KEY(value, sysattr, enumerator->match_sysattr, i) if (!match_sysattr_value(device, sysattr, value)) return false; @@ -389,7 +391,7 @@ static bool match_property(sd_device_enumerator *enumerator, sd_device *device) if (hashmap_isempty(enumerator->match_property)) return true; - HASHMAP_FOREACH_KEY(property, value, enumerator->match_property, i) { + HASHMAP_FOREACH_KEY(value, property, enumerator->match_property, i) { const char *property_dev, *value_dev; FOREACH_DEVICE_PROPERTY(device, property_dev, value_dev) { diff --git a/src/libsystemd/sd-device/device-private.c b/src/libsystemd/sd-device/device-private.c index 3cadedbf4a..2e60433246 100644 --- a/src/libsystemd/sd-device/device-private.c +++ b/src/libsystemd/sd-device/device-private.c @@ -636,10 +636,10 @@ int device_new_from_nulstr(sd_device **ret, uint8_t *nulstr, size_t len) { static int device_update_properties_bufs(sd_device *device) { const char *val, *prop; - char **buf_strv = NULL; - uint8_t *buf_nulstr = NULL; - size_t allocated_nulstr = 0, allocated_strv = 0; - size_t nulstr_len = 0, strv_size = 0; + _cleanup_free_ char **buf_strv = NULL; + _cleanup_free_ uint8_t *buf_nulstr = NULL; + size_t allocated_nulstr = 0; + size_t nulstr_len = 0, num = 0, i = 0; assert(device); @@ -655,20 +655,29 @@ static int device_update_properties_bufs(sd_device *device) { if (!buf_nulstr) return -ENOMEM; - buf_strv = GREEDY_REALLOC0(buf_strv, allocated_strv, strv_size + 2); - if (!buf_strv) - return -ENOMEM; - - buf_strv[++ strv_size] = (char *)&buf_nulstr[nulstr_len]; strscpyl((char *)buf_nulstr + nulstr_len, len + 1, prop, "=", val, NULL); nulstr_len += len + 1; + ++num; + } + + /* build buf_strv from buf_nulstr */ + buf_strv = new0(char *, num + 1); + if (!buf_strv) + return -ENOMEM; + + NULSTR_FOREACH(val, (char*) buf_nulstr) { + buf_strv[i] = (char *) val; + assert(i < num); + i++; } free(device->properties_nulstr); - free(device->properties_strv); device->properties_nulstr = buf_nulstr; + buf_nulstr = NULL; device->properties_nulstr_len = nulstr_len; + free(device->properties_strv); device->properties_strv = buf_strv; + buf_strv = NULL; device->properties_buf_outdated = false; diff --git a/src/libsystemd/sd-device/sd-device.c b/src/libsystemd/sd-device/sd-device.c index 97da4a8eea..8e63b9ef56 100644 --- a/src/libsystemd/sd-device/sd-device.c +++ b/src/libsystemd/sd-device/sd-device.c @@ -785,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; @@ -901,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; @@ -1188,6 +1191,8 @@ 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', @@ -1209,6 +1214,9 @@ 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 -ENOMEM; @@ -1262,7 +1270,7 @@ int device_read_db_aux(sd_device *device, bool force) { } /* devices with a database entry are initialized */ - device->is_initialized = true;; + device->is_initialized = true; for (i = 0; i < db_len; i++) { switch (state) { diff --git a/src/libsystemd/sd-event/sd-event.c b/src/libsystemd/sd-event/sd-event.c index 0dc4680376..2b8d1b87ed 100644 --- a/src/libsystemd/sd-event/sd-event.c +++ b/src/libsystemd/sd-event/sd-event.c @@ -33,6 +33,7 @@ #include "missing.h" #include "set.h" #include "list.h" +#include "signal-util.h" #include "sd-event.h" @@ -473,6 +474,9 @@ static int source_io_unregister(sd_event_source *s) { assert(s); assert(s->type == SOURCE_IO); + if (event_pid_changed(s->event)) + return 0; + if (!s->io.registered) return 0; @@ -603,6 +607,9 @@ static int event_update_signal_fd(sd_event *e) { assert(e); + if (event_pid_changed(e)) + return 0; + add_to_epoll = e->signal_fd < 0; r = signalfd(e->signal_fd, &e->sigset, SFD_NONBLOCK|SFD_CLOEXEC); diff --git a/src/libsystemd/sd-event/test-event.c b/src/libsystemd/sd-event/test-event.c index 721700be7b..94e98e0077 100644 --- a/src/libsystemd/sd-event/test-event.c +++ b/src/libsystemd/sd-event/test-event.c @@ -23,6 +23,7 @@ #include "log.h" #include "util.h" #include "macro.h" +#include "signal-util.h" static int prepare_handler(sd_event_source *s, void *userdata) { log_info("preparing %c", PTR_TO_INT(userdata)); diff --git a/src/libsystemd/sd-hwdb/sd-hwdb.c b/src/libsystemd/sd-hwdb/sd-hwdb.c index 3bbf02896b..2a0e00f7d2 100644 --- a/src/libsystemd/sd-hwdb/sd-hwdb.c +++ b/src/libsystemd/sd-hwdb/sd-hwdb.c @@ -317,7 +317,7 @@ _public_ int sd_hwdb_new(sd_hwdb **ret) { if (memcmp(hwdb->map, sig, sizeof(hwdb->head->signature)) != 0 || (size_t)hwdb->st.st_size != le64toh(hwdb->head->file_size)) { log_debug("error recognizing the format of %s", hwdb_bin_path); - return -EINVAL;; + return -EINVAL; } log_debug("=== trie on-disk ==="); diff --git a/src/libudev/libudev-device.c b/src/libudev/libudev-device.c index 893d72c19f..c27b01db96 100644 --- a/src/libudev/libudev-device.c +++ b/src/libudev/libudev-device.c @@ -178,7 +178,8 @@ _public_ const char *udev_device_get_subsystem(struct udev_device *udev_device) if (r < 0) { errno = -r; return NULL; - } + } else if (!subsystem) + errno = ENODATA; return subsystem; } diff --git a/src/libudev/libudev-enumerate.c b/src/libudev/libudev-enumerate.c index 255fbe808d..df088946df 100644 --- a/src/libudev/libudev-enumerate.c +++ b/src/libudev/libudev-enumerate.c @@ -196,6 +196,9 @@ _public_ struct udev_list_entry *udev_enumerate_get_list_entry(struct udev_enume _public_ int udev_enumerate_add_match_subsystem(struct udev_enumerate *udev_enumerate, const char *subsystem) { assert_return(udev_enumerate, -EINVAL); + if (!subsystem) + return 0; + return sd_device_enumerator_add_match_subsystem(udev_enumerate->enumerator, subsystem, true); } @@ -211,6 +214,9 @@ _public_ int udev_enumerate_add_match_subsystem(struct udev_enumerate *udev_enum _public_ int udev_enumerate_add_nomatch_subsystem(struct udev_enumerate *udev_enumerate, const char *subsystem) { assert_return(udev_enumerate, -EINVAL); + if (!subsystem) + return 0; + return sd_device_enumerator_add_match_subsystem(udev_enumerate->enumerator, subsystem, false); } @@ -227,6 +233,9 @@ _public_ int udev_enumerate_add_nomatch_subsystem(struct udev_enumerate *udev_en _public_ int udev_enumerate_add_match_sysattr(struct udev_enumerate *udev_enumerate, const char *sysattr, const char *value) { assert_return(udev_enumerate, -EINVAL); + if (!sysattr) + return 0; + return sd_device_enumerator_add_match_sysattr(udev_enumerate->enumerator, sysattr, value, true); } @@ -243,6 +252,9 @@ _public_ int udev_enumerate_add_match_sysattr(struct udev_enumerate *udev_enumer _public_ int udev_enumerate_add_nomatch_sysattr(struct udev_enumerate *udev_enumerate, const char *sysattr, const char *value) { assert_return(udev_enumerate, -EINVAL); + if (!sysattr) + return 0; + return sd_device_enumerator_add_match_sysattr(udev_enumerate->enumerator, sysattr, value, false); } @@ -259,6 +271,9 @@ _public_ int udev_enumerate_add_nomatch_sysattr(struct udev_enumerate *udev_enum _public_ int udev_enumerate_add_match_property(struct udev_enumerate *udev_enumerate, const char *property, const char *value) { assert_return(udev_enumerate, -EINVAL); + if (!property) + return 0; + return sd_device_enumerator_add_match_property(udev_enumerate->enumerator, property, value); } @@ -274,6 +289,9 @@ _public_ int udev_enumerate_add_match_property(struct udev_enumerate *udev_enume _public_ int udev_enumerate_add_match_tag(struct udev_enumerate *udev_enumerate, const char *tag) { assert_return(udev_enumerate, -EINVAL); + if (!tag) + return 0; + return sd_device_enumerator_add_match_tag(udev_enumerate->enumerator, tag); } @@ -335,6 +353,9 @@ _public_ int udev_enumerate_add_match_is_initialized(struct udev_enumerate *udev _public_ int udev_enumerate_add_match_sysname(struct udev_enumerate *udev_enumerate, const char *sysname) { assert_return(udev_enumerate, -EINVAL); + if (!sysname) + return 0; + return sd_device_enumerator_add_match_sysname(udev_enumerate->enumerator, sysname); } diff --git a/src/libudev/libudev-monitor.c b/src/libudev/libudev-monitor.c index b13c579460..282aa2b0d9 100644 --- a/src/libudev/libudev-monitor.c +++ b/src/libudev/libudev-monitor.c @@ -144,6 +144,22 @@ static bool udev_has_devtmpfs(struct udev *udev) { return false; } +static void monitor_set_nl_address(struct udev_monitor *udev_monitor) { + union sockaddr_union snl; + socklen_t addrlen; + int r; + + assert(udev_monitor); + + /* get the address the kernel has assigned us + * it is usually, but not necessarily the pid + */ + addrlen = sizeof(struct sockaddr_nl); + r = getsockname(udev_monitor->sock, &snl.sa, &addrlen); + if (r >= 0) + udev_monitor->snl.nl.nl_pid = snl.nl.nl_pid; +} + struct udev_monitor *udev_monitor_new_from_netlink_fd(struct udev *udev, const char *name, int fd) { struct udev_monitor *udev_monitor; @@ -183,7 +199,7 @@ struct udev_monitor *udev_monitor_new_from_netlink_fd(struct udev *udev, const c if (fd < 0) { udev_monitor->sock = socket(PF_NETLINK, SOCK_RAW|SOCK_CLOEXEC|SOCK_NONBLOCK, NETLINK_KOBJECT_UEVENT); - if (udev_monitor->sock == -1) { + if (udev_monitor->sock < 0) { log_debug_errno(errno, "error getting socket: %m"); free(udev_monitor); return NULL; @@ -191,6 +207,7 @@ struct udev_monitor *udev_monitor_new_from_netlink_fd(struct udev *udev, const c } else { udev_monitor->bound = true; udev_monitor->sock = fd; + monitor_set_nl_address(udev_monitor); } udev_monitor->snl.nl.nl_family = AF_NETLINK; @@ -366,6 +383,7 @@ int udev_monitor_allow_unicast_sender(struct udev_monitor *udev_monitor, struct udev_monitor->snl_trusted_sender.nl.nl_pid = sender->snl.nl.nl_pid; return 0; } + /** * udev_monitor_enable_receiving: * @udev_monitor: the monitor which should receive events @@ -388,19 +406,9 @@ _public_ int udev_monitor_enable_receiving(struct udev_monitor *udev_monitor) udev_monitor->bound = true; } - if (err >= 0) { - union sockaddr_union snl; - socklen_t addrlen; - - /* - * get the address the kernel has assigned us - * it is usually, but not necessarily the pid - */ - addrlen = sizeof(struct sockaddr_nl); - err = getsockname(udev_monitor->sock, &snl.sa, &addrlen); - if (err == 0) - udev_monitor->snl.nl.nl_pid = snl.nl.nl_pid; - } else { + if (err >= 0) + monitor_set_nl_address(udev_monitor); + else { log_debug_errno(errno, "bind failed: %m"); return -errno; } diff --git a/src/login/71-seat.rules.in b/src/login/71-seat.rules.in index ad26acbbb3..ab7b66f651 100644 --- a/src/login/71-seat.rules.in +++ b/src/login/71-seat.rules.in @@ -11,6 +11,7 @@ TAG=="uaccess", SUBSYSTEM!="sound", TAG+="seat" SUBSYSTEM=="sound", KERNEL=="card*", TAG+="seat" SUBSYSTEM=="input", KERNEL=="input*", TAG+="seat" SUBSYSTEM=="graphics", KERNEL=="fb[0-9]*", TAG+="seat", TAG+="master-of-seat" +SUBSYSTEM=="drm", KERNEL=="card[0-9]*", TAG+="seat", TAG+="master-of-seat" SUBSYSTEM=="usb", ATTR{bDeviceClass}=="09", TAG+="seat" # 'Plugable' USB hub, sound, network, graphics adapter diff --git a/src/login/loginctl.c b/src/login/loginctl.c index 4a5a618472..02d240c704 100644 --- a/src/login/loginctl.c +++ b/src/login/loginctl.c @@ -43,6 +43,7 @@ #include "verbs.h" #include "process-util.h" #include "terminal-util.h" +#include "signal-util.h" static char **arg_property = NULL; static bool arg_all = false; diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c index 10a9df0961..b272401e5b 100644 --- a/src/login/logind-dbus.c +++ b/src/login/logind-dbus.c @@ -2522,6 +2522,7 @@ int match_job_removed(sd_bus_message *message, void *userdata, sd_bus_error *err session_jobs_reply(session, unit, result); session_save(session); + user_save(session->user); session_add_to_gc_queue(session); } diff --git a/src/login/logind-user.c b/src/login/logind-user.c index 71bff96728..dc3db9abda 100644 --- a/src/login/logind-user.c +++ b/src/login/logind-user.c @@ -320,7 +320,7 @@ static int user_mkdir_runtime_path(User *u) { } else p = u->runtime_path; - if (path_is_mount_point(p, false) <= 0) { + if (path_is_mount_point(p, 0) <= 0) { _cleanup_free_ char *t = NULL; (void) mkdir(p, 0700); diff --git a/src/login/logind.c b/src/login/logind.c index 5e66cb924e..00f8dbdab2 100644 --- a/src/login/logind.c +++ b/src/login/logind.c @@ -30,9 +30,10 @@ #include "conf-parser.h" #include "bus-util.h" #include "bus-error.h" -#include "logind.h" #include "udev-util.h" #include "formats-util.h" +#include "signal-util.h" +#include "logind.h" static void manager_free(Manager *m); diff --git a/src/machine/machinectl.c b/src/machine/machinectl.c index b21a33941a..c86c36c2de 100644 --- a/src/machine/machinectl.c +++ b/src/machine/machinectl.c @@ -54,6 +54,7 @@ #include "import-util.h" #include "process-util.h" #include "terminal-util.h" +#include "signal-util.h" static char **arg_property = NULL; static bool arg_all = false; diff --git a/src/machine/machined.c b/src/machine/machined.c index 1e862ad8f2..754c770040 100644 --- a/src/machine/machined.c +++ b/src/machine/machined.c @@ -28,9 +28,10 @@ #include "bus-util.h" #include "bus-error.h" #include "label.h" +#include "formats-util.h" +#include "signal-util.h" #include "machine-image.h" #include "machined.h" -#include "formats-util.h" Manager *manager_new(void) { Manager *m; diff --git a/src/network/networkctl.c b/src/network/networkctl.c index 69b4ab4a5c..3454394977 100644 --- a/src/network/networkctl.c +++ b/src/network/networkctl.c @@ -62,7 +62,7 @@ static int link_get_type_string(int iftype, sd_device *d, char **ret) { assert(ret); if (iftype == ARPHRD_ETHER && d) { - const char *devtype, *id = NULL; + const char *devtype = NULL, *id = NULL; /* WLANs have iftype ARPHRD_ETHER, but we want * to show a more useful type string for * them */ diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index f039a2d687..b30fd7ae89 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -1481,6 +1481,9 @@ static int link_set_ipv4_forward(Link *link) { const char *p = NULL; int r; + if (link->network->ip_forward == ADDRESS_FAMILY_KERNEL) + return 0; + p = strjoina("/proc/sys/net/ipv4/conf/", link->ifname, "/forwarding"); r = write_string_file_no_create(p, one_zero(link_ipv4_forward_enabled(link))); if (r < 0) @@ -1497,6 +1500,9 @@ static int link_set_ipv6_forward(Link *link) { if (!socket_ipv6_is_supported()) return 0; + if (link->network->ip_forward == ADDRESS_FAMILY_KERNEL) + return 0; + p = strjoina("/proc/sys/net/ipv6/conf/", link->ifname, "/forwarding"); r = write_string_file_no_create(p, one_zero(link_ipv6_forward_enabled(link))); if (r < 0) diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c index db737ad484..2cc53df4b1 100644 --- a/src/network/networkd-manager.c +++ b/src/network/networkd-manager.c @@ -853,6 +853,8 @@ const char *address_family_boolean_to_string(AddressFamilyBoolean b) { return "ipv4"; if (b == ADDRESS_FAMILY_IPV6) return "ipv6"; + if (b == ADDRESS_FAMILY_KERNEL) + return "kernel"; return NULL; } @@ -872,6 +874,8 @@ AddressFamilyBoolean address_family_boolean_from_string(const char *s) { return ADDRESS_FAMILY_IPV4; if (streq(s, "ipv6")) return ADDRESS_FAMILY_IPV6; + if (streq(s, "kernel")) + return ADDRESS_FAMILY_KERNEL; return _ADDRESS_FAMILY_BOOLEAN_INVALID; } diff --git a/src/network/networkd-wait-online.c b/src/network/networkd-wait-online.c index f0ca6def87..6a96f1de55 100644 --- a/src/network/networkd-wait-online.c +++ b/src/network/networkd-wait-online.c @@ -21,11 +21,10 @@ #include <getopt.h> #include "sd-daemon.h" - -#include "networkd-wait-online.h" - #include "strv.h" #include "build.h" +#include "signal-util.h" +#include "networkd-wait-online.h" static bool arg_quiet = false; static usec_t arg_timeout = 120 * USEC_PER_SEC; diff --git a/src/network/networkd.c b/src/network/networkd.c index 543a4e4d95..41ec7cf904 100644 --- a/src/network/networkd.c +++ b/src/network/networkd.c @@ -19,9 +19,9 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ -#include "capability.h" #include "sd-daemon.h" - +#include "capability.h" +#include "signal-util.h" #include "networkd.h" int main(int argc, char *argv[]) { diff --git a/src/network/networkd.h b/src/network/networkd.h index 4b13d4aed1..49afeffe81 100644 --- a/src/network/networkd.h +++ b/src/network/networkd.h @@ -60,6 +60,7 @@ typedef enum AddressFamilyBoolean { ADDRESS_FAMILY_IPV4 = 1, ADDRESS_FAMILY_IPV6 = 2, ADDRESS_FAMILY_YES = 3, + ADDRESS_FAMILY_KERNEL = 4, _ADDRESS_FAMILY_BOOLEAN_MAX, _ADDRESS_FAMILY_BOOLEAN_INVALID = -1, } AddressFamilyBoolean; diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index 23bb959171..4211a3d779 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -96,6 +96,7 @@ #include "process-util.h" #include "terminal-util.h" #include "hostname-util.h" +#include "signal-util.h" #ifdef HAVE_SECCOMP #include "seccomp-util.h" @@ -1099,7 +1100,7 @@ static int mount_all(const char *dest, bool userns) { if (!where) return log_oom(); - r = path_is_mount_point(where, true); + r = path_is_mount_point(where, AT_SYMLINK_FOLLOW); if (r < 0 && r != -ENOENT) return log_error_errno(r, "Failed to detect whether %s is a mount point: %m", where); @@ -1298,7 +1299,7 @@ static int mount_cgroup_hierarchy(const char *dest, const char *controller, cons to = strjoina(dest, "/sys/fs/cgroup/", hierarchy); - r = path_is_mount_point(to, false); + r = path_is_mount_point(to, 0); if (r < 0 && r != -ENOENT) return log_error_errno(r, "Failed to determine if %s is mounted already: %m", to); if (r > 0) @@ -2154,7 +2155,7 @@ static int setup_journal(const char *directory) { p = strjoina("/var/log/journal/", id); q = prefix_roota(directory, p); - if (path_is_mount_point(p, false) > 0) { + if (path_is_mount_point(p, 0) > 0) { if (arg_link_journal != LINK_AUTO) { log_error("%s: already a mount point, refusing to use for journal", p); return -EEXIST; @@ -2163,7 +2164,7 @@ static int setup_journal(const char *directory) { return 0; } - if (path_is_mount_point(q, false) > 0) { + if (path_is_mount_point(q, 0) > 0) { if (arg_link_journal != LINK_AUTO) { log_error("%s: already a mount point, refusing to use for journal", q); return -EEXIST; @@ -4507,7 +4508,7 @@ int main(int argc, char *argv[]) { * the specified is not a mount point we * create the new snapshot in the parent * directory, just next to it. */ - r = path_is_mount_point(arg_directory, false); + r = path_is_mount_point(arg_directory, 0); if (r < 0) { log_error_errno(r, "Failed to determine whether directory %s is mount point: %m", arg_directory); goto finish; diff --git a/src/python-systemd/docs/layout.html b/src/python-systemd/docs/layout.html index be5ff980ef..930a6a7afe 100644 --- a/src/python-systemd/docs/layout.html +++ b/src/python-systemd/docs/layout.html @@ -4,8 +4,6 @@ <a href="../man/systemd.index.html">Index </a>· <a href="../man/systemd.directives.html">Directives </a>· <a href="index.html">Python </a>· - <a href="../libudev/index.html">libudev </a>· - <a href="../libudev/index.html">gudev </a> <span style="float:right">systemd {{release}}</span> <hr /> {% endblock %} diff --git a/src/remount-fs/remount-fs.c b/src/remount-fs/remount-fs.c index a09531b26f..e701fc9fae 100644 --- a/src/remount-fs/remount-fs.c +++ b/src/remount-fs/remount-fs.c @@ -29,6 +29,7 @@ #include "log.h" #include "util.h" #include "path-util.h" +#include "signal-util.h" #include "mount-setup.h" #include "exit-status.h" diff --git a/src/resolve/resolved.c b/src/resolve/resolved.c index 271247ca3f..e283d8a749 100644 --- a/src/resolve/resolved.c +++ b/src/resolve/resolved.c @@ -24,6 +24,7 @@ #include "mkdir.h" #include "capability.h" #include "selinux-util.h" +#include "signal-util.h" #include "resolved-manager.h" #include "resolved-conf.h" diff --git a/src/run/run.c b/src/run/run.c index fcd6b06f7d..5b9f31c4aa 100644 --- a/src/run/run.c +++ b/src/run/run.c @@ -35,6 +35,7 @@ #include "calendarspec.h" #include "ptyfwd.h" #include "formats-util.h" +#include "signal-util.h" static bool arg_scope = false; static bool arg_remain_after_exit = false; diff --git a/src/shared/ask-password-api.c b/src/shared/ask-password-api.c index a3a2e51bb9..ef3788be68 100644 --- a/src/shared/ask-password-api.c +++ b/src/shared/ask-password-api.c @@ -37,7 +37,7 @@ #include "strv.h" #include "random-util.h" #include "terminal-util.h" - +#include "signal-util.h" #include "ask-password-api.h" static void backspace_chars(int ttyfd, size_t p) { diff --git a/src/shared/cgroup-util.c b/src/shared/cgroup-util.c index c0b0ca4cf2..9988e5c574 100644 --- a/src/shared/cgroup-util.c +++ b/src/shared/cgroup-util.c @@ -489,7 +489,7 @@ int cg_get_path(const char *controller, const char *path, const char *suffix, ch if (_unlikely_(!good)) { int r; - r = path_is_mount_point("/sys/fs/cgroup", false); + r = path_is_mount_point("/sys/fs/cgroup", 0); if (r < 0) return r; if (r == 0) diff --git a/src/shared/condition.c b/src/shared/condition.c index 9f2574c2f6..24871b0dae 100644 --- a/src/shared/condition.c +++ b/src/shared/condition.c @@ -349,7 +349,7 @@ static int condition_test_path_is_mount_point(Condition *c) { assert(c->parameter); assert(c->type == CONDITION_PATH_IS_MOUNT_POINT); - return path_is_mount_point(c->parameter, true) > 0; + return path_is_mount_point(c->parameter, AT_SYMLINK_FOLLOW) > 0; } static int condition_test_path_is_read_write(Condition *c) { diff --git a/src/shared/conf-parser.c b/src/shared/conf-parser.c index 2c855157a9..7370c786f9 100644 --- a/src/shared/conf-parser.c +++ b/src/shared/conf-parser.c @@ -444,7 +444,7 @@ int config_parse_many(const char *conf_file, if (r < 0) \ log_syntax(unit, LOG_ERR, filename, line, -r, \ "Failed to parse %s value, ignoring: %s", \ - #vartype, rvalue); \ + #type, rvalue); \ \ return 0; \ } diff --git a/src/shared/log.c b/src/shared/log.c index 6168a2955d..b96afc4de4 100644 --- a/src/shared/log.c +++ b/src/shared/log.c @@ -38,6 +38,7 @@ #include "formats-util.h" #include "process-util.h" #include "terminal-util.h" +#include "signal-util.h" #define SNDBUF_SIZE (8*1024*1024) diff --git a/src/shared/machine-pool.c b/src/shared/machine-pool.c index 9920d150ab..d27931cb4a 100644 --- a/src/shared/machine-pool.c +++ b/src/shared/machine-pool.c @@ -30,6 +30,7 @@ #include "mkdir.h" #include "btrfs-util.h" #include "path-util.h" +#include "signal-util.h" #include "machine-pool.h" #define VAR_LIB_MACHINES_SIZE_START (1024UL*1024UL*500UL) @@ -198,7 +199,7 @@ int setup_machine_directory(uint64_t size, sd_bus_error *error) { return 0; } - if (path_is_mount_point("/var/lib/machines", true) > 0 || + if (path_is_mount_point("/var/lib/machines", AT_SYMLINK_FOLLOW) > 0 || dir_is_empty("/var/lib/machines") == 0) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "/var/lib/machines is not a btrfs file system. Operation is not supported on legacy file systems."); diff --git a/src/shared/missing.h b/src/shared/missing.h index 9194009491..be7f6186fc 100644 --- a/src/shared/missing.h +++ b/src/shared/missing.h @@ -269,6 +269,11 @@ struct btrfs_qgroup_inherit { __u64 qgroups[0]; }; +struct btrfs_ioctl_qgroup_limit_args { + __u64 qgroupid; + struct btrfs_qgroup_limit lim; +}; + struct btrfs_ioctl_vol_args_v2 { __s64 fd; __u64 transid; @@ -360,6 +365,14 @@ struct btrfs_ioctl_clone_range_args { __u64 src_offset, src_length; __u64 dest_offset; }; + +#define BTRFS_QUOTA_CTL_ENABLE 1 +#define BTRFS_QUOTA_CTL_DISABLE 2 +#define BTRFS_QUOTA_CTL_RESCAN__NOTUSED 3 +struct btrfs_ioctl_quota_ctl_args { + __u64 cmd; + __u64 status; +}; #endif #ifndef BTRFS_IOC_DEFRAG @@ -367,6 +380,11 @@ struct btrfs_ioctl_clone_range_args { struct btrfs_ioctl_vol_args) #endif +#ifndef BTRFS_IOC_RESIZE +#define BTRFS_IOC_RESIZE _IOW(BTRFS_IOCTL_MAGIC, 3, \ + struct btrfs_ioctl_vol_args) +#endif + #ifndef BTRFS_IOC_CLONE #define BTRFS_IOC_CLONE _IOW(BTRFS_IOCTL_MAGIC, 9, int) #endif @@ -424,6 +442,16 @@ struct btrfs_ioctl_clone_range_args { struct btrfs_ioctl_vol_args) #endif +#ifndef BTRFS_IOC_QUOTA_CTL +#define BTRFS_IOC_QUOTA_CTL _IOWR(BTRFS_IOCTL_MAGIC, 40, \ + struct btrfs_ioctl_quota_ctl_args) +#endif + +#ifndef BTRFS_IOC_QGROUP_LIMIT +#define BTRFS_IOC_QGROUP_LIMIT _IOR(BTRFS_IOCTL_MAGIC, 43, \ + struct btrfs_ioctl_qgroup_limit_args) +#endif + #ifndef BTRFS_FIRST_FREE_OBJECTID #define BTRFS_FIRST_FREE_OBJECTID 256 #endif diff --git a/src/shared/path-util.c b/src/shared/path-util.c index 7090989fcb..be50a1865d 100644 --- a/src/shared/path-util.c +++ b/src/shared/path-util.c @@ -509,7 +509,7 @@ static int fd_fdinfo_mnt_id(int fd, const char *filename, int flags, int *mnt_id return safe_atoi(p, mnt_id); } -int fd_is_mount_point(int fd) { +int fd_is_mount_point(int fd, const char *filename, int flags) { union file_handle_union h = FILE_HANDLE_INIT, h_parent = FILE_HANDLE_INIT; int mount_id = -1, mount_id_parent = -1; bool nosupp = false, check_st_dev = true; @@ -517,6 +517,7 @@ int fd_is_mount_point(int fd) { int r; assert(fd >= 0); + assert(filename); /* First we will try the name_to_handle_at() syscall, which * tells us the mount id and an opaque file "handle". It is @@ -541,7 +542,7 @@ int fd_is_mount_point(int fd) { * subvolumes have different st_dev, even though they aren't * real mounts of their own. */ - r = name_to_handle_at(fd, "", &h.handle, &mount_id, AT_EMPTY_PATH); + r = name_to_handle_at(fd, filename, &h.handle, &mount_id, flags); if (r < 0) { if (errno == ENOSYS) /* This kernel does not support name_to_handle_at() @@ -558,7 +559,7 @@ int fd_is_mount_point(int fd) { return -errno; } - r = name_to_handle_at(fd, "..", &h_parent.handle, &mount_id_parent, 0); + r = name_to_handle_at(fd, "", &h_parent.handle, &mount_id_parent, AT_EMPTY_PATH); if (r < 0) { if (errno == EOPNOTSUPP) { if (nosupp) @@ -593,13 +594,13 @@ int fd_is_mount_point(int fd) { return mount_id != mount_id_parent; fallback_fdinfo: - r = fd_fdinfo_mnt_id(fd, "", AT_EMPTY_PATH, &mount_id); + r = fd_fdinfo_mnt_id(fd, filename, flags, &mount_id); if (r == -EOPNOTSUPP) goto fallback_fstat; if (r < 0) return r; - r = fd_fdinfo_mnt_id(fd, "..", 0, &mount_id_parent); + r = fd_fdinfo_mnt_id(fd, "", AT_EMPTY_PATH, &mount_id_parent); if (r < 0) return r; @@ -615,10 +616,16 @@ fallback_fdinfo: check_st_dev = false; fallback_fstat: - if (fstatat(fd, "", &a, AT_EMPTY_PATH) < 0) + /* yay for fstatat() taking a different set of flags than the other + * _at() above */ + if (flags & AT_SYMLINK_FOLLOW) + flags &= ~AT_SYMLINK_FOLLOW; + else + flags |= AT_SYMLINK_NOFOLLOW; + if (fstatat(fd, filename, &a, flags) < 0) return -errno; - if (fstatat(fd, "..", &b, 0) < 0) + if (fstatat(fd, "", &b, AT_EMPTY_PATH) < 0) return -errno; /* A directory with same device and inode as its parent? Must @@ -630,19 +637,26 @@ fallback_fstat: return check_st_dev && (a.st_dev != b.st_dev); } -int path_is_mount_point(const char *t, bool allow_symlink) { +/* flags can be AT_SYMLINK_FOLLOW or 0 */ +int path_is_mount_point(const char *t, int flags) { _cleanup_close_ int fd = -1; + _cleanup_free_ char *parent = NULL; + int r; assert(t); if (path_equal(t, "/")) return 1; - fd = openat(AT_FDCWD, t, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|(allow_symlink ? 0 : O_PATH)); + r = path_get_parent(t, &parent); + if (r < 0) + return r; + + fd = openat(AT_FDCWD, parent, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_PATH); if (fd < 0) return -errno; - return fd_is_mount_point(fd); + return fd_is_mount_point(fd, basename(t), flags); } int path_is_read_only_fs(const char *path) { diff --git a/src/shared/path-util.h b/src/shared/path-util.h index 4f45cfd2b7..1eac89c51b 100644 --- a/src/shared/path-util.h +++ b/src/shared/path-util.h @@ -53,8 +53,8 @@ char** path_strv_make_absolute_cwd(char **l); char** path_strv_resolve(char **l, const char *prefix); char** path_strv_resolve_uniq(char **l, const char *prefix); -int fd_is_mount_point(int fd); -int path_is_mount_point(const char *path, bool allow_symlink); +int fd_is_mount_point(int fd, const char *filename, int flags); +int path_is_mount_point(const char *path, int flags); int path_is_read_only_fs(const char *path); int path_is_os_tree(const char *path); diff --git a/src/shared/process-util.c b/src/shared/process-util.c index 92a69f50e7..cfc876567d 100644 --- a/src/shared/process-util.c +++ b/src/shared/process-util.c @@ -28,10 +28,11 @@ #include <signal.h> #include <ctype.h> -#include "process-util.h" #include "fileio.h" #include "util.h" #include "log.h" +#include "signal-util.h" +#include "process-util.h" int get_process_state(pid_t pid) { const char *p; diff --git a/src/shared/pty.c b/src/shared/pty.c index 0f80f4863b..119d66e9a2 100644 --- a/src/shared/pty.c +++ b/src/shared/pty.c @@ -57,9 +57,10 @@ #include "barrier.h" #include "macro.h" -#include "pty.h" #include "ring.h" #include "util.h" +#include "signal-util.h" +#include "pty.h" #define PTY_BUFSIZE 4096 diff --git a/src/shared/random-util.c b/src/shared/random-util.c index 88f5182508..b230044f50 100644 --- a/src/shared/random-util.c +++ b/src/shared/random-util.c @@ -23,7 +23,9 @@ #include <sys/stat.h> #include <fcntl.h> #include <time.h> +#ifdef HAVE_SYS_AUXV_H #include <sys/auxv.h> +#endif #include <linux/random.h> #include "random-util.h" diff --git a/src/shared/rm-rf.c b/src/shared/rm-rf.c index a89e8afc2a..bafd483be2 100644 --- a/src/shared/rm-rf.c +++ b/src/shared/rm-rf.c @@ -103,7 +103,7 @@ int rm_rf_children(int fd, RemoveFlags flags, struct stat *root_dev) { } /* Stop at mount points */ - r = fd_is_mount_point(subdir_fd); + r = fd_is_mount_point(fd, de->d_name, 0); if (r < 0) { if (ret == 0 && r != -ENOENT) ret = r; diff --git a/src/shared/signal-util.c b/src/shared/signal-util.c new file mode 100644 index 0000000000..9a2973b6fd --- /dev/null +++ b/src/shared/signal-util.c @@ -0,0 +1,228 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +/*** + This file is part of systemd. + + Copyright 2015 Lennart Poettering + + 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 "util.h" +#include "signal-util.h" + +int reset_all_signal_handlers(void) { + int sig, r = 0; + + for (sig = 1; sig < _NSIG; sig++) { + static const struct sigaction sa = { + .sa_handler = SIG_DFL, + .sa_flags = SA_RESTART, + }; + + /* These two cannot be caught... */ + if (sig == SIGKILL || sig == SIGSTOP) + continue; + + /* On Linux the first two RT signals are reserved by + * glibc, and sigaction() will return EINVAL for them. */ + if ((sigaction(sig, &sa, NULL) < 0)) + if (errno != EINVAL && r == 0) + r = -errno; + } + + return r; +} + +int reset_signal_mask(void) { + sigset_t ss; + + if (sigemptyset(&ss) < 0) + return -errno; + + if (sigprocmask(SIG_SETMASK, &ss, NULL) < 0) + return -errno; + + return 0; +} + +int sigaction_many(const struct sigaction *sa, ...) { + va_list ap; + int r = 0, sig; + + va_start(ap, sa); + while ((sig = va_arg(ap, int)) > 0) + if (sigaction(sig, sa, NULL) < 0) + r = -errno; + va_end(ap); + + return r; +} + +int ignore_signals(int sig, ...) { + static const struct sigaction sa = { + .sa_handler = SIG_IGN, + .sa_flags = SA_RESTART, + }; + va_list ap; + int r = 0; + + if (sigaction(sig, &sa, NULL) < 0) + r = -errno; + + va_start(ap, sig); + while ((sig = va_arg(ap, int)) > 0) + if (sigaction(sig, &sa, NULL) < 0) + r = -errno; + va_end(ap); + + return r; +} + +int default_signals(int sig, ...) { + static const struct sigaction sa = { + .sa_handler = SIG_DFL, + .sa_flags = SA_RESTART, + }; + va_list ap; + int r = 0; + + if (sigaction(sig, &sa, NULL) < 0) + r = -errno; + + va_start(ap, sig); + while ((sig = va_arg(ap, int)) > 0) + if (sigaction(sig, &sa, NULL) < 0) + r = -errno; + va_end(ap); + + return r; +} + +void sigset_add_many(sigset_t *ss, ...) { + va_list ap; + int sig; + + assert(ss); + + va_start(ap, ss); + while ((sig = va_arg(ap, int)) > 0) + assert_se(sigaddset(ss, sig) == 0); + va_end(ap); +} + +int sigprocmask_many(int how, ...) { + va_list ap; + sigset_t ss; + int sig; + + assert_se(sigemptyset(&ss) == 0); + + va_start(ap, how); + while ((sig = va_arg(ap, int)) > 0) + assert_se(sigaddset(&ss, sig) == 0); + va_end(ap); + + if (sigprocmask(how, &ss, NULL) < 0) + return -errno; + + return 0; +} + +static const char *const __signal_table[] = { + [SIGHUP] = "HUP", + [SIGINT] = "INT", + [SIGQUIT] = "QUIT", + [SIGILL] = "ILL", + [SIGTRAP] = "TRAP", + [SIGABRT] = "ABRT", + [SIGBUS] = "BUS", + [SIGFPE] = "FPE", + [SIGKILL] = "KILL", + [SIGUSR1] = "USR1", + [SIGSEGV] = "SEGV", + [SIGUSR2] = "USR2", + [SIGPIPE] = "PIPE", + [SIGALRM] = "ALRM", + [SIGTERM] = "TERM", +#ifdef SIGSTKFLT + [SIGSTKFLT] = "STKFLT", /* Linux on SPARC doesn't know SIGSTKFLT */ +#endif + [SIGCHLD] = "CHLD", + [SIGCONT] = "CONT", + [SIGSTOP] = "STOP", + [SIGTSTP] = "TSTP", + [SIGTTIN] = "TTIN", + [SIGTTOU] = "TTOU", + [SIGURG] = "URG", + [SIGXCPU] = "XCPU", + [SIGXFSZ] = "XFSZ", + [SIGVTALRM] = "VTALRM", + [SIGPROF] = "PROF", + [SIGWINCH] = "WINCH", + [SIGIO] = "IO", + [SIGPWR] = "PWR", + [SIGSYS] = "SYS" +}; + +DEFINE_PRIVATE_STRING_TABLE_LOOKUP(__signal, int); + +const char *signal_to_string(int signo) { + static thread_local char buf[sizeof("RTMIN+")-1 + DECIMAL_STR_MAX(int) + 1]; + const char *name; + + name = __signal_to_string(signo); + if (name) + return name; + + if (signo >= SIGRTMIN && signo <= SIGRTMAX) + snprintf(buf, sizeof(buf), "RTMIN+%d", signo - SIGRTMIN); + else + snprintf(buf, sizeof(buf), "%d", signo); + + return buf; +} + +int signal_from_string(const char *s) { + int signo; + int offset = 0; + unsigned u; + + signo = __signal_from_string(s); + if (signo > 0) + return signo; + + if (startswith(s, "RTMIN+")) { + s += 6; + offset = SIGRTMIN; + } + if (safe_atou(s, &u) >= 0) { + signo = (int) u + offset; + if (signo > 0 && signo < _NSIG) + return signo; + } + return -EINVAL; +} + +int signal_from_string_try_harder(const char *s) { + int signo; + assert(s); + + signo = signal_from_string(s); + if (signo <= 0) + if (startswith(s, "SIG")) + return signal_from_string(s+3); + + return signo; +} diff --git a/src/shared/signal-util.h b/src/shared/signal-util.h new file mode 100644 index 0000000000..ddf64cda76 --- /dev/null +++ b/src/shared/signal-util.h @@ -0,0 +1,41 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +#pragma once + +/*** + This file is part of systemd. + + Copyright 2010-2015 Lennart Poettering + + 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 <signal.h> + +#include "macro.h" + +int reset_all_signal_handlers(void); +int reset_signal_mask(void); + +int ignore_signals(int sig, ...); +int default_signals(int sig, ...); +int sigaction_many(const struct sigaction *sa, ...); + +void sigset_add_many(sigset_t *ss, ...); +int sigprocmask_many(int how, ...); + +const char *signal_to_string(int i) _const_; +int signal_from_string(const char *s) _pure_; + +int signal_from_string_try_harder(const char *s); diff --git a/src/shared/util.c b/src/shared/util.c index 74a2190031..311acbb349 100644 --- a/src/shared/util.c +++ b/src/shared/util.c @@ -93,6 +93,7 @@ #include "random-util.h" #include "terminal-util.h" #include "hostname-util.h" +#include "signal-util.h" /* Put this test here for a lack of better place */ assert_cc(EAGAIN == EWOULDBLOCK); @@ -771,41 +772,6 @@ int readlink_and_canonicalize(const char *p, char **r) { return 0; } -int reset_all_signal_handlers(void) { - int sig, r = 0; - - for (sig = 1; sig < _NSIG; sig++) { - struct sigaction sa = { - .sa_handler = SIG_DFL, - .sa_flags = SA_RESTART, - }; - - /* These two cannot be caught... */ - if (sig == SIGKILL || sig == SIGSTOP) - continue; - - /* On Linux the first two RT signals are reserved by - * glibc, and sigaction() will return EINVAL for them. */ - if ((sigaction(sig, &sa, NULL) < 0)) - if (errno != EINVAL && r == 0) - r = -errno; - } - - return r; -} - -int reset_signal_mask(void) { - sigset_t ss; - - if (sigemptyset(&ss) < 0) - return -errno; - - if (sigprocmask(SIG_SETMASK, &ss, NULL) < 0) - return -errno; - - return 0; -} - char *strstrip(char *s) { char *e; @@ -1186,7 +1152,7 @@ static int cunescape_one(const char *p, size_t length, char *ret, uint32_t *ret_ int a, b, c; uint32_t m; - if (length != (size_t) -1 && length < 4) + if (length != (size_t) -1 && length < 3) return -EINVAL; a = unoctchar(p[0]); @@ -1561,59 +1527,6 @@ int flush_fd(int fd) { } } -int sigaction_many(const struct sigaction *sa, ...) { - va_list ap; - int r = 0, sig; - - va_start(ap, sa); - while ((sig = va_arg(ap, int)) > 0) - if (sigaction(sig, sa, NULL) < 0) - r = -errno; - va_end(ap); - - return r; -} - -int ignore_signals(int sig, ...) { - struct sigaction sa = { - .sa_handler = SIG_IGN, - .sa_flags = SA_RESTART, - }; - va_list ap; - int r = 0; - - if (sigaction(sig, &sa, NULL) < 0) - r = -errno; - - va_start(ap, sig); - while ((sig = va_arg(ap, int)) > 0) - if (sigaction(sig, &sa, NULL) < 0) - r = -errno; - va_end(ap); - - return r; -} - -int default_signals(int sig, ...) { - struct sigaction sa = { - .sa_handler = SIG_DFL, - .sa_flags = SA_RESTART, - }; - va_list ap; - int r = 0; - - if (sigaction(sig, &sa, NULL) < 0) - r = -errno; - - va_start(ap, sig); - while ((sig = va_arg(ap, int)) > 0) - if (sigaction(sig, &sa, NULL) < 0) - r = -errno; - va_end(ap); - - return r; -} - void safe_close_pair(int p[]) { assert(p); @@ -1927,35 +1840,6 @@ void rename_process(const char name[8]) { } } -void sigset_add_many(sigset_t *ss, ...) { - va_list ap; - int sig; - - assert(ss); - - va_start(ap, ss); - while ((sig = va_arg(ap, int)) > 0) - assert_se(sigaddset(ss, sig) == 0); - va_end(ap); -} - -int sigprocmask_many(int how, ...) { - va_list ap; - sigset_t ss; - int sig; - - assert_se(sigemptyset(&ss) == 0); - - va_start(ap, how); - while ((sig = va_arg(ap, int)) > 0) - assert_se(sigaddset(&ss, sig) == 0); - va_end(ap); - - if (sigprocmask(how, &ss, NULL) < 0) - return -errno; - - return 0; -} char *lookup_uid(uid_t uid) { long bufsize; char *name; @@ -2344,18 +2228,6 @@ DIR *xopendirat(int fd, const char *name, int flags) { return d; } -int signal_from_string_try_harder(const char *s) { - int signo; - assert(s); - - signo = signal_from_string(s); - if (signo <= 0) - if (startswith(s, "SIG")) - return signal_from_string(s+3); - - return signo; -} - static char *tag_to_udev_node(const char *tagvalue, const char *by) { _cleanup_free_ char *t = NULL, *u = NULL; size_t enc_len; @@ -3312,81 +3184,6 @@ static const char* const ip_tos_table[] = { DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(ip_tos, int, 0xff); -static const char *const __signal_table[] = { - [SIGHUP] = "HUP", - [SIGINT] = "INT", - [SIGQUIT] = "QUIT", - [SIGILL] = "ILL", - [SIGTRAP] = "TRAP", - [SIGABRT] = "ABRT", - [SIGBUS] = "BUS", - [SIGFPE] = "FPE", - [SIGKILL] = "KILL", - [SIGUSR1] = "USR1", - [SIGSEGV] = "SEGV", - [SIGUSR2] = "USR2", - [SIGPIPE] = "PIPE", - [SIGALRM] = "ALRM", - [SIGTERM] = "TERM", -#ifdef SIGSTKFLT - [SIGSTKFLT] = "STKFLT", /* Linux on SPARC doesn't know SIGSTKFLT */ -#endif - [SIGCHLD] = "CHLD", - [SIGCONT] = "CONT", - [SIGSTOP] = "STOP", - [SIGTSTP] = "TSTP", - [SIGTTIN] = "TTIN", - [SIGTTOU] = "TTOU", - [SIGURG] = "URG", - [SIGXCPU] = "XCPU", - [SIGXFSZ] = "XFSZ", - [SIGVTALRM] = "VTALRM", - [SIGPROF] = "PROF", - [SIGWINCH] = "WINCH", - [SIGIO] = "IO", - [SIGPWR] = "PWR", - [SIGSYS] = "SYS" -}; - -DEFINE_PRIVATE_STRING_TABLE_LOOKUP(__signal, int); - -const char *signal_to_string(int signo) { - static thread_local char buf[sizeof("RTMIN+")-1 + DECIMAL_STR_MAX(int) + 1]; - const char *name; - - name = __signal_to_string(signo); - if (name) - return name; - - if (signo >= SIGRTMIN && signo <= SIGRTMAX) - snprintf(buf, sizeof(buf), "RTMIN+%d", signo - SIGRTMIN); - else - snprintf(buf, sizeof(buf), "%d", signo); - - return buf; -} - -int signal_from_string(const char *s) { - int signo; - int offset = 0; - unsigned u; - - signo = __signal_from_string(s); - if (signo > 0) - return signo; - - if (startswith(s, "RTMIN+")) { - s += 6; - offset = SIGRTMIN; - } - if (safe_atou(s, &u) >= 0) { - signo = (int) u + offset; - if (signo > 0 && signo < _NSIG) - return signo; - } - return -EINVAL; -} - bool kexec_loaded(void) { bool loaded = false; char *s; diff --git a/src/shared/util.h b/src/shared/util.h index eb3595250d..467ae234a0 100644 --- a/src/shared/util.h +++ b/src/shared/util.h @@ -29,7 +29,6 @@ #include <stdbool.h> #include <stdlib.h> #include <stdio.h> -#include <signal.h> #include <sched.h> #include <limits.h> #include <sys/types.h> @@ -227,9 +226,6 @@ int readlink_value(const char *p, char **ret); int readlink_and_make_absolute(const char *p, char **r); int readlink_and_canonicalize(const char *p, char **r); -int reset_all_signal_handlers(void); -int reset_signal_mask(void); - char *strstrip(char *s); char *delete_chars(char *s, const char *bad); char *truncate_nl(char *s); @@ -334,10 +330,6 @@ bool fstype_is_network(const char *fstype); int flush_fd(int fd); -int ignore_signals(int sig, ...); -int default_signals(int sig, ...); -int sigaction_many(const struct sigaction *sa, ...); - int fopen_temporary(const char *path, FILE **_f, char **_temp_path); ssize_t loop_read(int fd, void *buf, size_t nbytes, bool do_poll); @@ -349,9 +341,6 @@ bool is_device_path(const char *path); int dir_is_empty(const char *path); char* dirname_malloc(const char *path); -void sigset_add_many(sigset_t *ss, ...); -int sigprocmask_many(int how, ...); - char* lookup_uid(uid_t uid); char* getlogname_malloc(void); char* getusername_malloc(void); @@ -465,11 +454,6 @@ int rlimit_from_string(const char *s) _pure_; int ip_tos_to_string_alloc(int i, char **s); int ip_tos_from_string(const char *s); -const char *signal_to_string(int i) _const_; -int signal_from_string(const char *s) _pure_; - -int signal_from_string_try_harder(const char *s); - extern int saved_argc; extern char **saved_argv; diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index f8e10a4710..b3d90d2c33 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -72,6 +72,7 @@ #include "process-util.h" #include "terminal-util.h" #include "hostname-util.h" +#include "signal-util.h" static char **arg_types = NULL; static char **arg_states = NULL; @@ -5098,7 +5099,7 @@ static int import_environment(sd_bus *bus, char **args) { static int enable_sysv_units(const char *verb, char **args) { int r = 0; -#if defined(HAVE_SYSV_COMPAT) && defined(HAVE_CHKCONFIG) +#if defined(HAVE_SYSV_COMPAT) unsigned f = 0; _cleanup_lookup_paths_free_ LookupPaths paths = {}; @@ -5123,7 +5124,7 @@ static int enable_sysv_units(const char *verb, char **args) { _cleanup_free_ char *p = NULL, *q = NULL, *l = NULL; bool found_native = false, found_sysv; unsigned c = 1; - const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL }; + const char *argv[6] = { ROOTLIBEXECDIR "/systemd-sysv-install", NULL, NULL, NULL, NULL }; char **k; int j; pid_t pid; @@ -5149,7 +5150,10 @@ static int enable_sysv_units(const char *verb, char **args) { break; } - if (found_native) + /* If we have both a native unit and a SysV script, + * enable/disable them both (below); for is-enabled, prefer the + * native unit */ + if (found_native && streq(verb, "is-enabled")) continue; p = path_join(arg_root, SYSTEM_SYSVINIT_PATH, name); @@ -5161,15 +5165,16 @@ static int enable_sysv_units(const char *verb, char **args) { if (!found_sysv) continue; - log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name); + if (found_native) + log_info("Synchronizing state of %s with SysV init with %s...", name, argv[0]); + else + log_info("%s is not a native service, redirecting to systemd-sysv-install", name); if (!isempty(arg_root)) argv[c++] = q = strappend("--root=", arg_root); + argv[c++] = verb; argv[c++] = basename(p); - argv[c++] = - streq(verb, "enable") ? "on" : - streq(verb, "disable") ? "off" : "--level=5"; argv[c] = NULL; l = strv_join((char**)argv, " "); @@ -5185,6 +5190,7 @@ static int enable_sysv_units(const char *verb, char **args) { /* Child */ execv(argv[0], (char**) argv); + log_error("Failed to execute %s: %m", argv[0]); _exit(EXIT_FAILURE); } @@ -5210,6 +5216,9 @@ static int enable_sysv_units(const char *verb, char **args) { } else return -EPROTO; + if (found_native) + continue; + /* Remove this entry, so that we don't try enabling it as native unit */ assert(f > 0); f--; @@ -5870,7 +5879,7 @@ static int run_editor(char **paths) { execvp(editor, (char* const*) args); } - FOREACH_STRING(p, "nano", "vim", "vi") { + FOREACH_STRING(p, "editor", "nano", "vim", "vi") { args[0] = p; execvp(p, (char* const*) args); /* We do not fail if the editor doesn't exist diff --git a/src/systemctl/systemd-sysv-install.SKELETON b/src/systemctl/systemd-sysv-install.SKELETON new file mode 100755 index 0000000000..a53a3e6221 --- /dev/null +++ b/src/systemctl/systemd-sysv-install.SKELETON @@ -0,0 +1,47 @@ +#!/bin/sh +# This script is called by "systemctl enable/disable" when the given unit is a +# SysV init.d script. It needs to call the distribution's mechanism for +# enabling/disabling those, such as chkconfig, update-rc.d, or similar. This +# can optionally take a --root argument for enabling a SysV init script +# in a chroot or similar. +set -e + +usage() { + echo "Usage: $0 [--root=path] enable|disable|is-enabled <sysv script name>" >&2 + exit 1 +} + +# parse options +eval set -- "$(getopt -o r: --long root: -- "$@")" +while true; do + case "$1" in + -r|--root) + ROOT="$2" + shift 2 ;; + --) shift ; break ;; + *) usage ;; + esac +done + +NAME="$2" +[ -n "$NAME" ] || usage + +case "$1" in + enable) + # call the command to enable SysV init script $NAME here + # (consider optional $ROOT) + echo "IMPLEMENT ME: enabling SysV init.d script $NAME" + ;; + disable) + # call the command to disable SysV init script $NAME here + # (consider optional $ROOT) + echo "IMPLEMENT ME: disabling SysV init.d script $NAME" + ;; + is-enabled) + # exit with 0 if $NAME is enabled, non-zero if it is disabled + # (consider optional $ROOT) + echo "IMPLEMENT ME: checking SysV init.d script $NAME" + ;; + *) + usage ;; +esac diff --git a/src/test/test-conf-parser.c b/src/test/test-conf-parser.c new file mode 100644 index 0000000000..463906d304 --- /dev/null +++ b/src/test/test-conf-parser.c @@ -0,0 +1,234 @@ +/*** + This file is part of systemd. + + Copyright 2015 Ronny Chevalier + + 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 "conf-parser.h" +#include "macro.h" +#include "util.h" +#include "strv.h" +#include "log.h" + +static void test_config_parse_path_one(const char *rvalue, const char *expected) { + char *path = NULL; + + assert_se(config_parse_path("unit", "filename", 1, "section", 1, "lvalue", 0, rvalue, &path, NULL) >= 0); + assert_se(streq_ptr(expected, path)); + + free(path); +} + +static void test_config_parse_log_level_one(const char *rvalue, int expected) { + int log_level = 0; + + assert_se(config_parse_log_level("unit", "filename", 1, "section", 1, "lvalue", 0, rvalue, &log_level, NULL) >= 0); + assert_se(expected == log_level); +} + +static void test_config_parse_log_facility_one(const char *rvalue, int expected) { + int log_facility = 0; + + assert_se(config_parse_log_facility("unit", "filename", 1, "section", 1, "lvalue", 0, rvalue, &log_facility, NULL) >= 0); + assert_se(expected == log_facility); +} + +static void test_config_parse_iec_size_one(const char *rvalue, size_t expected) { + size_t iec_size = 0; + + assert_se(config_parse_iec_size("unit", "filename", 1, "section", 1, "lvalue", 0, rvalue, &iec_size, NULL) >= 0); + assert_se(expected == iec_size); +} + +static void test_config_parse_si_size_one(const char *rvalue, size_t expected) { + size_t si_size = 0; + + assert_se(config_parse_si_size("unit", "filename", 1, "section", 1, "lvalue", 0, rvalue, &si_size, NULL) >= 0); + assert_se(expected == si_size); +} + +static void test_config_parse_int_one(const char *rvalue, int expected) { + int v = -1; + + assert_se(config_parse_int("unit", "filename", 1, "section", 1, "lvalue", 0, rvalue, &v, NULL) >= 0); + assert_se(expected == v); +} + +static void test_config_parse_unsigned_one(const char *rvalue, unsigned expected) { + unsigned v = 0; + + assert_se(config_parse_unsigned("unit", "filename", 1, "section", 1, "lvalue", 0, rvalue, &v, NULL) >= 0); + assert_se(expected == v); +} + +static void test_config_parse_strv_one(const char *rvalue, char **expected) { + char **strv = 0; + + assert_se(config_parse_strv("unit", "filename", 1, "section", 1, "lvalue", 0, rvalue, &strv, NULL) >= 0); + assert_se(strv_equal(expected, strv)); + + strv_free(strv); +} + +static void test_config_parse_mode_one(const char *rvalue, mode_t expected) { + mode_t v = 0; + + assert_se(config_parse_mode("unit", "filename", 1, "section", 1, "lvalue", 0, rvalue, &v, NULL) >= 0); + assert_se(expected == v); +} + +static void test_config_parse_sec_one(const char *rvalue, usec_t expected) { + usec_t v = 0; + + assert_se(config_parse_sec("unit", "filename", 1, "section", 1, "lvalue", 0, rvalue, &v, NULL) >= 0); + assert_se(expected == v); +} + +static void test_config_parse_nsec_one(const char *rvalue, nsec_t expected) { + nsec_t v = 0; + + assert_se(config_parse_nsec("unit", "filename", 1, "nsection", 1, "lvalue", 0, rvalue, &v, NULL) >= 0); + assert_se(expected == v); +} + +static void test_config_parse_path(void) { + test_config_parse_path_one("/path", "/path"); + test_config_parse_path_one("/path//////////", "/path"); + test_config_parse_path_one("///path/foo///bar////bar//", "/path/foo/bar/bar"); + + test_config_parse_path_one("not_absolute/path", NULL); +} + +static void test_config_parse_log_level(void) { + test_config_parse_log_level_one("debug", LOG_DEBUG); + test_config_parse_log_level_one("info", LOG_INFO); + + test_config_parse_log_level_one("garbage", 0); +} + +static void test_config_parse_log_facility(void) { + test_config_parse_log_facility_one("mail", LOG_MAIL); + test_config_parse_log_facility_one("user", LOG_USER); + + test_config_parse_log_facility_one("garbage", 0); +} + +static void test_config_parse_iec_size(void) { + test_config_parse_iec_size_one("1024", 1024); + test_config_parse_iec_size_one("2K", 2048); + test_config_parse_iec_size_one("10M", 10 * 1024 * 1024); + test_config_parse_iec_size_one("1G", 1 * 1024 * 1024 * 1024); + test_config_parse_iec_size_one("0G", 0); + test_config_parse_iec_size_one("0", 0); + + test_config_parse_iec_size_one("-982", 0); + test_config_parse_iec_size_one("49874444198739873000000G", 0); + test_config_parse_iec_size_one("garbage", 0); +} + +static void test_config_parse_si_size(void) { + test_config_parse_si_size_one("1024", 1024); + test_config_parse_si_size_one("2K", 2000); + test_config_parse_si_size_one("10M", 10 * 1000 * 1000); + test_config_parse_si_size_one("1G", 1 * 1000 * 1000 * 1000); + test_config_parse_si_size_one("0G", 0); + test_config_parse_si_size_one("0", 0); + + test_config_parse_si_size_one("-982", 0); + test_config_parse_si_size_one("49874444198739873000000G", 0); + test_config_parse_si_size_one("garbage", 0); +} + +static void test_config_parse_int(void) { + test_config_parse_int_one("1024", 1024); + test_config_parse_int_one("-1024", -1024); + test_config_parse_int_one("0", 0); + + test_config_parse_int_one("99999999999999999999999999999999999999999999999999999999", -1); + test_config_parse_int_one("-99999999999999999999999999999999999999999999999999999999", -1); + test_config_parse_int_one("1G", -1); + test_config_parse_int_one("garbage", -1); +} + +static void test_config_parse_unsigned(void) { + test_config_parse_unsigned_one("10241024", 10241024); + test_config_parse_unsigned_one("1024", 1024); + test_config_parse_unsigned_one("0", 0); + + test_config_parse_unsigned_one("99999999999999999999999999999999999999999999999999999999", 0); + test_config_parse_unsigned_one("1G", 0); + test_config_parse_unsigned_one("garbage", 0); + test_config_parse_unsigned_one("1000garbage", 0); +} + +static void test_config_parse_strv(void) { + test_config_parse_strv_one("", STRV_MAKE_EMPTY); + test_config_parse_strv_one("foo", STRV_MAKE("foo")); + test_config_parse_strv_one("foo bar foo", STRV_MAKE("foo", "bar", "foo")); + test_config_parse_strv_one("\"foo bar\" foo", STRV_MAKE("foo bar", "foo")); +} + +static void test_config_parse_mode(void) { + test_config_parse_mode_one("777", 0777); + test_config_parse_mode_one("644", 0644); + + test_config_parse_mode_one("-777", 0); + test_config_parse_mode_one("999", 0); + test_config_parse_mode_one("garbage", 0); + test_config_parse_mode_one("777garbage", 0); + test_config_parse_mode_one("777 garbage", 0); +} + +static void test_config_parse_sec(void) { + test_config_parse_sec_one("1", 1 * USEC_PER_SEC); + test_config_parse_sec_one("1s", 1 * USEC_PER_SEC); + test_config_parse_sec_one("100ms", 100 * USEC_PER_MSEC); + test_config_parse_sec_one("5min 20s", 5 * 60 * USEC_PER_SEC + 20 * USEC_PER_SEC); + + test_config_parse_sec_one("-1", 0); + test_config_parse_sec_one("10foo", 0); + test_config_parse_sec_one("garbage", 0); +} + +static void test_config_parse_nsec(void) { + test_config_parse_nsec_one("1", 1); + test_config_parse_nsec_one("1s", 1 * NSEC_PER_SEC); + test_config_parse_nsec_one("100ms", 100 * NSEC_PER_MSEC); + test_config_parse_nsec_one("5min 20s", 5 * 60 * NSEC_PER_SEC + 20 * NSEC_PER_SEC); + + test_config_parse_nsec_one("-1", 0); + test_config_parse_nsec_one("10foo", 0); + test_config_parse_nsec_one("garbage", 0); +} + +int main(int argc, char **argv) { + log_parse_environment(); + log_open(); + + test_config_parse_path(); + test_config_parse_log_level(); + test_config_parse_log_facility(); + test_config_parse_iec_size(); + test_config_parse_si_size(); + test_config_parse_int(); + test_config_parse_unsigned(); + test_config_parse_strv(); + test_config_parse_mode(); + test_config_parse_sec(); + test_config_parse_nsec(); + + return 0; +} diff --git a/src/test/test-fdset.c b/src/test/test-fdset.c index 91df7eb663..242c5d9dc2 100644 --- a/src/test/test-fdset.c +++ b/src/test/test-fdset.c @@ -154,6 +154,56 @@ static void test_fdset_iterate(void) { unlink(name); } +static void test_fdset_isempty(void) { + int fd; + _cleanup_fdset_free_ FDSet *fdset = NULL; + char name[] = "/tmp/test-fdset_isempty.XXXXXX"; + + fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC); + assert_se(fd >= 0); + + fdset = fdset_new(); + assert_se(fdset); + + assert_se(fdset_isempty(fdset)); + assert_se(fdset_put(fdset, fd) >= 0); + assert_se(!fdset_isempty(fdset)); + + unlink(name); +} + +static void test_fdset_steal_first(void) { + int fd; + _cleanup_fdset_free_ FDSet *fdset = NULL; + char name[] = "/tmp/test-fdset_steal_first.XXXXXX"; + + fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC); + assert_se(fd >= 0); + + fdset = fdset_new(); + assert_se(fdset); + + assert_se(fdset_steal_first(fdset) < 0); + assert_se(fdset_put(fdset, fd) >= 0); + assert_se(fdset_steal_first(fdset) == fd); + assert_se(fdset_steal_first(fdset) < 0); + assert_se(fdset_put(fdset, fd) >= 0); + + unlink(name); +} + +static void test_fdset_new_array(void) { + int fds[] = {10, 11, 12, 13}; + _cleanup_fdset_free_ FDSet *fdset = NULL; + + assert_se(fdset_new_array(&fdset, fds, 4) >= 0); + assert_se(fdset_size(fdset) == 4); + assert_se(fdset_contains(fdset, 10)); + assert_se(fdset_contains(fdset, 11)); + assert_se(fdset_contains(fdset, 12)); + assert_se(fdset_contains(fdset, 13)); +} + int main(int argc, char *argv[]) { test_fdset_new_fill(); test_fdset_put_dup(); @@ -161,6 +211,9 @@ int main(int argc, char *argv[]) { test_fdset_close_others(); test_fdset_remove(); test_fdset_iterate(); + test_fdset_isempty(); + test_fdset_steal_first(); + test_fdset_new_array(); return 0; } diff --git a/src/test/test-path-util.c b/src/test/test-path-util.c index 09f0f2f89e..0045ae6824 100644 --- a/src/test/test-path-util.c +++ b/src/test/test-path-util.c @@ -21,6 +21,7 @@ #include <stdio.h> #include <unistd.h> +#include <sys/mount.h> #include "path-util.h" #include "util.h" @@ -88,21 +89,9 @@ static void test_path(void) { test_parent("/aa///file...", "/aa///"); test_parent("file.../", NULL); - assert_se(path_is_mount_point("/", true) > 0); - assert_se(path_is_mount_point("/", false) > 0); - fd = open("/", O_RDONLY|O_CLOEXEC|O_DIRECTORY|O_NOCTTY); assert_se(fd >= 0); - assert_se(fd_is_mount_point(fd) > 0); - - assert_se(path_is_mount_point("/proc", true) > 0); - assert_se(path_is_mount_point("/proc", false) > 0); - - assert_se(path_is_mount_point("/proc/1", true) == 0); - assert_se(path_is_mount_point("/proc/1", false) == 0); - - assert_se(path_is_mount_point("/sys", true) > 0); - assert_se(path_is_mount_point("/sys", false) > 0); + assert_se(fd_is_mount_point(fd, "/", 0) > 0); { char p1[] = "aaa/bbb////ccc"; @@ -322,6 +311,66 @@ static void test_prefix_root(void) { test_prefix_root_one("/foo///", "//bar", "/foo/bar"); } +static void test_path_is_mount_point(void) { + int fd, rt, rf, rlt, rlf; + char tmp_dir[] = "/tmp/test-path-is-mount-point-XXXXXX"; + _cleanup_free_ char *file1 = NULL, *file2 = NULL, *link1 = NULL, *link2 = NULL; + + assert_se(path_is_mount_point("/", AT_SYMLINK_FOLLOW) > 0); + assert_se(path_is_mount_point("/", 0) > 0); + + assert_se(path_is_mount_point("/proc", AT_SYMLINK_FOLLOW) > 0); + assert_se(path_is_mount_point("/proc", 0) > 0); + + assert_se(path_is_mount_point("/proc/1", AT_SYMLINK_FOLLOW) == 0); + assert_se(path_is_mount_point("/proc/1", 0) == 0); + + assert_se(path_is_mount_point("/sys", AT_SYMLINK_FOLLOW) > 0); + assert_se(path_is_mount_point("/sys", 0) > 0); + + /* file mountpoints */ + assert_se(mkdtemp(tmp_dir) != NULL); + file1 = path_join(NULL, tmp_dir, "file1"); + assert_se(file1); + file2 = path_join(NULL, tmp_dir, "file2"); + assert_se(file2); + fd = open(file1, O_WRONLY|O_CREAT|O_EXCL|O_CLOEXEC, 0664); + assert_se(fd > 0); + close(fd); + fd = open(file2, O_WRONLY|O_CREAT|O_EXCL|O_CLOEXEC, 0664); + assert_se(fd > 0); + close(fd); + link1 = path_join(NULL, tmp_dir, "link1"); + assert_se(link1); + assert_se(symlink("file1", link1) == 0); + link2 = path_join(NULL, tmp_dir, "link2"); + assert_se(link1); + assert_se(symlink("file2", link2) == 0); + + assert_se(path_is_mount_point(file1, AT_SYMLINK_FOLLOW) == 0); + assert_se(path_is_mount_point(file1, 0) == 0); + assert_se(path_is_mount_point(link1, AT_SYMLINK_FOLLOW) == 0); + assert_se(path_is_mount_point(link1, 0) == 0); + + /* this test will only work as root */ + if (mount(file1, file2, NULL, MS_BIND, NULL) >= 0) { + rf = path_is_mount_point(file2, 0); + rt = path_is_mount_point(file2, AT_SYMLINK_FOLLOW); + rlf = path_is_mount_point(link2, 0); + rlt = path_is_mount_point(link2, AT_SYMLINK_FOLLOW); + + assert_se(umount(file2) == 0); + + assert_se(rf == 1); + assert_se(rt == 1); + assert_se(rlf == 0); + assert_se(rlt == 1); + } else + printf("Skipping bind mount file test: %m\n"); + + assert_se(rm_rf(tmp_dir, REMOVE_ROOT|REMOVE_PHYSICAL) == 0); +} + int main(int argc, char **argv) { test_path(); test_find_binary(argv[0], true); @@ -333,6 +382,7 @@ int main(int argc, char **argv) { test_strv_resolve(); test_path_startswith(); test_prefix_root(); + test_path_is_mount_point(); return 0; } diff --git a/src/test/test-pty.c b/src/test/test-pty.c index b5f4d4f094..f8807c9150 100644 --- a/src/test/test-pty.c +++ b/src/test/test-pty.c @@ -27,6 +27,7 @@ #include "pty.h" #include "util.h" +#include "signal-util.h" static const char sndmsg[] = "message\n"; static const char rcvmsg[] = "message\r\n"; diff --git a/src/test/test-udev.c b/src/test/test-udev.c index 23b7faa939..d1fe953071 100644 --- a/src/test/test-udev.c +++ b/src/test/test-udev.c @@ -28,6 +28,7 @@ #include "missing.h" #include "selinux-util.h" +#include "signal-util.h" #include "udev.h" #include "udev-util.h" @@ -79,7 +80,6 @@ int main(int argc, char *argv[]) { char syspath[UTIL_PATH_SIZE]; const char *devpath; const char *action; - sigset_t mask, sigmask_orig; int err; err = fake_filesystems(); @@ -93,8 +93,6 @@ int main(int argc, char *argv[]) { log_debug("version %s", VERSION); mac_selinux_init("/dev"); - sigprocmask(SIG_SETMASK, NULL, &sigmask_orig); - action = argv[1]; if (action == NULL) { log_error("action missing"); @@ -118,13 +116,7 @@ int main(int argc, char *argv[]) { event = udev_event_new(dev); - sigfillset(&mask); - sigprocmask(SIG_SETMASK, &mask, &sigmask_orig); - event->fd_signal = signalfd(-1, &mask, SFD_NONBLOCK|SFD_CLOEXEC); - if (event->fd_signal < 0) { - fprintf(stderr, "error creating signalfd\n"); - goto out; - } + assert_se(sigprocmask_many(SIG_BLOCK, SIGTERM, SIGINT, SIGHUP, SIGCHLD, -1) == 0); /* do what devtmpfs usually provides us */ if (udev_device_get_devnode(dev) != NULL) { @@ -147,14 +139,10 @@ int main(int argc, char *argv[]) { udev_event_execute_rules(event, 3 * USEC_PER_SEC, USEC_PER_SEC, NULL, - rules, - &sigmask_orig); + rules); udev_event_execute_run(event, - 3 * USEC_PER_SEC, USEC_PER_SEC, - NULL); + 3 * USEC_PER_SEC, USEC_PER_SEC); out: - if (event != NULL && event->fd_signal >= 0) - close(event->fd_signal); mac_selinux_finish(); return err ? EXIT_FAILURE : EXIT_SUCCESS; diff --git a/src/test/test-unit-file.c b/src/test/test-unit-file.c index a9711ac9f5..a8025c825b 100644 --- a/src/test/test-unit-file.c +++ b/src/test/test-unit-file.c @@ -225,6 +225,15 @@ static void test_config_parse_exec(void) { check_execcommand(c1, "/sbin/find", NULL, ";", "x", false); + log_info("/* encoded semicolon */"); + r = config_parse_exec(NULL, "fake", 5, "section", 1, + "LValue", 0, + "/bin/find \\073", + &c, NULL); + assert_se(r >= 0); + c1 = c1->command_next; + check_execcommand(c1, "/bin/find", NULL, ";", NULL, false); + log_info("/* spaces in the filename */"); r = config_parse_exec(NULL, "fake", 5, "section", 1, "LValue", 0, @@ -296,6 +305,16 @@ static void test_config_parse_exec(void) { c1 = c1->command_next; check_execcommand(c1, "/path ", NULL, NULL, NULL, false); + log_info("/* quoted backslashes */"); + r = config_parse_exec(NULL, "fake", 5, "section", 1, + "LValue", 0, + "/bin/grep '\\w+\\K'", + &c, NULL); + assert_se(r >= 0); + c1 = c1->command_next; + check_execcommand(c1, "/bin/grep", NULL, "\\w+\\K", NULL, false); + + log_info("/* trailing backslash: \\ */"); /* backslash is invalid */ r = config_parse_exec(NULL, "fake", 4, "section", 1, diff --git a/src/test/test-util.c b/src/test/test-util.c index 41cbe81b3d..9d5516a18d 100644 --- a/src/test/test-util.c +++ b/src/test/test-util.c @@ -39,6 +39,7 @@ #include "virt.h" #include "process-util.h" #include "hostname-util.h" +#include "signal-util.h" static void test_streq_ptr(void) { assert_se(streq_ptr(NULL, NULL)); @@ -459,6 +460,11 @@ static void test_cunescape(void) { assert_se(cunescape("\\u0000", 0, &unescaped) < 0); assert_se(cunescape("\\u00DF\\U000000df\\u03a0\\U00000041", UNESCAPE_RELAX, &unescaped) >= 0); assert_se(streq_ptr(unescaped, "ßßΠA")); + free(unescaped); + unescaped = NULL; + + assert_se(cunescape("\\073", 0, &unescaped) >= 0); + assert_se(streq_ptr(unescaped, ";")); } static void test_foreach_word(void) { diff --git a/src/timesync/timesyncd.c b/src/timesync/timesyncd.c index 735668bede..d69129ee03 100644 --- a/src/timesync/timesyncd.c +++ b/src/timesync/timesyncd.c @@ -24,6 +24,7 @@ #include "capability.h" #include "clock-util.h" #include "network-util.h" +#include "signal-util.h" #include "timesyncd-manager.h" #include "timesyncd-conf.h" diff --git a/src/tty-ask-password-agent/tty-ask-password-agent.c b/src/tty-ask-password-agent/tty-ask-password-agent.c index c440170f95..97251ef0aa 100644 --- a/src/tty-ask-password-agent/tty-ask-password-agent.c +++ b/src/tty-ask-password-agent/tty-ask-password-agent.c @@ -44,6 +44,7 @@ #include "def.h" #include "process-util.h" #include "terminal-util.h" +#include "signal-util.h" static enum { ACTION_LIST, diff --git a/src/udev/net/link-config.c b/src/udev/net/link-config.c index ce038abee5..5610b2808e 100644 --- a/src/udev/net/link-config.c +++ b/src/udev/net/link-config.c @@ -240,6 +240,10 @@ int link_config_get(link_config_ctx *ctx, struct udev_device *device, link_config **ret) { link_config *link; + assert(ctx); + assert(device); + assert(ret); + LIST_FOREACH(links, link, ctx->links) { const char* attr_value; diff --git a/src/udev/udev-builtin-hwdb.c b/src/udev/udev-builtin-hwdb.c index 5e0e7ebb11..7dfc74e6fa 100644 --- a/src/udev/udev-builtin-hwdb.c +++ b/src/udev/udev-builtin-hwdb.c @@ -85,6 +85,8 @@ static int udev_builtin_hwdb_search(struct udev_device *dev, struct udev_device bool last = false; int r = 0; + assert(dev); + for (d = srcdev; d && !last; d = udev_device_get_parent(d)) { const char *dsubsys; const char *modalias = NULL; diff --git a/src/udev/udev-builtin-input_id.c b/src/udev/udev-builtin-input_id.c index b14190e423..e3fa4bc162 100644 --- a/src/udev/udev-builtin-input_id.c +++ b/src/udev/udev-builtin-input_id.c @@ -133,79 +133,99 @@ static bool test_pointers(struct udev_device *dev, const unsigned long* bitmask_rel, const unsigned long* bitmask_props, bool test) { - int is_mouse = 0; - int is_touchpad = 0; - bool ret = false; - - if (test_bit(INPUT_PROP_ACCELEROMETER, bitmask_props)) { + bool has_abs_coordinates = false; + bool has_rel_coordinates = false; + bool has_mt_coordinates = false; + bool has_joystick_axes_or_buttons = false; + bool is_direct = false; + bool has_touch = false; + bool has_3d_coordinates = false; + bool has_keys = false; + bool stylus_or_pen = false; + bool finger_but_no_pen = false; + bool has_mouse_button = false; + bool is_mouse = false; + bool is_touchpad = false; + bool is_touchscreen = false; + bool is_tablet = false; + bool is_joystick = false; + bool is_accelerometer = false; + bool is_pointing_stick= false; + + has_keys = test_bit(EV_KEY, bitmask_ev); + has_abs_coordinates = test_bit(ABS_X, bitmask_abs) && test_bit(ABS_Y, bitmask_abs); + has_3d_coordinates = has_abs_coordinates && test_bit(ABS_Z, bitmask_abs); + is_accelerometer = test_bit(INPUT_PROP_ACCELEROMETER, bitmask_props); + + if (!has_keys && has_3d_coordinates) + is_accelerometer = true; + + if (is_accelerometer) { udev_builtin_add_property(dev, test, "ID_INPUT_ACCELEROMETER", "1"); return true; } - if (!test_bit(EV_KEY, bitmask_ev)) { - if (test_bit(EV_ABS, bitmask_ev) && - test_bit(ABS_X, bitmask_abs) && - test_bit(ABS_Y, bitmask_abs) && - test_bit(ABS_Z, bitmask_abs)) { - udev_builtin_add_property(dev, test, "ID_INPUT_ACCELEROMETER", "1"); - ret = true; - } - return ret; - } - - if (test_bit(EV_ABS, bitmask_ev) && - test_bit(ABS_X, bitmask_abs) && test_bit(ABS_Y, bitmask_abs)) { - if (test_bit(BTN_STYLUS, bitmask_key) || test_bit(BTN_TOOL_PEN, bitmask_key)) { - udev_builtin_add_property(dev, test, "ID_INPUT_TABLET", "1"); - ret = true; - } else if (test_bit(BTN_TOOL_FINGER, bitmask_key) && !test_bit(BTN_TOOL_PEN, bitmask_key)) { - is_touchpad = 1; - } else if (test_bit(BTN_MOUSE, bitmask_key)) { + is_pointing_stick = test_bit(INPUT_PROP_POINTING_STICK, bitmask_props); + stylus_or_pen = test_bit(BTN_STYLUS, bitmask_key) || test_bit(BTN_TOOL_PEN, bitmask_key); + finger_but_no_pen = test_bit(BTN_TOOL_FINGER, bitmask_key) && !test_bit(BTN_TOOL_PEN, bitmask_key); + has_mouse_button = test_bit(BTN_LEFT, bitmask_key); + has_rel_coordinates = test_bit(EV_REL, bitmask_ev) && test_bit(REL_X, bitmask_rel) && test_bit(REL_Y, bitmask_rel); + has_mt_coordinates = test_bit(ABS_MT_POSITION_X, bitmask_abs) && test_bit(ABS_MT_POSITION_Y, bitmask_abs); + + /* unset has_mt_coordinates if devices claims to have all abs axis */ + if(has_mt_coordinates && test_bit(ABS_MT_SLOT, bitmask_abs) && test_bit(ABS_MT_SLOT - 1, bitmask_abs)) + has_mt_coordinates = false; + is_direct = test_bit(INPUT_PROP_DIRECT, bitmask_props); + has_touch = test_bit(BTN_TOUCH, bitmask_key); + /* joysticks don't necessarily have buttons; e. g. + * rudders/pedals are joystick-like, but buttonless; they have + * other fancy axes */ + has_joystick_axes_or_buttons = test_bit(BTN_TRIGGER, bitmask_key) || + test_bit(BTN_A, bitmask_key) || + test_bit(BTN_1, bitmask_key) || + test_bit(ABS_RX, bitmask_abs) || + test_bit(ABS_RY, bitmask_abs) || + test_bit(ABS_RZ, bitmask_abs) || + test_bit(ABS_THROTTLE, bitmask_abs) || + test_bit(ABS_RUDDER, bitmask_abs) || + test_bit(ABS_WHEEL, bitmask_abs) || + test_bit(ABS_GAS, bitmask_abs) || + test_bit(ABS_BRAKE, bitmask_abs); + + if (has_abs_coordinates) { + if (stylus_or_pen) + is_tablet = true; + else if (finger_but_no_pen && !is_direct) + is_touchpad = true; + else if (has_mouse_button) /* This path is taken by VMware's USB mouse, which has * absolute axes, but no touch/pressure button. */ - is_mouse = 1; - } else if (test_bit(BTN_TOUCH, bitmask_key)) { - udev_builtin_add_property(dev, test, "ID_INPUT_TOUCHSCREEN", "1"); - ret = true; - /* joysticks don't necessarily have to have buttons; e. g. - * rudders/pedals are joystick-like, but buttonless; they have - * other fancy axes */ - } else if (test_bit(BTN_TRIGGER, bitmask_key) || - test_bit(BTN_A, bitmask_key) || - test_bit(BTN_1, bitmask_key) || - test_bit(ABS_RX, bitmask_abs) || - test_bit(ABS_RY, bitmask_abs) || - test_bit(ABS_RZ, bitmask_abs) || - test_bit(ABS_THROTTLE, bitmask_abs) || - test_bit(ABS_RUDDER, bitmask_abs) || - test_bit(ABS_WHEEL, bitmask_abs) || - test_bit(ABS_GAS, bitmask_abs) || - test_bit(ABS_BRAKE, bitmask_abs)) { - udev_builtin_add_property(dev, test, "ID_INPUT_JOYSTICK", "1"); - ret = true; - } + is_mouse = true; + else if (has_touch) + is_touchscreen = true; + else if (has_joystick_axes_or_buttons) + is_joystick = true; } + if (has_mt_coordinates && is_direct) + is_touchscreen = true; - if (test_bit(INPUT_PROP_POINTING_STICK, bitmask_props)) { - udev_builtin_add_property(dev, test, "ID_INPUT_POINTINGSTICK", "1"); - ret = true; - } + if (has_rel_coordinates && has_mouse_button) + is_mouse = true; - if (test_bit(EV_REL, bitmask_ev) && - test_bit(REL_X, bitmask_rel) && test_bit(REL_Y, bitmask_rel) && - test_bit(BTN_MOUSE, bitmask_key)) - is_mouse = 1; - - if (is_mouse) { + if (is_pointing_stick) + udev_builtin_add_property(dev, test, "ID_INPUT_POINTINGSTICK", "1"); + if (is_mouse) udev_builtin_add_property(dev, test, "ID_INPUT_MOUSE", "1"); - ret = true; - } - if (is_touchpad) { + if (is_touchpad) udev_builtin_add_property(dev, test, "ID_INPUT_TOUCHPAD", "1"); - ret = true; - } - - return ret; + if (is_touchscreen) + udev_builtin_add_property(dev, test, "ID_INPUT_TOUCHSCREEN", "1"); + if (is_joystick) + udev_builtin_add_property(dev, test, "ID_INPUT_JOYSTICK", "1"); + if (is_tablet) + udev_builtin_add_property(dev, test, "ID_INPUT_TABLET", "1"); + + return is_tablet || is_mouse || is_touchpad || is_touchscreen || is_joystick || is_pointing_stick; } /* key like devices */ @@ -268,6 +288,8 @@ static int builtin_input_id(struct udev_device *dev, int argc, char *argv[], boo bool is_pointer; bool is_key; + assert(dev); + /* walk up the parental chain until we find the real input device; the * argument is very likely a subdevice of this, like eventN */ pdev = dev; diff --git a/src/udev/udev-builtin-keyboard.c b/src/udev/udev-builtin-keyboard.c index ed990c58fb..01f3879f37 100644 --- a/src/udev/udev-builtin-keyboard.c +++ b/src/udev/udev-builtin-keyboard.c @@ -37,6 +37,9 @@ static int install_force_release(struct udev_device *dev, const unsigned *releas unsigned i; int ret; + assert(dev); + assert(release); + atkbd = udev_device_get_parent_with_subsystem_devtype(dev, "serio", NULL); if (!atkbd) return -ENODEV; @@ -152,6 +155,9 @@ static void set_trackpoint_sensitivity(struct udev_device *dev, const char *valu char val_s[DECIMAL_STR_MAX(int)]; int r, val_i; + assert(dev); + assert(value); + /* The sensitivity sysfs attr belongs to the serio parent device */ pdev = udev_device_get_parent_with_subsystem_devtype(dev, "serio", NULL); if (!pdev) { diff --git a/src/udev/udev-builtin-net_id.c b/src/udev/udev-builtin-net_id.c index 448920507a..6e7e1271fb 100644 --- a/src/udev/udev-builtin-net_id.c +++ b/src/udev/udev-builtin-net_id.c @@ -276,6 +276,9 @@ out: static int names_pci(struct udev_device *dev, struct netnames *names) { struct udev_device *parent; + assert(dev); + assert(names); + parent = udev_device_get_parent(dev); if (!parent) return -ENOENT; @@ -302,6 +305,9 @@ static int names_usb(struct udev_device *dev, struct netnames *names) { size_t l; char *s; + assert(dev); + assert(names); + usbdev = udev_device_get_parent_with_subsystem_devtype(dev, "usb", "usb_interface"); if (!usbdev) return -ENOENT; @@ -350,6 +356,9 @@ static int names_bcma(struct udev_device *dev, struct netnames *names) { struct udev_device *bcmadev; unsigned int core; + assert(dev); + assert(names); + bcmadev = udev_device_get_parent_with_subsystem_devtype(dev, "bcma", NULL); if (!bcmadev) return -ENOENT; @@ -371,6 +380,9 @@ static int names_ccw(struct udev_device *dev, struct netnames *names) { size_t bus_id_len; int rc; + assert(dev); + assert(names); + /* Retrieve the associated CCW device */ cdev = udev_device_get_parent(dev); if (!cdev) diff --git a/src/udev/udev-builtin-path_id.c b/src/udev/udev-builtin-path_id.c index b6749aab76..4ca0a69d7d 100644 --- a/src/udev/udev-builtin-path_id.c +++ b/src/udev/udev-builtin-path_id.c @@ -77,6 +77,9 @@ static int format_lun_number(struct udev_device *dev, char **path) { static struct udev_device *skip_subsystem(struct udev_device *dev, const char *subsys) { struct udev_device *parent = dev; + assert(dev); + assert(subsys); + while (parent != NULL) { const char *subsystem; @@ -96,6 +99,9 @@ static struct udev_device *handle_scsi_fibre_channel(struct udev_device *parent, const char *port; char *lun = NULL; + assert(parent); + assert(path); + targetdev = udev_device_get_parent_with_subsystem_devtype(parent, "scsi", "scsi_target"); if (targetdev == NULL) return NULL; @@ -126,6 +132,9 @@ static struct udev_device *handle_scsi_sas_wide_port(struct udev_device *parent, const char *sas_address; char *lun = NULL; + assert(parent); + assert(path); + targetdev = udev_device_get_parent_with_subsystem_devtype(parent, "scsi", "scsi_target"); if (targetdev == NULL) return NULL; @@ -169,6 +178,9 @@ static struct udev_device *handle_scsi_sas(struct udev_device *parent, char **pa const char *phy_count; char *lun = NULL; + assert(parent); + assert(path); + targetdev = udev_device_get_parent_with_subsystem_devtype(parent, "scsi", "scsi_target"); if (targetdev == NULL) return NULL; @@ -259,6 +271,9 @@ static struct udev_device *handle_scsi_iscsi(struct udev_device *parent, char ** const char *port; char *lun = NULL; + assert(parent); + assert(path); + /* find iscsi session */ transportdev = parent; for (;;) { @@ -316,6 +331,9 @@ static struct udev_device *handle_scsi_default(struct udev_device *parent, char struct dirent *dent; int basenum; + assert(parent); + assert(path); + hostdev = udev_device_get_parent_with_subsystem_devtype(parent, "scsi", "scsi_host"); if (hostdev == NULL) return NULL; @@ -398,6 +416,9 @@ static struct udev_device *handle_scsi_hyperv(struct udev_device *parent, char * char guid[38]; size_t i, k; + assert(parent); + assert(path); + hostdev = udev_device_get_parent_with_subsystem_devtype(parent, "scsi", "scsi_host"); if (!hostdev) return NULL; @@ -555,6 +576,10 @@ static struct udev_device *handle_bcma(struct udev_device *parent, char **path) static struct udev_device *handle_ccw(struct udev_device *parent, struct udev_device *dev, char **path) { struct udev_device *scsi_dev; + assert(parent); + assert(dev); + assert(path); + scsi_dev = udev_device_get_parent_with_subsystem_devtype(dev, "scsi", "scsi_device"); if (scsi_dev != NULL) { const char *wwpn; @@ -582,6 +607,8 @@ static int builtin_path_id(struct udev_device *dev, int argc, char *argv[], bool bool supported_transport = false; bool supported_parent = false; + assert(dev); + /* S390 ccw bus */ parent = udev_device_get_parent_with_subsystem_devtype(dev, "ccw", NULL); if (parent != NULL) { @@ -638,7 +665,8 @@ static int builtin_path_id(struct udev_device *dev, int argc, char *argv[], bool supported_parent = true; } - parent = udev_device_get_parent(parent); + if (parent) + parent = udev_device_get_parent(parent); } /* diff --git a/src/udev/udev-builtin-usb_id.c b/src/udev/udev-builtin-usb_id.c index 462efc5c86..d309dc31cb 100644 --- a/src/udev/udev-builtin-usb_id.c +++ b/src/udev/udev-builtin-usb_id.c @@ -252,6 +252,8 @@ static int builtin_usb_id(struct udev_device *dev, int argc, char *argv[], bool size_t l; char *s; + assert(dev); + /* shortcut, if we are called directly for a "usb_device" type */ if (udev_device_get_devtype(dev) != NULL && streq(udev_device_get_devtype(dev), "usb_device")) { dev_if_packed_info(dev, packed_if_str, sizeof(packed_if_str)); diff --git a/src/udev/udev-event.c b/src/udev/udev-event.c index 2fa26a40be..4dcf8f2e1c 100644 --- a/src/udev/udev-event.c +++ b/src/udev/udev-event.c @@ -30,9 +30,19 @@ #include <sys/wait.h> #include <sys/signalfd.h> -#include "udev.h" #include "rtnl-util.h" +#include "event-util.h" #include "formats-util.h" +#include "process-util.h" +#include "signal-util.h" +#include "udev.h" + +typedef struct Spawn { + const char *cmd; + pid_t pid; + usec_t timeout_warn; + usec_t timeout; +} Spawn; struct udev_event *udev_event_new(struct udev_device *dev) { struct udev *udev = udev_device_get_udev(dev); @@ -45,8 +55,7 @@ struct udev_event *udev_event_new(struct udev_device *dev) { event->udev = udev; udev_list_init(udev, &event->run_list, false); udev_list_init(udev, &event->seclabel_list, false); - event->fd_signal = -1; - event->birth_usec = now(CLOCK_MONOTONIC); + event->birth_usec = clock_boottime_or_monotonic(); return event; } @@ -110,6 +119,8 @@ size_t udev_event_apply_format(struct udev_event *event, const char *src, char * char *s; size_t l; + assert(dev); + from = src; s = dest; l = size; @@ -374,7 +385,7 @@ out: } static int spawn_exec(struct udev_event *event, - const char *cmd, char *const argv[], char **envp, const sigset_t *sigmask, + const char *cmd, char *const argv[], char **envp, int fd_stdout, int fd_stderr) { _cleanup_close_ int fd = -1; @@ -402,9 +413,8 @@ static int spawn_exec(struct udev_event *event, /* terminate child in case parent goes away */ prctl(PR_SET_PDEATHSIG, SIGTERM); - /* restore original udev sigmask before exec */ - if (sigmask) - sigprocmask(SIG_SETMASK, sigmask, NULL); + /* restore sigmask before exec */ + (void) reset_signal_mask(); execve(argv[0], argv, envp); @@ -467,7 +477,7 @@ static void spawn_read(struct udev_event *event, if (timeout_usec > 0) { usec_t age_usec; - age_usec = now(CLOCK_MONOTONIC) - event->birth_usec; + age_usec = clock_boottime_or_monotonic() - event->birth_usec; if (age_usec >= timeout_usec) { log_error("timeout '%s'", cmd); return; @@ -540,102 +550,116 @@ static void spawn_read(struct udev_event *event, result[respos] = '\0'; } +static int on_spawn_timeout(sd_event_source *s, uint64_t usec, void *userdata) { + Spawn *spawn = userdata; + char timeout[FORMAT_TIMESTAMP_RELATIVE_MAX]; + + assert(spawn); + + kill_and_sigcont(spawn->pid, SIGKILL); + + log_error("spawned process '%s' ["PID_FMT"] timed out after %s, killing", spawn->cmd, spawn->pid, + format_timestamp_relative(timeout, sizeof(timeout), spawn->timeout)); + + return 1; +} + +static int on_spawn_timeout_warning(sd_event_source *s, uint64_t usec, void *userdata) { + Spawn *spawn = userdata; + char timeout[FORMAT_TIMESTAMP_RELATIVE_MAX]; + + assert(spawn); + + log_warning("spawned process '%s' ["PID_FMT"] is taking longer than %s to complete", spawn->cmd, spawn->pid, + format_timestamp_relative(timeout, sizeof(timeout), spawn->timeout)); + + return 1; +} + +static int on_spawn_sigchld(sd_event_source *s, const siginfo_t *si, void *userdata) { + Spawn *spawn = userdata; + + assert(spawn); + + switch (si->si_code) { + case CLD_EXITED: + if (si->si_status != 0) + log_warning("process '%s' failed with exit code %i.", spawn->cmd, si->si_status); + else { + log_debug("process '%s' succeeded.", spawn->cmd); + sd_event_exit(sd_event_source_get_event(s), 0); + + return 1; + } + + break; + case CLD_KILLED: + case CLD_DUMPED: + log_warning("process '%s' terminated by signal %s.", spawn->cmd, signal_to_string(si->si_status)); + + break; + default: + log_error("process '%s' failed due to unknown reason.", spawn->cmd); + } + + sd_event_exit(sd_event_source_get_event(s), -EIO); + + return 1; +} + static int spawn_wait(struct udev_event *event, usec_t timeout_usec, usec_t timeout_warn_usec, const char *cmd, pid_t pid) { - struct pollfd pfd[1]; - int err = 0; + Spawn spawn = { + .cmd = cmd, + .pid = pid, + }; + _cleanup_event_unref_ sd_event *e = NULL; + int r, ret; - pfd[0].events = POLLIN; - pfd[0].fd = event->fd_signal; + r = sd_event_new(&e); + if (r < 0) + return r; - while (pid > 0) { - int timeout; - int timeout_warn = 0; - int fdcount; + if (timeout_usec > 0) { + usec_t usec, age_usec; - if (timeout_usec > 0) { - usec_t age_usec; + usec = now(clock_boottime_or_monotonic()); + age_usec = usec - event->birth_usec; + if (age_usec < timeout_usec) { + if (timeout_warn_usec > 0 && timeout_warn_usec < timeout_usec && age_usec < timeout_warn_usec) { + spawn.timeout_warn = timeout_warn_usec - age_usec; - age_usec = now(CLOCK_MONOTONIC) - event->birth_usec; - if (age_usec >= timeout_usec) - timeout = 1000; - else { - if (timeout_warn_usec > 0) - timeout_warn = ((timeout_warn_usec - age_usec) / USEC_PER_MSEC) + MSEC_PER_SEC; - - timeout = ((timeout_usec - timeout_warn_usec - age_usec) / USEC_PER_MSEC) + MSEC_PER_SEC; + r = sd_event_add_time(e, NULL, clock_boottime_or_monotonic(), + usec + spawn.timeout_warn, USEC_PER_SEC, + on_spawn_timeout_warning, &spawn); + if (r < 0) + return r; } - } else { - timeout = -1; - } - fdcount = poll(pfd, 1, timeout_warn); - if (fdcount < 0) { - if (errno == EINTR) - continue; - err = -errno; - log_error_errno(errno, "failed to poll: %m"); - goto out; - } - if (fdcount == 0) { - log_warning("slow: '%s' ["PID_FMT"]", cmd, pid); + spawn.timeout = timeout_usec - age_usec; - fdcount = poll(pfd, 1, timeout); - if (fdcount < 0) { - if (errno == EINTR) - continue; - err = -errno; - log_error_errno(errno, "failed to poll: %m"); - goto out; - } - if (fdcount == 0) { - log_error("timeout: killing '%s' ["PID_FMT"]", cmd, pid); - kill(pid, SIGKILL); - } + r = sd_event_add_time(e, NULL, clock_boottime_or_monotonic(), + usec + spawn.timeout, USEC_PER_SEC, on_spawn_timeout, &spawn); + if (r < 0) + return r; } + } - if (pfd[0].revents & POLLIN) { - struct signalfd_siginfo fdsi; - int status; - ssize_t size; + r = sd_event_add_child(e, NULL, pid, WEXITED, on_spawn_sigchld, &spawn); + if (r < 0) + return r; - size = read(event->fd_signal, &fdsi, sizeof(struct signalfd_siginfo)); - if (size != sizeof(struct signalfd_siginfo)) - continue; + r = sd_event_loop(e); + if (r < 0) + return r; - switch (fdsi.ssi_signo) { - case SIGTERM: - event->sigterm = true; - break; - case SIGCHLD: - if (waitpid(pid, &status, WNOHANG) < 0) - break; - if (WIFEXITED(status)) { - log_debug("'%s' ["PID_FMT"] exit with return code %i", cmd, pid, WEXITSTATUS(status)); - if (WEXITSTATUS(status) != 0) - err = -1; - } else if (WIFSIGNALED(status)) { - log_error("'%s' ["PID_FMT"] terminated by signal %i (%s)", cmd, pid, WTERMSIG(status), strsignal(WTERMSIG(status))); - err = -1; - } else if (WIFSTOPPED(status)) { - log_error("'%s' ["PID_FMT"] stopped", cmd, pid); - err = -1; - } else if (WIFCONTINUED(status)) { - log_error("'%s' ["PID_FMT"] continued", cmd, pid); - err = -1; - } else { - log_error("'%s' ["PID_FMT"] exit with status 0x%04x", cmd, pid, status); - err = -1; - } - pid = 0; - break; - } - } - } -out: - return err; + r = sd_event_get_exit_code(e, &ret); + if (r < 0) + return r; + + return ret; } int udev_build_argv(struct udev *udev, char *cmd, int *argc, char *argv[]) { @@ -674,7 +698,7 @@ out: int udev_event_spawn(struct udev_event *event, usec_t timeout_usec, usec_t timeout_warn_usec, - const char *cmd, char **envp, const sigset_t *sigmask, + const char *cmd, char **envp, char *result, size_t ressize) { int outpipe[2] = {-1, -1}; int errpipe[2] = {-1, -1}; @@ -724,7 +748,7 @@ int udev_event_spawn(struct udev_event *event, log_debug("starting '%s'", cmd); - spawn_exec(event, cmd, argv, envp, sigmask, + spawn_exec(event, cmd, argv, envp, outpipe[WRITE_END], errpipe[WRITE_END]); _exit(2 ); @@ -786,8 +810,7 @@ static int rename_netif(struct udev_event *event) { void udev_event_execute_rules(struct udev_event *event, usec_t timeout_usec, usec_t timeout_warn_usec, struct udev_list *properties_list, - struct udev_rules *rules, - const sigset_t *sigmask) { + struct udev_rules *rules) { struct udev_device *dev = event->dev; if (udev_device_get_subsystem(dev) == NULL) @@ -803,8 +826,7 @@ void udev_event_execute_rules(struct udev_event *event, udev_rules_apply_to_event(rules, event, timeout_usec, timeout_warn_usec, - properties_list, - sigmask); + properties_list); if (major(udev_device_get_devnum(dev)) != 0) udev_node_remove(dev); @@ -822,8 +844,7 @@ void udev_event_execute_rules(struct udev_event *event, udev_rules_apply_to_event(rules, event, timeout_usec, timeout_warn_usec, - properties_list, - sigmask); + properties_list); /* rename a new network interface, if needed */ if (udev_device_get_ifindex(dev) > 0 && streq(udev_device_get_action(dev), "add") && @@ -886,7 +907,7 @@ void udev_event_execute_rules(struct udev_event *event, } } -void udev_event_execute_run(struct udev_event *event, usec_t timeout_usec, usec_t timeout_warn_usec, const sigset_t *sigmask) { +void udev_event_execute_run(struct udev_event *event, usec_t timeout_usec, usec_t timeout_warn_usec) { struct udev_list_entry *list_entry; udev_list_entry_foreach(list_entry, udev_list_get_entry(&event->run_list)) { @@ -909,7 +930,7 @@ void udev_event_execute_run(struct udev_event *event, usec_t timeout_usec, usec_ udev_event_apply_format(event, cmd, program, sizeof(program)); envp = udev_device_get_properties_envp(event->dev); - udev_event_spawn(event, timeout_usec, timeout_warn_usec, program, envp, sigmask, NULL, 0); + udev_event_spawn(event, timeout_usec, timeout_warn_usec, program, envp, NULL, 0); } } } diff --git a/src/udev/udev-rules.c b/src/udev/udev-rules.c index 4262119886..915371525f 100644 --- a/src/udev/udev-rules.c +++ b/src/udev/udev-rules.c @@ -633,7 +633,7 @@ static int import_file_into_properties(struct udev_device *dev, const char *file static int import_program_into_properties(struct udev_event *event, usec_t timeout_usec, usec_t timeout_warn_usec, - const char *program, const sigset_t *sigmask) { + const char *program) { struct udev_device *dev = event->dev; char **envp; char result[UTIL_LINE_SIZE]; @@ -641,7 +641,7 @@ static int import_program_into_properties(struct udev_event *event, int err; envp = udev_device_get_properties_envp(dev); - err = udev_event_spawn(event, timeout_usec, timeout_warn_usec, program, envp, sigmask, result, sizeof(result)); + err = udev_event_spawn(event, timeout_usec, timeout_warn_usec, program, envp, result, sizeof(result)); if (err < 0) return err; @@ -664,6 +664,9 @@ static int import_parent_into_properties(struct udev_device *dev, const char *fi struct udev_device *dev_parent; struct udev_list_entry *list_entry; + assert(dev); + assert(filter); + dev_parent = udev_device_get_parent(dev); if (dev_parent == NULL) return -1; @@ -1892,8 +1895,7 @@ int udev_rules_apply_to_event(struct udev_rules *rules, struct udev_event *event, usec_t timeout_usec, usec_t timeout_warn_usec, - struct udev_list *properties_list, - const sigset_t *sigmask) { + struct udev_list *properties_list) { struct token *cur; struct token *rule; enum escape_type esc = ESCAPE_UNSET; @@ -2129,7 +2131,7 @@ int udev_rules_apply_to_event(struct udev_rules *rules, rules_str(rules, rule->rule.filename_off), rule->rule.filename_line); - if (udev_event_spawn(event, timeout_usec, timeout_warn_usec, program, envp, sigmask, result, sizeof(result)) < 0) { + if (udev_event_spawn(event, timeout_usec, timeout_warn_usec, program, envp, result, sizeof(result)) < 0) { if (cur->key.op != OP_NOMATCH) goto nomatch; } else { @@ -2165,7 +2167,7 @@ int udev_rules_apply_to_event(struct udev_rules *rules, rules_str(rules, rule->rule.filename_off), rule->rule.filename_line); - if (import_program_into_properties(event, timeout_usec, timeout_warn_usec, import, sigmask) != 0) + if (import_program_into_properties(event, timeout_usec, timeout_warn_usec, import) != 0) if (cur->key.op != OP_NOMATCH) goto nomatch; break; diff --git a/src/udev/udev.h b/src/udev/udev.h index dece6eccab..fd8504c424 100644 --- a/src/udev/udev.h +++ b/src/udev/udev.h @@ -20,7 +20,6 @@ #include <sys/types.h> #include <sys/param.h> -#include <signal.h> #include "macro.h" #include "sd-rtnl.h" @@ -44,11 +43,9 @@ struct udev_event { struct udev_list run_list; int exec_delay; usec_t birth_usec; - int fd_signal; sd_rtnl *rtnl; unsigned int builtin_run; unsigned int builtin_ret; - bool sigterm; bool inotify_watch; bool inotify_watch_final; bool group_set; @@ -75,8 +72,7 @@ struct udev_rules *udev_rules_unref(struct udev_rules *rules); bool udev_rules_check_timestamp(struct udev_rules *rules); int udev_rules_apply_to_event(struct udev_rules *rules, struct udev_event *event, usec_t timeout_usec, usec_t timeout_warn_usec, - struct udev_list *properties_list, - const sigset_t *sigmask); + struct udev_list *properties_list); int udev_rules_apply_static_dev_perms(struct udev_rules *rules); /* udev-event.c */ @@ -88,14 +84,13 @@ int udev_event_apply_subsys_kernel(struct udev_event *event, const char *string, int udev_event_spawn(struct udev_event *event, usec_t timeout_usec, usec_t timeout_warn_usec, - const char *cmd, char **envp, const sigset_t *sigmask, + const char *cmd, char **envp, char *result, size_t ressize); void udev_event_execute_rules(struct udev_event *event, usec_t timeout_usec, usec_t timeout_warn_usec, struct udev_list *properties_list, - struct udev_rules *rules, - const sigset_t *sigset); -void udev_event_execute_run(struct udev_event *event, usec_t timeout_usec, usec_t timeout_warn_usec, const sigset_t *sigset); + struct udev_rules *rules); +void udev_event_execute_run(struct udev_event *event, usec_t timeout_usec, usec_t timeout_warn_usec); int udev_build_argv(struct udev *udev, char *cmd, int *argc, char *argv[]); /* udev-watch.c */ diff --git a/src/udev/udevadm-test.c b/src/udev/udevadm-test.c index fe092cfbd9..d04e618d0d 100644 --- a/src/udev/udevadm-test.c +++ b/src/udev/udevadm-test.c @@ -131,18 +131,11 @@ static int adm_test(struct udev *udev, int argc, char *argv[]) { sigfillset(&mask); sigprocmask(SIG_SETMASK, &mask, &sigmask_orig); - event->fd_signal = signalfd(-1, &mask, SFD_NONBLOCK|SFD_CLOEXEC); - if (event->fd_signal < 0) { - fprintf(stderr, "error creating signalfd\n"); - rc = 5; - goto out; - } udev_event_execute_rules(event, 60 * USEC_PER_SEC, 20 * USEC_PER_SEC, NULL, - rules, - &sigmask_orig); + rules); udev_list_entry_foreach(entry, udev_device_get_properties_list_entry(dev)) printf("%s=%s\n", udev_list_entry_get_name(entry), udev_list_entry_get_value(entry)); @@ -154,8 +147,6 @@ static int adm_test(struct udev *udev, int argc, char *argv[]) { printf("run: '%s'\n", program); } out: - if (event != NULL && event->fd_signal >= 0) - close(event->fd_signal); udev_builtin_exit(udev); return rc; } diff --git a/src/udev/udevd.c b/src/udev/udevd.c index 299fda8a3a..eb43091190 100644 --- a/src/udev/udevd.c +++ b/src/udev/udevd.c @@ -41,6 +41,10 @@ #include <sys/inotify.h> #include "sd-daemon.h" +#include "sd-event.h" + +#include "signal-util.h" +#include "event-util.h" #include "rtnl-util.h" #include "cgroup-util.h" #include "process-util.h" @@ -62,11 +66,11 @@ static usec_t arg_event_timeout_warn_usec = 180 * USEC_PER_SEC / 3; typedef struct Manager { struct udev *udev; + sd_event *event; Hashmap *workers; struct udev_list_node events; - char *cgroup; + const char *cgroup; pid_t pid; /* the process that originally allocated the manager object */ - sigset_t sigmask_orig; struct udev_rules *rules; struct udev_list properties; @@ -74,17 +78,16 @@ typedef struct Manager { struct udev_monitor *monitor; struct udev_ctrl *ctrl; struct udev_ctrl_connection *ctrl_conn_blocking; - - int fd_ep; - int fd_ctrl; - int fd_uevent; - int fd_signal; int fd_inotify; - int fd_worker; int worker_watch[2]; + sd_event_source *ctrl_event; + sd_event_source *uevent_event; + sd_event_source *inotify_event; + + usec_t last_usec; + bool stop_exec_queue:1; - bool reload:1; bool exit:1; } Manager; @@ -110,8 +113,8 @@ struct event { dev_t devnum; int ifindex; bool is_block; - usec_t start_usec; - bool warned; + sd_event_source *timeout_warning; + sd_event_source *timeout; }; static inline struct event *node_to_event(struct udev_list_node *node) { @@ -151,6 +154,9 @@ static void event_free(struct event *event) { udev_device_unref(event->dev); udev_device_unref(event->dev_kernel); + sd_event_source_unref(event->timeout_warning); + sd_event_source_unref(event->timeout); + if (event->worker) event->worker->event = NULL; @@ -252,7 +258,12 @@ static int on_event_timeout_warning(sd_event_source *s, uint64_t usec, void *use } static void worker_attach_event(struct worker *worker, struct event *event) { + sd_event *e; + uint64_t usec; + int r; + assert(worker); + assert(worker->manager); assert(event); assert(!event->worker); assert(!worker->event); @@ -260,9 +271,19 @@ static void worker_attach_event(struct worker *worker, struct event *event) { worker->state = WORKER_RUNNING; worker->event = event; event->state = EVENT_RUNNING; - event->start_usec = now(CLOCK_MONOTONIC); - event->warned = false; event->worker = worker; + + e = worker->manager->event; + + r = sd_event_now(e, clock_boottime_or_monotonic(), &usec); + if (r < 0) + return; + + (void) sd_event_add_time(e, &event->timeout_warning, clock_boottime_or_monotonic(), + usec + arg_event_timeout_warn_usec, USEC_PER_SEC, on_event_timeout_warning, event); + + (void) sd_event_add_time(e, &event->timeout, clock_boottime_or_monotonic(), + usec + arg_event_timeout_usec, USEC_PER_SEC, on_event_timeout, event); } static void manager_free(Manager *manager) { @@ -271,7 +292,12 @@ static void manager_free(Manager *manager) { udev_builtin_exit(manager->udev); + sd_event_source_unref(manager->ctrl_event); + sd_event_source_unref(manager->uevent_event); + sd_event_source_unref(manager->inotify_event); + udev_unref(manager->udev); + sd_event_unref(manager->event); manager_workers_free(manager); event_queue_cleanup(manager, EVENT_UNDEF); @@ -281,10 +307,7 @@ static void manager_free(Manager *manager) { udev_list_cleanup(&manager->properties); udev_rules_unref(manager->rules); - free(manager->cgroup); - safe_close(manager->fd_ep); - safe_close(manager->fd_signal); safe_close(manager->fd_inotify); safe_close_pair(manager->worker_watch); @@ -328,17 +351,23 @@ static void worker_spawn(Manager *manager, struct event *event) { dev = event->dev; event->dev = NULL; + unsetenv("NOTIFY_SOCKET"); + manager_workers_free(manager); event_queue_cleanup(manager, EVENT_UNDEF); manager->monitor = udev_monitor_unref(manager->monitor); manager->ctrl_conn_blocking = udev_ctrl_connection_unref(manager->ctrl_conn_blocking); manager->ctrl = udev_ctrl_unref(manager->ctrl); - - manager->fd_ep = safe_close(manager->fd_ep); - manager->fd_signal = safe_close(manager->fd_signal); + manager->ctrl_conn_blocking = udev_ctrl_connection_unref(manager->ctrl_conn_blocking); manager->worker_watch[READ_END] = safe_close(manager->worker_watch[READ_END]); + manager->ctrl_event = sd_event_source_unref(manager->ctrl_event); + manager->uevent_event = sd_event_source_unref(manager->uevent_event); + manager->inotify_event = sd_event_source_unref(manager->inotify_event); + + manager->event = sd_event_unref(manager->event); + sigfillset(&mask); fd_signal = signalfd(-1, &mask, SFD_NONBLOCK|SFD_CLOEXEC); if (fd_signal < 0) { @@ -372,6 +401,8 @@ static void worker_spawn(Manager *manager, struct event *event) { struct udev_event *udev_event; int fd_lock = -1; + assert(dev); + log_debug("seq %llu running", udev_device_get_seqnum(dev)); udev_event = udev_event_new(dev); if (udev_event == NULL) { @@ -379,9 +410,6 @@ static void worker_spawn(Manager *manager, struct event *event) { goto out; } - /* needed for SIGCHLD/SIGTERM in spawn() */ - udev_event->fd_signal = fd_signal; - if (arg_exec_delay > 0) udev_event->exec_delay = arg_exec_delay; @@ -420,12 +448,10 @@ static void worker_spawn(Manager *manager, struct event *event) { udev_event_execute_rules(udev_event, arg_event_timeout_usec, arg_event_timeout_warn_usec, &manager->properties, - manager->rules, - &manager->sigmask_orig); + manager->rules); udev_event_execute_run(udev_event, - arg_event_timeout_usec, arg_event_timeout_warn_usec, - &manager->sigmask_orig); + arg_event_timeout_usec, arg_event_timeout_warn_usec); if (udev_event->rtnl) /* in case rtnl was initialized */ @@ -454,11 +480,6 @@ skip: udev_device_unref(dev); dev = NULL; - if (udev_event->sigterm) { - udev_event_unref(udev_event); - goto out; - } - udev_event_unref(udev_event); /* wait for more device messages from main udevd, or term signal */ @@ -689,11 +710,104 @@ static bool is_devpath_busy(Manager *manager, struct event *event) { return false; } +static int on_exit_timeout(sd_event_source *s, uint64_t usec, void *userdata) { + Manager *manager = userdata; + + assert(manager); + + log_error_errno(ETIMEDOUT, "giving up waiting for workers to finish"); + + sd_event_exit(manager->event, -ETIMEDOUT); + + return 1; +} + +static void manager_exit(Manager *manager) { + uint64_t usec; + int r; + + assert(manager); + + manager->exit = true; + + sd_notify(false, + "STOPPING=1\n" + "STATUS=Starting shutdown..."); + + /* close sources of new events and discard buffered events */ + manager->ctrl = udev_ctrl_unref(manager->ctrl); + manager->ctrl_event = sd_event_source_unref(manager->ctrl_event); + + manager->fd_inotify = safe_close(manager->fd_inotify); + manager->inotify_event = sd_event_source_unref(manager->inotify_event); + + manager->monitor = udev_monitor_unref(manager->monitor); + manager->uevent_event = sd_event_source_unref(manager->uevent_event); + + /* discard queued events and kill workers */ + event_queue_cleanup(manager, EVENT_QUEUED); + manager_kill_workers(manager); + + r = sd_event_now(manager->event, clock_boottime_or_monotonic(), &usec); + if (r < 0) + return; + + r = sd_event_add_time(manager->event, NULL, clock_boottime_or_monotonic(), + usec + 30 * USEC_PER_SEC, USEC_PER_SEC, on_exit_timeout, manager); + if (r < 0) + return; +} + +/* reload requested, HUP signal received, rules changed, builtin changed */ +static void manager_reload(Manager *manager) { + + assert(manager); + + sd_notify(false, + "RELOADING=1\n" + "STATUS=Flushing configuration..."); + + manager_kill_workers(manager); + manager->rules = udev_rules_unref(manager->rules); + udev_builtin_exit(manager->udev); + + sd_notify(false, + "READY=1\n" + "STATUS=Processing..."); +} + static void event_queue_start(Manager *manager) { struct udev_list_node *loop; + usec_t usec; + int r; assert(manager); + if (udev_list_node_is_empty(&manager->events) || + manager->exit || manager->stop_exec_queue) + return; + + r = sd_event_now(manager->event, clock_boottime_or_monotonic(), &usec); + if (r >= 0) { + /* check for changed config, every 3 seconds at most */ + if (manager->last_usec == 0 || + (usec - manager->last_usec) > 3 * USEC_PER_SEC) { + if (udev_rules_check_timestamp(manager->rules) || + udev_builtin_validate(manager->udev)) + manager_reload(manager); + + manager->last_usec = usec; + } + } + + udev_builtin_init(manager->udev); + + if (!manager->rules) { + manager->rules = udev_rules_new(manager->udev, arg_resolve_names); + if (!manager->rules) + return; + } + udev_list_node_foreach(loop, &manager->events) { struct event *event = node_to_event(loop); @@ -787,6 +901,9 @@ static int on_worker(sd_event_source *s, int fd, uint32_t revents, void *userdat event_free(worker->event); } + /* we have free workers, try to schedule events */ + event_queue_start(manager); + return 1; } @@ -803,6 +920,9 @@ static int on_uevent(sd_event_source *s, int fd, uint32_t revents, void *userdat r = event_queue_insert(manager, dev); if (r < 0) udev_device_unref(dev); + else + /* we have fresh events, try to schedule them */ + event_queue_start(manager); } return 1; @@ -841,11 +961,12 @@ static int on_ctrl_msg(sd_event_source *s, int fd, uint32_t revents, void *userd if (udev_ctrl_get_start_exec_queue(ctrl_msg) > 0) { log_debug("udevd message (START_EXEC_QUEUE) received"); manager->stop_exec_queue = false; + event_queue_start(manager); } if (udev_ctrl_get_reload(ctrl_msg) > 0) { log_debug("udevd message (RELOAD) received"); - manager->reload = true; + manager_reload(manager); } str = udev_ctrl_get_set_env(ctrl_msg); @@ -884,7 +1005,7 @@ static int on_ctrl_msg(sd_event_source *s, int fd, uint32_t revents, void *userd if (udev_ctrl_get_exit(ctrl_msg) > 0) { log_debug("udevd message (EXIT) received"); - manager->exit = true; + manager_exit(manager); /* keep reference to block the client until we exit TODO: deal with several blocking exit requests */ manager->ctrl_conn_blocking = udev_ctrl_connection_ref(ctrl_conn); @@ -1042,7 +1163,7 @@ static int on_sigterm(sd_event_source *s, const struct signalfd_siginfo *si, voi assert(manager); - manager->exit = true; + manager_exit(manager); return 1; } @@ -1052,7 +1173,7 @@ static int on_sighup(sd_event_source *s, const struct signalfd_siginfo *si, void assert(manager); - manager->reload = true; + manager_reload(manager); return 1; } @@ -1107,41 +1228,124 @@ static int on_sigchld(sd_event_source *s, const struct signalfd_siginfo *si, voi worker_free(worker); } + /* we can start new workers, try to schedule events */ + event_queue_start(manager); + + return 1; +} + +static int on_post(sd_event_source *s, void *userdata) { + Manager *manager = userdata; + int r; + + assert(manager); + + if (udev_list_node_is_empty(&manager->events)) { + /* no pending events */ + if (!hashmap_isempty(manager->workers)) { + /* there are idle workers */ + log_debug("cleanup idle workers"); + manager_kill_workers(manager); + } else { + /* we are idle */ + if (manager->exit) { + r = sd_event_exit(manager->event, 0); + if (r < 0) + return r; + } else if (manager->cgroup) + /* cleanup possible left-over processes in our cgroup */ + cg_kill(SYSTEMD_CGROUP_CONTROLLER, manager->cgroup, SIGKILL, false, true, NULL); + } + } + return 1; } -static int systemd_fds(int *rctrl, int *rnetlink) { - int ctrl = -1, netlink = -1; - int fd, n; +static int listen_fds(int *rctrl, int *rnetlink) { + _cleanup_udev_unref_ struct udev *udev = NULL; + int ctrl_fd = -1, netlink_fd = -1; + int fd, n, r; + + assert(rctrl); + assert(rnetlink); n = sd_listen_fds(true); - if (n <= 0) - return -1; + if (n < 0) + return n; for (fd = SD_LISTEN_FDS_START; fd < n + SD_LISTEN_FDS_START; fd++) { if (sd_is_socket(fd, AF_LOCAL, SOCK_SEQPACKET, -1)) { - if (ctrl >= 0) - return -1; - ctrl = fd; + if (ctrl_fd >= 0) + return -EINVAL; + ctrl_fd = fd; continue; } if (sd_is_socket(fd, AF_NETLINK, SOCK_RAW, -1)) { - if (netlink >= 0) - return -1; - netlink = fd; + if (netlink_fd >= 0) + return -EINVAL; + netlink_fd = fd; continue; } - return -1; + return -EINVAL; + } + + if (ctrl_fd < 0) { + _cleanup_udev_ctrl_unref_ struct udev_ctrl *ctrl = NULL; + + udev = udev_new(); + if (!udev) + return -ENOMEM; + + ctrl = udev_ctrl_new(udev); + if (!ctrl) + return log_error_errno(EINVAL, "error initializing udev control socket"); + + r = udev_ctrl_enable_receiving(ctrl); + if (r < 0) + return log_error_errno(EINVAL, "error binding udev control socket"); + + fd = udev_ctrl_get_fd(ctrl); + if (fd < 0) + return log_error_errno(EIO, "could not get ctrl fd"); + + ctrl_fd = fcntl(fd, F_DUPFD_CLOEXEC, 3); + if (ctrl_fd < 0) + return log_error_errno(errno, "could not dup ctrl fd: %m"); } - if (ctrl < 0 || netlink < 0) - return -1; + if (netlink_fd < 0) { + _cleanup_udev_monitor_unref_ struct udev_monitor *monitor = NULL; + + if (!udev) { + udev = udev_new(); + if (!udev) + return -ENOMEM; + } + + monitor = udev_monitor_new_from_netlink(udev, "kernel"); + if (!monitor) + return log_error_errno(EINVAL, "error initializing netlink socket"); + + (void) udev_monitor_set_receive_buffer_size(monitor, 128 * 1024 * 1024); + + r = udev_monitor_enable_receiving(monitor); + if (r < 0) + return log_error_errno(EINVAL, "error binding netlink socket"); + + fd = udev_monitor_get_fd(monitor); + if (fd < 0) + return log_error_errno(netlink_fd, "could not get uevent fd: %m"); + + netlink_fd = fcntl(fd, F_DUPFD_CLOEXEC, 3); + if (ctrl_fd < 0) + return log_error_errno(errno, "could not dup netlink fd: %m"); + } + + *rctrl = ctrl_fd; + *rnetlink = netlink_fd; - log_debug("ctrl=%i netlink=%i", ctrl, netlink); - *rctrl = ctrl; - *rnetlink = netlink; return 0; } @@ -1286,19 +1490,18 @@ static int parse_argv(int argc, char *argv[]) { return 1; } -static int manager_new(Manager **ret) { +static int manager_new(Manager **ret, int fd_ctrl, int fd_uevent, const char *cgroup) { _cleanup_(manager_freep) Manager *manager = NULL; + int r, fd_worker, one = 1; assert(ret); + assert(fd_ctrl >= 0); + assert(fd_uevent >= 0); manager = new0(Manager, 1); if (!manager) return log_oom(); - manager->fd_ep = -1; - manager->fd_ctrl = -1; - manager->fd_uevent = -1; - manager->fd_signal = -1; manager->fd_inotify = -1; manager->worker_watch[WRITE_END] = -1; manager->worker_watch[READ_END] = -1; @@ -1316,110 +1519,98 @@ static int manager_new(Manager **ret) { udev_list_node_init(&manager->events); udev_list_init(manager->udev, &manager->properties, true); - *ret = manager; - manager = NULL; + manager->cgroup = cgroup; - return 0; -} + manager->ctrl = udev_ctrl_new_from_fd(manager->udev, fd_ctrl); + if (!manager->ctrl) + return log_error_errno(EINVAL, "error taking over udev control socket"); -static int manager_listen(Manager *manager) { - struct epoll_event ep_ctrl = { .events = EPOLLIN }; - struct epoll_event ep_inotify = { .events = EPOLLIN }; - struct epoll_event ep_signal = { .events = EPOLLIN }; - struct epoll_event ep_netlink = { .events = EPOLLIN }; - struct epoll_event ep_worker = { .events = EPOLLIN }; - sigset_t mask; - int r, one = 1; + manager->monitor = udev_monitor_new_from_netlink_fd(manager->udev, "kernel", fd_uevent); + if (!manager->monitor) + return log_error_errno(EINVAL, "error taking over netlink socket"); - assert(manager); + /* unnamed socket from workers to the main daemon */ + r = socketpair(AF_LOCAL, SOCK_DGRAM|SOCK_CLOEXEC, 0, manager->worker_watch); + if (r < 0) + return log_error_errno(errno, "error creating socketpair: %m"); - r = systemd_fds(&manager->fd_ctrl, &manager->fd_uevent); - if (r >= 0) { - /* get control and netlink socket from systemd */ - manager->ctrl = udev_ctrl_new_from_fd(manager->udev, manager->fd_ctrl); - if (!manager->ctrl) - return log_error_errno(EINVAL, "error taking over udev control socket"); + fd_worker = manager->worker_watch[READ_END]; - manager->monitor = udev_monitor_new_from_netlink_fd(manager->udev, "kernel", manager->fd_uevent); - if (!manager->monitor) - return log_error_errno(EINVAL, "error taking over netlink socket"); + r = setsockopt(fd_worker, SOL_SOCKET, SO_PASSCRED, &one, sizeof(one)); + if (r < 0) + return log_error_errno(errno, "could not enable SO_PASSCRED: %m"); - /* get our own cgroup, we regularly kill everything udev has left behind */ - r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, 0, &manager->cgroup); - if (r < 0) - log_warning_errno(r, "failed to get cgroup: %m"); - } else { - /* open control and netlink socket */ - manager->ctrl = udev_ctrl_new(manager->udev); - if (!manager->ctrl) - return log_error_errno(EINVAL, "error initializing udev control socket"); + manager->fd_inotify = udev_watch_init(manager->udev); + if (manager->fd_inotify < 0) + return log_error_errno(ENOMEM, "error initializing inotify"); - manager->fd_ctrl = udev_ctrl_get_fd(manager->ctrl); + udev_watch_restore(manager->udev); - manager->monitor = udev_monitor_new_from_netlink(manager->udev, "kernel"); - if (!manager->monitor) - return log_error_errno(EINVAL, "error initializing netlink socket"); + /* block and listen to all signals on signalfd */ + assert_se(sigprocmask_many(SIG_BLOCK, SIGTERM, SIGINT, SIGHUP, SIGCHLD, -1) == 0); - manager->fd_uevent = udev_monitor_get_fd(manager->monitor); + r = sd_event_default(&manager->event); + if (r < 0) + return log_error_errno(errno, "could not allocate event loop: %m"); - (void) udev_monitor_set_receive_buffer_size(manager->monitor, 128 * 1024 * 1024); - } + r = sd_event_add_signal(manager->event, NULL, SIGINT, on_sigterm, manager); + if (r < 0) + return log_error_errno(r, "error creating sigint event source: %m"); - r = udev_monitor_enable_receiving(manager->monitor); + r = sd_event_add_signal(manager->event, NULL, SIGTERM, on_sigterm, manager); if (r < 0) - return log_error_errno(EINVAL, "error binding netlink socket"); + return log_error_errno(r, "error creating sigterm event source: %m"); - r = udev_ctrl_enable_receiving(manager->ctrl); + r = sd_event_add_signal(manager->event, NULL, SIGHUP, on_sighup, manager); if (r < 0) - return log_error_errno(EINVAL, "error binding udev control socket"); + return log_error_errno(r, "error creating sighup event source: %m"); - /* unnamed socket from workers to the main daemon */ - r = socketpair(AF_LOCAL, SOCK_DGRAM|SOCK_CLOEXEC, 0, manager->worker_watch); + r = sd_event_add_signal(manager->event, NULL, SIGCHLD, on_sigchld, manager); if (r < 0) - return log_error_errno(errno, "error creating socketpair: %m"); + return log_error_errno(r, "error creating sigchld event source: %m"); - manager->fd_worker = manager->worker_watch[READ_END]; + r = sd_event_set_watchdog(manager->event, true); + if (r < 0) + return log_error_errno(r, "error creating watchdog event source: %m"); - r = setsockopt(manager->fd_worker, SOL_SOCKET, SO_PASSCRED, &one, sizeof(one)); + r = sd_event_add_io(manager->event, &manager->ctrl_event, fd_ctrl, EPOLLIN, on_ctrl_msg, manager); if (r < 0) - return log_error_errno(errno, "could not enable SO_PASSCRED: %m"); + return log_error_errno(r, "error creating ctrl event source: %m"); - manager->fd_inotify = udev_watch_init(manager->udev); - if (manager->fd_inotify < 0) - return log_error_errno(ENOMEM, "error initializing inotify"); + /* This needs to be after the inotify and uevent handling, to make sure + * that the ping is send back after fully processing the pending uevents + * (including the synthetic ones we may create due to inotify events). + */ + r = sd_event_source_set_priority(manager->ctrl_event, SD_EVENT_PRIORITY_IDLE); + if (r < 0) + return log_error_errno(r, "cold not set IDLE event priority for ctrl event source: %m"); - udev_watch_restore(manager->udev); + r = sd_event_add_io(manager->event, &manager->inotify_event, manager->fd_inotify, EPOLLIN, on_inotify, manager); + if (r < 0) + return log_error_errno(r, "error creating inotify event source: %m"); - /* block and listen to all signals on signalfd */ - sigfillset(&mask); - sigprocmask(SIG_SETMASK, &mask, &manager->sigmask_orig); - manager->fd_signal = signalfd(-1, &mask, SFD_NONBLOCK|SFD_CLOEXEC); - if (manager->fd_signal < 0) - return log_error_errno(errno, "error creating signalfd"); - - ep_ctrl.data.fd = manager->fd_ctrl; - ep_inotify.data.fd = manager->fd_inotify; - ep_signal.data.fd = manager->fd_signal; - ep_netlink.data.fd = manager->fd_uevent; - ep_worker.data.fd = manager->fd_worker; - - manager->fd_ep = epoll_create1(EPOLL_CLOEXEC); - if (manager->fd_ep < 0) - return log_error_errno(errno, "error creating epoll fd: %m"); - - if (epoll_ctl(manager->fd_ep, EPOLL_CTL_ADD, manager->fd_ctrl, &ep_ctrl) < 0 || - epoll_ctl(manager->fd_ep, EPOLL_CTL_ADD, manager->fd_inotify, &ep_inotify) < 0 || - epoll_ctl(manager->fd_ep, EPOLL_CTL_ADD, manager->fd_signal, &ep_signal) < 0 || - epoll_ctl(manager->fd_ep, EPOLL_CTL_ADD, manager->fd_uevent, &ep_netlink) < 0 || - epoll_ctl(manager->fd_ep, EPOLL_CTL_ADD, manager->fd_worker, &ep_worker) < 0) - return log_error_errno(errno, "fail to add fds to epoll: %m"); + r = sd_event_add_io(manager->event, &manager->uevent_event, fd_uevent, EPOLLIN, on_uevent, manager); + if (r < 0) + return log_error_errno(r, "error creating uevent event source: %m"); + + r = sd_event_add_io(manager->event, NULL, fd_worker, EPOLLIN, on_worker, manager); + if (r < 0) + return log_error_errno(r, "error creating worker event source: %m"); + + r = sd_event_add_post(manager->event, NULL, on_post, manager); + if (r < 0) + return log_error_errno(r, "error creating post event source: %m"); + + *ret = manager; + manager = NULL; return 0; } int main(int argc, char *argv[]) { _cleanup_(manager_freep) Manager *manager = NULL; - int r; + _cleanup_free_ char *cgroup = NULL; + int r, fd_ctrl, fd_uevent; log_set_target(LOG_TARGET_AUTO); log_parse_environment(); @@ -1453,23 +1644,6 @@ int main(int argc, char *argv[]) { log_debug("set children_max to %u", arg_children_max); } - /* before opening new files, make sure std{in,out,err} fds are in a sane state */ - if (arg_daemonize) { - int fd; - - fd = open("/dev/null", O_RDWR); - if (fd < 0) - log_error("cannot open /dev/null"); - else { - if (write(STDOUT_FILENO, 0, 0) < 0) - dup2(fd, STDOUT_FILENO); - if (write(STDERR_FILENO, 0, 0) < 0) - dup2(fd, STDERR_FILENO); - if (fd > STDERR_FILENO) - close(fd); - } - } - /* set umask before creating any file/directory */ r = chdir("/"); if (r < 0) { @@ -1493,19 +1667,26 @@ int main(int argc, char *argv[]) { dev_setup(NULL, UID_INVALID, GID_INVALID); - r = manager_new(&manager); - if (r < 0) - goto exit; - - log_info("starting version " VERSION); + if (getppid() == 1) { + /* get our own cgroup, we regularly kill everything udev has left behind + we only do this on systemd systems, and only if we are directly spawned + by PID1. otherwise we are not guaranteed to have a dedicated cgroup */ + r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, 0, &cgroup); + if (r < 0) + log_warning_errno(r, "failed to get cgroup: %m"); + } - r = udev_rules_apply_static_dev_perms(manager->rules); - if (r < 0) - log_error_errno(r, "failed to apply permissions on static device nodes: %m"); + r = listen_fds(&fd_ctrl, &fd_uevent); + if (r < 0) { + r = log_error_errno(r, "could not listen on fds: %m"); + goto exit; + } if (arg_daemonize) { pid_t pid; + log_info("starting version " VERSION); + pid = fork(); switch (pid) { case 0: @@ -1522,192 +1703,35 @@ int main(int argc, char *argv[]) { setsid(); write_string_file("/proc/self/oom_score_adj", "-1000"); - } else - sd_notify(1, "READY=1"); - - r = manager_listen(manager); - if (r < 0) - return log_error_errno(r, "failed to set up fds and listen for events: %m"); - - for (;;) { - static usec_t last_usec; - struct epoll_event ev[8]; - int fdcount; - int timeout; - bool is_worker, is_signal, is_inotify, is_uevent, is_ctrl; - int i; - - if (manager->exit) { - /* close sources of new events and discard buffered events */ - if (manager->fd_ctrl >= 0) { - epoll_ctl(manager->fd_ep, EPOLL_CTL_DEL, manager->fd_ctrl, NULL); - manager->fd_ctrl = safe_close(manager->fd_ctrl); - } - - if (manager->monitor) { - epoll_ctl(manager->fd_ep, EPOLL_CTL_DEL, manager->fd_uevent, NULL); - manager->monitor = udev_monitor_unref(manager->monitor); - } - - if (manager->fd_inotify >= 0) { - epoll_ctl(manager->fd_ep, EPOLL_CTL_DEL, manager->fd_inotify, NULL); - manager->fd_inotify = safe_close(manager->fd_inotify); - } - - /* discard queued events and kill workers */ - event_queue_cleanup(manager, EVENT_QUEUED); - manager_kill_workers(manager); - - /* exit after all has cleaned up */ - if (udev_list_node_is_empty(&manager->events) && hashmap_isempty(manager->workers)) - break; - - /* timeout at exit for workers to finish */ - timeout = 30 * MSEC_PER_SEC; - } else if (udev_list_node_is_empty(&manager->events) && hashmap_isempty(manager->workers)) { - /* we are idle */ - timeout = -1; - - /* cleanup possible left-over processes in our cgroup */ - if (manager->cgroup) - cg_kill(SYSTEMD_CGROUP_CONTROLLER, manager->cgroup, SIGKILL, false, true, NULL); - } else { - /* kill idle or hanging workers */ - timeout = 3 * MSEC_PER_SEC; - } - - fdcount = epoll_wait(manager->fd_ep, ev, ELEMENTSOF(ev), timeout); - if (fdcount < 0) - continue; - - if (fdcount == 0) { - struct worker *worker; - Iterator j; - - /* timeout */ - if (manager->exit) { - log_error("timeout, giving up waiting for workers to finish"); - break; - } - - /* kill idle workers */ - if (udev_list_node_is_empty(&manager->events)) { - log_debug("cleanup idle workers"); - manager_kill_workers(manager); - } - - /* check for hanging events */ - HASHMAP_FOREACH(worker, manager->workers, j) { - struct event *event = worker->event; - usec_t ts; - - if (worker->state != WORKER_RUNNING) - continue; - - assert(event); - - ts = now(CLOCK_MONOTONIC); - - if ((ts - event->start_usec) > arg_event_timeout_warn_usec) { - if ((ts - event->start_usec) > arg_event_timeout_usec) - on_event_timeout(NULL, 0, event); - else if (!event->warned) { - on_event_timeout_warning(NULL, 0, event); - event->warned = true; - } - } - } - - } - - is_worker = is_signal = is_inotify = is_uevent = is_ctrl = false; - for (i = 0; i < fdcount; i++) { - if (ev[i].data.fd == manager->fd_worker && ev[i].events & EPOLLIN) - is_worker = true; - else if (ev[i].data.fd == manager->fd_uevent && ev[i].events & EPOLLIN) - is_uevent = true; - else if (ev[i].data.fd == manager->fd_signal && ev[i].events & EPOLLIN) - is_signal = true; - else if (ev[i].data.fd == manager->fd_inotify && ev[i].events & EPOLLIN) - is_inotify = true; - else if (ev[i].data.fd == manager->fd_ctrl && ev[i].events & EPOLLIN) - is_ctrl = true; - } - - /* check for changed config, every 3 seconds at most */ - if ((now(CLOCK_MONOTONIC) - last_usec) > 3 * USEC_PER_SEC) { - if (udev_rules_check_timestamp(manager->rules)) - manager->reload = true; - if (udev_builtin_validate(manager->udev)) - manager->reload = true; - - last_usec = now(CLOCK_MONOTONIC); - } - - /* reload requested, HUP signal received, rules changed, builtin changed */ - if (manager->reload) { - manager_kill_workers(manager); - manager->rules = udev_rules_unref(manager->rules); - udev_builtin_exit(manager->udev); - manager->reload = false; - } - - /* event has finished */ - if (is_worker) - on_worker(NULL, manager->fd_worker, 0, manager); - - /* uevent from kernel */ - if (is_uevent) - on_uevent(NULL, manager->fd_uevent, 0, manager); - - /* start new events */ - if (!udev_list_node_is_empty(&manager->events) && !manager->exit && !manager->stop_exec_queue) { - udev_builtin_init(manager->udev); - if (!manager->rules) - manager->rules = udev_rules_new(manager->udev, arg_resolve_names); - if (manager->rules) - event_queue_start(manager); - } + } - if (is_signal) { - struct signalfd_siginfo fdsi; - ssize_t size; - - size = read(manager->fd_signal, &fdsi, sizeof(struct signalfd_siginfo)); - if (size == sizeof(struct signalfd_siginfo)) { - switch (fdsi.ssi_signo) { - case SIGINT: - case SIGTERM: - on_sigterm(NULL, &fdsi, manager); - break; - case SIGHUP: - on_sighup(NULL, &fdsi, manager); - break; - case SIGCHLD: - on_sigchld(NULL, &fdsi, manager); - break; - } - } - } + r = manager_new(&manager, fd_ctrl, fd_uevent, cgroup); + if (r < 0) { + r = log_error_errno(r, "failed to allocate manager object: %m"); + goto exit; + } - /* we are shutting down, the events below are not handled anymore */ - if (manager->exit) - continue; + r = udev_rules_apply_static_dev_perms(manager->rules); + if (r < 0) + log_error_errno(r, "failed to apply permissions on static device nodes: %m"); - /* device node watch */ - if (is_inotify) - on_inotify(NULL, manager->fd_inotify, 0, manager); + (void) sd_notify(false, + "READY=1\n" + "STATUS=Processing..."); - /* - * This needs to be after the inotify handling, to make sure, - * that the ping is send back after the possibly generated - * "change" events by the inotify device node watch. - */ - if (is_ctrl) - on_ctrl_msg(NULL, manager->fd_ctrl, 0, manager); + r = sd_event_loop(manager->event); + if (r < 0) { + log_error_errno(r, "event loop failed: %m"); + goto exit; } + sd_event_get_exit_code(manager->event, &r); + exit: + sd_notify(false, + "STOPPING=1\n" + "STATUS=Shutting down..."); + if (manager) udev_ctrl_cleanup(manager->ctrl); mac_selinux_finish(); |