2012-11-12 22:36:23 +04:00
/***
This file is part of systemd .
Copyright 2008 - 2012 Kay Sievers < kay @ vrfy . org >
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 .
systemd 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
Lesser General Public License for more details .
You should have received a copy of the GNU Lesser General Public License
along with systemd ; If not , see < http : //www.gnu.org/licenses/>.
* * */
2008-08-27 19:11:58 +04:00
# include <stdio.h>
# include <stdarg.h>
2008-10-01 11:34:07 +04:00
# include <stdlib.h>
2008-08-29 01:05:01 +04:00
# include <unistd.h>
# include <errno.h>
# include <string.h>
2008-09-12 02:58:40 +04:00
# include <getopt.h>
# include <syslog.h>
2008-09-22 10:28:56 +04:00
# include <fcntl.h>
2011-04-15 14:18:06 +04:00
# include <sys/epoll.h>
2008-08-29 01:05:01 +04:00
2008-08-27 19:11:58 +04:00
# include "libudev.h"
2012-04-16 22:27:44 +04:00
# include "util.h"
2008-08-27 19:11:58 +04:00
2011-04-15 14:18:06 +04:00
# define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
2008-08-27 19:11:58 +04:00
static void log_fn ( struct udev * udev ,
2012-01-10 04:34:15 +04:00
int priority , const char * file , int line , const char * fn ,
const char * format , va_list args )
2008-08-27 19:11:58 +04:00
{
2012-01-10 04:34:15 +04:00
printf ( " test-libudev: %s %s:%d " , fn , file , line ) ;
vprintf ( format , args ) ;
2008-08-27 19:11:58 +04:00
}
2008-08-29 01:05:01 +04:00
static void print_device ( struct udev_device * device )
{
2012-01-10 04:34:15 +04:00
const char * str ;
dev_t devnum ;
int count ;
struct udev_list_entry * list_entry ;
printf ( " *** device: %p *** \n " , device ) ;
str = udev_device_get_action ( device ) ;
if ( str ! = NULL )
printf ( " action: '%s' \n " , str ) ;
str = udev_device_get_syspath ( device ) ;
printf ( " syspath: '%s' \n " , str ) ;
str = udev_device_get_sysname ( device ) ;
printf ( " sysname: '%s' \n " , str ) ;
str = udev_device_get_sysnum ( device ) ;
if ( str ! = NULL )
printf ( " sysnum: '%s' \n " , str ) ;
str = udev_device_get_devpath ( device ) ;
printf ( " devpath: '%s' \n " , str ) ;
str = udev_device_get_subsystem ( device ) ;
if ( str ! = NULL )
printf ( " subsystem: '%s' \n " , str ) ;
str = udev_device_get_devtype ( device ) ;
if ( str ! = NULL )
printf ( " devtype: '%s' \n " , str ) ;
str = udev_device_get_driver ( device ) ;
if ( str ! = NULL )
printf ( " driver: '%s' \n " , str ) ;
str = udev_device_get_devnode ( device ) ;
if ( str ! = NULL )
printf ( " devname: '%s' \n " , str ) ;
devnum = udev_device_get_devnum ( device ) ;
if ( major ( devnum ) > 0 )
printf ( " devnum: %u:%u \n " , major ( devnum ) , minor ( devnum ) ) ;
count = 0 ;
udev_list_entry_foreach ( list_entry , udev_device_get_devlinks_list_entry ( device ) ) {
printf ( " link: '%s' \n " , udev_list_entry_get_name ( list_entry ) ) ;
count + + ;
}
if ( count > 0 )
printf ( " found %i links \n " , count ) ;
count = 0 ;
udev_list_entry_foreach ( list_entry , udev_device_get_properties_list_entry ( device ) ) {
printf ( " property: '%s=%s' \n " ,
udev_list_entry_get_name ( list_entry ) ,
udev_list_entry_get_value ( list_entry ) ) ;
count + + ;
}
if ( count > 0 )
printf ( " found %i properties \n " , count ) ;
str = udev_device_get_property_value ( device , " MAJOR " ) ;
if ( str ! = NULL )
printf ( " MAJOR: '%s' \n " , str ) ;
str = udev_device_get_sysattr_value ( device , " dev " ) ;
if ( str ! = NULL )
printf ( " attr{dev}: '%s' \n " , str ) ;
printf ( " \n " ) ;
2008-08-29 01:05:01 +04:00
}
2008-09-16 04:12:47 +04:00
static int test_device ( struct udev * udev , const char * syspath )
2008-08-29 01:05:01 +04:00
{
2012-01-10 04:34:15 +04:00
struct udev_device * device ;
printf ( " looking at device: %s \n " , syspath ) ;
device = udev_device_new_from_syspath ( udev , syspath ) ;
if ( device = = NULL ) {
printf ( " no device found \n " ) ;
return - 1 ;
}
print_device ( device ) ;
udev_device_unref ( device ) ;
return 0 ;
2008-08-27 19:11:58 +04:00
}
2008-09-16 04:12:47 +04:00
static int test_device_parents ( struct udev * udev , const char * syspath )
2008-09-11 19:08:12 +04:00
{
2012-01-10 04:34:15 +04:00
struct udev_device * device ;
struct udev_device * device_parent ;
printf ( " looking at device: %s \n " , syspath ) ;
device = udev_device_new_from_syspath ( udev , syspath ) ;
if ( device = = NULL )
return - 1 ;
printf ( " looking at parents \n " ) ;
device_parent = device ;
do {
print_device ( device_parent ) ;
device_parent = udev_device_get_parent ( device_parent ) ;
} while ( device_parent ! = NULL ) ;
printf ( " looking at parents again \n " ) ;
device_parent = device ;
do {
print_device ( device_parent ) ;
device_parent = udev_device_get_parent ( device_parent ) ;
} while ( device_parent ! = NULL ) ;
udev_device_unref ( device ) ;
return 0 ;
2008-09-11 19:08:12 +04:00
}
2008-09-22 10:28:56 +04:00
static int test_device_devnum ( struct udev * udev )
{
2012-01-10 04:34:15 +04:00
dev_t devnum = makedev ( 1 , 3 ) ;
struct udev_device * device ;
printf ( " looking up device: %u:%u \n " , major ( devnum ) , minor ( devnum ) ) ;
device = udev_device_new_from_devnum ( udev , ' c ' , devnum ) ;
if ( device = = NULL )
return - 1 ;
print_device ( device ) ;
udev_device_unref ( device ) ;
return 0 ;
2008-09-22 10:28:56 +04:00
}
2008-10-07 22:20:34 +04:00
static int test_device_subsys_name ( struct udev * udev )
{
2012-01-10 04:34:15 +04:00
struct udev_device * device ;
printf ( " looking up device: 'block':'sda' \n " ) ;
device = udev_device_new_from_subsystem_sysname ( udev , " block " , " sda " ) ;
if ( device = = NULL )
return - 1 ;
print_device ( device ) ;
udev_device_unref ( device ) ;
printf ( " looking up device: 'subsystem':'pci' \n " ) ;
device = udev_device_new_from_subsystem_sysname ( udev , " subsystem " , " pci " ) ;
if ( device = = NULL )
return - 1 ;
print_device ( device ) ;
udev_device_unref ( device ) ;
printf ( " looking up device: 'drivers':'scsi:sd' \n " ) ;
device = udev_device_new_from_subsystem_sysname ( udev , " drivers " , " scsi:sd " ) ;
if ( device = = NULL )
return - 1 ;
print_device ( device ) ;
udev_device_unref ( device ) ;
printf ( " looking up device: 'module':'printk' \n " ) ;
device = udev_device_new_from_subsystem_sysname ( udev , " module " , " printk " ) ;
if ( device = = NULL )
return - 1 ;
print_device ( device ) ;
udev_device_unref ( device ) ;
return 0 ;
2008-10-07 22:20:34 +04:00
}
2008-09-28 19:39:31 +04:00
static int test_enumerate_print_list ( struct udev_enumerate * enumerate )
2008-08-27 19:11:58 +04:00
{
2012-01-10 04:34:15 +04:00
struct udev_list_entry * list_entry ;
int count = 0 ;
udev_list_entry_foreach ( list_entry , udev_enumerate_get_list_entry ( enumerate ) ) {
struct udev_device * device ;
device = udev_device_new_from_syspath ( udev_enumerate_get_udev ( enumerate ) ,
udev_list_entry_get_name ( list_entry ) ) ;
if ( device ! = NULL ) {
printf ( " device: '%s' (%s) \n " ,
udev_device_get_syspath ( device ) ,
udev_device_get_subsystem ( device ) ) ;
udev_device_unref ( device ) ;
count + + ;
}
}
printf ( " found %i devices \n \n " , count ) ;
return count ;
2008-08-29 01:05:01 +04:00
}
2009-04-18 15:23:10 +04:00
static int test_monitor ( struct udev * udev )
2008-08-29 01:05:01 +04:00
{
2012-01-10 04:34:15 +04:00
struct udev_monitor * udev_monitor = NULL ;
int fd_ep ;
int fd_udev = - 1 ;
struct epoll_event ep_udev , ep_stdin ;
fd_ep = epoll_create1 ( EPOLL_CLOEXEC ) ;
if ( fd_ep < 0 ) {
printf ( " error creating epoll fd: %m \n " ) ;
goto out ;
}
udev_monitor = udev_monitor_new_from_netlink ( udev , " udev " ) ;
if ( udev_monitor = = NULL ) {
printf ( " no socket \n " ) ;
goto out ;
}
fd_udev = udev_monitor_get_fd ( udev_monitor ) ;
if ( udev_monitor_filter_add_match_subsystem_devtype ( udev_monitor , " block " , NULL ) < 0 | |
udev_monitor_filter_add_match_subsystem_devtype ( udev_monitor , " tty " , NULL ) < 0 | |
udev_monitor_filter_add_match_subsystem_devtype ( udev_monitor , " usb " , " usb_device " ) < 0 ) {
printf ( " filter failed \n " ) ;
goto out ;
}
if ( udev_monitor_enable_receiving ( udev_monitor ) < 0 ) {
printf ( " bind failed \n " ) ;
goto out ;
}
memset ( & ep_udev , 0 , sizeof ( struct epoll_event ) ) ;
ep_udev . events = EPOLLIN ;
ep_udev . data . fd = fd_udev ;
if ( epoll_ctl ( fd_ep , EPOLL_CTL_ADD , fd_udev , & ep_udev ) < 0 ) {
printf ( " fail to add fd to epoll: %m \n " ) ;
goto out ;
}
memset ( & ep_stdin , 0 , sizeof ( struct epoll_event ) ) ;
ep_stdin . events = EPOLLIN ;
ep_stdin . data . fd = STDIN_FILENO ;
if ( epoll_ctl ( fd_ep , EPOLL_CTL_ADD , STDIN_FILENO , & ep_stdin ) < 0 ) {
printf ( " fail to add fd to epoll: %m \n " ) ;
goto out ;
}
for ( ; ; ) {
int fdcount ;
struct epoll_event ev [ 4 ] ;
struct udev_device * device ;
int i ;
printf ( " waiting for events from udev, press ENTER to exit \n " ) ;
fdcount = epoll_wait ( fd_ep , ev , ARRAY_SIZE ( ev ) , - 1 ) ;
printf ( " epoll fd count: %i \n " , fdcount ) ;
for ( i = 0 ; i < fdcount ; i + + ) {
if ( ev [ i ] . data . fd = = fd_udev & & ev [ i ] . events & EPOLLIN ) {
device = udev_monitor_receive_device ( udev_monitor ) ;
if ( device = = NULL ) {
printf ( " no device from socket \n " ) ;
continue ;
}
print_device ( device ) ;
udev_device_unref ( device ) ;
} else if ( ev [ i ] . data . fd = = STDIN_FILENO & & ev [ i ] . events & EPOLLIN ) {
printf ( " exiting loop \n " ) ;
goto out ;
}
}
}
2011-04-15 14:18:06 +04:00
out :
2012-01-10 04:34:15 +04:00
if ( fd_ep > = 0 )
close ( fd_ep ) ;
udev_monitor_unref ( udev_monitor ) ;
return 0 ;
2008-08-27 19:11:58 +04:00
}
2008-10-01 11:34:07 +04:00
static int test_queue ( struct udev * udev )
{
2012-01-10 04:34:15 +04:00
struct udev_queue * udev_queue ;
unsigned long long int seqnum ;
struct udev_list_entry * list_entry ;
udev_queue = udev_queue_new ( udev ) ;
if ( udev_queue = = NULL )
return - 1 ;
seqnum = udev_queue_get_kernel_seqnum ( udev_queue ) ;
printf ( " seqnum kernel: %llu \n " , seqnum ) ;
seqnum = udev_queue_get_udev_seqnum ( udev_queue ) ;
printf ( " seqnum udev : %llu \n " , seqnum ) ;
if ( udev_queue_get_queue_is_empty ( udev_queue ) )
printf ( " queue is empty \n " ) ;
printf ( " get queue list \n " ) ;
udev_list_entry_foreach ( list_entry , udev_queue_get_queued_list_entry ( udev_queue ) )
printf ( " queued: '%s' [%s] \n " , udev_list_entry_get_name ( list_entry ) , udev_list_entry_get_value ( list_entry ) ) ;
printf ( " \n " ) ;
printf ( " get queue list again \n " ) ;
udev_list_entry_foreach ( list_entry , udev_queue_get_queued_list_entry ( udev_queue ) )
printf ( " queued: '%s' [%s] \n " , udev_list_entry_get_name ( list_entry ) , udev_list_entry_get_value ( list_entry ) ) ;
printf ( " \n " ) ;
list_entry = udev_queue_get_queued_list_entry ( udev_queue ) ;
if ( list_entry ! = NULL ) {
printf ( " event [%llu] is queued \n " , seqnum ) ;
seqnum = strtoull ( udev_list_entry_get_value ( list_entry ) , NULL , 10 ) ;
if ( udev_queue_get_seqnum_is_finished ( udev_queue , seqnum ) )
printf ( " event [%llu] is not finished \n " , seqnum ) ;
else
printf ( " event [%llu] is finished \n " , seqnum ) ;
}
printf ( " \n " ) ;
udev_queue_unref ( udev_queue ) ;
return 0 ;
2008-10-01 11:34:07 +04:00
}
2008-10-07 22:20:34 +04:00
static int test_enumerate ( struct udev * udev , const char * subsystem )
{
2012-01-10 04:34:15 +04:00
struct udev_enumerate * udev_enumerate ;
printf ( " enumerate '%s' \n " , subsystem = = NULL ? " <all> " : subsystem ) ;
udev_enumerate = udev_enumerate_new ( udev ) ;
if ( udev_enumerate = = NULL )
return - 1 ;
udev_enumerate_add_match_subsystem ( udev_enumerate , subsystem ) ;
udev_enumerate_scan_devices ( udev_enumerate ) ;
test_enumerate_print_list ( udev_enumerate ) ;
udev_enumerate_unref ( udev_enumerate ) ;
printf ( " enumerate 'net' + duplicated scan + null + zero \n " ) ;
udev_enumerate = udev_enumerate_new ( udev ) ;
if ( udev_enumerate = = NULL )
return - 1 ;
udev_enumerate_add_match_subsystem ( udev_enumerate , " net " ) ;
udev_enumerate_scan_devices ( udev_enumerate ) ;
udev_enumerate_scan_devices ( udev_enumerate ) ;
udev_enumerate_add_syspath ( udev_enumerate , " /sys/class/mem/zero " ) ;
udev_enumerate_add_syspath ( udev_enumerate , " /sys/class/mem/null " ) ;
udev_enumerate_add_syspath ( udev_enumerate , " /sys/class/mem/zero " ) ;
udev_enumerate_add_syspath ( udev_enumerate , " /sys/class/mem/null " ) ;
udev_enumerate_add_syspath ( udev_enumerate , " /sys/class/mem/zero " ) ;
udev_enumerate_add_syspath ( udev_enumerate , " /sys/class/mem/null " ) ;
udev_enumerate_add_syspath ( udev_enumerate , " /sys/class/mem/null " ) ;
udev_enumerate_add_syspath ( udev_enumerate , " /sys/class/mem/zero " ) ;
udev_enumerate_add_syspath ( udev_enumerate , " /sys/class/mem/zero " ) ;
udev_enumerate_scan_devices ( udev_enumerate ) ;
test_enumerate_print_list ( udev_enumerate ) ;
udev_enumerate_unref ( udev_enumerate ) ;
printf ( " enumerate 'block' \n " ) ;
udev_enumerate = udev_enumerate_new ( udev ) ;
if ( udev_enumerate = = NULL )
return - 1 ;
udev_enumerate_add_match_subsystem ( udev_enumerate , " block " ) ;
udev_enumerate_add_match_is_initialized ( udev_enumerate ) ;
udev_enumerate_scan_devices ( udev_enumerate ) ;
test_enumerate_print_list ( udev_enumerate ) ;
udev_enumerate_unref ( udev_enumerate ) ;
printf ( " enumerate 'not block' \n " ) ;
udev_enumerate = udev_enumerate_new ( udev ) ;
if ( udev_enumerate = = NULL )
return - 1 ;
udev_enumerate_add_nomatch_subsystem ( udev_enumerate , " block " ) ;
udev_enumerate_scan_devices ( udev_enumerate ) ;
test_enumerate_print_list ( udev_enumerate ) ;
udev_enumerate_unref ( udev_enumerate ) ;
printf ( " enumerate 'pci, mem, vc' \n " ) ;
udev_enumerate = udev_enumerate_new ( udev ) ;
if ( udev_enumerate = = NULL )
return - 1 ;
udev_enumerate_add_match_subsystem ( udev_enumerate , " pci " ) ;
udev_enumerate_add_match_subsystem ( udev_enumerate , " mem " ) ;
udev_enumerate_add_match_subsystem ( udev_enumerate , " vc " ) ;
udev_enumerate_scan_devices ( udev_enumerate ) ;
test_enumerate_print_list ( udev_enumerate ) ;
udev_enumerate_unref ( udev_enumerate ) ;
printf ( " enumerate 'subsystem' \n " ) ;
udev_enumerate = udev_enumerate_new ( udev ) ;
if ( udev_enumerate = = NULL )
return - 1 ;
udev_enumerate_scan_subsystems ( udev_enumerate ) ;
test_enumerate_print_list ( udev_enumerate ) ;
udev_enumerate_unref ( udev_enumerate ) ;
printf ( " enumerate 'property IF_FS_*=filesystem' \n " ) ;
udev_enumerate = udev_enumerate_new ( udev ) ;
if ( udev_enumerate = = NULL )
return - 1 ;
udev_enumerate_add_match_property ( udev_enumerate , " ID_FS* " , " filesystem " ) ;
udev_enumerate_scan_devices ( udev_enumerate ) ;
test_enumerate_print_list ( udev_enumerate ) ;
udev_enumerate_unref ( udev_enumerate ) ;
return 0 ;
2008-10-07 22:20:34 +04:00
}
2012-10-27 22:59:01 +04:00
static int test_hwdb ( struct udev * udev , const char * modalias ) {
struct udev_hwdb * hwdb ;
struct udev_list_entry * entry ;
hwdb = udev_hwdb_new ( udev ) ;
udev_list_entry_foreach ( entry , udev_hwdb_get_properties_list_entry ( hwdb , modalias , 0 ) )
printf ( " '%s'='%s' \n " , udev_list_entry_get_name ( entry ) , udev_list_entry_get_value ( entry ) ) ;
printf ( " \n " ) ;
hwdb = udev_hwdb_unref ( hwdb ) ;
return 0 ;
}
2008-10-07 22:20:34 +04:00
int main ( int argc , char * argv [ ] )
2008-08-27 19:11:58 +04:00
{
2012-01-10 04:34:15 +04:00
struct udev * udev = NULL ;
static const struct option options [ ] = {
{ " syspath " , required_argument , NULL , ' p ' } ,
{ " subsystem " , required_argument , NULL , ' s ' } ,
{ " debug " , no_argument , NULL , ' d ' } ,
{ " help " , no_argument , NULL , ' h ' } ,
{ " version " , no_argument , NULL , ' V ' } ,
{ }
} ;
const char * syspath = " /devices/virtual/mem/null " ;
const char * subsystem = NULL ;
char path [ 1024 ] ;
udev = udev_new ( ) ;
printf ( " context: %p \n " , udev ) ;
if ( udev = = NULL ) {
printf ( " no context \n " ) ;
return 1 ;
}
udev_set_log_fn ( udev , log_fn ) ;
printf ( " set log: %p \n " , log_fn ) ;
for ( ; ; ) {
int option ;
option = getopt_long ( argc , argv , " +p:s:dhV " , options , NULL ) ;
if ( option = = - 1 )
break ;
switch ( option ) {
case ' p ' :
syspath = optarg ;
break ;
case ' s ' :
subsystem = optarg ;
break ;
case ' d ' :
if ( udev_get_log_priority ( udev ) < LOG_INFO )
udev_set_log_priority ( udev , LOG_INFO ) ;
break ;
case ' h ' :
printf ( " --debug --syspath= --subsystem= --help \n " ) ;
goto out ;
case ' V ' :
printf ( " %s \n " , VERSION ) ;
goto out ;
default :
goto out ;
}
}
/* add sys path if needed */
2012-04-16 22:27:44 +04:00
if ( ! startswith ( syspath , " /sys " ) ) {
2012-04-16 19:21:22 +04:00
snprintf ( path , sizeof ( path ) , " /sys/%s " , syspath ) ;
2012-01-10 04:34:15 +04:00
syspath = path ;
}
test_device ( udev , syspath ) ;
test_device_devnum ( udev ) ;
test_device_subsys_name ( udev ) ;
test_device_parents ( udev , syspath ) ;
test_enumerate ( udev , subsystem ) ;
test_queue ( udev ) ;
2012-10-27 22:59:01 +04:00
test_hwdb ( udev , " usb:v0D50p0011* " ) ;
2012-01-10 04:34:15 +04:00
test_monitor ( udev ) ;
2008-09-12 02:58:40 +04:00
out :
2012-01-10 04:34:15 +04:00
udev_unref ( udev ) ;
return 0 ;
2008-08-27 19:11:58 +04:00
}