2006-03-17 03:52:15 +03:00
/*
2009-08-01 17:39:18 +04:00
* Copyright ( C ) 2008 - 2009 Kay Sievers < kay . sievers @ vrfy . org >
2006-03-17 03:52:15 +03:00
*
2008-09-10 04:40:42 +04:00
* 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
* the Free Software Foundation , either version 2 of the License , or
* ( at your option ) any later version .
2006-03-17 03:52:15 +03:00
*
2008-09-10 04:40:42 +04:00
* 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/>.
2006-03-17 03:52:15 +03:00
*/
# include <stdlib.h>
# include <stddef.h>
# include <string.h>
# include <stdio.h>
# include <unistd.h>
2006-09-03 05:04:20 +04:00
# include <getopt.h>
2006-03-17 03:52:15 +03:00
# include <errno.h>
# include <dirent.h>
# include <fcntl.h>
# include <syslog.h>
2006-09-03 05:04:20 +04:00
# include <fnmatch.h>
2006-03-17 03:52:15 +03:00
# include <sys/stat.h>
# include <sys/types.h>
2008-03-27 02:58:20 +03:00
# include <sys/socket.h>
# include <sys/un.h>
2006-03-17 03:52:15 +03:00
# include "udev.h"
2006-09-19 19:51:31 +04:00
static int verbose ;
static int dry_run ;
2008-09-30 15:43:35 +04:00
static void exec_list ( struct udev_enumerate * udev_enumerate , const char * action )
2006-09-19 19:51:31 +04:00
{
2008-09-30 15:43:35 +04:00
struct udev * udev = udev_enumerate_get_udev ( udev_enumerate ) ;
struct udev_list_entry * entry ;
2008-03-27 02:58:20 +03:00
2008-09-30 15:43:35 +04:00
udev_list_entry_foreach ( entry , udev_enumerate_get_list_entry ( udev_enumerate ) ) {
char filename [ UTIL_PATH_SIZE ] ;
2006-09-03 05:04:20 +04:00
int fd ;
2008-09-30 15:43:35 +04:00
if ( verbose )
printf ( " %s \n " , udev_list_entry_get_name ( entry ) ) ;
if ( dry_run )
continue ;
2009-05-20 19:57:52 +04:00
util_strscpyl ( filename , sizeof ( filename ) , udev_list_entry_get_name ( entry ) , " /uevent " , NULL ) ;
2008-09-30 15:43:35 +04:00
fd = open ( filename , O_WRONLY ) ;
if ( fd < 0 ) {
dbg ( udev , " error on opening %s: %m \n " , filename ) ;
continue ;
2006-03-17 03:52:15 +03:00
}
2008-09-30 15:43:35 +04:00
if ( write ( fd , action , strlen ( action ) ) < 0 )
info ( udev , " error writing '%s' to '%s': %m \n " , action , filename ) ;
close ( fd ) ;
2006-03-17 03:52:15 +03:00
}
}
2008-10-01 16:41:43 +04:00
static int scan_failed ( struct udev_enumerate * udev_enumerate )
2006-08-20 20:22:44 +04:00
{
2008-09-30 15:43:35 +04:00
struct udev * udev = udev_enumerate_get_udev ( udev_enumerate ) ;
2008-10-01 16:41:43 +04:00
struct udev_queue * udev_queue ;
struct udev_list_entry * list_entry ;
2006-08-20 20:22:44 +04:00
2008-10-01 16:41:43 +04:00
udev_queue = udev_queue_new ( udev ) ;
if ( udev_queue = = NULL )
return - 1 ;
2008-10-02 13:54:33 +04:00
udev_list_entry_foreach ( list_entry , udev_queue_get_failed_list_entry ( udev_queue ) )
udev_enumerate_add_syspath ( udev_enumerate , udev_list_entry_get_name ( list_entry ) ) ;
2008-09-30 15:43:35 +04:00
return 0 ;
2006-08-20 20:22:44 +04:00
}
2009-06-07 04:07:54 +04:00
static const char * keyval ( const char * str , const char * * val , char * buf , size_t size )
{
char * pos ;
util_strscpy ( buf , size , str ) ;
pos = strchr ( buf , ' = ' ) ;
if ( pos ! = NULL ) {
pos [ 0 ] = 0 ;
pos + + ;
}
* val = pos ;
return buf ;
}
2008-09-06 17:45:31 +04:00
int udevadm_trigger ( struct udev * udev , int argc , char * argv [ ] )
2006-03-17 03:52:15 +03:00
{
2006-09-03 16:12:51 +04:00
static const struct option options [ ] = {
2008-10-02 18:49:05 +04:00
{ " verbose " , no_argument , NULL , ' v ' } ,
{ " dry-run " , no_argument , NULL , ' n ' } ,
{ " type " , required_argument , NULL , ' t ' } ,
{ " action " , required_argument , NULL , ' c ' } ,
{ " subsystem-match " , required_argument , NULL , ' s ' } ,
{ " subsystem-nomatch " , required_argument , NULL , ' S ' } ,
{ " attr-match " , required_argument , NULL , ' a ' } ,
{ " attr-nomatch " , required_argument , NULL , ' A ' } ,
2009-06-07 04:07:54 +04:00
{ " property-match " , required_argument , NULL , ' p ' } ,
2010-04-22 20:12:36 +04:00
{ " tag-match " , required_argument , NULL , ' g ' } ,
2009-07-23 02:02:28 +04:00
{ " sysname-match " , required_argument , NULL , ' y ' } ,
2008-10-02 18:49:05 +04:00
{ " help " , no_argument , NULL , ' h ' } ,
2006-09-03 05:04:20 +04:00
{ }
} ;
2008-09-30 15:43:35 +04:00
enum {
TYPE_DEVICES ,
TYPE_SUBSYSTEMS ,
TYPE_FAILED ,
} device_type = TYPE_DEVICES ;
2010-04-12 19:56:32 +04:00
const char * action = " change " ;
2008-09-30 15:43:35 +04:00
struct udev_enumerate * udev_enumerate ;
int rc = 0 ;
2006-03-17 03:52:15 +03:00
2008-09-06 17:45:31 +04:00
dbg ( udev , " version %s \n " , VERSION ) ;
2008-09-30 15:43:35 +04:00
udev_enumerate = udev_enumerate_new ( udev ) ;
if ( udev_enumerate = = NULL ) {
rc = 1 ;
goto exit ;
}
2006-03-17 03:52:15 +03:00
2010-05-27 17:11:00 +04:00
for ( ; ; ) {
2008-09-30 15:43:35 +04:00
int option ;
2009-06-07 04:07:54 +04:00
const char * key ;
const char * val ;
char buf [ UTIL_PATH_SIZE ] ;
2008-09-30 15:43:35 +04:00
2010-07-28 08:56:13 +04:00
option = getopt_long ( argc , argv , " vng:o:t:hc:p:s:S:a:A:y: " , options , NULL ) ;
2006-09-03 05:04:20 +04:00
if ( option = = - 1 )
break ;
2006-03-17 03:52:15 +03:00
2006-09-03 05:04:20 +04:00
switch ( option ) {
case ' v ' :
2006-03-17 03:52:15 +03:00
verbose = 1 ;
2006-09-03 05:04:20 +04:00
break ;
case ' n ' :
2006-03-17 03:52:15 +03:00
dry_run = 1 ;
2006-09-03 05:04:20 +04:00
break ;
2008-09-30 15:43:35 +04:00
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 {
err ( udev , " unknown type --type=%s \n " , optarg ) ;
rc = 2 ;
goto exit ;
}
2006-09-03 05:04:20 +04:00
break ;
2007-07-09 05:59:08 +04:00
case ' c ' :
action = optarg ;
break ;
2006-09-03 05:04:20 +04:00
case ' s ' :
2008-09-30 15:43:35 +04:00
udev_enumerate_add_match_subsystem ( udev_enumerate , optarg ) ;
2006-09-03 05:04:20 +04:00
break ;
case ' S ' :
2008-09-30 15:43:35 +04:00
udev_enumerate_add_nomatch_subsystem ( udev_enumerate , optarg ) ;
2006-09-03 05:04:20 +04:00
break ;
case ' a ' :
2009-06-07 04:07:54 +04:00
key = keyval ( optarg , & val , buf , sizeof ( buf ) ) ;
udev_enumerate_add_match_sysattr ( udev_enumerate , key , val ) ;
2006-09-03 05:04:20 +04:00
break ;
case ' A ' :
2009-06-07 04:07:54 +04:00
key = keyval ( optarg , & val , buf , sizeof ( buf ) ) ;
udev_enumerate_add_nomatch_sysattr ( udev_enumerate , key , val ) ;
break ;
case ' p ' :
key = keyval ( optarg , & val , buf , sizeof ( buf ) ) ;
udev_enumerate_add_match_property ( udev_enumerate , key , val ) ;
2006-09-03 05:04:20 +04:00
break ;
2010-04-22 20:12:36 +04:00
case ' g ' :
udev_enumerate_add_match_tag ( udev_enumerate , optarg ) ;
break ;
2009-07-23 02:02:28 +04:00
case ' y ' :
udev_enumerate_add_match_sysname ( udev_enumerate , optarg ) ;
break ;
2006-09-03 05:04:20 +04:00
case ' h ' :
2007-11-08 19:51:59 +03:00
printf ( " Usage: udevadm trigger OPTIONS \n "
2006-09-03 07:45:51 +04:00
" --verbose print the list of devices while running \n "
" --dry-run do not actually trigger the events \n "
2008-09-30 15:43:35 +04:00
" --type= type of events to trigger \n "
2009-03-17 12:31:32 +03:00
" devices sys devices (default) \n "
2008-09-30 15:43:35 +04:00
" subsystems sys subsystems and drivers \n "
" failed trigger only the events which have been \n "
" marked as failed during a previous run \n "
2010-04-12 19:56:32 +04:00
" --action=<action> event action value, default is \" change \" \n "
2009-08-08 17:29:38 +04:00
" --subsystem-match=<subsystem> trigger devices from a matching subsystem \n "
" --subsystem-nomatch=<subsystem> exclude devices from a matching subsystem \n "
2008-09-30 15:43:35 +04:00
" --attr-match=<file[=<value>]> trigger devices with a matching attribute \n "
" --attr-nomatch=<file[=<value>]> exclude devices with a matching attribute \n "
2009-06-07 04:07:54 +04:00
" --property-match=<key>=<value> trigger devices with a matching property \n "
2010-04-22 20:12:36 +04:00
" --tag-match=<key>=<value> trigger devices with a matching property \n "
2009-07-23 02:02:28 +04:00
" --sysname-match=<name> trigger devices with a matching name \n "
2009-03-07 04:32:40 +03:00
" --help \n \n " ) ;
2006-09-03 05:04:20 +04:00
goto exit ;
default :
2006-08-20 20:22:44 +04:00
goto exit ;
2006-03-17 03:52:15 +03:00
}
}
2008-09-30 15:43:35 +04:00
switch ( device_type ) {
case TYPE_FAILED :
2008-10-01 16:41:43 +04:00
scan_failed ( udev_enumerate ) ;
2008-09-30 15:43:35 +04:00
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 :
2008-04-22 05:01:29 +04:00
goto exit ;
2008-03-27 02:58:20 +03:00
}
2006-03-17 03:52:15 +03:00
exit :
2008-09-30 15:43:35 +04:00
udev_enumerate_unref ( udev_enumerate ) ;
return rc ;
2006-03-17 03:52:15 +03:00
}