udevadm-trigger.c revision 17fcfb5972977b6a3aedca6ad2aa8d1fbfbc761d
/*
* Copyright (C) 2004-2008 Kay Sievers <kay@vrfy.org>
* Copyright (C) 2006 Hannes Reinecke <hare@suse.de>
*
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <getopt.h>
#include <errno.h>
#include <dirent.h>
#include <fcntl.h>
#include <syslog.h>
#include <fnmatch.h>
#include "udev.h"
#include "udev_rules.h"
static int verbose;
static int dry_run;
static int sock = -1;
static struct sockaddr_un saddr;
/* devices that should run last cause of their dependencies */
static int delay_device(const char *devpath)
{
static const char *delay_device_list[] = {
"*/md*",
"*/dm-*",
};
int i;
for (i = 0; delay_device_list[i] != NULL; i++)
return 1;
return 0;
}
{
char filename[UTIL_PATH_SIZE];
char devpath[UTIL_PATH_SIZE];
/* we only have a device, if we have an uevent file */
return -1;
return -1;
/* resolve possible link to real target */
return -1;
return -1;
return 0;
}
{
char filename[UTIL_PATH_SIZE];
int fd;
if (verbose)
if (dry_run)
return;
if (fd < 0) {
return;
}
}
static int pass_to_socket(struct udev *udev, const char *devpath, const char *action, const char *env)
{
struct name_entry *name_loop;
char buf[4096];
char path[UTIL_PATH_SIZE];
int fd;
char link_target[UTIL_PATH_SIZE];
int len;
int err = 0;
if (verbose)
return -1;
/* add header */
bufpos++;
/* add cookie */
bufpos++;
}
/* add standard keys */
bufpos++;
bufpos++;
/* add subsystem */
if (len > 0) {
char *pos;
bufpos++;
}
}
/* add symlinks and node name */
path[0] = '\0';
}
if (path[0] != '\0') {
bufpos++;
}
bufpos++;
}
/* add keys from device "uevent" file */
if (fd >= 0) {
char value[4096];
if (count > 0) {
char *key;
while (key[0] != '\0') {
char *next;
break;
next[0] = '\0';
bufpos++;
}
}
}
/* add keys from database */
bufpos++;
}
if (count < 0)
err = -1;
return err;
}
{
struct name_entry *loop_device;
struct name_entry *tmp_device;
continue;
if (sock >= 0)
else
}
/* trigger remaining delayed devices */
if (sock >= 0)
else
}
}
static int subsystem_filtered(const char *subsystem)
{
struct name_entry *loop_name;
/* skip devices matching the listed subsystems */
return 1;
/* skip devices not matching the listed subsystems */
if (!list_empty(&filter_subsystem_match_list)) {
return 0;
return 1;
}
return 0;
}
{
char attr[UTIL_NAME_SIZE];
char file[UTIL_PATH_SIZE];
char *match_value;
/* separate attr and match value */
if (match_value != NULL) {
match_value[0] = '\0';
}
if (match_value != NULL) {
/* match file content */
char value[UTIL_NAME_SIZE];
int fd;
if (fd < 0)
return 0;
if (size < 0)
return 0;
/* match if attribute value matches */
return 1;
} else {
/* match if attribute exists */
return 1;
}
return 0;
}
static int attr_filtered(const char *path)
{
struct name_entry *loop_name;
/* skip devices matching the listed sysfs attributes */
return 1;
/* skip devices not matching the listed sysfs attributes */
if (!list_empty(&filter_attr_match_list)) {
return 0;
return 1;
}
return 0;
}
enum scan_type {
};
{
char base[UTIL_PATH_SIZE];
const char *subdir;
if (scan == SCAN_DEVICES)
subdir = "/devices";
else if (scan == SCAN_SUBSYSTEM)
subdir = "/drivers";
else
return;
char dirname[UTIL_PATH_SIZE];
continue;
if (scan == SCAN_DEVICES)
continue;
if (scan == SCAN_SUBSYSTEM) {
if (attr_filtered(dirname))
continue;
if (!subsystem_filtered("subsystem"))
if (subsystem_filtered("drivers"))
continue;
}
char dirname2[UTIL_PATH_SIZE];
continue;
if (attr_filtered(dirname2))
continue;
}
}
}
}
}
{
char base[UTIL_PATH_SIZE];
if (subsystem_filtered("block"))
return;
char dirname[UTIL_PATH_SIZE];
continue;
if (attr_filtered(dirname))
continue;
continue;
/* look for partitions */
char dirname2[UTIL_PATH_SIZE];
continue;
continue;
if (attr_filtered(dirname2))
continue;
}
}
}
}
}
{
char base[UTIL_PATH_SIZE];
char dirname[UTIL_PATH_SIZE];
continue;
continue;
char dirname2[UTIL_PATH_SIZE];
continue;
continue;
if (attr_filtered(dirname2))
continue;
}
}
}
}
}
{
char base[UTIL_PATH_SIZE];
char device[UTIL_PATH_SIZE];
continue;
}
}
}
{
int failed = 0;
int option;
const char *action = "add";
{}
};
while (1) {
if (option == -1)
break;
switch (option) {
case 'v':
verbose = 1;
break;
case 'n':
dry_run = 1;
break;
case 'F':
failed = 1;
break;
case 'o':
break;
case 'c':
break;
case 'e':
break;
case 's':
break;
case 'S':
break;
case 'a':
break;
case 'A':
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=<socket path> pass events to socket instead of triggering kernel events\n"
" --env=<KEY>=<value> pass an additional key (works only with --socket=)\n"
" --subsystem-match=<subsystem> trigger devices from a matching subystem\n"
" --subsystem-nomatch=<subsystem> exclude devices from a matching subystem\n"
" --attr-match=<file[=<value>]> trigger devices with a matching sysfs\n"
" attribute\n"
" --attr-nomatch=<file[=<value>]> exclude devices with a matching sysfs\n"
" attribute\n"
" --help print this text\n"
"\n");
goto exit;
default:
goto exit;
}
}
if (sockpath[0] == '@') {
/* abstract namespace socket requested */
/* existing socket file */
} else {
/* no socket file, assume abstract namespace socket */
}
goto exit;
}
if (failed) {
} else {
char base[UTIL_PATH_SIZE];
} else {
/* scan "block" if it isn't a "class" */
}
}
exit:
if (sock >= 0)
return 0;
}