From f5001d2465be849306149c902a9db5b031d10428 Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Tue, 30 Sep 2008 13:43:35 +0200 Subject: [PATCH] udevadm: trigger: use libudev --- NEWS | 5 + TODO | 2 +- udev/udevadm-trigger.c | 689 +++++++---------------------------------- udev/udevadm.xml | 27 +- 4 files changed, 118 insertions(+), 605 deletions(-) diff --git a/NEWS b/NEWS index 1468ec39..86e78334 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,8 @@ +udev 129 +======== +More libudev work. Most of udevadm's functionality comes from libudev +now. + udev 128 ======== Bugfixes. diff --git a/TODO b/TODO index 2cbb7cc1..2bbfdb66 100644 --- a/TODO +++ b/TODO @@ -1,6 +1,6 @@ - o use enumerate for "trigger" o add libudev queue - interface for /dev/.udev/queue/ state use queue interface for "settle" + use queue interface for --type=failed #129 o use libudev device in udev_rules.c diff --git a/udev/udevadm-trigger.c b/udev/udevadm-trigger.c index a0f10dac..67180d87 100644 --- a/udev/udevadm-trigger.c +++ b/udev/udevadm-trigger.c @@ -1,6 +1,5 @@ /* - * Copyright (C) 2004-2008 Kay Sievers - * Copyright (C) 2006 Hannes Reinecke + * Copyright (C) 2008 Kay Sievers * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -33,503 +32,39 @@ #include #include "udev.h" -#include "udev_rules.h" static int verbose; static int dry_run; -LIST_HEAD(device_list); -LIST_HEAD(filter_subsystem_match_list); -LIST_HEAD(filter_subsystem_nomatch_list); -LIST_HEAD(filter_attr_match_list); -LIST_HEAD(filter_attr_nomatch_list); -static int sock = -1; -static struct sockaddr_un saddr; -static socklen_t saddrlen; -/* devices that should run last cause of their dependencies */ -static int delay_device(const char *syspath) +static void exec_list(struct udev_enumerate *udev_enumerate, const char *action) { - static const char *delay_device_list[] = { - "*/md*", - "*/dm-*", - NULL - }; - int i; - - for (i = 0; delay_device_list[i] != NULL; i++) - if (fnmatch(delay_device_list[i], syspath, 0) == 0) - return 1; - return 0; -} - -static int device_list_insert(struct udev *udev, const char *path) -{ - char filename[UTIL_PATH_SIZE]; - struct stat statbuf; - - dbg(udev, "add '%s'\n" , path); - - /* we only have a device, if we have an uevent file */ - util_strlcpy(filename, path, sizeof(filename)); - util_strlcat(filename, "/uevent", sizeof(filename)); - if (stat(filename, &statbuf) < 0) - return -1; - if (!(statbuf.st_mode & S_IWUSR)) - return -1; - - /* resolve possible link to real target */ - util_strlcpy(filename, path, sizeof(filename)); - if (lstat(filename, &statbuf) < 0) - return -1; - if (S_ISLNK(statbuf.st_mode)) - if (util_resolve_sys_link(udev, filename, sizeof(filename)) != 0) - return -1; - - name_list_add(udev, &device_list, filename, 1); - return 0; -} - -static void trigger_uevent(struct udev *udev, const char *syspath, const char *action) -{ - char filename[UTIL_PATH_SIZE]; - int fd; - - util_strlcpy(filename, syspath, sizeof(filename)); - util_strlcat(filename, "/uevent", sizeof(filename)); - - if (verbose) - printf("%s\n", syspath); - - if (dry_run) - return; - - fd = open(filename, O_WRONLY); - if (fd < 0) { - dbg(udev, "error on opening %s: %m\n", filename); - return; - } - - if (write(fd, action, strlen(action)) < 0) - info(udev, "error writing '%s' to '%s': %m\n", action, filename); - - close(fd); -} - -static int pass_to_socket(struct udev *udev, const char *syspath, const char *action, const char *env) -{ - struct udevice *udevice; - struct name_entry *name_loop; - char buf[4096]; - size_t bufpos = 0; - ssize_t count; - char path[UTIL_PATH_SIZE]; - int fd; - char link_target[UTIL_PATH_SIZE]; - int len; - const char *devpath = &syspath[strlen(udev_get_sys_path(udev))]; - int err = 0; - - if (verbose) - printf("%s\n", devpath); - - udevice = udev_device_init(udev); - if (udevice == NULL) - return -1; - udev_db_get_device(udevice, devpath); - - /* add header */ - bufpos = snprintf(buf, sizeof(buf)-1, "%s@%s", action, devpath); - bufpos++; - - /* add cookie */ - if (env != NULL) { - bufpos += snprintf(&buf[bufpos], sizeof(buf)-1, "%s", env); - bufpos++; - } - - /* add standard keys */ - bufpos += snprintf(&buf[bufpos], sizeof(buf)-1, "DEVPATH=%s", devpath); - bufpos++; - bufpos += snprintf(&buf[bufpos], sizeof(buf)-1, "ACTION=%s", action); - bufpos++; - - /* add subsystem */ - util_strlcpy(path, udev_get_sys_path(udev), sizeof(path)); - util_strlcat(path, devpath, sizeof(path)); - util_strlcat(path, "/subsystem", sizeof(path)); - len = readlink(path, link_target, sizeof(link_target)); - if (len > 0) { - char *pos; - - link_target[len] = '\0'; - pos = strrchr(link_target, '/'); - if (pos != NULL) { - bufpos += snprintf(&buf[bufpos], sizeof(buf)-1, "SUBSYSTEM=%s", &pos[1]); - bufpos++; - } - } - - /* add symlinks and node name */ - path[0] = '\0'; - list_for_each_entry(name_loop, &udevice->symlink_list, node) { - util_strlcat(path, udev_get_dev_path(udev), sizeof(path)); - util_strlcat(path, "/", sizeof(path)); - util_strlcat(path, name_loop->name, sizeof(path)); - util_strlcat(path, " ", sizeof(path)); - } - util_remove_trailing_chars(path, ' '); - if (path[0] != '\0') { - bufpos += snprintf(&buf[bufpos], sizeof(buf)-1, "DEVLINKS=%s", path); - bufpos++; - } - if (udevice->name[0] != '\0') { - util_strlcpy(path, udev_get_dev_path(udev), sizeof(path)); - util_strlcat(path, "/", sizeof(path)); - util_strlcat(path, udevice->name, sizeof(path)); - bufpos += snprintf(&buf[bufpos], sizeof(buf)-1, "DEVNAME=%s", path); - bufpos++; - } - - /* add keys from device "uevent" file */ - util_strlcpy(path, syspath, sizeof(path)); - util_strlcat(path, "/uevent", sizeof(path)); - fd = open(path, O_RDONLY); - if (fd >= 0) { - char value[4096]; - - count = read(fd, value, sizeof(value)); - close(fd); - if (count > 0) { - char *key; - - value[count] = '\0'; - key = value; - while (key[0] != '\0') { - char *next; - - next = strchr(key, '\n'); - if (next == NULL) - break; - next[0] = '\0'; - bufpos += util_strlcpy(&buf[bufpos], key, sizeof(buf) - bufpos-1); - bufpos++; - key = &next[1]; - } - } - } - - /* add keys from database */ - list_for_each_entry(name_loop, &udevice->env_list, node) { - bufpos += util_strlcpy(&buf[bufpos], name_loop->name, sizeof(buf) - bufpos-1); - bufpos++; - } - if (bufpos > sizeof(buf)) - bufpos = sizeof(buf); - - count = sendto(sock, &buf, bufpos, 0, (struct sockaddr *)&saddr, saddrlen); - if (count < 0) - err = -1; + struct udev *udev = udev_enumerate_get_udev(udev_enumerate); + struct udev_list_entry *entry; - return err; -} - -static void exec_list(struct udev *udev, const char *action, const char *env) -{ - struct name_entry *loop_device; - struct name_entry *tmp_device; - - list_for_each_entry_safe(loop_device, tmp_device, &device_list, node) { - if (delay_device(loop_device->name)) - continue; - if (sock >= 0) - pass_to_socket(udev, loop_device->name, action, env); - else - trigger_uevent(udev, loop_device->name, action); - list_del(&loop_device->node); - free(loop_device); - } - - /* trigger remaining delayed devices */ - list_for_each_entry_safe(loop_device, tmp_device, &device_list, node) { - if (sock >= 0) - pass_to_socket(udev, loop_device->name, action, env); - else - trigger_uevent(udev, loop_device->name, action); - list_del(&loop_device->node); - free(loop_device); - } -} - -static int subsystem_filtered(const char *subsystem) -{ - struct name_entry *loop_name; - - /* skip devices matching the listed subsystems */ - list_for_each_entry(loop_name, &filter_subsystem_nomatch_list, node) - if (fnmatch(loop_name->name, subsystem, 0) == 0) - return 1; - - /* skip devices not matching the listed subsystems */ - if (!list_empty(&filter_subsystem_match_list)) { - list_for_each_entry(loop_name, &filter_subsystem_match_list, node) - if (fnmatch(loop_name->name, subsystem, 0) == 0) - return 0; - return 1; - } - - return 0; -} - -static int attr_match(const char *path, const char *attr_value) -{ - char attr[UTIL_NAME_SIZE]; - char file[UTIL_PATH_SIZE]; - char *match_value; - - util_strlcpy(attr, attr_value, sizeof(attr)); - - /* separate attr and match value */ - match_value = strchr(attr, '='); - if (match_value != NULL) { - match_value[0] = '\0'; - match_value = &match_value[1]; - } - - util_strlcpy(file, path, sizeof(file)); - util_strlcat(file, "/", sizeof(file)); - util_strlcat(file, attr, sizeof(file)); - - if (match_value != NULL) { - /* match file content */ - char value[UTIL_NAME_SIZE]; + udev_list_entry_foreach(entry, udev_enumerate_get_list_entry(udev_enumerate)) { + char filename[UTIL_PATH_SIZE]; int fd; - ssize_t size; - fd = open(file, O_RDONLY); - if (fd < 0) - return 0; - size = read(fd, value, sizeof(value)); - close(fd); - if (size < 0) - return 0; - value[size] = '\0'; - util_remove_trailing_chars(value, '\n'); - - /* match if attribute value matches */ - if (fnmatch(match_value, value, 0) == 0) - return 1; - } else { - /* match if attribute exists */ - struct stat statbuf; - - if (stat(file, &statbuf) == 0) - return 1; - } - return 0; -} - -static int attr_filtered(const char *path) -{ - struct name_entry *loop_name; - - /* skip devices matching the listed sysfs attributes */ - list_for_each_entry(loop_name, &filter_attr_nomatch_list, node) - if (attr_match(path, loop_name->name)) - return 1; - - /* skip devices not matching the listed sysfs attributes */ - if (!list_empty(&filter_attr_match_list)) { - list_for_each_entry(loop_name, &filter_attr_match_list, node) - if (attr_match(path, loop_name->name)) - return 0; - return 1; - } - return 0; -} - -enum scan_type { - SCAN_DEVICES, - SCAN_SUBSYSTEM, -}; - -static void scan_subsystem(struct udev *udev, const char *subsys, enum scan_type scan) -{ - char base[UTIL_PATH_SIZE]; - DIR *dir; - struct dirent *dent; - const char *subdir; - - if (scan == SCAN_DEVICES) - subdir = "/devices"; - else if (scan == SCAN_SUBSYSTEM) - subdir = "/drivers"; - else - return; - - util_strlcpy(base, udev_get_sys_path(udev), sizeof(base)); - util_strlcat(base, "/", sizeof(base)); - util_strlcat(base, subsys, sizeof(base)); - - dir = opendir(base); - if (dir != NULL) { - for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) { - char dirname[UTIL_PATH_SIZE]; - DIR *dir2; - struct dirent *dent2; - - if (dent->d_name[0] == '.') - continue; - - if (scan == SCAN_DEVICES) - if (subsystem_filtered(dent->d_name)) - continue; - - util_strlcpy(dirname, base, sizeof(dirname)); - util_strlcat(dirname, "/", sizeof(dirname)); - util_strlcat(dirname, dent->d_name, sizeof(dirname)); - - if (scan == SCAN_SUBSYSTEM) { - if (attr_filtered(dirname)) - continue; - if (!subsystem_filtered("subsystem")) - device_list_insert(udev, dirname); - if (subsystem_filtered("drivers")) - continue; - } - - util_strlcat(dirname, subdir, sizeof(dirname)); - - /* look for devices/drivers */ - dir2 = opendir(dirname); - if (dir2 != NULL) { - for (dent2 = readdir(dir2); dent2 != NULL; dent2 = readdir(dir2)) { - char dirname2[UTIL_PATH_SIZE]; - - if (dent2->d_name[0] == '.') - continue; - - util_strlcpy(dirname2, dirname, sizeof(dirname2)); - util_strlcat(dirname2, "/", sizeof(dirname2)); - util_strlcat(dirname2, dent2->d_name, sizeof(dirname2)); - if (attr_filtered(dirname2)) - continue; - device_list_insert(udev, dirname2); - } - closedir(dir2); - } - } - closedir(dir); - } -} - -static void scan_block(struct udev *udev) -{ - char base[UTIL_PATH_SIZE]; - DIR *dir; - struct dirent *dent; - - if (subsystem_filtered("block")) - return; - - util_strlcpy(base, udev_get_sys_path(udev), sizeof(base)); - util_strlcat(base, "/block", sizeof(base)); - - dir = opendir(base); - if (dir != NULL) { - for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) { - char dirname[UTIL_PATH_SIZE]; - DIR *dir2; - struct dirent *dent2; - - if (dent->d_name[0] == '.') - continue; - - util_strlcpy(dirname, base, sizeof(dirname)); - util_strlcat(dirname, "/", sizeof(dirname)); - util_strlcat(dirname, dent->d_name, sizeof(dirname)); - if (attr_filtered(dirname)) - continue; - if (device_list_insert(udev, dirname) != 0) - continue; - - /* look for partitions */ - dir2 = opendir(dirname); - if (dir2 != NULL) { - for (dent2 = readdir(dir2); dent2 != NULL; dent2 = readdir(dir2)) { - char dirname2[UTIL_PATH_SIZE]; - - if (dent2->d_name[0] == '.') - continue; - - if (!strcmp(dent2->d_name,"device")) - continue; - - util_strlcpy(dirname2, dirname, sizeof(dirname2)); - util_strlcat(dirname2, "/", sizeof(dirname2)); - util_strlcat(dirname2, dent2->d_name, sizeof(dirname2)); - if (attr_filtered(dirname2)) - continue; - device_list_insert(udev, dirname2); - } - closedir(dir2); - } - } - closedir(dir); - } -} - -static void scan_class(struct udev *udev) -{ - char base[UTIL_PATH_SIZE]; - DIR *dir; - struct dirent *dent; - - util_strlcpy(base, udev_get_sys_path(udev), sizeof(base)); - util_strlcat(base, "/class", sizeof(base)); - - dir = opendir(base); - if (dir != NULL) { - for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) { - char dirname[UTIL_PATH_SIZE]; - DIR *dir2; - struct dirent *dent2; - - if (dent->d_name[0] == '.') - continue; - - if (subsystem_filtered(dent->d_name)) - continue; - - util_strlcpy(dirname, base, sizeof(dirname)); - util_strlcat(dirname, "/", sizeof(dirname)); - util_strlcat(dirname, dent->d_name, sizeof(dirname)); - dir2 = opendir(dirname); - if (dir2 != NULL) { - for (dent2 = readdir(dir2); dent2 != NULL; dent2 = readdir(dir2)) { - char dirname2[UTIL_PATH_SIZE]; - - if (dent2->d_name[0] == '.') - continue; - - if (!strcmp(dent2->d_name, "device")) - continue; - - util_strlcpy(dirname2, dirname, sizeof(dirname2)); - util_strlcat(dirname2, "/", sizeof(dirname2)); - util_strlcat(dirname2, dent2->d_name, sizeof(dirname2)); - if (attr_filtered(dirname2)) - continue; - device_list_insert(udev, dirname2); - } - closedir(dir2); - } + if (verbose) + printf("%s\n", udev_list_entry_get_name(entry)); + if (dry_run) + continue; + util_strlcpy(filename, udev_list_entry_get_name(entry), sizeof(filename)); + util_strlcat(filename, "/uevent", sizeof(filename)); + fd = open(filename, O_WRONLY); + if (fd < 0) { + dbg(udev, "error on opening %s: %m\n", filename); + continue; } - closedir(dir); + if (write(fd, action, strlen(action)) < 0) + info(udev, "error writing '%s' to '%s': %m\n", action, filename); + close(fd); } } -static void scan_failed(struct udev *udev) +static int enumerate_scan_failed(struct udev_enumerate *udev_enumerate) { + struct udev *udev = udev_enumerate_get_udev(udev_enumerate); char base[UTIL_PATH_SIZE]; DIR *dir; struct dirent *dent; @@ -540,49 +75,63 @@ static void scan_failed(struct udev *udev) dir = opendir(base); if (dir != NULL) { for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) { - char device[UTIL_PATH_SIZE]; + char syspath[UTIL_PATH_SIZE]; size_t start; + struct udev_device *device; if (dent->d_name[0] == '.') continue; - - start = util_strlcpy(device, udev_get_sys_path(udev), sizeof(device)); - if(start >= sizeof(device)) - start = sizeof(device) - 1; - util_strlcat(device, dent->d_name, sizeof(device)); - util_path_decode(&device[start]); - device_list_insert(udev, device); + start = util_strlcpy(syspath, udev_get_sys_path(udev), sizeof(syspath)); + util_strlcat(syspath, dent->d_name, sizeof(syspath)); + util_path_decode(&syspath[start]); + device = udev_device_new_from_syspath(udev, syspath); + if (device == NULL) + continue; + udev_enumerate_add_device(udev_enumerate, device); + udev_device_unref(device); } closedir(dir); } + return 0; } int udevadm_trigger(struct udev *udev, int argc, char *argv[]) { - int failed = 0; - const char *sockpath = NULL; - int option; - const char *action = "add"; - const char *env = NULL; static const struct option options[] = { { "verbose", 0, NULL, 'v' }, { "dry-run", 0, NULL, 'n' }, + { "type", 0, NULL, 't' }, { "retry-failed", 0, NULL, 'F' }, - { "socket", 1, NULL, 'o' }, - { "help", 0, NULL, 'h' }, { "action", 1, NULL, 'c' }, { "subsystem-match", 1, NULL, 's' }, { "subsystem-nomatch", 1, NULL, 'S' }, { "attr-match", 1, NULL, 'a' }, { "attr-nomatch", 1, NULL, 'A' }, - { "env", 1, NULL, 'e' }, + { "help", 0, NULL, 'h' }, {} }; + enum { + TYPE_DEVICES, + TYPE_SUBSYSTEMS, + TYPE_FAILED, + } device_type = TYPE_DEVICES; + const char *action = "add"; + struct udev_enumerate *udev_enumerate; + int rc = 0; dbg(udev, "version %s\n", VERSION); + udev_enumerate = udev_enumerate_new(udev); + if (udev_enumerate == NULL) { + rc = 1; + goto exit; + } while (1) { - option = getopt_long(argc, argv, "vnFo:hce::s:S:a:A:", options, NULL); + int option; + char attr[UTIL_PATH_SIZE]; + char *val; + + option = getopt_long(argc, argv, "vnFo:t:hce::s:S:a:A:", options, NULL); if (option == -1) break; @@ -593,45 +142,63 @@ int udevadm_trigger(struct udev *udev, int argc, char *argv[]) case 'n': dry_run = 1; break; - case 'F': - failed = 1; + case 't': + if (strcmp(optarg, "devices") == 0) { + device_type = TYPE_DEVICES; + } else if (strcmp(optarg, "subsystems") == 0) { + device_type = TYPE_SUBSYSTEMS; + } else if (strcmp(optarg, "failed") == 0) { + device_type = TYPE_FAILED; + } else { + fprintf(stderr, "unknown type --type=%s\n", optarg); + err(udev, "unknown type --type=%s\n", optarg); + rc = 2; + goto exit; + } break; - case 'o': - sockpath = optarg; + case 'F': + device_type = TYPE_FAILED; break; case 'c': action = optarg; break; - case 'e': - if (strchr(optarg, '=') != NULL) - env = optarg; - break; case 's': - name_list_add(udev, &filter_subsystem_match_list, optarg, 0); + udev_enumerate_add_match_subsystem(udev_enumerate, optarg); break; case 'S': - name_list_add(udev, &filter_subsystem_nomatch_list, optarg, 0); + udev_enumerate_add_nomatch_subsystem(udev_enumerate, optarg); break; case 'a': - name_list_add(udev, &filter_attr_match_list, optarg, 0); + util_strlcpy(attr, optarg, sizeof(attr)); + val = strchr(attr, '='); + if (val != NULL) { + val[0] = 0; + val = &val[1]; + } + udev_enumerate_add_match_attr(udev_enumerate, attr, val); break; case 'A': - name_list_add(udev, &filter_attr_nomatch_list, optarg, 0); + util_strlcpy(attr, optarg, sizeof(attr)); + val = strchr(attr, '='); + if (val != NULL) { + val[0] = 0; + val = &val[1]; + } + udev_enumerate_add_nomatch_attr(udev_enumerate, attr, val); break; case 'h': printf("Usage: udevadm trigger OPTIONS\n" " --verbose print the list of devices while running\n" " --dry-run do not actually trigger the events\n" - " --retry-failed trigger only the events which have been\n" - " marked as failed during a previous run\n" - " --socket= pass events to socket instead of triggering kernel events\n" - " --env== pass an additional key (works only with --socket=)\n" + " --type= type of events to trigger\n" + " devices sys devices\n" + " subsystems sys subsystems and drivers\n" + " failed trigger only the events which have been\n" + " marked as failed during a previous run\n" " --subsystem-match= trigger devices from a matching subystem\n" " --subsystem-nomatch= exclude devices from a matching subystem\n" - " --attr-match=]> trigger devices with a matching sysfs\n" - " attribute\n" - " --attr-nomatch=]> exclude devices with a matching sysfs\n" - " attribute\n" + " --attr-match=]> trigger devices with a matching attribute\n" + " --attr-nomatch=]> exclude devices with a matching attribute\n" " --help print this text\n" "\n"); goto exit; @@ -640,67 +207,23 @@ int udevadm_trigger(struct udev *udev, int argc, char *argv[]) } } - if (sockpath != NULL) { - struct stat stats; - - sock = socket(AF_LOCAL, SOCK_DGRAM, 0); - memset(&saddr, 0x00, sizeof(struct sockaddr_un)); - saddr.sun_family = AF_LOCAL; - if (sockpath[0] == '@') { - /* abstract namespace socket requested */ - util_strlcpy(&saddr.sun_path[1], &sockpath[1], sizeof(saddr.sun_path)-1); - saddrlen = offsetof(struct sockaddr_un, sun_path) + 1 + strlen(&saddr.sun_path[1]); - } else if (stat(sockpath, &stats) == 0 && S_ISSOCK(stats.st_mode)) { - /* existing socket file */ - util_strlcpy(saddr.sun_path, sockpath, sizeof(saddr.sun_path)); - saddrlen = offsetof(struct sockaddr_un, sun_path) + strlen(saddr.sun_path); - } else { - /* no socket file, assume abstract namespace socket */ - util_strlcpy(&saddr.sun_path[1], sockpath, sizeof(saddr.sun_path)-1); - saddrlen = offsetof(struct sockaddr_un, sun_path) + 1 + strlen(&saddr.sun_path[1]); - } - } else if (env != NULL) { - fprintf(stderr, "error: --env= only valid with --socket= option\n"); + switch (device_type) { + case TYPE_FAILED: + enumerate_scan_failed(udev_enumerate); + exec_list(udev_enumerate, action); + goto exit; + case TYPE_SUBSYSTEMS: + udev_enumerate_scan_subsystems(udev_enumerate); + exec_list(udev_enumerate, action); + goto exit; + case TYPE_DEVICES: + udev_enumerate_scan_devices(udev_enumerate); + exec_list(udev_enumerate, action); + goto exit; + default: goto exit; } - - if (failed) { - scan_failed(udev); - exec_list(udev, action, env); - } else { - char base[UTIL_PATH_SIZE]; - struct stat statbuf; - - /* if we have /sys/subsystem, forget all the old stuff */ - util_strlcpy(base, udev_get_sys_path(udev), sizeof(base)); - util_strlcat(base, "/subsystem", sizeof(base)); - if (stat(base, &statbuf) == 0) { - scan_subsystem(udev, "subsystem", SCAN_SUBSYSTEM); - exec_list(udev, action, env); - scan_subsystem(udev, "subsystem", SCAN_DEVICES); - exec_list(udev, action, env); - } else { - scan_subsystem(udev, "bus", SCAN_SUBSYSTEM); - exec_list(udev, action, env); - scan_subsystem(udev, "bus", SCAN_DEVICES); - scan_class(udev); - - /* scan "block" if it isn't a "class" */ - util_strlcpy(base, udev_get_sys_path(udev), sizeof(base)); - util_strlcat(base, "/class/block", sizeof(base)); - if (stat(base, &statbuf) != 0) - scan_block(udev); - exec_list(udev, action, env); - } - } - exit: - name_list_cleanup(udev, &filter_subsystem_match_list); - name_list_cleanup(udev, &filter_subsystem_nomatch_list); - name_list_cleanup(udev, &filter_attr_match_list); - name_list_cleanup(udev, &filter_attr_nomatch_list); - - if (sock >= 0) - close(sock); - return 0; + udev_enumerate_unref(udev_enumerate); + return rc; } diff --git a/udev/udevadm.xml b/udev/udevadm.xml index b86b33ac..b7687d5d 100644 --- a/udev/udevadm.xml +++ b/udev/udevadm.xml @@ -150,7 +150,7 @@ udevadm trigger <optional>options</optional> - Request device uevents, usually used to replay events at system coldplug. + Request device events from the kernel. Usually used to replay events at system coldplug time. @@ -165,15 +165,17 @@ - + - Trigger only the events which are failed during a previous run. + Trigger a specific type of devices. Valid types are: + devices, subsystems, failed. + The default value is devices. - Type of event to be triggered. The default value is "add". + Type of event to be triggered. The default value is add. @@ -208,23 +210,6 @@ of the sysfs attribute is checked. This option can be specified multiple times. - - - - Pass the synthesized events to the specified socket, instead of triggering - a global kernel event. All available event values will be send in the same format - the kernel sends an uevent, or - sends a message. If the first character of the specified path is an @ character, - an abstract namespace socket is used, instead of an existing socket file. - - - - - - Pass an additional environemt key to the event. This works only with the - --socket option. - - -- 2.39.5