LIST_HEAD(filter_attr_match_list);
LIST_HEAD(filter_attr_nomatch_list);
-#ifdef USE_LOG
-void log_message(int priority, const char *format, ...)
-{
- va_list args;
-
- if (priority > udev_log_priority)
- return;
-
- va_start(args, format);
- vsyslog(priority, format, args);
- va_end(args);
-}
-#endif
-
/* devices that should run last cause of their dependencies */
static int delay_device(const char *devpath)
{
return 0;
}
-static void trigger_uevent(const char *devpath)
+static void trigger_uevent(const char *devpath, const char *action)
{
char filename[PATH_SIZE];
int fd;
fd = open(filename, O_WRONLY);
if (fd < 0) {
- dbg("error on opening %s: %s\n", filename, strerror(errno));
+ dbg("error on opening %s: %s", filename, strerror(errno));
return;
}
- if (write(fd, "add", 3) < 0)
- info("error on triggering %s: %s\n", filename, strerror(errno));
+ if (write(fd, action, strlen(action)) < 0)
+ info("error writing '%s' to '%s': %s", action, filename, strerror(errno));
close(fd);
}
-static void exec_list(void)
+static void exec_list(const char *action)
{
struct name_entry *loop_device;
struct name_entry *tmp_device;
if (delay_device(loop_device->name))
continue;
- trigger_uevent(loop_device->name);
+ trigger_uevent(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) {
- trigger_uevent(loop_device->name);
+ trigger_uevent(loop_device->name, action);
list_del(&loop_device->node);
free(loop_device);
}
return 0;
}
-static void scan_subsystem(const char *subsys)
+enum scan_type {
+ SCAN_DEVICES,
+ SCAN_SUBSYSTEM,
+};
+
+static void scan_subsystem(const char *subsys, enum scan_type scan)
{
char base[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;
strlcpy(base, sysfs_path, sizeof(base));
strlcat(base, "/", sizeof(base));
if (dent->d_name[0] == '.')
continue;
- if (subsystem_filtered(dent->d_name))
- continue;
+ if (scan == SCAN_DEVICES)
+ if (subsystem_filtered(dent->d_name))
+ continue;
strlcpy(dirname, base, sizeof(dirname));
strlcat(dirname, "/", sizeof(dirname));
strlcat(dirname, dent->d_name, sizeof(dirname));
- strlcat(dirname, "/devices", sizeof(dirname));
- /* look for devices */
+ if (scan == SCAN_SUBSYSTEM) {
+ if (!subsystem_filtered("subsystem"))
+ device_list_insert(dirname);
+ if (subsystem_filtered("drivers"))
+ continue;
+ }
+
+ strlcat(dirname, subdir, sizeof(dirname));
+
+ /* look for devices/drivers */
dir2 = opendir(dirname);
if (dir2 != NULL) {
for (dent2 = readdir(dir2); dent2 != NULL; dent2 = readdir(dir2)) {
if (dent->d_name[0] == '.')
continue;
- strlcpy(device, sysfs_path, sizeof(device));
- start = strlcat(device, "/", sizeof(device));
+ start = strlcpy(device, sysfs_path, sizeof(device));
+ if(start >= sizeof(device))
+ start = sizeof(device) - 1;
strlcat(device, dent->d_name, sizeof(device));
path_decode(&device[start]);
device_list_insert(device);
}
}
-int main(int argc, char *argv[], char *envp[])
+int udevtrigger(int argc, char *argv[], char *envp[])
{
int failed = 0;
int option;
+ const char *action = "add";
static const struct option options[] = {
{ "verbose", 0, NULL, 'v' },
{ "dry-run", 0, NULL, 'n' },
{ "retry-failed", 0, NULL, 'F' },
{ "help", 0, NULL, 'h' },
+ { "action", 1, NULL, 'c' },
{ "subsystem-match", 1, NULL, 's' },
{ "subsystem-nomatch", 1, NULL, 'S' },
{ "attr-match", 1, NULL, 'a' },
sysfs_init();
while (1) {
- option = getopt_long(argc, argv, "vnFhs:S:a:A:", options, NULL);
+ option = getopt_long(argc, argv, "vnFhc:s:S:a:A:", options, NULL);
if (option == -1)
break;
case 'F':
failed = 1;
break;
+ case 'c':
+ action = optarg;
+ break;
case 's':
name_list_add(&filter_subsystem_match_list, optarg, 0);
break;
name_list_add(&filter_attr_nomatch_list, optarg, 0);
break;
case 'h':
- printf("Usage: udevtrigger OPTIONS\n"
+ 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"
}
}
- if (failed)
+ if (failed) {
scan_failed();
- else {
+ exec_list(action);
+ } else {
char base[PATH_SIZE];
struct stat statbuf;
/* if we have /sys/subsystem, forget all the old stuff */
strlcpy(base, sysfs_path, sizeof(base));
strlcat(base, "/subsystem", sizeof(base));
- if (stat(base, &statbuf) == 0)
- scan_subsystem("subsystem");
- else {
- scan_subsystem("bus");
+ if (stat(base, &statbuf) == 0) {
+ scan_subsystem("subsystem", SCAN_SUBSYSTEM);
+ exec_list(action);
+ scan_subsystem("subsystem", SCAN_DEVICES);
+ exec_list(action);
+ } else {
+ scan_subsystem("bus", SCAN_SUBSYSTEM);
+ exec_list(action);
+ scan_subsystem("bus", SCAN_DEVICES);
scan_class();
/* scan "block" if it isn't a "class" */
strlcat(base, "/class/block", sizeof(base));
if (stat(base, &statbuf) != 0)
scan_block();
+ exec_list(action);
}
}
- exec_list();
exit:
name_list_cleanup(&filter_subsystem_match_list);