diff options
Diffstat (limited to 'src')
144 files changed, 1281 insertions, 3744 deletions
diff --git a/src/activate/activate.c b/src/activate/activate.c index d345e28567..5318829442 100644 --- a/src/activate/activate.c +++ b/src/activate/activate.c @@ -33,6 +33,7 @@ #include "log.h" #include "strv.h" #include "macro.h" +#include "signal-util.h" static char** arg_listen = NULL; static bool arg_accept = false; @@ -192,6 +193,10 @@ static int launch1(const char* child, char** argv, char **env, int fd) { /* In the child */ if (child_pid == 0) { + + (void) reset_all_signal_handlers(); + (void) reset_signal_mask(); + r = dup2(fd, STDIN_FILENO); if (r < 0) { log_error_errno(errno, "Failed to dup connection to stdin: %m"); diff --git a/src/bootchart/bootchart.c b/src/bootchart/bootchart.c index 45fab92598..3360bc85be 100644 --- a/src/bootchart/bootchart.c +++ b/src/bootchart/bootchart.c @@ -531,7 +531,7 @@ int main(int argc, char *argv[]) { /* don't complain when overrun once, happens most commonly on 1st sample */ if (overrun > 1) - log_warning("systemd-boochart: sample time overrun %i times\n", overrun); + log_warning("systemd-bootchart: sample time overrun %i times\n", overrun); return 0; } diff --git a/src/core/busname.c b/src/core/busname.c index 11f3b98009..2085721546 100644 --- a/src/core/busname.c +++ b/src/core/busname.c @@ -125,7 +125,7 @@ static int busname_arm_timer(BusName *n) { return sd_event_source_set_enabled(n->timer_event_source, SD_EVENT_ONESHOT); } - r = sd_event_add_time( + r = sd_event_add_time( UNIT(n)->manager->event, &n->timer_event_source, CLOCK_MONOTONIC, @@ -408,8 +408,8 @@ static int busname_make_starter(BusName *n, pid_t *_pid) { if (pid == 0) { int ret; - default_signals(SIGNALS_CRASH_HANDLER, SIGNALS_IGNORE, -1); - ignore_signals(SIGPIPE, -1); + (void) default_signals(SIGNALS_CRASH_HANDLER, SIGNALS_IGNORE, -1); + (void) ignore_signals(SIGPIPE, -1); log_forget_fds(); r = bus_kernel_make_starter(n->starter_fd, n->name, n->activating, n->accept_fd, n->policy, n->policy_world); diff --git a/src/core/execute.c b/src/core/execute.c index 4120493bda..f13c6936e0 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -823,6 +823,7 @@ static int setup_pam( /* Block SIGTERM, so that we know that it won't get lost in * the child */ + if (sigemptyset(&ss) < 0 || sigaddset(&ss, SIGTERM) < 0 || sigprocmask(SIG_BLOCK, &ss, &old_ss) < 0) @@ -857,6 +858,8 @@ static int setup_pam( if (setresuid(uid, uid, uid) < 0) log_error_errno(r, "Error: Failed to setresuid() in sd-pam: %m"); + (void) ignore_signals(SIGPIPE, -1); + /* Wait until our parent died. This will only work if * the above setresuid() succeeds, otherwise the kernel * will not allow unprivileged parents kill their privileged @@ -1324,11 +1327,11 @@ static int exec_child( * others we leave untouched because we set them to * SIG_DFL or a valid handler initially, both of which * will be demoted to SIG_DFL. */ - default_signals(SIGNALS_CRASH_HANDLER, - SIGNALS_IGNORE, -1); + (void) default_signals(SIGNALS_CRASH_HANDLER, + SIGNALS_IGNORE, -1); if (context->ignore_sigpipe) - ignore_signals(SIGPIPE, -1); + (void) ignore_signals(SIGPIPE, -1); r = reset_signal_mask(); if (r < 0) { 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/killall.c b/src/core/killall.c index 6e85923581..2a9d72c901 100644 --- a/src/core/killall.c +++ b/src/core/killall.c @@ -158,6 +158,7 @@ static int killall(int sig, Set *pids, bool send_sighup) { while ((d = readdir(dir))) { pid_t pid; + int r; if (d->d_type != DT_DIR && d->d_type != DT_UNKNOWN) @@ -177,8 +178,11 @@ static int killall(int sig, Set *pids, bool send_sighup) { } if (kill(pid, sig) >= 0) { - if (pids) - set_put(pids, ULONG_TO_PTR(pid)); + if (pids) { + r = set_put(pids, ULONG_TO_PTR(pid)); + if (r < 0) + log_oom(); + } } else if (errno != ENOENT) log_warning_errno(errno, "Could not kill %d: %m", pid); diff --git a/src/core/kmod-setup.c b/src/core/kmod-setup.c index 6cc5951719..cf543c81a3 100644 --- a/src/core/kmod-setup.c +++ b/src/core/kmod-setup.c @@ -53,26 +53,27 @@ int kmod_setup(void) { static const struct { const char *module; const char *path; - bool warn; + bool warn_if_unavailable:1; + bool warn_if_module:1; bool (*condition_fn)(void); } kmod_table[] = { /* auto-loading on use doesn't work before udev is up */ - { "autofs4", "/sys/class/misc/autofs", true, NULL }, + { "autofs4", "/sys/class/misc/autofs", true, false, NULL }, /* early configure of ::1 on the loopback device */ - { "ipv6", "/sys/module/ipv6", true, NULL }, + { "ipv6", "/sys/module/ipv6", false, true, NULL }, /* this should never be a module */ - { "unix", "/proc/net/unix", true, NULL }, + { "unix", "/proc/net/unix", true, true, NULL }, #ifdef ENABLE_KDBUS /* IPC is needed before we bring up any other services */ - { "kdbus", "/sys/fs/kdbus", false, is_kdbus_wanted }, + { "kdbus", "/sys/fs/kdbus", false, false, is_kdbus_wanted }, #endif #ifdef HAVE_LIBIPTC /* netfilter is needed by networkd, nspawn among others, and cannot be autoloaded */ - { "ip_tables", "/proc/net/ip_tables_names", false, NULL }, + { "ip_tables", "/proc/net/ip_tables_names", false, false, NULL }, #endif }; struct kmod_ctx *ctx = NULL; @@ -91,7 +92,7 @@ int kmod_setup(void) { if (kmod_table[i].condition_fn && !kmod_table[i].condition_fn()) continue; - if (kmod_table[i].warn) + if (kmod_table[i].warn_if_module) log_debug("Your kernel apparently lacks built-in %s support. Might be " "a good idea to compile it in. We'll now try to work around " "this by loading the module...", kmod_table[i].module); @@ -116,8 +117,9 @@ int kmod_setup(void) { log_info("Inserted module '%s'", kmod_module_get_name(mod)); else if (r == KMOD_PROBE_APPLY_BLACKLIST) log_info("Module '%s' is blacklisted", kmod_module_get_name(mod)); - else if (kmod_table[i].warn) - log_error("Failed to insert module '%s'", kmod_module_get_name(mod)); + else + log_full((kmod_table[i].warn_if_unavailable || (r < 0 && r != -ENOENT)) ? LOG_ERR : LOG_DEBUG, + "Failed to insert module '%s'", kmod_module_get_name(mod)); kmod_module_unref(mod); } diff --git a/src/core/main.c b/src/core/main.c index 674e47e788..332453a0ea 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -1405,9 +1405,8 @@ int main(int argc, char *argv[]) { } /* Reset all signal handlers. */ - assert_se(reset_all_signal_handlers() == 0); - - ignore_signals(SIGNALS_IGNORE, -1); + (void) reset_all_signal_handlers(); + (void) ignore_signals(SIGNALS_IGNORE, -1); if (parse_config_file() < 0) { error_message = "Failed to parse config file"; @@ -1606,14 +1605,10 @@ int main(int argc, char *argv[]) { } } - if (arg_running_as == MANAGER_USER) { + if (arg_running_as == MANAGER_USER) /* Become reaper of our children */ - if (prctl(PR_SET_CHILD_SUBREAPER, 1) < 0) { + if (prctl(PR_SET_CHILD_SUBREAPER, 1) < 0) log_warning_errno(errno, "Failed to make us a subreaper: %m"); - if (errno == EINVAL) - log_info("Perhaps the kernel version is too old (< 3.4?)"); - } - } if (arg_running_as == MANAGER_SYSTEM) { bump_rlimit_nofile(&saved_rlimit_nofile); @@ -1935,8 +1930,8 @@ finish: /* Reenable any blocked signals, especially important * if we switch from initial ramdisk to init=... */ - reset_all_signal_handlers(); - reset_signal_mask(); + (void) reset_all_signal_handlers(); + (void) reset_signal_mask(); if (switch_root_init) { args[0] = switch_root_init; diff --git a/src/core/manager.c b/src/core/manager.c index ae473d05c2..eb80dd1b46 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -665,7 +665,7 @@ static int manager_setup_notify(Manager *m) { if (m->notify_fd < 0) { _cleanup_close_ int fd = -1; - union sockaddr_union sa = { + union sockaddr_union sa = { .sa.sa_family = AF_UNIX, }; static const int one = 1; @@ -741,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); @@ -1549,7 +1546,7 @@ static int manager_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t return -errno; } - for (cmsg = CMSG_FIRSTHDR(&msghdr); cmsg; cmsg = CMSG_NXTHDR(&msghdr, cmsg)) { + CMSG_FOREACH(cmsg, &msghdr) { if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) { fd_array = (int*) CMSG_DATA(cmsg); 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 01a817bf23..045321e1d4 100644 --- a/src/core/namespace.c +++ b/src/core/namespace.c @@ -696,12 +696,11 @@ int setup_netns(int netns_storage_socket[2]) { } else { /* Yay, found something, so let's join the namespace */ - for (cmsg = CMSG_FIRSTHDR(&mh); cmsg; cmsg = CMSG_NXTHDR(&mh, cmsg)) { + CMSG_FOREACH(cmsg, &mh) if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) { assert(cmsg->cmsg_len == CMSG_LEN(sizeof(int))); netns = *(int*) CMSG_DATA(cmsg); } - } if (setns(netns, CLONE_NEWNET) < 0) { r = -errno; diff --git a/src/core/selinux-access.c b/src/core/selinux-access.c index 5e9a4a5e02..decd42f95a 100644 --- a/src/core/selinux-access.c +++ b/src/core/selinux-access.c @@ -261,7 +261,7 @@ int mac_selinux_generic_access_check( audit_info.path = path; audit_info.cmdline = cl; - r = selinux_check_access((security_context_t) scon, fcon, tclass, permission, &audit_info); + r = selinux_check_access(scon, fcon, tclass, permission, &audit_info); if (r < 0) r = sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "SELinux policy denies access."); diff --git a/src/core/socket.c b/src/core/socket.c index fc5eb1464a..d3178e642b 100644 --- a/src/core/socket.c +++ b/src/core/socket.c @@ -832,7 +832,7 @@ static void socket_apply_socket_options(Socket *s, int fd) { } if (s->keep_alive_interval) { - int value = s->keep_alive_interval / USEC_PER_SEC; + int value = s->keep_alive_interval / USEC_PER_SEC; if (setsockopt(fd, SOL_TCP, TCP_KEEPINTVL, &value, sizeof(value)) < 0) log_unit_warning_errno(UNIT(s), errno, "TCP_KEEPINTVL failed: %m"); } @@ -1473,8 +1473,8 @@ static int socket_chown(Socket *s, pid_t *_pid) { gid_t gid = GID_INVALID; int ret; - default_signals(SIGNALS_CRASH_HANDLER, SIGNALS_IGNORE, -1); - ignore_signals(SIGPIPE, -1); + (void) default_signals(SIGNALS_CRASH_HANDLER, SIGNALS_IGNORE, -1); + (void) ignore_signals(SIGPIPE, -1); log_forget_fds(); if (!isempty(s->user)) { @@ -2589,7 +2589,7 @@ static void socket_trigger_notify(Unit *u, Unit *other) { /* Don't propagate state changes from the service if we are already down or accepting connections */ - if ((s->state != SOCKET_RUNNING && + if ((s->state != SOCKET_RUNNING && s->state != SOCKET_LISTENING) || s->accept) return; diff --git a/src/cryptsetup/cryptsetup.c b/src/cryptsetup/cryptsetup.c index a5018f13ed..5c6c7c0ed8 100644 --- a/src/cryptsetup/cryptsetup.c +++ b/src/cryptsetup/cryptsetup.c @@ -238,6 +238,23 @@ static void log_glue(int level, const char *msg, void *usrptr) { log_debug("%s", msg); } +static int disk_major_minor(const char *path, char **ret) { + struct stat st; + + assert(path); + + if (stat(path, &st) < 0) + return -errno; + + if (!S_ISBLK(st.st_mode)) + return -EINVAL; + + if (asprintf(ret, "/dev/block/%d:%d", major(st.st_rdev), minor(st.st_rdev)) < 0) + return -errno; + + return 0; +} + static char* disk_description(const char *path) { static const char name_fields[] = @@ -295,20 +312,55 @@ static char *disk_mount_point(const char *label) { return NULL; } -static int get_password(const char *name, usec_t until, bool accept_cached, char ***passwords) { - int r; +static int get_password(const char *vol, const char *src, usec_t until, bool accept_cached, char ***passwords) { + int r = 0; char **p; _cleanup_free_ char *text = NULL; _cleanup_free_ char *escaped_name = NULL; char *id; + const char *name = NULL; + _cleanup_free_ char *description = NULL, *name_buffer = NULL, + *mount_point = NULL, *maj_min = NULL; - assert(name); + assert(vol); + assert(src); assert(passwords); + description = disk_description(src); + mount_point = disk_mount_point(vol); + + if (description && streq(vol, description)) { + /* If the description string is simply the + * volume name, then let's not show this + * twice */ + free(description); + description = NULL; + } + + if (mount_point && description) + r = asprintf(&name_buffer, "%s (%s) on %s", description, vol, mount_point); + else if (mount_point) + r = asprintf(&name_buffer, "%s on %s", vol, mount_point); + else if (description) + r = asprintf(&name_buffer, "%s (%s)", description, vol); + + if (r < 0) + return log_oom(); + + name = name_buffer ? name_buffer : vol; + if (asprintf(&text, "Please enter passphrase for disk %s!", name) < 0) return log_oom(); - escaped_name = cescape(name); + if (src) + (void) disk_major_minor(src, &maj_min); + + if (maj_min) { + escaped_name = maj_min; + maj_min = NULL; + } else + escaped_name = cescape(name); + if (!escaped_name) return log_oom(); @@ -552,8 +604,7 @@ int main(int argc, char *argv[]) { unsigned tries; usec_t until; crypt_status_info status; - const char *key_file = NULL, *name = NULL; - _cleanup_free_ char *description = NULL, *name_buffer = NULL, *mount_point = NULL; + const char *key_file = NULL; /* Arguments: systemd-cryptsetup attach VOLUME SOURCE-DEVICE [PASSWORD] [OPTIONS] */ @@ -581,31 +632,6 @@ int main(int argc, char *argv[]) { /* A delicious drop of snake oil */ mlockall(MCL_FUTURE); - description = disk_description(argv[3]); - mount_point = disk_mount_point(argv[2]); - - if (description && streq(argv[2], description)) { - /* If the description string is simply the - * volume name, then let's not show this - * twice */ - free(description); - description = NULL; - } - - k = 0; - if (mount_point && description) - k = asprintf(&name_buffer, "%s (%s) on %s", description, argv[2], mount_point); - else if (mount_point) - k = asprintf(&name_buffer, "%s on %s", argv[2], mount_point); - else if (description) - k = asprintf(&name_buffer, "%s (%s)", description, argv[2]); - - if (k < 0) { - log_oom(); - goto finish; - } - name = name_buffer ? name_buffer : argv[2]; - if (arg_header) { log_debug("LUKS header: %s", arg_header); k = crypt_init(&cd, arg_header); @@ -652,7 +678,7 @@ int main(int argc, char *argv[]) { _cleanup_strv_free_ char **passwords = NULL; if (!key_file) { - k = get_password(name, until, tries == 0 && !arg_verify, &passwords); + k = get_password(argv[2], argv[3], until, tries == 0 && !arg_verify, &passwords); if (k == -EAGAIN) continue; else if (k < 0) diff --git a/src/delta/delta.c b/src/delta/delta.c index c764bb4b46..b60aaef734 100644 --- a/src/delta/delta.c +++ b/src/delta/delta.c @@ -24,6 +24,7 @@ #include <string.h> #include <unistd.h> #include <getopt.h> +#include <sys/prctl.h> #include "hashmap.h" #include "util.h" @@ -34,6 +35,7 @@ #include "strv.h" #include "process-util.h" #include "terminal-util.h" +#include "signal-util.h" static const char prefixes[] = "/etc\0" @@ -189,9 +191,14 @@ static int found_override(const char *top, const char *bottom) { if (pid < 0) return log_error_errno(errno, "Failed to fork off diff: %m"); else if (pid == 0) { + + (void) reset_all_signal_handlers(); + (void) reset_signal_mask(); + assert_se(prctl(PR_SET_PDEATHSIG, SIGTERM) == 0); + execlp("diff", "diff", "-us", "--", bottom, top, NULL); log_error_errno(errno, "Failed to execute diff: %m"); - _exit(1); + _exit(EXIT_FAILURE); } wait_for_terminate_and_warn("diff", pid, false); diff --git a/src/fsck/fsck.c b/src/fsck/fsck.c index f0e5c5f239..30254b6680 100644 --- a/src/fsck/fsck.c +++ b/src/fsck/fsck.c @@ -394,8 +394,8 @@ int main(int argc, char *argv[]) { /* Child */ - reset_all_signal_handlers(); - reset_signal_mask(); + (void) reset_all_signal_handlers(); + (void) reset_signal_mask(); assert_se(prctl(PR_SET_PDEATHSIG, SIGTERM) == 0); /* Close the reading side of the progress pipe */ 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 d4bc88e010..e563bee96e 100644 --- a/src/import/export.c +++ b/src/import/export.c @@ -311,7 +311,7 @@ int main(int argc, char *argv[]) { if (r <= 0) goto finish; - ignore_signals(SIGPIPE, -1); + (void) ignore_signals(SIGPIPE, -1); r = export_main(argc, argv); diff --git a/src/import/import-common.c b/src/import/import-common.c index 9711614000..950c7b4acd 100644 --- a/src/import/import-common.c +++ b/src/import/import-common.c @@ -97,8 +97,8 @@ int import_fork_tar_x(const char *path, pid_t *ret) { /* Child */ - reset_all_signal_handlers(); - reset_signal_mask(); + (void) reset_all_signal_handlers(); + (void) reset_signal_mask(); assert_se(prctl(PR_SET_PDEATHSIG, SIGTERM) == 0); pipefd[1] = safe_close(pipefd[1]); @@ -171,8 +171,8 @@ int import_fork_tar_c(const char *path, pid_t *ret) { /* Child */ - reset_all_signal_handlers(); - reset_signal_mask(); + (void) reset_all_signal_handlers(); + (void) reset_signal_mask(); assert_se(prctl(PR_SET_PDEATHSIG, SIGTERM) == 0); pipefd[0] = safe_close(pipefd[0]); diff --git a/src/import/import.c b/src/import/import.c index fff5a104b1..3091ed1c45 100644 --- a/src/import/import.c +++ b/src/import/import.c @@ -328,7 +328,7 @@ int main(int argc, char *argv[]) { if (r <= 0) goto finish; - ignore_signals(SIGPIPE, -1); + (void) ignore_signals(SIGPIPE, -1); r = import_main(argc, argv); diff --git a/src/import/importd.c b/src/import/importd.c index 50566a6e5c..05a619ac0c 100644 --- a/src/import/importd.c +++ b/src/import/importd.c @@ -390,8 +390,8 @@ static int transfer_start(Transfer *t) { /* Child */ - reset_all_signal_handlers(); - reset_signal_mask(); + (void) reset_all_signal_handlers(); + (void) reset_signal_mask(); assert_se(prctl(PR_SET_PDEATHSIG, SIGTERM) == 0); pipefd[0] = safe_close(pipefd[0]); @@ -599,7 +599,7 @@ static int manager_on_notify(sd_event_source *s, int fd, uint32_t revents, void cmsg_close_all(&msghdr); - for (cmsg = CMSG_FIRSTHDR(&msghdr); cmsg; cmsg = CMSG_NXTHDR(&msghdr, cmsg)) { + CMSG_FOREACH(cmsg, &msghdr) { if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_CREDENTIALS && cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))) { diff --git a/src/import/pull-common.c b/src/import/pull-common.c index d2588d4fa0..652277e4be 100644 --- a/src/import/pull-common.c +++ b/src/import/pull-common.c @@ -339,8 +339,8 @@ int pull_verify( /* Child */ - reset_all_signal_handlers(); - reset_signal_mask(); + (void) reset_all_signal_handlers(); + (void) reset_signal_mask(); assert_se(prctl(PR_SET_PDEATHSIG, SIGTERM) == 0); gpg_pipe[1] = safe_close(gpg_pipe[1]); diff --git a/src/import/pull.c b/src/import/pull.c index eec4583868..03fe3dcaf4 100644 --- a/src/import/pull.c +++ b/src/import/pull.c @@ -440,7 +440,7 @@ int main(int argc, char *argv[]) { if (r <= 0) goto finish; - ignore_signals(SIGPIPE, -1); + (void) ignore_signals(SIGPIPE, -1); r = pull_main(argc, argv); diff --git a/src/journal-remote/journal-remote.c b/src/journal-remote/journal-remote.c index 911e2a178b..ae332d826f 100644 --- a/src/journal-remote/journal-remote.c +++ b/src/journal-remote/journal-remote.c @@ -96,6 +96,10 @@ static int spawn_child(const char* child, char** argv) { /* In the child */ if (child_pid == 0) { + + (void) reset_all_signal_handlers(); + (void) reset_signal_mask(); + r = dup2(fd[1], STDOUT_FILENO); if (r < 0) { log_error_errno(errno, "Failed to dup pipe to stdout: %m"); diff --git a/src/journal/coredumpctl.c b/src/journal/coredumpctl.c index 381bf72776..fc49b2e174 100644 --- a/src/journal/coredumpctl.c +++ b/src/journal/coredumpctl.c @@ -757,6 +757,9 @@ static int run_gdb(sd_journal *j) { goto finish; } if (pid == 0) { + (void) reset_all_signal_handlers(); + (void) reset_signal_mask(); + execlp("gdb", "gdb", exe, path, NULL); log_error_errno(errno, "Failed to invoke gdb: %m"); diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c index 3353024f4e..32da8d61fc 100644 --- a/src/journal/journald-server.c +++ b/src/journal/journald-server.c @@ -1177,7 +1177,7 @@ int server_process_datagram(sd_event_source *es, int fd, uint32_t revents, void return -errno; } - for (cmsg = CMSG_FIRSTHDR(&msghdr); cmsg; cmsg = CMSG_NXTHDR(&msghdr, cmsg)) { + CMSG_FOREACH(cmsg, &msghdr) { if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_CREDENTIALS && diff --git a/src/journal/journald-stream.c b/src/journal/journald-stream.c index b572147a56..db2f581972 100644 --- a/src/journal/journald-stream.c +++ b/src/journal/journald-stream.c @@ -59,10 +59,7 @@ struct StdoutStream { int fd; struct ucred ucred; -#ifdef HAVE_SELINUX - security_context_t security_context; -#endif - + char *label; char *identifier; char *unit_id; int priority; @@ -99,12 +96,7 @@ void stdout_stream_free(StdoutStream *s) { } safe_close(s->fd); - -#ifdef HAVE_SELINUX - if (s->security_context) - freecon(s->security_context); -#endif - + free(s->label); free(s->identifier); free(s->unit_id); free(s->state_file); @@ -225,8 +217,7 @@ static int stdout_stream_log(StdoutStream *s, const char *p) { char syslog_facility[sizeof("SYSLOG_FACILITY=")-1 + DECIMAL_STR_MAX(int) + 1]; _cleanup_free_ char *message = NULL, *syslog_identifier = NULL; unsigned n = 0; - char *label = NULL; - size_t label_len = 0; + size_t label_len; assert(s); assert(p); @@ -271,14 +262,8 @@ static int stdout_stream_log(StdoutStream *s, const char *p) { if (message) IOVEC_SET_STRING(iovec[n++], message); -#ifdef HAVE_SELINUX - if (s->security_context) { - label = (char*) s->security_context; - label_len = strlen((char*) s->security_context); - } -#endif - - server_dispatch_message(s->server, iovec, n, ELEMENTSOF(iovec), &s->ucred, NULL, label, label_len, s->unit_id, priority, 0); + label_len = s->label ? strlen(s->label) : 0; + server_dispatch_message(s->server, iovec, n, ELEMENTSOF(iovec), &s->ucred, NULL, s->label, label_len, s->unit_id, priority, 0); return 0; } @@ -489,12 +474,11 @@ static int stdout_stream_install(Server *s, int fd, StdoutStream **ret) { if (r < 0) return log_error_errno(r, "Failed to determine peer credentials: %m"); -#ifdef HAVE_SELINUX if (mac_selinux_use()) { - if (getpeercon(fd, &stream->security_context) < 0 && errno != ENOPROTOOPT) - log_error_errno(errno, "Failed to determine peer security context: %m"); + r = getpeersec(fd, &stream->label); + if (r < 0 && r != -EOPNOTSUPP) + (void) log_warning_errno(r, "Failed to determine peer security context: %m"); } -#endif (void) shutdown(fd, SHUT_WR); 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-network/lldp-tlv.c b/src/libsystemd-network/lldp-tlv.c index e32783f3eb..0cea5b10a6 100644 --- a/src/libsystemd-network/lldp-tlv.c +++ b/src/libsystemd-network/lldp-tlv.c @@ -221,7 +221,7 @@ int tlv_packet_read_string(tlv_packet *m, char **data, uint16_t *data_length) { return r; *data = (char *) val; - *data_length = m->container->length; + *data_length = m->container->length; m->container->read_pos += m->container->length; diff --git a/src/libsystemd-network/sd-dhcp-client.c b/src/libsystemd-network/sd-dhcp-client.c index 0193e42d65..6853038b67 100644 --- a/src/libsystemd-network/sd-dhcp-client.c +++ b/src/libsystemd-network/sd-dhcp-client.c @@ -1588,7 +1588,7 @@ static int client_receive_message_raw(sd_event_source *s, int fd, } else if ((size_t)len < sizeof(DHCPPacket)) return 0; - for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) { + CMSG_FOREACH(cmsg, &msg) { if (cmsg->cmsg_level == SOL_PACKET && cmsg->cmsg_type == PACKET_AUXDATA && cmsg->cmsg_len == CMSG_LEN(sizeof(struct tpacket_auxdata))) { diff --git a/src/libsystemd-network/sd-dhcp-lease.c b/src/libsystemd-network/sd-dhcp-lease.c index 8a4220621b..d8bc76edda 100644 --- a/src/libsystemd-network/sd-dhcp-lease.c +++ b/src/libsystemd-network/sd-dhcp-lease.c @@ -32,6 +32,7 @@ #include "dhcp-lease-internal.h" #include "sd-dhcp-lease.h" #include "network-internal.h" +#include "dns-domain.h" int sd_dhcp_lease_get_address(sd_dhcp_lease *lease, struct in_addr *addr) { assert_return(lease, -EINVAL); @@ -504,9 +505,18 @@ int dhcp_lease_parse_options(uint8_t code, uint8_t len, const uint8_t *option, if (e) *e = 0; - if (!hostname_is_valid(domainname) || is_localhost(domainname)) + if (is_localhost(domainname)) break; + r = dns_name_is_valid(domainname); + if (r <= 0) { + if (r < 0) + log_error_errno(r, "Failed to validate domain name: %s: %m", domainname); + if (r == 0) + log_warning("Domain name is not valid, ignoring: %s", domainname); + break; + } + free(lease->domainname); lease->domainname = domainname; domainname = NULL; diff --git a/src/libsystemd-network/sd-dhcp-server.c b/src/libsystemd-network/sd-dhcp-server.c index a0a2320efa..cc5e032344 100644 --- a/src/libsystemd-network/sd-dhcp-server.c +++ b/src/libsystemd-network/sd-dhcp-server.c @@ -902,7 +902,7 @@ static int server_receive_message(sd_event_source *s, int fd, else if ((size_t)len < sizeof(DHCPMessage)) return 0; - for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) { + CMSG_FOREACH(cmsg, &msg) { if (cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IP_PKTINFO && cmsg->cmsg_len == CMSG_LEN(sizeof(struct in_pktinfo))) { diff --git a/src/libsystemd-terminal/sysview.c b/src/libsystemd-terminal/sysview.c index c8bbce43d3..2e9b15859a 100644 --- a/src/libsystemd-terminal/sysview.c +++ b/src/libsystemd-terminal/sysview.c @@ -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/libsystemd.sym.m4 b/src/libsystemd/libsystemd.sym.m4 index 0b94a87dd6..3121e71282 100644 --- a/src/libsystemd/libsystemd.sym.m4 +++ b/src/libsystemd/libsystemd.sym.m4 @@ -320,6 +320,7 @@ global: sd_bus_get_name_creds; sd_bus_get_name_machine_id; sd_bus_call_method; + sd_bus_call_method_async; sd_bus_get_property; sd_bus_get_property_trivial; sd_bus_get_property_string; diff --git a/src/libsystemd/sd-bus/bus-bloom.c b/src/libsystemd/sd-bus/bus-bloom.c index 3556774074..91fab90cb0 100644 --- a/src/libsystemd/sd-bus/bus-bloom.c +++ b/src/libsystemd/sd-bus/bus-bloom.c @@ -116,11 +116,19 @@ void bloom_add_prefixes(uint64_t filter[], size_t size, unsigned k, const char * p = stpcpy(stpcpy(c, a), ":"); strcpy(p, b); + bloom_add_data(filter, size, k, c, n); + for (;;) { char *e; e = strrchr(p, sep); - if (!e || e == p) + if (!e) + break; + + *(e + 1) = 0; + bloom_add_data(filter, size, k, c, e - c + 1); + + if (e == p) break; *e = 0; diff --git a/src/libsystemd/sd-bus/bus-container.c b/src/libsystemd/sd-bus/bus-container.c index f157c25bba..fa7a207448 100644 --- a/src/libsystemd/sd-bus/bus-container.c +++ b/src/libsystemd/sd-bus/bus-container.c @@ -222,7 +222,7 @@ int bus_container_connect_kernel(sd_bus *b) { if (recvmsg(pair[0], &mh, MSG_NOSIGNAL|MSG_CMSG_CLOEXEC) < 0) return -errno; - for (cmsg = CMSG_FIRSTHDR(&mh); cmsg; cmsg = CMSG_NXTHDR(&mh, cmsg)) + CMSG_FOREACH(cmsg, &mh) if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) { int *fds; unsigned n_fds; diff --git a/src/libsystemd/sd-bus/bus-control.c b/src/libsystemd/sd-bus/bus-control.c index 43ddfc651d..7a59702cb2 100644 --- a/src/libsystemd/sd-bus/bus-control.c +++ b/src/libsystemd/sd-bus/bus-control.c @@ -979,8 +979,10 @@ static int bus_get_owner_creds_dbus1(sd_bus *bus, uint64_t mask, sd_bus_creds ** _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL; pid_t pid = 0; int r; + bool do_label = bus->label && (mask & SD_BUS_CREDS_SELINUX_CONTEXT); - if (!bus->ucred_valid && !isempty(bus->label)) + /* Avoid allocating anything if we have no chance of returning useful data */ + if (!bus->ucred_valid && !do_label) return -ENODATA; c = bus_creds_new(); @@ -1004,7 +1006,7 @@ static int bus_get_owner_creds_dbus1(sd_bus *bus, uint64_t mask, sd_bus_creds ** } } - if (!isempty(bus->label) && (mask & SD_BUS_CREDS_SELINUX_CONTEXT)) { + if (do_label) { c->label = strdup(bus->label); if (!c->label) return -ENOMEM; @@ -1289,10 +1291,8 @@ int bus_add_match_internal_kernel( break; case BUS_MATCH_PATH_NAMESPACE: - if (!streq(c->value_str, "/")) { - bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "path-slash-prefix", c->value_str); - using_bloom = true; - } + bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "path-slash-prefix", c->value_str); + using_bloom = true; break; case BUS_MATCH_ARG...BUS_MATCH_ARG_LAST: { @@ -1308,11 +1308,18 @@ int bus_add_match_internal_kernel( } case BUS_MATCH_ARG_PATH...BUS_MATCH_ARG_PATH_LAST: { - char buf[sizeof("arg")-1 + 2 + sizeof("-slash-prefix")]; - - xsprintf(buf, "arg%i-slash-prefix", c->type - BUS_MATCH_ARG_PATH); - bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str); - using_bloom = true; + /* + * XXX: DBus spec defines arg[0..63]path= matching to be + * a two-way glob. That is, if either string is a prefix + * of the other, it matches. + * This is really hard to realize in bloom-filters, as + * we would have to create a bloom-match for each prefix + * of @c->value_str. This is excessive, hence we just + * ignore all those matches and accept everything from + * the kernel. People should really avoid those matches. + * If they're used in real-life some day, we will have + * to properly support multiple-matches here. + */ break; } diff --git a/src/libsystemd/sd-bus/bus-convenience.c b/src/libsystemd/sd-bus/bus-convenience.c index 28bc8d2818..dfd82e746d 100644 --- a/src/libsystemd/sd-bus/bus-convenience.c +++ b/src/libsystemd/sd-bus/bus-convenience.c @@ -58,6 +58,43 @@ _public_ int sd_bus_emit_signal( return sd_bus_send(bus, m, NULL); } +_public_ int sd_bus_call_method_async( + sd_bus *bus, + sd_bus_slot **slot, + const char *destination, + const char *path, + const char *interface, + const char *member, + sd_bus_message_handler_t callback, + void *userdata, + const char *types, ...) { + + _cleanup_bus_message_unref_ sd_bus_message *m = NULL; + int r; + + assert_return(bus, -EINVAL); + assert_return(!bus_pid_changed(bus), -ECHILD); + + if (!BUS_IS_OPEN(bus->state)) + return -ENOTCONN; + + r = sd_bus_message_new_method_call(bus, &m, destination, path, interface, member); + if (r < 0) + return r; + + if (!isempty(types)) { + va_list ap; + + va_start(ap, types); + r = bus_message_append_ap(m, types, ap); + va_end(ap); + if (r < 0) + return r; + } + + return sd_bus_call_async(bus, slot, m, callback, userdata, 0); +} + _public_ int sd_bus_call_method( sd_bus *bus, const char *destination, diff --git a/src/libsystemd/sd-bus/bus-creds.c b/src/libsystemd/sd-bus/bus-creds.c index 4d67619cf8..1c365b7fcd 100644 --- a/src/libsystemd/sd-bus/bus-creds.c +++ b/src/libsystemd/sd-bus/bus-creds.c @@ -773,11 +773,13 @@ int bus_creds_add_more(sd_bus_creds *c, uint64_t mask, pid_t pid, pid_t tid) { return 0; /* Try to retrieve PID from creds if it wasn't passed to us */ - if (pid <= 0 && (c->mask & SD_BUS_CREDS_PID)) + if (pid > 0) { + c->pid = pid; + c->mask |= SD_BUS_CREDS_PID; + } else if (c->mask & SD_BUS_CREDS_PID) pid = c->pid; - - /* Without pid we cannot do much... */ - if (pid <= 0) + else + /* Without pid we cannot do much... */ return 0; /* Try to retrieve TID from creds if it wasn't passed to us */ @@ -789,9 +791,6 @@ int bus_creds_add_more(sd_bus_creds *c, uint64_t mask, pid_t pid, pid_t tid) { if (missing == 0) return 0; - c->pid = pid; - c->mask |= SD_BUS_CREDS_PID; - if (tid > 0) { c->tid = tid; c->mask |= SD_BUS_CREDS_TID; diff --git a/src/libsystemd/sd-bus/bus-internal.c b/src/libsystemd/sd-bus/bus-internal.c index 91b288cd25..37793e48ed 100644 --- a/src/libsystemd/sd-bus/bus-internal.c +++ b/src/libsystemd/sd-bus/bus-internal.c @@ -211,6 +211,17 @@ bool member_name_is_valid(const char *p) { return true; } +/* + * Complex pattern match + * This checks whether @a is a 'complex-prefix' of @b, or @b is a + * 'complex-prefix' of @a, based on strings that consist of labels with @c as + * spearator. This function returns true if: + * - both strings are equal + * - either is a prefix of the other and ends with @c + * The second rule makes sure that either string needs to be fully included in + * the other, and the string which is considered the prefix needs to end with a + * separator. + */ static bool complex_pattern_check(char c, const char *a, const char *b) { bool separator = false; @@ -222,9 +233,7 @@ static bool complex_pattern_check(char c, const char *a, const char *b) { for (;;) { if (*a != *b) - return (separator && (*a == 0 || *b == 0)) || - (*a == 0 && *b == c && b[1] == 0) || - (*b == 0 && *a == c && a[1] == 0); + return (separator && (*a == 0 || *b == 0)); if (*a == 0) return true; @@ -243,7 +252,18 @@ bool path_complex_pattern(const char *pattern, const char *value) { return complex_pattern_check('/', pattern, value); } +/* + * Simple pattern match + * This checks whether @a is a 'simple-prefix' of @b, based on strings that + * consist of labels with @c as separator. This function returns true, if: + * - if @a and @b are equal + * - if @a is a prefix of @b, and the first following character in @b (or the + * last character in @a) is @c + * The second rule basically makes sure that if @a is a prefix of @b, then @b + * must follow with a new label separated by @c. It cannot extend the label. + */ static bool simple_pattern_check(char c, const char *a, const char *b) { + bool separator = false; if (!a && !b) return true; @@ -253,11 +273,13 @@ static bool simple_pattern_check(char c, const char *a, const char *b) { for (;;) { if (*a != *b) - return *a == 0 && *b == c; + return *a == 0 && (*b == c || separator); if (*a == 0) return true; + separator = *a == c; + a++, b++; } } diff --git a/src/libsystemd/sd-bus/bus-internal.h b/src/libsystemd/sd-bus/bus-internal.h index 1351938c80..2ee0eabc02 100644 --- a/src/libsystemd/sd-bus/bus-internal.h +++ b/src/libsystemd/sd-bus/bus-internal.h @@ -261,7 +261,7 @@ struct sd_bus { usec_t auth_timeout; struct ucred ucred; - char label[NAME_MAX]; + char *label; uint64_t creds_mask; diff --git a/src/libsystemd/sd-bus/bus-kernel.c b/src/libsystemd/sd-bus/bus-kernel.c index d5cc8100ce..3aaaabf4ed 100644 --- a/src/libsystemd/sd-bus/bus-kernel.c +++ b/src/libsystemd/sd-bus/bus-kernel.c @@ -498,7 +498,6 @@ static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k) { footer, footer_size, n_bytes, fds, n_fds, - NULL, seclabel, 0, &m); if (r < 0) return r; @@ -1574,7 +1573,6 @@ int bus_kernel_create_bus(const char *name, bool world, char **s) { make = alloca0_align(offsetof(struct kdbus_cmd, items) + ALIGN8(offsetof(struct kdbus_item, bloom_parameter) + sizeof(struct kdbus_bloom_parameter)) + ALIGN8(offsetof(struct kdbus_item, data64) + sizeof(uint64_t)) + - ALIGN8(offsetof(struct kdbus_item, data64) + sizeof(uint64_t)) + ALIGN8(offsetof(struct kdbus_item, str) + DECIMAL_STR_MAX(uid_t) + 1 + l + 1), 8); @@ -1593,14 +1591,6 @@ int bus_kernel_create_bus(const char *name, bool world, char **s) { make->size += ALIGN8(n->size); - /* The buses we create make no restrictions on what metadata - * peers can read from incoming messages. */ - n = KDBUS_ITEM_NEXT(n); - n->type = KDBUS_ITEM_ATTACH_FLAGS_RECV; - n->size = offsetof(struct kdbus_item, data64) + sizeof(uint64_t); - n->data64[0] = _KDBUS_ATTACH_ANY; - make->size += ALIGN8(n->size); - /* Provide all metadata via bus-owner queries */ n = KDBUS_ITEM_NEXT(n); n->type = KDBUS_ITEM_ATTACH_FLAGS_SEND; @@ -1770,32 +1760,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-message.c b/src/libsystemd/sd-bus/bus-message.c index 6ee209dd1b..c38b2a5fa5 100644 --- a/src/libsystemd/sd-bus/bus-message.c +++ b/src/libsystemd/sd-bus/bus-message.c @@ -435,7 +435,6 @@ int bus_message_from_header( size_t message_size, int *fds, unsigned n_fds, - const struct ucred *ucred, const char *label, size_t extra, sd_bus_message **ret) { @@ -528,23 +527,6 @@ int bus_message_from_header( m->fds = fds; m->n_fds = n_fds; - if (ucred) { - m->creds.pid = ucred->pid; - m->creds.euid = ucred->uid; - m->creds.egid = ucred->gid; - - /* Due to namespace translations some data might be - * missing from this ucred record. */ - if (m->creds.pid > 0) - m->creds.mask |= SD_BUS_CREDS_PID; - - if (m->creds.euid != UID_INVALID) - m->creds.mask |= SD_BUS_CREDS_EUID; - - if (m->creds.egid != GID_INVALID) - m->creds.mask |= SD_BUS_CREDS_EGID; - } - if (label) { m->creds.label = (char*) m + ALIGN(sizeof(sd_bus_message)) + ALIGN(extra); memcpy(m->creds.label, label, label_sz + 1); @@ -565,7 +547,6 @@ int bus_message_from_malloc( size_t length, int *fds, unsigned n_fds, - const struct ucred *ucred, const char *label, sd_bus_message **ret) { @@ -579,7 +560,7 @@ int bus_message_from_malloc( buffer, length, length, fds, n_fds, - ucred, label, + label, 0, &m); if (r < 0) return r; diff --git a/src/libsystemd/sd-bus/bus-message.h b/src/libsystemd/sd-bus/bus-message.h index d784e603dd..088d5b1109 100644 --- a/src/libsystemd/sd-bus/bus-message.h +++ b/src/libsystemd/sd-bus/bus-message.h @@ -205,7 +205,6 @@ int bus_message_from_header( size_t message_size, int *fds, unsigned n_fds, - const struct ucred *ucred, const char *label, size_t extra, sd_bus_message **ret); @@ -216,7 +215,6 @@ int bus_message_from_malloc( size_t length, int *fds, unsigned n_fds, - const struct ucred *ucred, const char *label, sd_bus_message **ret); diff --git a/src/libsystemd/sd-bus/bus-socket.c b/src/libsystemd/sd-bus/bus-socket.c index 4fffc6581d..322d57ddbb 100644 --- a/src/libsystemd/sd-bus/bus-socket.c +++ b/src/libsystemd/sd-bus/bus-socket.c @@ -500,11 +500,8 @@ static int bus_socket_read_auth(sd_bus *b) { void *p; union { struct cmsghdr cmsghdr; - uint8_t buf[CMSG_SPACE(sizeof(int) * BUS_FDS_MAX) + - CMSG_SPACE(sizeof(struct ucred)) + - CMSG_SPACE(NAME_MAX)]; /*selinux label */ + uint8_t buf[CMSG_SPACE(sizeof(int) * BUS_FDS_MAX)]; } control; - struct cmsghdr *cmsg; bool handle_cmsg = false; assert(b); @@ -555,7 +552,9 @@ static int bus_socket_read_auth(sd_bus *b) { b->rbuffer_size += k; if (handle_cmsg) { - for (cmsg = CMSG_FIRSTHDR(&mh); cmsg; cmsg = CMSG_NXTHDR(&mh, cmsg)) { + struct cmsghdr *cmsg; + + CMSG_FOREACH(cmsg, &mh) if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) { int j; @@ -566,30 +565,9 @@ static int bus_socket_read_auth(sd_bus *b) { j = (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int); close_many((int*) CMSG_DATA(cmsg), j); return -EIO; - - } else if (cmsg->cmsg_level == SOL_SOCKET && - cmsg->cmsg_type == SCM_CREDENTIALS && - cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))) { - - /* Ignore bogus data, which we might - * get on socketpair() sockets */ - if (((struct ucred*) CMSG_DATA(cmsg))->pid != 0) { - memcpy(&b->ucred, CMSG_DATA(cmsg), sizeof(struct ucred)); - b->ucred_valid = true; - } - - } else if (cmsg->cmsg_level == SOL_SOCKET && - cmsg->cmsg_type == SCM_SECURITY) { - - size_t l; - - l = cmsg->cmsg_len - CMSG_LEN(0); - if (l > 0) { - memcpy(&b->label, CMSG_DATA(cmsg), l); - b->label[l] = 0; - } - } - } + } else + log_debug("Got unexpected auxiliary data with level=%d and type=%d", + cmsg->cmsg_level, cmsg->cmsg_type); } r = bus_socket_auth_verify(b); @@ -600,18 +578,8 @@ static int bus_socket_read_auth(sd_bus *b) { } void bus_socket_setup(sd_bus *b) { - int enable; - assert(b); - /* Enable SO_PASSCRED + SO_PASSEC. We try this on any - * socket, just in case. */ - enable = !b->bus_client; - (void) setsockopt(b->input_fd, SOL_SOCKET, SO_PASSCRED, &enable, sizeof(enable)); - - enable = !b->bus_client && (b->attach_flags & KDBUS_ATTACH_SECLABEL); - (void) setsockopt(b->input_fd, SOL_SOCKET, SO_PASSSEC, &enable, sizeof(enable)); - /* Increase the buffers to 8 MB */ fd_inc_rcvbuf(b->input_fd, SNDBUF_SIZE); fd_inc_sndbuf(b->output_fd, SNDBUF_SIZE); @@ -622,10 +590,17 @@ void bus_socket_setup(sd_bus *b) { } static void bus_get_peercred(sd_bus *b) { + int r; + assert(b); /* Get the peer for socketpair() sockets */ b->ucred_valid = getpeercred(b->input_fd, &b->ucred) >= 0; + + /* Get the SELinux context of the peer */ + r = getpeersec(b->input_fd, &b->label); + if (r < 0 && r != -EOPNOTSUPP) + log_debug_errno(r, "Failed to determine peer security context: %m"); } static int bus_socket_start_auth_client(sd_bus *b) { @@ -738,7 +713,8 @@ int bus_socket_exec(sd_bus *b) { if (pid == 0) { /* Child */ - reset_all_signal_handlers(); + (void) reset_all_signal_handlers(); + (void) reset_signal_mask(); close_all_fds(s+1, 1); @@ -914,7 +890,6 @@ static int bus_socket_make_message(sd_bus *bus, size_t size) { bus->rbuffer, size, bus->fds, bus->n_fds, NULL, - NULL, &t); if (r < 0) { free(b); @@ -941,11 +916,8 @@ int bus_socket_read_message(sd_bus *bus) { void *b; union { struct cmsghdr cmsghdr; - uint8_t buf[CMSG_SPACE(sizeof(int) * BUS_FDS_MAX) + - CMSG_SPACE(sizeof(struct ucred)) + - CMSG_SPACE(NAME_MAX)]; /*selinux label */ + uint8_t buf[CMSG_SPACE(sizeof(int) * BUS_FDS_MAX)]; } control; - struct cmsghdr *cmsg; bool handle_cmsg = false; assert(bus); @@ -991,7 +963,9 @@ int bus_socket_read_message(sd_bus *bus) { bus->rbuffer_size += k; if (handle_cmsg) { - for (cmsg = CMSG_FIRSTHDR(&mh); cmsg; cmsg = CMSG_NXTHDR(&mh, cmsg)) { + struct cmsghdr *cmsg; + + CMSG_FOREACH(cmsg, &mh) if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) { int n, *f; @@ -1016,28 +990,9 @@ int bus_socket_read_message(sd_bus *bus) { memcpy(f + bus->n_fds, CMSG_DATA(cmsg), n * sizeof(int)); bus->fds = f; bus->n_fds += n; - } else if (cmsg->cmsg_level == SOL_SOCKET && - cmsg->cmsg_type == SCM_CREDENTIALS && - cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))) { - - /* Ignore bogus data, which we might - * get on socketpair() sockets */ - if (((struct ucred*) CMSG_DATA(cmsg))->pid != 0) { - memcpy(&bus->ucred, CMSG_DATA(cmsg), sizeof(struct ucred)); - bus->ucred_valid = true; - } - - } else if (cmsg->cmsg_level == SOL_SOCKET && - cmsg->cmsg_type == SCM_SECURITY) { - - size_t l; - l = cmsg->cmsg_len - CMSG_LEN(0); - if (l > 0) { - memcpy(&bus->label, CMSG_DATA(cmsg), l); - bus->label[l] = 0; - } - } - } + } else + log_debug("Got unexpected auxiliary data with level=%d and type=%d", + cmsg->cmsg_level, cmsg->cmsg_type); } r = bus_socket_read_message_need(bus, &need); 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/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c index edc27aef87..2805b29839 100644 --- a/src/libsystemd/sd-bus/sd-bus.c +++ b/src/libsystemd/sd-bus/sd-bus.c @@ -49,6 +49,21 @@ #include "bus-track.h" #include "bus-slot.h" +#define log_debug_bus_message(m) \ + do { \ + sd_bus_message *_mm = (m); \ + log_debug("Got message type=%s sender=%s destination=%s object=%s interface=%s member=%s cookie=%" PRIu64 " reply_cookie=%" PRIu64 " error=%s", \ + bus_message_type_to_string(_mm->header->type), \ + strna(sd_bus_message_get_sender(_mm)), \ + strna(sd_bus_message_get_destination(_mm)), \ + strna(sd_bus_message_get_path(_mm)), \ + strna(sd_bus_message_get_interface(_mm)), \ + strna(sd_bus_message_get_member(_mm)), \ + BUS_MESSAGE_COOKIE(_mm), \ + _mm->reply_cookie, \ + strna(_mm->error.message)); \ + } while (false) + static int bus_poll(sd_bus *bus, bool need_more, uint64_t timeout_usec); static int attach_io_events(sd_bus *b); static void detach_io_events(sd_bus *b); @@ -116,6 +131,7 @@ static void bus_free(sd_bus *b) { if (b->kdbus_buffer) munmap(b->kdbus_buffer, KDBUS_POOL_SIZE); + free(b->label); free(b->rbuffer); free(b->unique_name); free(b->auth_buffer); @@ -1992,6 +2008,7 @@ _public_ int sd_bus_call( memmove(bus->rqueue + i, bus->rqueue + i + 1, sizeof(sd_bus_message*) * (bus->rqueue_size - i - 1)); bus->rqueue_size--; + log_debug_bus_message(incoming); if (incoming->header->type == SD_BUS_MESSAGE_METHOD_RETURN) { @@ -2480,16 +2497,7 @@ static int process_message(sd_bus *bus, sd_bus_message *m) { bus->current_message = m; bus->iteration_counter++; - log_debug("Got message type=%s sender=%s destination=%s object=%s interface=%s member=%s cookie=%" PRIu64 " reply_cookie=%" PRIu64 " error=%s", - bus_message_type_to_string(m->header->type), - strna(sd_bus_message_get_sender(m)), - strna(sd_bus_message_get_destination(m)), - strna(sd_bus_message_get_path(m)), - strna(sd_bus_message_get_interface(m)), - strna(sd_bus_message_get_member(m)), - BUS_MESSAGE_COOKIE(m), - m->reply_cookie, - strna(m->error.message)); + log_debug_bus_message(m); r = process_hello(bus, m); if (r != 0) diff --git a/src/libsystemd/sd-bus/test-bus-gvariant.c b/src/libsystemd/sd-bus/test-bus-gvariant.c index 992edacb28..22ea00c2fb 100644 --- a/src/libsystemd/sd-bus/test-bus-gvariant.c +++ b/src/libsystemd/sd-bus/test-bus-gvariant.c @@ -198,7 +198,7 @@ static void test_marshal(void) { } #endif - assert_se(bus_message_from_malloc(bus, blob, sz, NULL, 0, NULL, NULL, &n) >= 0); + assert_se(bus_message_from_malloc(bus, blob, sz, NULL, 0, NULL, &n) >= 0); blob = NULL; assert_se(bus_message_dump(n, NULL, BUS_MESSAGE_DUMP_WITH_HEADER) >= 0); diff --git a/src/libsystemd/sd-bus/test-bus-kernel-bloom.c b/src/libsystemd/sd-bus/test-bus-kernel-bloom.c index b11c43bd7b..90eb1f2a33 100644 --- a/src/libsystemd/sd-bus/test-bus-kernel-bloom.c +++ b/src/libsystemd/sd-bus/test-bus-kernel-bloom.c @@ -26,6 +26,14 @@ #include "bus-kernel.h" #include "bus-util.h" +static int test_match(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) { + int *found = userdata; + + *found = 1; + + return 0; +} + static void test_one( const char *path, const char *interface, @@ -39,7 +47,7 @@ static void test_one( _cleanup_free_ char *name = NULL, *bus_name = NULL, *address = NULL; _cleanup_bus_message_unref_ sd_bus_message *m = NULL; sd_bus *a, *b; - int r; + int r, found = 0; assert_se(asprintf(&name, "deine-mutter-%u", (unsigned) getpid()) >= 0); @@ -71,7 +79,7 @@ static void test_one( assert_se(r >= 0); log_debug("match"); - r = sd_bus_add_match(b, NULL, match, NULL, NULL); + r = sd_bus_add_match(b, NULL, match, test_match, &found); assert_se(r >= 0); log_debug("signal"); @@ -83,7 +91,7 @@ static void test_one( assert_se(r >= 0); r = sd_bus_process(b, &m); - assert_se(r >= 0 && (good == !!m)); + assert_se(r >= 0 && good == !!found); sd_bus_unref(a); sd_bus_unref(b); @@ -115,6 +123,17 @@ int main(int argc, char *argv[]) { test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path_namespace='/foo'", true); test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path_namespace='/'", true); test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path_namespace='/quux'", false); + test_one("/", "waldo.com", "Piep", false, "foobar", "path_namespace='/'", true); + + test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path='/foo/bar/waldo/'", false); + test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path='/foo/'", false); + test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path_namespace='/foo/bar/waldo/'", false); + test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path_namespace='/foo/'", true); + + test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "/foo/bar/waldo", "arg0path='/foo/'", true); + test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "/foo", "arg0path='/foo'", true); + test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "/foo", "arg0path='/foo/bar/waldo'", false); + test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "/foo/", "arg0path='/foo/bar/waldo'", true); return 0; } 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-bus/test-bus-marshal.c b/src/libsystemd/sd-bus/test-bus-marshal.c index f8ecadf499..a866a56179 100644 --- a/src/libsystemd/sd-bus/test-bus-marshal.c +++ b/src/libsystemd/sd-bus/test-bus-marshal.c @@ -212,7 +212,7 @@ int main(int argc, char *argv[]) { m = sd_bus_message_unref(m); - r = bus_message_from_malloc(bus, buffer, sz, NULL, 0, NULL, NULL, &m); + r = bus_message_from_malloc(bus, buffer, sz, NULL, 0, NULL, &m); assert_se(r >= 0); bus_message_dump(m, stdout, BUS_MESSAGE_DUMP_WITH_HEADER); diff --git a/src/libsystemd/sd-bus/test-bus-signature.c b/src/libsystemd/sd-bus/test-bus-signature.c index 4165c9273a..17c6188ca0 100644 --- a/src/libsystemd/sd-bus/test-bus-signature.c +++ b/src/libsystemd/sd-bus/test-bus-signature.c @@ -95,23 +95,28 @@ int main(int argc, char *argv[]) { assert_se(!namespace_complex_pattern("foo.", "")); assert_se(path_complex_pattern("", "")); - assert_se(path_complex_pattern("", "/")); - assert_se(path_complex_pattern("/", "")); + assert_se(!path_complex_pattern("", "/")); + assert_se(!path_complex_pattern("/", "")); assert_se(path_complex_pattern("/", "/")); assert_se(path_complex_pattern("/foobar/", "/")); - assert_se(path_complex_pattern("/foobar/", "/foobar")); + assert_se(!path_complex_pattern("/foobar/", "/foobar")); assert_se(path_complex_pattern("/foobar", "/foobar")); - assert_se(path_complex_pattern("/foobar", "/foobar/")); + assert_se(!path_complex_pattern("/foobar", "/foobar/")); assert_se(!path_complex_pattern("/foobar", "/foobar/waldo")); assert_se(path_complex_pattern("/foobar/", "/foobar/waldo")); + assert_se(path_complex_pattern("/foobar/waldo", "/foobar/")); + + assert_se(path_simple_pattern("/foo/", "/foo/bar/waldo")); assert_se(namespace_simple_pattern("", "")); + assert_se(namespace_simple_pattern("", ".foobar")); assert_se(namespace_simple_pattern("foobar", "foobar")); assert_se(namespace_simple_pattern("foobar.waldo", "foobar.waldo")); assert_se(namespace_simple_pattern("foobar", "foobar.waldo")); assert_se(!namespace_simple_pattern("foobar.waldo", "foobar")); assert_se(!namespace_simple_pattern("", "foo")); assert_se(!namespace_simple_pattern("foo", "")); + assert_se(namespace_simple_pattern("foo.", "foo.bar.waldo")); assert_se(streq(object_path_startswith("/foo/bar", "/foo"), "bar")); assert_se(streq(object_path_startswith("/foo", "/foo"), "")); diff --git a/src/libsystemd/sd-device/device-enumerator.c b/src/libsystemd/sd-device/device-enumerator.c index 3692d46e06..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) 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 cc8bc50c04..00880c983b 100644 --- a/src/libsystemd/sd-event/sd-event.c +++ b/src/libsystemd/sd-event/sd-event.c @@ -474,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; @@ -604,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); @@ -2378,7 +2384,6 @@ _public_ int sd_event_wait(sd_event *e, uint64_t timeout) { } r = -errno; - goto finish; } 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/libsystemd/sd-network/sd-network.c b/src/libsystemd/sd-network/sd-network.c index db1f6997cb..207eda163b 100644 --- a/src/libsystemd/sd-network/sd-network.c +++ b/src/libsystemd/sd-network/sd-network.c @@ -297,8 +297,31 @@ static inline sd_network_monitor* FD_TO_MONITOR(int fd) { return (sd_network_monitor*) (unsigned long) (fd + 1); } +static int monitor_add_inotify_watch(int fd) { + int k; + + k = inotify_add_watch(fd, "/run/systemd/netif/links/", IN_MOVED_TO|IN_DELETE); + if (k >= 0) + return 0; + else if (errno != ENOENT) + return -errno; + + k = inotify_add_watch(fd, "/run/systemd/netif/", IN_CREATE|IN_ISDIR); + if (k >= 0) + return 0; + else if (errno != ENOENT) + return -errno; + + k = inotify_add_watch(fd, "/run/systemd/", IN_CREATE|IN_ISDIR); + if (k < 0) + return -errno; + + return 0; +} + _public_ int sd_network_monitor_new(sd_network_monitor **m, const char *category) { - int fd, k; + _cleanup_close_ int fd = -1; + int k; bool good = false; assert_return(m, -EINVAL); @@ -308,11 +331,9 @@ _public_ int sd_network_monitor_new(sd_network_monitor **m, const char *category return -errno; if (!category || streq(category, "links")) { - k = inotify_add_watch(fd, "/run/systemd/netif/links/", IN_MOVED_TO|IN_DELETE); - if (k < 0) { - safe_close(fd); - return -errno; - } + k = monitor_add_inotify_watch(fd); + if (k < 0) + return k; good = true; } @@ -323,25 +344,53 @@ _public_ int sd_network_monitor_new(sd_network_monitor **m, const char *category } *m = FD_TO_MONITOR(fd); + fd = -1; + return 0; } _public_ sd_network_monitor* sd_network_monitor_unref(sd_network_monitor *m) { int fd; - assert_return(m, NULL); - - fd = MONITOR_TO_FD(m); - close_nointr(fd); + if (m) { + fd = MONITOR_TO_FD(m); + close_nointr(fd); + } return NULL; } _public_ int sd_network_monitor_flush(sd_network_monitor *m) { + union inotify_event_buffer buffer; + struct inotify_event *e; + ssize_t l; + int fd, k; assert_return(m, -EINVAL); - return flush_fd(MONITOR_TO_FD(m)); + fd = MONITOR_TO_FD(m); + + l = read(fd, &buffer, sizeof(buffer)); + if (l < 0) { + if (errno == EAGAIN || errno == EINTR) + return 0; + + return -errno; + } + + FOREACH_INOTIFY_EVENT(e, buffer, l) { + if (e->mask & IN_ISDIR) { + k = monitor_add_inotify_watch(fd); + if (k < 0) + return k; + + k = inotify_rm_watch(fd, e->wd); + if (k < 0) + return -errno; + } + } + + return 0; } _public_ int sd_network_monitor_get_fd(sd_network_monitor *m) { diff --git a/src/libsystemd/sd-rtnl/rtnl-message.c b/src/libsystemd/sd-rtnl/rtnl-message.c index bab2a4ff08..9dcf7df559 100644 --- a/src/libsystemd/sd-rtnl/rtnl-message.c +++ b/src/libsystemd/sd-rtnl/rtnl-message.c @@ -1442,7 +1442,7 @@ static int socket_recv_message(int fd, struct iovec *iov, uint32_t *_group, bool return (errno == EAGAIN || errno == EINTR) ? 0 : -errno; } - for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) { + CMSG_FOREACH(cmsg, &msg) { if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_CREDENTIALS && cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))) { 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/inhibit.c b/src/login/inhibit.c index 57cfb5d0b5..0e5dce5925 100644 --- a/src/login/inhibit.c +++ b/src/login/inhibit.c @@ -33,6 +33,7 @@ #include "strv.h" #include "formats-util.h" #include "process-util.h" +#include "signal-util.h" static const char* arg_what = "idle:sleep:shutdown"; static const char* arg_who = NULL; @@ -274,6 +275,9 @@ int main(int argc, char *argv[]) { if (pid == 0) { /* Child */ + (void) reset_all_signal_handlers(); + (void) reset_signal_mask(); + close_all_fds(NULL, 0); execvp(argv[optind], argv + optind); 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 dc3db9abda..c0b473930d 100644 --- a/src/login/logind-user.c +++ b/src/login/logind-user.c @@ -738,54 +738,70 @@ int user_kill(User *u, int signo) { return manager_kill_unit(u->manager, u->slice, KILL_ALL, signo, NULL); } +static bool elect_display_filter(Session *s) { + /* Return true if the session is a candidate for the user’s ‘primary + * session’ or ‘display’. */ + assert(s); + + return (s->class == SESSION_USER && !s->stopping); +} + +static int elect_display_compare(Session *s1, Session *s2) { + /* Indexed by SessionType. Lower numbers mean more preferred. */ + const int type_ranks[_SESSION_TYPE_MAX] = { + [SESSION_UNSPECIFIED] = 0, + [SESSION_TTY] = -2, + [SESSION_X11] = -3, + [SESSION_WAYLAND] = -3, + [SESSION_MIR] = -3, + [SESSION_WEB] = -1, + }; + + /* Calculate the partial order relationship between s1 and s2, + * returning < 0 if s1 is preferred as the user’s ‘primary session’, + * 0 if s1 and s2 are equally preferred or incomparable, or > 0 if s2 + * is preferred. + * + * s1 or s2 may be NULL. */ + if ((s1 == NULL) != (s2 == NULL)) + return (s1 == NULL) - (s2 == NULL); + + if (s1->stopping != s2->stopping) + return s1->stopping - s2->stopping; + + if ((s1->class != SESSION_USER) != (s2->class != SESSION_USER)) + return (s1->class != SESSION_USER) - (s2->class != SESSION_USER); + + if ((s1->type == _SESSION_TYPE_INVALID) != (s2->type == _SESSION_TYPE_INVALID)) + return (s1->type == _SESSION_TYPE_INVALID) - (s2->type == _SESSION_TYPE_INVALID); + + if (s1->type != s2->type) + return type_ranks[s1->type] - type_ranks[s2->type]; + + return 0; +} + void user_elect_display(User *u) { - Session *graphical = NULL, *text = NULL, *other = NULL, *s; + Session *s; assert(u); /* This elects a primary session for each user, which we call * the "display". We try to keep the assignment stable, but we * "upgrade" to better choices. */ + log_debug("Electing new display for user %s", u->name); LIST_FOREACH(sessions_by_user, s, u->sessions) { - - if (s->class != SESSION_USER) - continue; - - if (s->stopping) + if (!elect_display_filter(s)) { + log_debug("Ignoring session %s", s->id); continue; + } - if (SESSION_TYPE_IS_GRAPHICAL(s->type)) - graphical = s; - else if (s->type == SESSION_TTY) - text = s; - else - other = s; - } - - if (graphical && - (!u->display || - u->display->class != SESSION_USER || - u->display->stopping || - !SESSION_TYPE_IS_GRAPHICAL(u->display->type))) { - u->display = graphical; - return; - } - - if (text && - (!u->display || - u->display->class != SESSION_USER || - u->display->stopping || - u->display->type != SESSION_TTY)) { - u->display = text; - return; + if (elect_display_compare(s, u->display) < 0) { + log_debug("Choosing session %s in preference to %s", s->id, u->display ? u->display->id : "-"); + u->display = s; + } } - - if (other && - (!u->display || - u->display->class != SESSION_USER || - u->display->stopping)) - u->display = other; } static const char* const user_state_table[_USER_STATE_MAX] = { diff --git a/src/network/networkctl.c b/src/network/networkctl.c index 3454394977..68925debe6 100644 --- a/src/network/networkctl.c +++ b/src/network/networkctl.c @@ -814,7 +814,7 @@ static char *lldp_system_caps(uint16_t cap) { } if (cap & LLDP_SYSTEM_CAPABILITIES_ROUTER) { - s = strjoin(t, lldp_system_capability_to_string(LLDP_SYSTEM_CAPABILITIES_ROUTER), " ", NULL); + s = strjoin(t, lldp_system_capability_to_string(LLDP_SYSTEM_CAPABILITIES_ROUTER), " ", NULL); if (!s) return NULL; diff --git a/src/network/networkd-dhcp4.c b/src/network/networkd-dhcp4.c index 20aee53d6e..71cc722bcc 100644 --- a/src/network/networkd-dhcp4.c +++ b/src/network/networkd-dhcp4.c @@ -561,7 +561,7 @@ int dhcp4_configure(Link *link) { assert(link); assert(link->network); - assert(IN_SET(link->network->dhcp, ADDRESS_FAMILY_YES, ADDRESS_FAMILY_IPV4)); + assert(link->network->dhcp & ADDRESS_FAMILY_IPV4); r = sd_dhcp_client_new(&link->dhcp_client); if (r < 0) diff --git a/src/network/networkd-ipv4ll.c b/src/network/networkd-ipv4ll.c index 8050801e19..14b8770429 100644 --- a/src/network/networkd-ipv4ll.c +++ b/src/network/networkd-ipv4ll.c @@ -34,7 +34,7 @@ static int ipv4ll_address_lost(Link *link) { assert(link); link->ipv4ll_route = false; - link->ipv4ll_address = false; + link->ipv4ll_address = false; r = sd_ipv4ll_get_address(link->ipv4ll, &addr); if (r < 0) @@ -209,7 +209,7 @@ int ipv4ll_configure(Link *link) { assert(link); assert(link->network); - assert(IN_SET(link->network->link_local, ADDRESS_FAMILY_IPV4, ADDRESS_FAMILY_YES)); + assert(link->network->link_local & ADDRESS_FAMILY_IPV4); r = sd_ipv4ll_new(&link->ipv4ll); if (r < 0) diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index f039a2d687..7841f69dab 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -40,7 +40,7 @@ bool link_dhcp6_enabled(Link *link) { if (!link->network) return false; - return IN_SET(link->network->dhcp, ADDRESS_FAMILY_IPV6, ADDRESS_FAMILY_YES); + return link->network->dhcp & ADDRESS_FAMILY_IPV6; } bool link_dhcp4_enabled(Link *link) { @@ -50,7 +50,7 @@ bool link_dhcp4_enabled(Link *link) { if (!link->network) return false; - return IN_SET(link->network->dhcp, ADDRESS_FAMILY_IPV4, ADDRESS_FAMILY_YES); + return link->network->dhcp & ADDRESS_FAMILY_IPV4; } bool link_dhcp4_server_enabled(Link *link) { @@ -70,7 +70,7 @@ bool link_ipv4ll_enabled(Link *link) { if (!link->network) return false; - return IN_SET(link->network->link_local, ADDRESS_FAMILY_IPV4, ADDRESS_FAMILY_YES); + return link->network->link_local & ADDRESS_FAMILY_IPV4; } bool link_ipv6ll_enabled(Link *link) { @@ -80,7 +80,7 @@ bool link_ipv6ll_enabled(Link *link) { if (!link->network) return false; - return IN_SET(link->network->link_local, ADDRESS_FAMILY_IPV6, ADDRESS_FAMILY_YES); + return link->network->link_local & ADDRESS_FAMILY_IPV6; } bool link_lldp_enabled(Link *link) { @@ -103,7 +103,7 @@ static bool link_ipv4_forward_enabled(Link *link) { if (!link->network) return false; - return IN_SET(link->network->ip_forward, ADDRESS_FAMILY_IPV4, ADDRESS_FAMILY_YES); + return link->network->ip_forward & ADDRESS_FAMILY_IPV4; } static bool link_ipv6_forward_enabled(Link *link) { @@ -113,7 +113,7 @@ static bool link_ipv6_forward_enabled(Link *link) { if (!link->network) return false; - return IN_SET(link->network->ip_forward, ADDRESS_FAMILY_IPV6, ADDRESS_FAMILY_YES); + return link->network->ip_forward & ADDRESS_FAMILY_IPV6; } #define FLAG_STRING(string, flag, old, new) \ @@ -749,7 +749,6 @@ static int set_hostname_handler(sd_bus_message *m, void *userdata, sd_bus_error } int link_set_hostname(Link *link, const char *hostname) { - _cleanup_bus_message_unref_ sd_bus_message *m = NULL; int r = 0; assert(link); @@ -764,22 +763,19 @@ int link_set_hostname(Link *link, const char *hostname) { return 0; } - r = sd_bus_message_new_method_call( + r = sd_bus_call_method_async( link->manager->bus, - &m, + NULL, "org.freedesktop.hostname1", "/org/freedesktop/hostname1", "org.freedesktop.hostname1", - "SetHostname"); - if (r < 0) - return r; - - r = sd_bus_message_append(m, "sb", hostname, false); - if (r < 0) - return r; + "SetHostname", + set_hostname_handler, + link, + "sb", + hostname, + false); - r = sd_bus_call_async(link->manager->bus, NULL, m, set_hostname_handler, - link, 0); if (r < 0) return log_link_error_errno(link, r, "Could not set transient hostname: %m"); diff --git a/src/network/networkd-netdev-bond.c b/src/network/networkd-netdev-bond.c index 70df08a5e1..9919955f51 100644 --- a/src/network/networkd-netdev-bond.c +++ b/src/network/networkd-netdev-bond.c @@ -191,215 +191,132 @@ static int netdev_bond_fill_message_create(NetDev *netdev, Link *link, sd_rtnl_m if (b->mode != _NETDEV_BOND_MODE_INVALID) { r = sd_rtnl_message_append_u8(m, IFLA_BOND_MODE, bond_mode_to_kernel(b->mode)); - if (r < 0) { - log_netdev_error(netdev, - "Could not append IFLA_BOND_MODE attribute: %s", - strerror(-r)); - return r; - } + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_MODE attribute: %m"); } if (b->xmit_hash_policy != _NETDEV_BOND_XMIT_HASH_POLICY_INVALID) { r = sd_rtnl_message_append_u8(m, IFLA_BOND_XMIT_HASH_POLICY, bond_xmit_hash_policy_to_kernel(b->xmit_hash_policy)); - if (r < 0) { - log_netdev_error(netdev, - "Could not append IFLA_BOND_XMIT_HASH_POLICY attribute: %s", - strerror(-r)); - return r; - } + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_XMIT_HASH_POLICY attribute: %m"); } if (b->lacp_rate != _NETDEV_BOND_LACP_RATE_INVALID && b->mode == NETDEV_BOND_MODE_802_3AD) { r = sd_rtnl_message_append_u8(m, IFLA_BOND_AD_LACP_RATE, b->lacp_rate ); if (r < 0) { - log_netdev_error(netdev, - "Could not append IFLA_BOND_AD_LACP_RATE attribute: %s", - strerror(-r)); - return r; + return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_AD_LACP_RATE attribute: %m"); } } if (b->miimon != 0) { r = sd_rtnl_message_append_u32(m, IFLA_BOND_MIIMON, b->miimon / USEC_PER_MSEC); - if (r < 0) { - log_netdev_error(netdev, - "Could not append IFLA_BOND_BOND_MIIMON attribute: %s", - strerror(-r)); - return r; - } + if (r < 0) + log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_BOND_MIIMON attribute: %m"); } if (b->downdelay != 0) { r = sd_rtnl_message_append_u32(m, IFLA_BOND_DOWNDELAY, b->downdelay / USEC_PER_MSEC); - if (r < 0) { - log_netdev_error(netdev, - "Could not append IFLA_BOND_DOWNDELAY attribute: %s", - strerror(-r)); - return r; - } + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_DOWNDELAY attribute: %m"); } if (b->updelay != 0) { r = sd_rtnl_message_append_u32(m, IFLA_BOND_UPDELAY, b->updelay / USEC_PER_MSEC); - if (r < 0) { - log_netdev_error(netdev, - "Could not append IFLA_BOND_UPDELAY attribute: %s", - strerror(-r)); - return r; - } + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_UPDELAY attribute: %m"); } if (b->arp_interval != 0) { r = sd_rtnl_message_append_u32(m, IFLA_BOND_ARP_INTERVAL, b->arp_interval / USEC_PER_MSEC); - if (r < 0) { - log_netdev_error(netdev, - "Could not append IFLA_BOND_ARP_INTERVAL attribute: %s", - strerror(-r)); - return r; - } - } - - if ((b->lp_interval >= LEARNING_PACKETS_INTERVAL_MIN_SEC) && - (b->lp_interval <= LEARNING_PACKETS_INTERVAL_MAX_SEC)) { - r = sd_rtnl_message_append_u32(m, IFLA_BOND_LP_INTERVAL, b->lp_interval / USEC_PER_SEC); - if (r < 0) { - log_netdev_error(netdev, - "Could not append IFLA_BOND_LP_INTERVAL attribute: %s", - strerror(-r)); - return r; + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_ARP_INTERVAL attribute: %m"); + + if ((b->lp_interval >= LEARNING_PACKETS_INTERVAL_MIN_SEC) && + (b->lp_interval <= LEARNING_PACKETS_INTERVAL_MAX_SEC)) { + r = sd_rtnl_message_append_u32(m, IFLA_BOND_LP_INTERVAL, b->lp_interval / USEC_PER_SEC); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_LP_INTERVAL attribute: %m"); } } if (b->ad_select != _NETDEV_BOND_AD_SELECT_INVALID && b->mode == BOND_MODE_8023AD) { r = sd_rtnl_message_append_u8(m, IFLA_BOND_AD_SELECT, b->ad_select); - if (r < 0) { - log_netdev_error(netdev, - "Could not append IFLA_BOND_AD_SELECT attribute: %s", - strerror(-r)); - return r; - } + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_AD_SELECT attribute: %m"); } if (b->fail_over_mac != _NETDEV_BOND_FAIL_OVER_MAC_INVALID && b->mode == NETDEV_BOND_MODE_ACTIVE_BACKUP) { r = sd_rtnl_message_append_u8(m, IFLA_BOND_FAIL_OVER_MAC, b->fail_over_mac); - if (r < 0) { - log_netdev_error(netdev, - "Could not append IFLA_BOND_FAIL_OVER_MAC attribute: %s", - strerror(-r)); - return r; - } + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_FAIL_OVER_MAC attribute: %m"); } if (b->arp_validate != _NETDEV_BOND_ARP_VALIDATE_INVALID) { r = sd_rtnl_message_append_u32(m, IFLA_BOND_ARP_VALIDATE, b->arp_validate); - if (r < 0) { - log_netdev_error(netdev, - "Could not append IFLA_BOND_ARP_VALIDATE attribute: %s", - strerror(-r)); - return r; - } + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_ARP_VALIDATE attribute: %m"); } if (b->arp_all_targets != _NETDEV_BOND_ARP_ALL_TARGETS_INVALID) { r = sd_rtnl_message_append_u32(m, IFLA_BOND_ARP_ALL_TARGETS, b->arp_all_targets); - if (r < 0) { - log_netdev_error(netdev, - "Could not append IFLA_BOND_ARP_VALIDATE attribute: %s", - strerror(-r)); - return r; - } + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_ARP_VALIDATE attribute: %m"); } if (b->primary_reselect != _NETDEV_BOND_PRIMARY_RESELECT_INVALID) { r = sd_rtnl_message_append_u32(m, IFLA_BOND_ARP_ALL_TARGETS, b->primary_reselect); - if (r < 0) { - log_netdev_error(netdev, - "Could not append IFLA_BOND_ARP_ALL_TARGETS attribute: %s", - strerror(-r)); - return r; - } + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_ARP_ALL_TARGETS attribute: %m"); } if (b->resend_igmp <= RESEND_IGMP_MAX) { r = sd_rtnl_message_append_u32(m, IFLA_BOND_RESEND_IGMP, b->resend_igmp); - if (r < 0) { - log_netdev_error(netdev, - "Could not append IFLA_BOND_RESEND_IGMP attribute: %s", - strerror(-r)); - return r; - } + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_RESEND_IGMP attribute: %m"); } if (b->packets_per_slave <= PACKETS_PER_SLAVE_MAX) { r = sd_rtnl_message_append_u32(m, IFLA_BOND_PACKETS_PER_SLAVE, b->packets_per_slave); - if (r < 0) { - log_netdev_error(netdev, - "Could not append IFLA_BOND_PACKETS_PER_SLAVE attribute: %s", - strerror(-r)); - return r; - } + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_PACKETS_PER_SLAVE attribute: %m"); } if (b->num_grat_arp <= GRATUITOUS_ARP_MAX) { r = sd_rtnl_message_append_u8(m, IFLA_BOND_NUM_PEER_NOTIF, b->num_grat_arp); - if (r < 0) { - log_netdev_error(netdev, - "Could not append IFLA_BOND_NUM_PEER_NOTIF attribute: %s", - strerror(-r)); - return r; - } + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_NUM_PEER_NOTIF attribute: %m"); } if (b->min_links != 0) { r = sd_rtnl_message_append_u32(m, IFLA_BOND_MIN_LINKS, b->min_links); - if (r < 0) { - log_netdev_error(netdev, - "Could not append IFLA_BOND_MIN_LINKS attribute: %s", - strerror(-r)); - return r; - } + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_MIN_LINKS attribute: %m"); } r = sd_rtnl_message_append_u8(m, IFLA_BOND_ALL_SLAVES_ACTIVE, b->all_slaves_active); - if (r < 0) { - log_netdev_error(netdev, - "Could not append IFLA_BOND_ALL_SLAVES_ACTIVE attribute: %s", - strerror(-r)); - return r; - } + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_ALL_SLAVES_ACTIVE attribute: %m"); if (b->arp_interval > 0) { if (b->n_arp_ip_targets > 0) { r = sd_rtnl_message_open_container(m, IFLA_BOND_ARP_IP_TARGET); - if (r < 0) { - log_netdev_error(netdev, - "Could not open contaniner IFLA_BOND_ARP_IP_TARGET : %s", - strerror(-r)); - return r; - } + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not open contaniner IFLA_BOND_ARP_IP_TARGET : %m"); LIST_FOREACH(arp_ip_target, target, b->arp_ip_targets) { r = sd_rtnl_message_append_u32(m, i++, target->ip.in.s_addr); - if (r < 0) { - log_netdev_error(netdev, - "Could not append IFLA_BOND_ARP_ALL_TARGETS attribute: %s", - strerror(-r)); - return r; - } + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_ARP_ALL_TARGETS attribute: %m"); } r = sd_rtnl_message_close_container(m); - if (r < 0) { - log_netdev_error(netdev, - "Could not close contaniner IFLA_BOND_ARP_IP_TARGET : %s", - strerror(-r)); - return r; - } + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not close contaniner IFLA_BOND_ARP_IP_TARGET : %m"); } } diff --git a/src/network/networkd-netdev-veth.c b/src/network/networkd-netdev-veth.c index 9e9e1225e7..7bb02d1ae1 100644 --- a/src/network/networkd-netdev-veth.c +++ b/src/network/networkd-netdev-veth.c @@ -35,12 +35,8 @@ static int netdev_veth_fill_message_create(NetDev *netdev, Link *link, sd_rtnl_m assert(m); r = sd_rtnl_message_open_container(m, VETH_INFO_PEER); - if (r < 0) { - log_netdev_error(netdev, - "Could not append VETH_INFO_PEER attribute: %s", - strerror(-r)); - return r; - } + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append VETH_INFO_PEER attribute: %m"); if (v->ifname_peer) { r = sd_rtnl_message_append_string(m, IFLA_IFNAME, v->ifname_peer); @@ -50,21 +46,13 @@ static int netdev_veth_fill_message_create(NetDev *netdev, Link *link, sd_rtnl_m if (v->mac_peer) { r = sd_rtnl_message_append_ether_addr(m, IFLA_ADDRESS, v->mac_peer); - if (r < 0) { - log_netdev_error(netdev, - "Could not append IFLA_ADDRESS attribute: %s", - strerror(-r)); - return r; - } + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_ADDRESS attribute: %m"); } r = sd_rtnl_message_close_container(m); - if (r < 0) { - log_netdev_error(netdev, - "Could not append IFLA_INFO_DATA attribute: %s", - strerror(-r)); - return r; - } + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_INFO_DATA attribute: %m"); return r; } diff --git a/src/network/networkd-netdev-vxlan.c b/src/network/networkd-netdev-vxlan.c index e2c2b108b9..01a1e5089c 100644 --- a/src/network/networkd-netdev-vxlan.c +++ b/src/network/networkd-netdev-vxlan.c @@ -39,123 +39,67 @@ static int netdev_vxlan_fill_message_create(NetDev *netdev, Link *link, sd_rtnl_ if (v->id <= VXLAN_VID_MAX) { r = sd_rtnl_message_append_u32(m, IFLA_VXLAN_ID, v->id); - if (r < 0) { - log_netdev_error(netdev, - "Could not append IFLA_VXLAN_ID attribute: %s", - strerror(-r)); - return r; - } + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_ID attribute: %m"); } r = sd_rtnl_message_append_in_addr(m, IFLA_VXLAN_GROUP, &v->group.in); - if (r < 0) { - log_netdev_error(netdev, - "Could not append IFLA_VXLAN_GROUP attribute: %s", - strerror(-r)); - return r; - } + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_GROUP attribute: %m"); r = sd_rtnl_message_append_u32(m, IFLA_VXLAN_LINK, link->ifindex); - if (r < 0) { - log_netdev_error(netdev, - "Could not append IFLA_VXLAN_LINK attribute: %s", - strerror(-r)); - return r; - } + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_LINK attribute: %m"); if(v->ttl) { r = sd_rtnl_message_append_u8(m, IFLA_VXLAN_TTL, v->ttl); - if (r < 0) { - log_netdev_error(netdev, - "Could not append IFLA_VXLAN_TTL attribute: %s", - strerror(-r)); - return r; - } + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_TTL attribute: %m"); } if(v->tos) { r = sd_rtnl_message_append_u8(m, IFLA_VXLAN_TOS, v->tos); - if (r < 0) { - log_netdev_error(netdev, - "Could not append IFLA_VXLAN_TOS attribute: %s", - strerror(-r)); - return r; - } + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_TOS attribute: %m"); } r = sd_rtnl_message_append_u8(m, IFLA_VXLAN_LEARNING, v->learning); - if (r < 0) { - log_netdev_error(netdev, - "Could not append IFLA_VXLAN_LEARNING attribute: %s", - strerror(-r)); - return r; - } + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_LEARNING attribute: %m"); r = sd_rtnl_message_append_u8(m, IFLA_VXLAN_RSC, v->route_short_circuit); - if (r < 0) { - log_netdev_error(netdev, - "Could not append IFLA_VXLAN_RSC attribute: %s", - strerror(-r)); - return r; - } + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_RSC attribute: %m"); r = sd_rtnl_message_append_u8(m, IFLA_VXLAN_PROXY, v->arp_proxy); - if (r < 0) { - log_netdev_error(netdev, - "Could not append IFLA_VXLAN_PROXY attribute: %s", - strerror(-r)); - return r; - } + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_PROXY attribute: %m"); r = sd_rtnl_message_append_u8(m, IFLA_VXLAN_L2MISS, v->l2miss); - if (r < 0) { - log_netdev_error(netdev, - "Could not append IFLA_VXLAN_L2MISS attribute: %s", - strerror(-r)); - return r; - } + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_L2MISS attribute: %m"); r = sd_rtnl_message_append_u8(m, IFLA_VXLAN_L3MISS, v->l3miss); - if (r < 0) { - log_netdev_error(netdev, - "Could not append IFLA_VXLAN_L3MISS attribute: %s", - strerror(-r)); - return r; - } + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_L3MISS attribute: %m"); if(v->fdb_ageing) { r = sd_rtnl_message_append_u32(m, IFLA_VXLAN_AGEING, v->fdb_ageing / USEC_PER_SEC); - if (r < 0) { - log_netdev_error(netdev, - "Could not append IFLA_VXLAN_AGEING attribute: %s", - strerror(-r)); - return r; - } + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_AGEING attribute: %m"); } r = sd_rtnl_message_append_u8(m, IFLA_VXLAN_UDP_CSUM, v->udpcsum); - if (r < 0) { - log_netdev_error(netdev, - "Could not append IFLA_VXLAN_UDP_CSUM attribute: %s", - strerror(-r)); - return r; - } + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_UDP_CSUM attribute: %m"); r = sd_rtnl_message_append_u8(m, IFLA_VXLAN_UDP_ZERO_CSUM6_TX, v->udp6zerocsumtx); - if (r < 0) { - log_netdev_error(netdev, - "Could not append IFLA_VXLAN_UDP_ZERO_CSUM6_TX attribute: %s", - strerror(-r)); - return r; - } + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_UDP_ZERO_CSUM6_TX attribute: %m"); r = sd_rtnl_message_append_u8(m, IFLA_VXLAN_UDP_ZERO_CSUM6_RX, v->udp6zerocsumrx); - if (r < 0) { - log_netdev_error(netdev, - "Could not append IFLA_VXLAN_UDP_ZERO_CSUM6_RX attribute: %s", - strerror(-r)); - return r; - } + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_UDP_ZERO_CSUM6_RX attribute: %m"); return r; } diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index 5947084106..6f32e5f4a4 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -30,6 +30,7 @@ #include "networkd-netdev.h" #include "networkd-link.h" #include "network-internal.h" +#include "dns-domain.h" static int network_load_one(Manager *manager, const char *filename) { _cleanup_network_free_ Network *network = NULL; @@ -466,11 +467,16 @@ int config_parse_domains(const char *unit, STRV_FOREACH(domain, *domains) { if (is_localhost(*domain)) log_syntax(unit, LOG_ERR, filename, line, EINVAL, "'localhost' domain names may not be configured, ignoring assignment: %s", *domain); - else if (!hostname_is_valid(*domain)) { - if (!streq(*domain, "*")) - log_syntax(unit, LOG_ERR, filename, line, EINVAL, "domain name is not valid, ignoring assignment: %s", *domain); - } else - continue; + else { + r = dns_name_is_valid(*domain); + if (r <= 0 && !streq(*domain, "*")) { + if (r < 0) + log_error_errno(r, "Failed to validate domain name: %s: %m", *domain); + if (r == 0) + log_warning("Domain name is not valid, ignoring assignment: %s", *domain); + } else + continue; + } strv_remove(*domains, *domain); diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index 4211a3d779..251af4a67c 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -3656,7 +3656,8 @@ static int spawn_getent(const char *database, const char *key, pid_t *rpid) { if (nullfd > 2) safe_close(nullfd); - reset_all_signal_handlers(); + (void) reset_all_signal_handlers(); + (void) reset_signal_mask(); close_all_fds(NULL, 0); execle("/usr/bin/getent", "getent", database, key, NULL, &empty_env); @@ -4739,8 +4740,8 @@ int main(int argc, char *argv[]) { rtnl_socket_pair[0] = safe_close(rtnl_socket_pair[0]); pid_socket_pair[0] = safe_close(pid_socket_pair[0]); - reset_all_signal_handlers(); - reset_signal_mask(); + (void) reset_all_signal_handlers(); + (void) reset_signal_mask(); r = outer_child(&barrier, arg_directory, diff --git a/src/nss-resolve/nss-resolve.c b/src/nss-resolve/nss-resolve.c index bc6c5dc2a0..8f181a6c72 100644 --- a/src/nss-resolve/nss-resolve.c +++ b/src/nss-resolve/nss-resolve.c @@ -365,13 +365,13 @@ enum nss_status _nss_resolve_gethostbyname3_r( int32_t *ttlp, char **canonp); - fallback = (enum nss_status (*)(const char *name, - int af, - struct hostent *result, - char *buffer, size_t buflen, - int *errnop, int *h_errnop, - int32_t *ttlp, - char **canonp)) + fallback = (enum nss_status (*)(const char *name, + int af, + struct hostent *result, + char *buffer, size_t buflen, + int *errnop, int *h_errnop, + int32_t *ttlp, + char **canonp)) find_fallback("libnss_dns.so.2", "_nss_dns_gethostbyname3_r"); if (fallback) return fallback(name, af, result, buffer, buflen, errnop, h_errnop, ttlp, canonp); 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/quotacheck/quotacheck.c b/src/quotacheck/quotacheck.c index a729f592cf..cf6a239402 100644 --- a/src/quotacheck/quotacheck.c +++ b/src/quotacheck/quotacheck.c @@ -23,9 +23,11 @@ #include <stdbool.h> #include <errno.h> #include <unistd.h> +#include <sys/prctl.h> #include "util.h" #include "process-util.h" +#include "signal-util.h" static bool arg_skip = false; static bool arg_force = false; @@ -105,7 +107,13 @@ int main(int argc, char *argv[]) { log_error_errno(errno, "fork(): %m"); return EXIT_FAILURE; } else if (pid == 0) { + /* Child */ + + (void) reset_all_signal_handlers(); + (void) reset_signal_mask(); + assert_se(prctl(PR_SET_PDEATHSIG, SIGTERM) == 0); + execv(cmdline[0], (char**) cmdline); _exit(1); /* Operational error */ } diff --git a/src/remount-fs/remount-fs.c b/src/remount-fs/remount-fs.c index e701fc9fae..f904e48e75 100644 --- a/src/remount-fs/remount-fs.c +++ b/src/remount-fs/remount-fs.c @@ -95,6 +95,9 @@ int main(int argc, char *argv[]) { const char *arguments[5]; /* Child */ + (void) reset_all_signal_handlers(); + (void) reset_signal_mask(); + arguments[0] = MOUNT_PATH; arguments[1] = me->mnt_dir; arguments[2] = "-o"; diff --git a/src/resolve/resolved-bus.c b/src/resolve/resolved-bus.c index 171141e3a4..6db12511f9 100644 --- a/src/resolve/resolved-bus.c +++ b/src/resolve/resolved-bus.c @@ -22,7 +22,7 @@ #include "bus-common-errors.h" #include "bus-util.h" -#include "resolved-dns-domain.h" +#include "dns-domain.h" #include "resolved-bus.h" #include "resolved-def.h" diff --git a/src/resolve/resolved-dns-answer.c b/src/resolve/resolved-dns-answer.c index e08eb667cc..f77b98e505 100644 --- a/src/resolve/resolved-dns-answer.c +++ b/src/resolve/resolved-dns-answer.c @@ -20,7 +20,7 @@ ***/ #include "resolved-dns-answer.h" -#include "resolved-dns-domain.h" +#include "dns-domain.h" DnsAnswer *dns_answer_new(unsigned n) { DnsAnswer *a; diff --git a/src/resolve/resolved-dns-packet.c b/src/resolve/resolved-dns-packet.c index 21756f566f..bb74b1828e 100644 --- a/src/resolve/resolved-dns-packet.c +++ b/src/resolve/resolved-dns-packet.c @@ -23,7 +23,7 @@ #include "util.h" #include "strv.h" #include "unaligned.h" -#include "resolved-dns-domain.h" +#include "dns-domain.h" #include "resolved-dns-packet.h" int dns_packet_new(DnsPacket **ret, DnsProtocol protocol, size_t mtu) { diff --git a/src/resolve/resolved-dns-question.c b/src/resolve/resolved-dns-question.c index 45bcbbf23a..4d71f5e3d4 100644 --- a/src/resolve/resolved-dns-question.c +++ b/src/resolve/resolved-dns-question.c @@ -20,7 +20,7 @@ ***/ #include "resolved-dns-question.h" -#include "resolved-dns-domain.h" +#include "dns-domain.h" DnsQuestion *dns_question_new(unsigned n) { DnsQuestion *q; diff --git a/src/resolve/resolved-dns-rr.c b/src/resolve/resolved-dns-rr.c index 78d9e4a412..c1818eef9c 100644 --- a/src/resolve/resolved-dns-rr.c +++ b/src/resolve/resolved-dns-rr.c @@ -23,7 +23,7 @@ #include "strv.h" -#include "resolved-dns-domain.h" +#include "dns-domain.h" #include "resolved-dns-rr.h" #include "resolved-dns-packet.h" #include "dns-type.h" diff --git a/src/resolve/resolved-dns-scope.c b/src/resolve/resolved-dns-scope.c index 7369cbf50f..c25ac2216d 100644 --- a/src/resolve/resolved-dns-scope.c +++ b/src/resolve/resolved-dns-scope.c @@ -27,7 +27,7 @@ #include "af-list.h" #include "random-util.h" #include "hostname-util.h" -#include "resolved-dns-domain.h" +#include "dns-domain.h" #include "resolved-dns-scope.h" #define MULTICAST_RATELIMIT_INTERVAL_USEC (1*USEC_PER_SEC) diff --git a/src/resolve/resolved-dns-stream.c b/src/resolve/resolved-dns-stream.c index 4c0b557bad..7f47e7223a 100644 --- a/src/resolve/resolved-dns-stream.c +++ b/src/resolve/resolved-dns-stream.c @@ -113,7 +113,8 @@ static int dns_stream_identify(DnsStream *s) { mh.msg_control = &control; mh.msg_controllen = sl; - for (cmsg = CMSG_FIRSTHDR(&mh); cmsg; cmsg = CMSG_NXTHDR(&mh, cmsg)) { + + CMSG_FOREACH(cmsg, &mh) { if (cmsg->cmsg_level == IPPROTO_IPV6) { assert(s->peer.sa.sa_family == AF_INET6); diff --git a/src/resolve/resolved-dns-zone.c b/src/resolve/resolved-dns-zone.c index a4c9b7d7af..32d771a954 100644 --- a/src/resolve/resolved-dns-zone.c +++ b/src/resolve/resolved-dns-zone.c @@ -22,7 +22,7 @@ #include "list.h" #include "resolved-dns-zone.h" -#include "resolved-dns-domain.h" +#include "dns-domain.h" #include "resolved-dns-packet.h" /* Never allow more than 1K entries */ diff --git a/src/resolve/resolved-manager.c b/src/resolve/resolved-manager.c index 52695376f0..f8d4db7aad 100644 --- a/src/resolve/resolved-manager.c +++ b/src/resolve/resolved-manager.c @@ -34,7 +34,7 @@ #include "random-util.h" #include "hostname-util.h" -#include "resolved-dns-domain.h" +#include "dns-domain.h" #include "resolved-conf.h" #include "resolved-bus.h" #include "resolved-manager.h" @@ -920,7 +920,7 @@ int manager_recv(Manager *m, int fd, DnsProtocol protocol, DnsPacket **ret) { } else return -EAFNOSUPPORT; - for (cmsg = CMSG_FIRSTHDR(&mh); cmsg; cmsg = CMSG_NXTHDR(&mh, cmsg)) { + CMSG_FOREACH(cmsg, &mh) { if (cmsg->cmsg_level == IPPROTO_IPV6) { assert(p->family == AF_INET6); diff --git a/src/run/run.c b/src/run/run.c index 5b9f31c4aa..f18f77b55a 100644 --- a/src/run/run.c +++ b/src/run/run.c @@ -68,7 +68,7 @@ static void help(void) { printf("%s [OPTIONS...] {COMMAND} [ARGS...]\n\n" "Run the specified command in a transient scope or service or timer\n" "unit. If timer option is specified and unit is exist which is\n" - "specified with --unit option then command can be ommited.\n\n" + "specified with --unit option then command can be omitted.\n\n" " -h --help Show this help\n" " --version Show package version\n" " --user Run as user unit\n" diff --git a/src/resolve/resolved-dns-domain.c b/src/shared/dns-domain.c index e1eb3ddfe5..20a44ce4e1 100644 --- a/src/resolve/resolved-dns-domain.c +++ b/src/shared/dns-domain.c @@ -24,7 +24,7 @@ #include <stringprep.h> #endif -#include "resolved-dns-domain.h" +#include "dns-domain.h" int dns_label_unescape(const char **name, char *dest, size_t sz) { const char *n; diff --git a/src/resolve/resolved-dns-domain.h b/src/shared/dns-domain.h index 516d244f7a..00caf5d700 100644 --- a/src/resolve/resolved-dns-domain.h +++ b/src/shared/dns-domain.h @@ -35,6 +35,15 @@ int dns_label_apply_idna(const char *encoded, size_t encoded_size, char *decoded int dns_label_undo_idna(const char *encoded, size_t encoded_size, char *decoded, size_t decoded_max); int dns_name_normalize(const char *s, char **_ret); +static inline int dns_name_is_valid(const char *s) { + int r; + r = dns_name_normalize(s, NULL); + if (r == -EINVAL) + return 0; + if (r < 0) + return r; + return 1; +} unsigned long dns_name_hash_func(const void *s, const uint8_t hash_key[HASH_KEY_SIZE]); int dns_name_compare_func(const void *a, const void *b); diff --git a/src/shared/efivars.c b/src/shared/efivars.c index d34d977b9a..0d6ecf52cf 100644 --- a/src/shared/efivars.c +++ b/src/shared/efivars.c @@ -483,7 +483,7 @@ int efi_add_boot_option(uint16_t id, const char *title, devicep->length = offsetof(struct device_path, drive) + sizeof(struct drive_path); devicep->drive.part_nr = part; devicep->drive.part_start = pstart; - devicep->drive.part_size = psize; + devicep->drive.part_size = psize; devicep->drive.signature_type = SIGNATURE_TYPE_GUID; devicep->drive.mbr_type = MBR_TYPE_EFI_PARTITION_TABLE_HEADER; id128_to_efi_guid(part_uuid, devicep->drive.signature); diff --git a/src/shared/generator.c b/src/shared/generator.c index 807569a1b8..e58bbea77c 100644 --- a/src/shared/generator.c +++ b/src/shared/generator.c @@ -34,9 +34,14 @@ static int write_fsck_sysroot_service(const char *dir, const char *what) { const char *unit; _cleanup_free_ char *device = NULL; + _cleanup_free_ char *escaped; _cleanup_fclose_ FILE *f = NULL; int r; + escaped = cescape(what); + if (!escaped) + return log_oom(); + unit = strjoina(dir, "/systemd-fsck-root.service"); log_debug("Creating %s", unit); @@ -61,11 +66,12 @@ static int write_fsck_sysroot_service(const char *dir, const char *what) { "[Service]\n" "Type=oneshot\n" "RemainAfterExit=yes\n" - "ExecStart=" SYSTEMD_FSCK_PATH " %2$s\n" + "ExecStart=" SYSTEMD_FSCK_PATH " %4$s\n" "TimeoutSec=0\n", program_invocation_short_name, what, - device); + device, + escaped); r = fflush_and_check(f); if (r < 0) diff --git a/src/shared/machine-pool.c b/src/shared/machine-pool.c index d27931cb4a..8c64908b1a 100644 --- a/src/shared/machine-pool.c +++ b/src/shared/machine-pool.c @@ -109,8 +109,8 @@ static int setup_machine_raw(uint64_t size, sd_bus_error *error) { /* Child */ - reset_all_signal_handlers(); - reset_signal_mask(); + (void) reset_all_signal_handlers(); + (void) reset_signal_mask(); assert_se(prctl(PR_SET_PDEATHSIG, SIGTERM) == 0); fd = safe_close(fd); diff --git a/src/shared/macro.h b/src/shared/macro.h index 7ae1ed80b6..cc1c9e73c0 100644 --- a/src/shared/macro.h +++ b/src/shared/macro.h @@ -467,4 +467,7 @@ do { \ } \ struct __useless_struct_to_allow_trailing_semicolon__ +#define CMSG_FOREACH(cmsg, mh) \ + for ((cmsg) = CMSG_FIRSTHDR(mh); (cmsg); (cmsg) = CMSG_NXTHDR((mh), (cmsg))) + #include "log.h" 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/pager.c b/src/shared/pager.c index 58b62fdccf..13f03e798b 100644 --- a/src/shared/pager.c +++ b/src/shared/pager.c @@ -30,6 +30,7 @@ #include "process-util.h" #include "macro.h" #include "terminal-util.h" +#include "signal-util.h" static pid_t pager_pid = 0; @@ -85,6 +86,9 @@ int pager_open(bool jump_to_end) { if (pager_pid == 0) { const char* less_opts; + (void) reset_all_signal_handlers(); + (void) reset_signal_mask(); + dup2(fd[0], STDIN_FILENO); safe_close_pair(fd); @@ -178,6 +182,10 @@ int show_man_page(const char *desc, bool null_stdio) { if (pid == 0) { /* Child */ + + (void) reset_all_signal_handlers(); + (void) reset_signal_mask(); + if (null_stdio) { r = make_null_stdio(); if (r < 0) { diff --git a/src/shared/path-util.c b/src/shared/path-util.c index be50a1865d..537705446a 100644 --- a/src/shared/path-util.c +++ b/src/shared/path-util.c @@ -640,7 +640,7 @@ fallback_fstat: /* 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; + _cleanup_free_ char *canonical = NULL, *parent = NULL; int r; assert(t); @@ -648,7 +648,17 @@ int path_is_mount_point(const char *t, int flags) { if (path_equal(t, "/")) return 1; - r = path_get_parent(t, &parent); + /* we need to resolve symlinks manually, we can't just rely on + * fd_is_mount_point() to do that for us; if we have a structure like + * /bin -> /usr/bin/ and /usr is a mount point, then the parent that we + * look at needs to be /usr, not /. */ + if (flags & AT_SYMLINK_FOLLOW) { + canonical = canonicalize_file_name(t); + if (!canonical) + return -errno; + } + + r = path_get_parent(canonical ?: t, &parent); if (r < 0) return r; @@ -656,7 +666,7 @@ int path_is_mount_point(const char *t, int flags) { if (fd < 0) return -errno; - return fd_is_mount_point(fd, basename(t), flags); + return fd_is_mount_point(fd, basename(canonical ?: t), flags); } int path_is_read_only_fs(const char *path) { diff --git a/src/shared/pty.c b/src/shared/pty.c index 119d66e9a2..a87b3ce6f0 100644 --- a/src/shared/pty.c +++ b/src/shared/pty.c @@ -239,7 +239,7 @@ int pty_setup_child(Pty *pty) { assert_return(pty_is_child(pty), -EINVAL); assert_return(pty_is_open(pty), -EALREADY); - r = sigprocmask_many(SIG_SETMASK, -1); + r = reset_signal_mask(); if (r < 0) return r; 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/signal-util.c b/src/shared/signal-util.c index 9a2973b6fd..84cf42b285 100644 --- a/src/shared/signal-util.c +++ b/src/shared/signal-util.c @@ -23,13 +23,13 @@ #include "signal-util.h" int reset_all_signal_handlers(void) { + static const struct sigaction sa = { + .sa_handler = SIG_DFL, + .sa_flags = SA_RESTART, + }; 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) @@ -38,7 +38,7 @@ int reset_all_signal_handlers(void) { /* 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) + if (errno != EINVAL && r >= 0) r = -errno; } @@ -57,83 +57,123 @@ int reset_signal_mask(void) { return 0; } +static int sigaction_many_ap(const struct sigaction *sa, int sig, va_list ap) { + int r = 0; + + /* negative signal ends the list. 0 signal is skipped. */ + + if (sig < 0) + return 0; + + if (sig > 0) { + if (sigaction(sig, sa, NULL) < 0) + r = -errno; + } + + while ((sig = va_arg(ap, int)) >= 0) { + + if (sig == 0) + continue; + + if (sigaction(sig, sa, NULL) < 0) { + if (r >= 0) + r = -errno; + } + } + + return r; +} + int sigaction_many(const struct sigaction *sa, ...) { va_list ap; - int r = 0, sig; + int r; va_start(ap, sa); - while ((sig = va_arg(ap, int)) > 0) - if (sigaction(sig, sa, NULL) < 0) - r = -errno; + r = sigaction_many_ap(sa, 0, ap); 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_list ap; + int r; va_start(ap, sig); - while ((sig = va_arg(ap, int)) > 0) - if (sigaction(sig, &sa, NULL) < 0) - r = -errno; + r = sigaction_many_ap(&sa, sig, ap); 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_list ap; + int r; va_start(ap, sig); - while ((sig = va_arg(ap, int)) > 0) - if (sigaction(sig, &sa, NULL) < 0) - r = -errno; + r = sigaction_many_ap(&sa, sig, ap); va_end(ap); return r; } -void sigset_add_many(sigset_t *ss, ...) { - va_list ap; - int sig; +static int sigset_add_many_ap(sigset_t *ss, va_list ap) { + int sig, r = 0; assert(ss); + while ((sig = va_arg(ap, int)) >= 0) { + + if (sig == 0) + continue; + + if (sigaddset(ss, sig) < 0) { + if (r >= 0) + r = -errno; + } + } + + return r; +} + +int sigset_add_many(sigset_t *ss, ...) { + va_list ap; + int r; + va_start(ap, ss); - while ((sig = va_arg(ap, int)) > 0) - assert_se(sigaddset(ss, sig) == 0); + r = sigset_add_many_ap(ss, ap); va_end(ap); + + return r; } int sigprocmask_many(int how, ...) { va_list ap; sigset_t ss; - int sig; + int r; - assert_se(sigemptyset(&ss) == 0); + if (sigemptyset(&ss) < 0) + return -errno; va_start(ap, how); - while ((sig = va_arg(ap, int)) > 0) - assert_se(sigaddset(&ss, sig) == 0); + r = sigset_add_many_ap(&ss, ap); va_end(ap); + if (r < 0) + return r; + if (sigprocmask(how, &ss, NULL) < 0) return -errno; diff --git a/src/shared/signal-util.h b/src/shared/signal-util.h index ddf64cda76..9dc8a28726 100644 --- a/src/shared/signal-util.h +++ b/src/shared/signal-util.h @@ -32,7 +32,7 @@ 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 sigset_add_many(sigset_t *ss, ...); int sigprocmask_many(int how, ...); const char *signal_to_string(int i) _const_; diff --git a/src/shared/util.c b/src/shared/util.c index 8a6107969a..6f6906f877 100644 --- a/src/shared/util.c +++ b/src/shared/util.c @@ -1152,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]); @@ -2301,8 +2301,8 @@ static int do_execute(char **directories, usec_t timeout, char *argv[]) { /* We fork this all off from a child process so that we can * somewhat cleanly make use of SIGALRM to set a time limit */ - reset_all_signal_handlers(); - reset_signal_mask(); + (void) reset_all_signal_handlers(); + (void) reset_signal_mask(); assert_se(prctl(PR_SET_PDEATHSIG, SIGTERM) == 0); @@ -3344,8 +3344,8 @@ int fork_agent(pid_t *pid, const int except[], unsigned n_except, const char *pa /* Make sure we actually can kill the agent, if we need to, in * case somebody invoked us from a shell script that trapped * SIGTERM or so... */ - reset_all_signal_handlers(); - reset_signal_mask(); + (void) reset_all_signal_handlers(); + (void) reset_signal_mask(); /* Check whether our parent died before we were able * to set the death signal and unblock the signals */ @@ -4932,7 +4932,7 @@ int bind_remount_recursive(const char *prefix, bool ro) { while ((x = set_steal_first(todo))) { r = set_consume(done, x); - if (r == -EEXIST) + if (r == -EEXIST || r == 0) continue; if (r < 0) return r; @@ -5520,7 +5520,7 @@ int openpt_in_namespace(pid_t pid, int flags) { if (recvmsg(pair[0], &mh, MSG_NOSIGNAL|MSG_CMSG_CLOEXEC) < 0) return -errno; - for (cmsg = CMSG_FIRSTHDR(&mh); cmsg; cmsg = CMSG_NXTHDR(&mh, cmsg)) + CMSG_FOREACH(cmsg, &mh) if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) { int *fds; unsigned n_fds; @@ -5908,7 +5908,7 @@ void cmsg_close_all(struct msghdr *mh) { assert(mh); - for (cmsg = CMSG_FIRSTHDR(mh); cmsg; cmsg = CMSG_NXTHDR(mh, cmsg)) + CMSG_FOREACH(cmsg, mh) if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) close_many((int*) CMSG_DATA(cmsg), (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int)); } diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index a7b8e54a9c..5075e4e176 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -5189,6 +5189,9 @@ static int enable_sysv_units(const char *verb, char **args) { else if (pid == 0) { /* Child */ + (void) reset_all_signal_handlers(); + (void) reset_signal_mask(); + execv(argv[0], (char**) argv); log_error("Failed to execute %s: %m", argv[0]); _exit(EXIT_FAILURE); @@ -5854,6 +5857,9 @@ static int run_editor(char **paths) { unsigned i = 1; size_t argc; + (void) reset_all_signal_handlers(); + (void) reset_signal_mask(); + argc = strv_length(paths)/2 + 1; args = newa(const char*, argc + 1); @@ -5879,7 +5885,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/systemd/sd-bus.h b/src/systemd/sd-bus.h index e6e2ecd0b7..57e46ced8e 100644 --- a/src/systemd/sd-bus.h +++ b/src/systemd/sd-bus.h @@ -299,6 +299,7 @@ int sd_bus_get_name_machine_id(sd_bus *bus, const char *name, sd_id128_t *machin /* Convenience calls */ int sd_bus_call_method(sd_bus *bus, const char *destination, const char *path, const char *interface, const char *member, sd_bus_error *ret_error, sd_bus_message **reply, const char *types, ...); +int sd_bus_call_method_async(sd_bus *bus, sd_bus_slot **slot, const char *destination, const char *path, const char *interface, const char *member, sd_bus_message_handler_t callback, void *userdata, const char *types, ...); int sd_bus_get_property(sd_bus *bus, const char *destination, const char *path, const char *interface, const char *member, sd_bus_error *ret_error, sd_bus_message **reply, const char *type); int sd_bus_get_property_trivial(sd_bus *bus, const char *destination, const char *path, const char *interface, const char *member, sd_bus_error *ret_error, char type, void *ret_ptr); int sd_bus_get_property_string(sd_bus *bus, const char *destination, const char *path, const char *interface, const char *member, sd_bus_error *ret_error, char **ret); /* free the result! */ diff --git a/src/test/test-copy.c b/src/test/test-copy.c index 403d85bff0..e55ffaa16a 100644 --- a/src/test/test-copy.c +++ b/src/test/test-copy.c @@ -133,10 +133,45 @@ static void test_copy_tree(void) { (void) rm_rf(original_dir, REMOVE_ROOT|REMOVE_PHYSICAL); } +static void test_copy_bytes(void) { + _cleanup_close_pair_ int pipefd[2] = {-1, -1}; + _cleanup_close_ int infd = -1; + int r, r2; + char buf[1024], buf2[1024]; + + infd = open("/etc/os-release", O_RDONLY|O_CLOEXEC); + assert_se(infd >= 0); + + assert_se(pipe2(pipefd, O_CLOEXEC) == 0); + + r = copy_bytes(infd, pipefd[1], (off_t) -1, false); + assert_se(r == 0); + + r = read(pipefd[0], buf, sizeof(buf)); + assert_se(r >= 0); + + assert_se(lseek(infd, 0, SEEK_SET) == 0); + r2 = read(infd, buf2, sizeof(buf2)); + assert_se(r == r2); + + assert_se(strneq(buf, buf2, r)); + + /* test copy_bytes with invalid descriptors */ + r = copy_bytes(pipefd[0], pipefd[0], 1, false); + assert_se(r == -EBADF); + + r = copy_bytes(pipefd[1], pipefd[1], 1, false); + assert_se(r == -EBADF); + + r = copy_bytes(pipefd[1], infd, 1, false); + assert_se(r == -EBADF); +} + int main(int argc, char *argv[]) { test_copy_file(); test_copy_file_fd(); test_copy_tree(); + test_copy_bytes(); return 0; } diff --git a/src/resolve/test-dns-domain.c b/src/test/test-dns-domain.c index c3208abc78..527cdd3b54 100644 --- a/src/resolve/test-dns-domain.c +++ b/src/test/test-dns-domain.c @@ -20,7 +20,7 @@ ***/ #include "macro.h" -#include "resolved-dns-domain.h" +#include "dns-domain.h" static void test_dns_label_unescape_one(const char *what, const char *expect, size_t buffer_sz, int ret) { char buffer[buffer_sz]; diff --git a/src/test/test-path-util.c b/src/test/test-path-util.c index 0045ae6824..fce4e81a09 100644 --- a/src/test/test-path-util.c +++ b/src/test/test-path-util.c @@ -312,9 +312,11 @@ static void test_prefix_root(void) { } static void test_path_is_mount_point(void) { - int fd, rt, rf, rlt, rlf; + int fd; char tmp_dir[] = "/tmp/test-path-is-mount-point-XXXXXX"; _cleanup_free_ char *file1 = NULL, *file2 = NULL, *link1 = NULL, *link2 = NULL; + _cleanup_free_ char *dir1 = NULL, *dir1file = NULL, *dirlink1 = NULL, *dirlink1file = NULL; + _cleanup_free_ char *dir2 = NULL, *dir2file = NULL; assert_se(path_is_mount_point("/", AT_SYMLINK_FOLLOW) > 0); assert_se(path_is_mount_point("/", 0) > 0); @@ -328,6 +330,19 @@ static void test_path_is_mount_point(void) { assert_se(path_is_mount_point("/sys", AT_SYMLINK_FOLLOW) > 0); assert_se(path_is_mount_point("/sys", 0) > 0); + /* we'll create a hierarchy of different kinds of dir/file/link + * layouts: + * + * <tmp>/file1, <tmp>/file2 + * <tmp>/link1 -> file1, <tmp>/link2 -> file2 + * <tmp>/dir1/ + * <tmp>/dir1/file + * <tmp>/dirlink1 -> dir1 + * <tmp>/dirlink1file -> dirlink1/file + * <tmp>/dir2/ + * <tmp>/dir2/file + */ + /* file mountpoints */ assert_se(mkdtemp(tmp_dir) != NULL); file1 = path_join(NULL, tmp_dir, "file1"); @@ -352,8 +367,43 @@ static void test_path_is_mount_point(void) { 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 */ + /* directory mountpoints */ + dir1 = path_join(NULL, tmp_dir, "dir1"); + assert_se(dir1); + assert_se(mkdir(dir1, 0755) == 0); + dirlink1 = path_join(NULL, tmp_dir, "dirlink1"); + assert_se(dirlink1); + assert_se(symlink("dir1", dirlink1) == 0); + dirlink1file = path_join(NULL, tmp_dir, "dirlink1file"); + assert_se(dirlink1file); + assert_se(symlink("dirlink1/file", dirlink1file) == 0); + dir2 = path_join(NULL, tmp_dir, "dir2"); + assert_se(dir2); + assert_se(mkdir(dir2, 0755) == 0); + + assert_se(path_is_mount_point(dir1, AT_SYMLINK_FOLLOW) == 0); + assert_se(path_is_mount_point(dir1, 0) == 0); + assert_se(path_is_mount_point(dirlink1, AT_SYMLINK_FOLLOW) == 0); + assert_se(path_is_mount_point(dirlink1, 0) == 0); + + /* file in subdirectory mountpoints */ + dir1file = path_join(NULL, dir1, "file"); + assert_se(dir1file); + fd = open(dir1file, O_WRONLY|O_CREAT|O_EXCL|O_CLOEXEC, 0664); + assert_se(fd > 0); + close(fd); + + assert_se(path_is_mount_point(dir1file, AT_SYMLINK_FOLLOW) == 0); + assert_se(path_is_mount_point(dir1file, 0) == 0); + assert_se(path_is_mount_point(dirlink1file, AT_SYMLINK_FOLLOW) == 0); + assert_se(path_is_mount_point(dirlink1file, 0) == 0); + + /* these tests will only work as root */ if (mount(file1, file2, NULL, MS_BIND, NULL) >= 0) { + int rt, rf, rlt, rlf, rl1t, rl1f; + + /* files */ + /* capture results in vars, to avoid dangling mounts on failure */ rf = path_is_mount_point(file2, 0); rt = path_is_mount_point(file2, AT_SYMLINK_FOLLOW); rlf = path_is_mount_point(link2, 0); @@ -365,6 +415,33 @@ static void test_path_is_mount_point(void) { assert_se(rt == 1); assert_se(rlf == 0); assert_se(rlt == 1); + + /* dirs */ + dir2file = path_join(NULL, dir2, "file"); + assert_se(dir2file); + fd = open(dir2file, O_WRONLY|O_CREAT|O_EXCL|O_CLOEXEC, 0664); + assert_se(fd > 0); + close(fd); + + assert_se(mount(dir2, dir1, NULL, MS_BIND, NULL) >= 0); + + rf = path_is_mount_point(dir1, 0); + rt = path_is_mount_point(dir1, AT_SYMLINK_FOLLOW); + rlf = path_is_mount_point(dirlink1, 0); + rlt = path_is_mount_point(dirlink1, AT_SYMLINK_FOLLOW); + /* its parent is a mount point, but not /file itself */ + rl1f = path_is_mount_point(dirlink1file, 0); + rl1t = path_is_mount_point(dirlink1file, AT_SYMLINK_FOLLOW); + + assert_se(umount(dir1) == 0); + + assert_se(rf == 1); + assert_se(rt == 1); + assert_se(rlf == 0); + assert_se(rlt == 1); + assert_se(rl1f == 0); + assert_se(rl1t == 0); + } else printf("Skipping bind mount file test: %m\n"); diff --git a/src/test/test-udev.c b/src/test/test-udev.c index f3953fe26a..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,8 +116,7 @@ int main(int argc, char *argv[]) { event = udev_event_new(dev); - sigfillset(&mask); - sigprocmask(SIG_SETMASK, &mask, &sigmask_orig); + 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) { @@ -142,11 +139,9 @@ 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: mac_selinux_finish(); diff --git a/src/test/test-unit-file.c b/src/test/test-unit-file.c index 31b12d50d7..a8025c825b 100644 --- a/src/test/test-unit-file.c +++ b/src/test/test-unit-file.c @@ -232,7 +232,7 @@ static void test_config_parse_exec(void) { &c, NULL); assert_se(r >= 0); c1 = c1->command_next; - check_execcommand(c1, "/bin/find", NULL, "\\073", NULL, false); + check_execcommand(c1, "/bin/find", NULL, ";", NULL, false); log_info("/* spaces in the filename */"); r = config_parse_exec(NULL, "fake", 5, "section", 1, diff --git a/src/test/test-util.c b/src/test/test-util.c index e0269821d7..9d5516a18d 100644 --- a/src/test/test-util.c +++ b/src/test/test-util.c @@ -460,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-manager.c b/src/timesync/timesyncd-manager.c index 88e9cf98ed..40e0fd31fe 100644 --- a/src/timesync/timesyncd-manager.c +++ b/src/timesync/timesyncd-manager.c @@ -528,7 +528,7 @@ static int manager_receive_response(sd_event_source *source, int fd, uint32_t re } recv_time = NULL; - for (cmsg = CMSG_FIRSTHDR(&msghdr); cmsg; cmsg = CMSG_NXTHDR(&msghdr, cmsg)) { + CMSG_FOREACH(cmsg, &msghdr) { if (cmsg->cmsg_level != SOL_SOCKET) continue; 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 a5c3edbff8..8d17c5e1e3 100644 --- a/src/udev/udev-event.c +++ b/src/udev/udev-event.c @@ -119,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; @@ -383,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; @@ -411,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); @@ -630,9 +631,9 @@ static int spawn_wait(struct udev_event *event, if (timeout_warn_usec > 0 && timeout_warn_usec < timeout_usec && age_usec < timeout_warn_usec) { spawn.timeout_warn = timeout_warn_usec - age_usec; - r = sd_event_add_time(e, NULL, clock_boottime_or_monotonic(), - usec + spawn.timeout_warn, USEC_PER_SEC, - on_spawn_timeout_warning, &spawn); + 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; } @@ -697,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}; @@ -747,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 ); @@ -809,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) @@ -826,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); @@ -845,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") && @@ -909,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)) { @@ -932,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..7be9a2311a 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; @@ -1939,7 +1941,7 @@ int udev_rules_apply_to_event(struct udev_rules *rules, udev_list_entry_foreach(list_entry, udev_device_get_devlinks_list_entry(event->dev)) { const char *devlink; - devlink = udev_list_entry_get_name(list_entry) + strlen("/dev/"); + devlink = udev_list_entry_get_name(list_entry) + strlen("/dev/"); if (match_key(rules, cur, devlink) == 0) { match = true; break; @@ -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 1b17c615b8..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" @@ -73,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 */ @@ -86,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 46ec0e3225..d04e618d0d 100644 --- a/src/udev/udevadm-test.c +++ b/src/udev/udevadm-test.c @@ -135,8 +135,7 @@ static int adm_test(struct udev *udev, int argc, char *argv[]) { 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)); diff --git a/src/udev/udevd.c b/src/udev/udevd.c index 34e88af539..2affb5944a 100644 --- a/src/udev/udevd.c +++ b/src/udev/udevd.c @@ -42,6 +42,8 @@ #include "sd-daemon.h" #include "sd-event.h" + +#include "signal-util.h" #include "event-util.h" #include "rtnl-util.h" #include "cgroup-util.h" @@ -67,9 +69,8 @@ typedef struct Manager { 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; @@ -306,7 +307,6 @@ static void manager_free(Manager *manager) { udev_list_cleanup(&manager->properties); udev_rules_unref(manager->rules); - free(manager->cgroup); safe_close(manager->fd_inotify); safe_close_pair(manager->worker_watch); @@ -401,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) { @@ -446,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 */ @@ -875,7 +875,7 @@ static int on_worker(sd_event_source *s, int fd, uint32_t revents, void *userdat continue; } - for (cmsg = CMSG_FIRSTHDR(&msghdr); cmsg; cmsg = CMSG_NXTHDR(&msghdr, cmsg)) { + CMSG_FOREACH(cmsg, &msghdr) { if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_CREDENTIALS && cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))) @@ -1261,38 +1261,91 @@ static int on_post(sd_event_source *s, void *userdata) { 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 < 0 || netlink < 0) - return -1; + 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 (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; } @@ -1437,11 +1490,13 @@ 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_ctrl, fd_uevent; + int r, fd_worker, one = 1; assert(ret); + assert(fd_ctrl >= 0); + assert(fd_uevent >= 0); manager = new0(Manager, 1); if (!manager) @@ -1464,57 +1519,15 @@ static int manager_new(Manager **ret) { udev_list_node_init(&manager->events); udev_list_init(manager->udev, &manager->properties, true); - r = systemd_fds(&fd_ctrl, &fd_uevent); - if (r >= 0) { - /* get control and netlink socket from systemd */ - 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"); - - 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"); - - /* 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"); - - fd_ctrl = udev_ctrl_get_fd(manager->ctrl); - - manager->monitor = udev_monitor_new_from_netlink(manager->udev, "kernel"); - if (!manager->monitor) - return log_error_errno(EINVAL, "error initializing netlink socket"); - - fd_uevent = udev_monitor_get_fd(manager->monitor); - - (void) udev_monitor_set_receive_buffer_size(manager->monitor, 128 * 1024 * 1024); - } - - r = udev_monitor_enable_receiving(manager->monitor); - if (r < 0) - return log_error_errno(EINVAL, "error binding netlink socket"); - - r = udev_ctrl_enable_receiving(manager->ctrl); - if (r < 0) - return log_error_errno(EINVAL, "error binding udev control socket"); + manager->cgroup = cgroup; - *ret = manager; - manager = NULL; + 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"); - return 0; -} - -static int manager_listen(Manager *manager) { - sigset_t mask; - int r, fd_worker, one = 1; - - assert(manager); + 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"); /* unnamed socket from workers to the main daemon */ r = socketpair(AF_LOCAL, SOCK_DGRAM|SOCK_CLOEXEC, 0, manager->worker_watch); @@ -1534,8 +1547,7 @@ static int manager_listen(Manager *manager) { udev_watch_restore(manager->udev); /* block and listen to all signals on signalfd */ - sigfillset(&mask); - sigprocmask(SIG_SETMASK, &mask, &manager->sigmask_orig); + assert_se(sigprocmask_many(SIG_BLOCK, SIGTERM, SIGINT, SIGHUP, SIGCHLD, -1) == 0); r = sd_event_default(&manager->event); if (r < 0) @@ -1561,7 +1573,7 @@ static int manager_listen(Manager *manager) { if (r < 0) return log_error_errno(r, "error creating watchdog event source: %m"); - r = sd_event_add_io(manager->event, &manager->ctrl_event, udev_ctrl_get_fd(manager->ctrl), EPOLLIN, on_ctrl_msg, manager); + r = sd_event_add_io(manager->event, &manager->ctrl_event, fd_ctrl, EPOLLIN, on_ctrl_msg, manager); if (r < 0) return log_error_errno(r, "error creating ctrl event source: %m"); @@ -1577,7 +1589,7 @@ static int manager_listen(Manager *manager) { if (r < 0) return log_error_errno(r, "error creating inotify event source: %m"); - r = sd_event_add_io(manager->event, &manager->uevent_event, udev_monitor_get_fd(manager->monitor), EPOLLIN, on_uevent, manager); + 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"); @@ -1589,12 +1601,16 @@ static int manager_listen(Manager *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(); @@ -1622,7 +1638,7 @@ int main(int argc, char *argv[]) { arg_children_max = 8; if (sched_getaffinity(0, sizeof (cpu_set), &cpu_set) == 0) { - arg_children_max += CPU_COUNT(&cpu_set) * 2; + arg_children_max += CPU_COUNT(&cpu_set) * 2; } log_debug("set children_max to %u", arg_children_max); @@ -1651,13 +1667,20 @@ int main(int argc, char *argv[]) { dev_setup(NULL, UID_INVALID, GID_INVALID); - r = manager_new(&manager); - if (r < 0) - goto exit; + 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; @@ -1680,14 +1703,21 @@ int main(int argc, char *argv[]) { setsid(); write_string_file("/proc/self/oom_score_adj", "-1000"); - } else - sd_notify(false, - "READY=1\n" - "STATUS=Processing..."); + } - r = manager_listen(manager); + 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; + } + + r = udev_rules_apply_static_dev_perms(manager->rules); if (r < 0) - return log_error_errno(r, "failed to set up fds and listen for events: %m"); + log_error_errno(r, "failed to apply permissions on static device nodes: %m"); + + (void) sd_notify(false, + "READY=1\n" + "STATUS=Processing..."); r = sd_event_loop(manager->event); if (r < 0) { diff --git a/src/vconsole/vconsole-setup.c b/src/vconsole/vconsole-setup.c index 6c782b3130..f7728dcfff 100644 --- a/src/vconsole/vconsole-setup.c +++ b/src/vconsole/vconsole-setup.c @@ -37,6 +37,7 @@ #include "fileio.h" #include "process-util.h" #include "terminal-util.h" +#include "signal-util.h" static bool is_vconsole(int fd) { unsigned char data[1]; @@ -122,6 +123,10 @@ static int keyboard_load_and_wait(const char *vc, const char *map, const char *m if (pid < 0) return log_error_errno(errno, "Failed to fork: %m"); else if (pid == 0) { + + (void) reset_all_signal_handlers(); + (void) reset_signal_mask(); + execv(args[0], (char **) args); _exit(EXIT_FAILURE); } @@ -160,6 +165,10 @@ static int font_load_and_wait(const char *vc, const char *font, const char *map, if (pid < 0) return log_error_errno(errno, "Failed to fork: %m"); else if (pid == 0) { + + (void) reset_all_signal_handlers(); + (void) reset_signal_mask(); + execv(args[0], (char **) args); _exit(EXIT_FAILURE); } |