2003-07-17 12:24:51 +04:00
/*
* namedev . c
*
* Userspace devfs
*
* Copyright ( C ) 2003 Greg Kroah - Hartman < greg @ kroah . com >
*
*
* 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 version 2 of the License .
*
* 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 , write to the Free Software Foundation , Inc . ,
* 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*
*/
# include <stddef.h>
# include <stdlib.h>
# include <string.h>
# include <stdio.h>
# include <fcntl.h>
# include <ctype.h>
# include <unistd.h>
# include <errno.h>
2003-10-15 10:32:17 +04:00
# include <sys/wait.h>
2003-07-17 12:24:51 +04:00
# include "list.h"
# include "udev.h"
# include "udev_version.h"
# include "namedev.h"
2003-07-19 09:48:28 +04:00
# include "libsysfs/libsysfs.h"
2003-11-24 07:44:41 +03:00
# include "klibc_fixups.h"
2003-07-17 12:24:51 +04:00
2003-12-03 05:38:30 +03:00
LIST_HEAD ( config_device_list ) ;
2003-12-04 05:33:58 +03:00
LIST_HEAD ( perm_device_list ) ;
2003-07-17 12:24:51 +04:00
2003-12-03 17:22:53 +03:00
/* compare string with pattern (supports * ? [0-9] [!A-Z]) */
static int strcmp_pattern ( const char * p , const char * s )
2003-11-24 08:14:33 +03:00
{
2003-12-03 17:22:53 +03:00
if ( * s = = ' \0 ' ) {
while ( * p = = ' * ' )
p + + ;
return ( * p ! = ' \0 ' ) ;
}
switch ( * p ) {
case ' [ ' :
{
int not = 0 ;
p + + ;
if ( * p = = ' ! ' ) {
not = 1 ;
p + + ;
}
while ( * p & & ( * p ! = ' ] ' ) ) {
int match = 0 ;
if ( p [ 1 ] = = ' - ' ) {
if ( ( * s > = * p ) & & ( * s < = p [ 2 ] ) )
match = 1 ;
p + = 3 ;
} else {
match = ( * p = = * s ) ;
p + + ;
}
if ( match ^ not ) {
while ( * p & & ( * p ! = ' ] ' ) )
p + + ;
return strcmp_pattern ( p + 1 , s + 1 ) ;
}
}
}
break ;
case ' * ' :
if ( strcmp_pattern ( p , s + 1 ) )
return strcmp_pattern ( p + 1 , s ) ;
return 0 ;
case ' \0 ' :
if ( * s = = ' \0 ' ) {
return 0 ;
}
break ;
default :
if ( ( * p = = * s ) | | ( * p = = ' ? ' ) )
return strcmp_pattern ( p + 1 , s + 1 ) ;
break ;
}
return 1 ;
2003-11-24 08:14:33 +03:00
}
2003-07-17 12:24:51 +04:00
# define copy_var(a, b, var) \
if ( b - > var ) \
2003-07-18 18:46:17 +04:00
a - > var = b - > var ;
2003-07-17 12:24:51 +04:00
# define copy_string(a, b, var) \
if ( strlen ( b - > var ) ) \
2003-07-18 18:46:17 +04:00
strcpy ( a - > var , b - > var ) ;
2003-07-17 12:24:51 +04:00
2003-12-03 05:38:30 +03:00
int add_config_dev ( struct config_device * new_dev )
2003-07-17 12:24:51 +04:00
{
struct list_head * tmp ;
struct config_device * tmp_dev ;
2003-11-19 17:19:06 +03:00
/* update the values if we already have the device */
2003-07-17 12:24:51 +04:00
list_for_each ( tmp , & config_device_list ) {
struct config_device * dev = list_entry ( tmp , struct config_device , node ) ;
2003-12-03 17:22:53 +03:00
if ( strcmp_pattern ( new_dev - > name , dev - > name ) )
2003-11-24 08:14:33 +03:00
continue ;
2003-11-27 04:45:05 +03:00
if ( strncmp ( dev - > bus , new_dev - > bus , sizeof ( dev - > name ) ) )
continue ;
2003-11-19 17:19:06 +03:00
copy_var ( dev , new_dev , type ) ;
copy_string ( dev , new_dev , bus ) ;
copy_string ( dev , new_dev , sysfs_file ) ;
copy_string ( dev , new_dev , sysfs_value ) ;
copy_string ( dev , new_dev , id ) ;
copy_string ( dev , new_dev , place ) ;
copy_string ( dev , new_dev , kernel_name ) ;
2003-11-27 04:45:05 +03:00
copy_string ( dev , new_dev , exec_program ) ;
2003-12-07 20:12:07 +03:00
copy_string ( dev , new_dev , symlink ) ;
2003-11-19 17:19:06 +03:00
return 0 ;
2003-07-17 12:24:51 +04:00
}
[PATCH] namedev.c whitespace + debug text cleanup
here is mainly a whitespace cleanup for namedev.c. I changed the
dbg_parse() output a bit for better readability:
current:
Nov 19 19:00:59 pim udev[25582]: do_number: NUMBER path='/sys/devices/pci0000:00/0000:00:1d.1/usb2/2-1/2-1.1'
Nov 19 19:00:59 pim udev[25582]: do_number: NUMBER temp='/2-1.1' id='00:07.1'
Nov 19 19:00:59 pim udev[25582]: do_number: NUMBER temp='/2-1' id='00:07.1'
Nov 19 19:00:59 pim udev[25582]: do_number: NUMBER path='/sys/devices/pci0000:00/0000:00:1d.1/usb2/2-1/2-1.1'
Nov 19 19:00:59 pim udev[25582]: do_number: NUMBER temp='/2-1.1' id='00:0b.0'
Nov 19 19:00:59 pim udev[25582]: do_number: NUMBER temp='/2-1' id='00:0b.0'
Nov 19 19:00:59 pim udev[25582]: do_number: NUMBER path='/sys/devices/pci0000:00/0000:00:1d.1/usb2/2-1/2-1.1'
Nov 19 19:00:59 pim udev[25582]: do_number: NUMBER temp='/2-1.1' id='2-1.1'
Nov 19 19:00:59 pim udev[25582]: do_number: device id '2-1.1' becomes 'webcam%n' - owner='', group ='', mode=0
becomes:
Nov 19 19:23:40 pim udev[26091]: do_number: search '00:07.1' in '/2-1.1', path='/sys/devices/pci0000:00/0000:00:1d.1/usb2/2-1/2-1.1'
Nov 19 19:23:40 pim udev[26091]: do_number: search '00:07.1' in '/2-1', path='/sys/devices/pci0000:00/0000:00:1d.1/usb2/2-1'
Nov 19 19:23:40 pim udev[26091]: do_number: search '00:0b.0' in '/2-1.1', path='/sys/devices/pci0000:00/0000:00:1d.1/usb2/2-1/2-1.1'
Nov 19 19:23:40 pim udev[26091]: do_number: search '00:0b.0' in '/2-1', path='/sys/devices/pci0000:00/0000:00:1d.1/usb2/2-1'
Nov 19 19:23:40 pim udev[26091]: do_number: search '2-1.1' in '/2-1.1', path='/sys/devices/pci0000:00/0000:00:1d.1/usb2/2-1/2-1.1'
Nov 19 19:23:40 pim udev[26091]: do_number: found id '2-1.1', 'video0' becomes 'webcam%n' - owner='', group ='', mode=0
2003-11-21 05:37:01 +03:00
/* not found, add new structure to the device list */
2003-07-17 12:24:51 +04:00
tmp_dev = malloc ( sizeof ( * tmp_dev ) ) ;
if ( ! tmp_dev )
return - ENOMEM ;
memcpy ( tmp_dev , new_dev , sizeof ( * tmp_dev ) ) ;
2003-12-03 04:45:19 +03:00
list_add_tail ( & tmp_dev - > node , & config_device_list ) ;
2003-12-03 05:38:30 +03:00
//dump_config_dev(tmp_dev);
2003-07-18 18:46:17 +04:00
return 0 ;
}
2003-07-17 12:24:51 +04:00
2003-12-04 05:33:58 +03:00
int add_perm_dev ( struct perm_device * new_dev )
{
struct list_head * tmp ;
struct perm_device * tmp_dev ;
/* update the values if we already have the device */
list_for_each ( tmp , & perm_device_list ) {
struct perm_device * dev = list_entry ( tmp , struct perm_device , node ) ;
if ( strcmp_pattern ( new_dev - > name , dev - > name ) )
continue ;
copy_var ( dev , new_dev , mode ) ;
copy_string ( dev , new_dev , owner ) ;
copy_string ( dev , new_dev , group ) ;
return 0 ;
}
/* not found, add new structure to the perm list */
tmp_dev = malloc ( sizeof ( * tmp_dev ) ) ;
if ( ! tmp_dev )
return - ENOMEM ;
memcpy ( tmp_dev , new_dev , sizeof ( * tmp_dev ) ) ;
list_add_tail ( & tmp_dev - > node , & perm_device_list ) ;
//dump_perm_dev(tmp_dev);
return 0 ;
}
static struct perm_device * find_perm ( char * name )
{
struct list_head * tmp ;
struct perm_device * perm = NULL ;
list_for_each ( tmp , & perm_device_list ) {
perm = list_entry ( tmp , struct perm_device , node ) ;
if ( strcmp_pattern ( perm - > name , name ) )
continue ;
return perm ;
}
return NULL ;
}
2003-10-20 08:56:21 +04:00
static mode_t get_default_mode ( struct sysfs_class_device * class_dev )
2003-07-19 09:48:28 +04:00
{
2003-12-04 04:41:02 +03:00
mode_t mode = 0600 ; /* default to owner rw only */
if ( strlen ( default_mode_str ) ! = 0 ) {
mode = strtol ( default_mode_str , NULL , 8 ) ;
}
return mode ;
2003-07-19 09:48:28 +04:00
}
2003-11-24 09:25:13 +03:00
static void build_kernel_number ( struct sysfs_class_device * class_dev , struct udevice * udev )
{
char * dig ;
/* FIXME, figure out how to handle stuff like sdaj which will not work right now. */
dig = class_dev - > name + strlen ( class_dev - > name ) ;
while ( isdigit ( * ( dig - 1 ) ) )
dig - - ;
strfieldcpy ( udev - > kernel_number , dig ) ;
2003-11-25 09:27:17 +03:00
dbg ( " kernel_number='%s' " , udev - > kernel_number ) ;
2003-11-24 09:25:13 +03:00
}
static void apply_format ( struct udevice * udev , unsigned char * string )
{
char name [ NAME_SIZE ] ;
char * pos ;
while ( 1 ) {
pos = strchr ( string , ' % ' ) ;
if ( pos ) {
strfieldcpy ( name , pos + 2 ) ;
* pos = 0x00 ;
switch ( pos [ 1 ] ) {
case ' b ' :
if ( strlen ( udev - > bus_id ) = = 0 )
break ;
2003-11-25 09:27:20 +03:00
strcat ( pos , udev - > bus_id ) ;
2003-11-24 09:25:13 +03:00
dbg ( " substitute bus_id '%s' " , udev - > bus_id ) ;
break ;
case ' n ' :
if ( strlen ( udev - > kernel_number ) = = 0 )
break ;
strcat ( pos , udev - > kernel_number ) ;
dbg ( " substitute kernel number '%s' " , udev - > kernel_number ) ;
break ;
2003-11-25 10:41:40 +03:00
case ' D ' :
if ( strlen ( udev - > kernel_number ) = = 0 ) {
2003-12-11 09:12:30 +03:00
strcat ( pos , " disc " ) ;
2003-11-25 10:41:40 +03:00
break ;
}
strcat ( pos , " part " ) ;
strcat ( pos , udev - > kernel_number ) ;
dbg ( " substitute kernel number '%s' " , udev - > kernel_number ) ;
break ;
2003-11-24 09:25:13 +03:00
case ' m ' :
sprintf ( pos , " %u " , udev - > minor ) ;
dbg ( " substitute minor number '%u' " , udev - > minor ) ;
break ;
case ' M ' :
sprintf ( pos , " %u " , udev - > major ) ;
dbg ( " substitute major number '%u' " , udev - > major ) ;
break ;
case ' c ' :
if ( strlen ( udev - > callout_value ) = = 0 )
break ;
strcat ( pos , udev - > callout_value ) ;
dbg ( " substitute callout output '%s' " , udev - > callout_value ) ;
break ;
default :
dbg ( " unknown substitution type '%%%c' " , pos [ 1 ] ) ;
break ;
}
strcat ( string , name ) ;
} else
break ;
}
}
2003-07-19 16:06:55 +04:00
2003-10-15 10:32:17 +04:00
static int exec_callout ( struct config_device * dev , char * value , int len )
{
int retval ;
int res ;
int status ;
int fds [ 2 ] ;
pid_t pid ;
int value_set = 0 ;
char buffer [ 256 ] ;
2003-11-21 17:48:01 +03:00
char * arg ;
char * args [ CALLOUT_MAXARG ] ;
int i ;
2003-10-15 10:32:17 +04:00
[PATCH] namedev.c whitespace + debug text cleanup
here is mainly a whitespace cleanup for namedev.c. I changed the
dbg_parse() output a bit for better readability:
current:
Nov 19 19:00:59 pim udev[25582]: do_number: NUMBER path='/sys/devices/pci0000:00/0000:00:1d.1/usb2/2-1/2-1.1'
Nov 19 19:00:59 pim udev[25582]: do_number: NUMBER temp='/2-1.1' id='00:07.1'
Nov 19 19:00:59 pim udev[25582]: do_number: NUMBER temp='/2-1' id='00:07.1'
Nov 19 19:00:59 pim udev[25582]: do_number: NUMBER path='/sys/devices/pci0000:00/0000:00:1d.1/usb2/2-1/2-1.1'
Nov 19 19:00:59 pim udev[25582]: do_number: NUMBER temp='/2-1.1' id='00:0b.0'
Nov 19 19:00:59 pim udev[25582]: do_number: NUMBER temp='/2-1' id='00:0b.0'
Nov 19 19:00:59 pim udev[25582]: do_number: NUMBER path='/sys/devices/pci0000:00/0000:00:1d.1/usb2/2-1/2-1.1'
Nov 19 19:00:59 pim udev[25582]: do_number: NUMBER temp='/2-1.1' id='2-1.1'
Nov 19 19:00:59 pim udev[25582]: do_number: device id '2-1.1' becomes 'webcam%n' - owner='', group ='', mode=0
becomes:
Nov 19 19:23:40 pim udev[26091]: do_number: search '00:07.1' in '/2-1.1', path='/sys/devices/pci0000:00/0000:00:1d.1/usb2/2-1/2-1.1'
Nov 19 19:23:40 pim udev[26091]: do_number: search '00:07.1' in '/2-1', path='/sys/devices/pci0000:00/0000:00:1d.1/usb2/2-1'
Nov 19 19:23:40 pim udev[26091]: do_number: search '00:0b.0' in '/2-1.1', path='/sys/devices/pci0000:00/0000:00:1d.1/usb2/2-1/2-1.1'
Nov 19 19:23:40 pim udev[26091]: do_number: search '00:0b.0' in '/2-1', path='/sys/devices/pci0000:00/0000:00:1d.1/usb2/2-1'
Nov 19 19:23:40 pim udev[26091]: do_number: search '2-1.1' in '/2-1.1', path='/sys/devices/pci0000:00/0000:00:1d.1/usb2/2-1/2-1.1'
Nov 19 19:23:40 pim udev[26091]: do_number: found id '2-1.1', 'video0' becomes 'webcam%n' - owner='', group ='', mode=0
2003-11-21 05:37:01 +03:00
dbg ( " callout to '%s' " , dev - > exec_program ) ;
2003-10-15 10:32:17 +04:00
retval = pipe ( fds ) ;
if ( retval ! = 0 ) {
dbg ( " pipe failed " ) ;
return - 1 ;
}
pid = fork ( ) ;
if ( pid = = - 1 ) {
dbg ( " fork failed " ) ;
return - 1 ;
}
if ( pid = = 0 ) {
[PATCH] namedev.c whitespace + debug text cleanup
here is mainly a whitespace cleanup for namedev.c. I changed the
dbg_parse() output a bit for better readability:
current:
Nov 19 19:00:59 pim udev[25582]: do_number: NUMBER path='/sys/devices/pci0000:00/0000:00:1d.1/usb2/2-1/2-1.1'
Nov 19 19:00:59 pim udev[25582]: do_number: NUMBER temp='/2-1.1' id='00:07.1'
Nov 19 19:00:59 pim udev[25582]: do_number: NUMBER temp='/2-1' id='00:07.1'
Nov 19 19:00:59 pim udev[25582]: do_number: NUMBER path='/sys/devices/pci0000:00/0000:00:1d.1/usb2/2-1/2-1.1'
Nov 19 19:00:59 pim udev[25582]: do_number: NUMBER temp='/2-1.1' id='00:0b.0'
Nov 19 19:00:59 pim udev[25582]: do_number: NUMBER temp='/2-1' id='00:0b.0'
Nov 19 19:00:59 pim udev[25582]: do_number: NUMBER path='/sys/devices/pci0000:00/0000:00:1d.1/usb2/2-1/2-1.1'
Nov 19 19:00:59 pim udev[25582]: do_number: NUMBER temp='/2-1.1' id='2-1.1'
Nov 19 19:00:59 pim udev[25582]: do_number: device id '2-1.1' becomes 'webcam%n' - owner='', group ='', mode=0
becomes:
Nov 19 19:23:40 pim udev[26091]: do_number: search '00:07.1' in '/2-1.1', path='/sys/devices/pci0000:00/0000:00:1d.1/usb2/2-1/2-1.1'
Nov 19 19:23:40 pim udev[26091]: do_number: search '00:07.1' in '/2-1', path='/sys/devices/pci0000:00/0000:00:1d.1/usb2/2-1'
Nov 19 19:23:40 pim udev[26091]: do_number: search '00:0b.0' in '/2-1.1', path='/sys/devices/pci0000:00/0000:00:1d.1/usb2/2-1/2-1.1'
Nov 19 19:23:40 pim udev[26091]: do_number: search '00:0b.0' in '/2-1', path='/sys/devices/pci0000:00/0000:00:1d.1/usb2/2-1'
Nov 19 19:23:40 pim udev[26091]: do_number: search '2-1.1' in '/2-1.1', path='/sys/devices/pci0000:00/0000:00:1d.1/usb2/2-1/2-1.1'
Nov 19 19:23:40 pim udev[26091]: do_number: found id '2-1.1', 'video0' becomes 'webcam%n' - owner='', group ='', mode=0
2003-11-21 05:37:01 +03:00
/* child */
2003-10-15 10:32:17 +04:00
close ( STDOUT_FILENO ) ;
dup ( fds [ 1 ] ) ; /* dup write side of pipe to STDOUT */
2003-11-21 17:48:01 +03:00
if ( strchr ( dev - > exec_program , ' ' ) ) {
/* callout with arguments */
arg = dev - > exec_program ;
for ( i = 0 ; i < CALLOUT_MAXARG - 1 ; i + + ) {
args [ i ] = strsep ( & arg , " " ) ;
if ( args [ i ] = = NULL )
break ;
}
if ( args [ i ] ) {
2003-11-24 08:14:10 +03:00
dbg ( " too many args - %d " , i ) ;
2003-11-21 17:48:01 +03:00
args [ i ] = NULL ;
}
retval = execve ( args [ 0 ] , args , main_envp ) ;
} else {
retval = execve ( dev - > exec_program , main_argv , main_envp ) ;
}
2003-10-15 10:32:17 +04:00
if ( retval ! = 0 ) {
dbg ( " child execve failed " ) ;
exit ( 1 ) ;
}
return - 1 ; /* avoid compiler warning */
} else {
[PATCH] namedev.c whitespace + debug text cleanup
here is mainly a whitespace cleanup for namedev.c. I changed the
dbg_parse() output a bit for better readability:
current:
Nov 19 19:00:59 pim udev[25582]: do_number: NUMBER path='/sys/devices/pci0000:00/0000:00:1d.1/usb2/2-1/2-1.1'
Nov 19 19:00:59 pim udev[25582]: do_number: NUMBER temp='/2-1.1' id='00:07.1'
Nov 19 19:00:59 pim udev[25582]: do_number: NUMBER temp='/2-1' id='00:07.1'
Nov 19 19:00:59 pim udev[25582]: do_number: NUMBER path='/sys/devices/pci0000:00/0000:00:1d.1/usb2/2-1/2-1.1'
Nov 19 19:00:59 pim udev[25582]: do_number: NUMBER temp='/2-1.1' id='00:0b.0'
Nov 19 19:00:59 pim udev[25582]: do_number: NUMBER temp='/2-1' id='00:0b.0'
Nov 19 19:00:59 pim udev[25582]: do_number: NUMBER path='/sys/devices/pci0000:00/0000:00:1d.1/usb2/2-1/2-1.1'
Nov 19 19:00:59 pim udev[25582]: do_number: NUMBER temp='/2-1.1' id='2-1.1'
Nov 19 19:00:59 pim udev[25582]: do_number: device id '2-1.1' becomes 'webcam%n' - owner='', group ='', mode=0
becomes:
Nov 19 19:23:40 pim udev[26091]: do_number: search '00:07.1' in '/2-1.1', path='/sys/devices/pci0000:00/0000:00:1d.1/usb2/2-1/2-1.1'
Nov 19 19:23:40 pim udev[26091]: do_number: search '00:07.1' in '/2-1', path='/sys/devices/pci0000:00/0000:00:1d.1/usb2/2-1'
Nov 19 19:23:40 pim udev[26091]: do_number: search '00:0b.0' in '/2-1.1', path='/sys/devices/pci0000:00/0000:00:1d.1/usb2/2-1/2-1.1'
Nov 19 19:23:40 pim udev[26091]: do_number: search '00:0b.0' in '/2-1', path='/sys/devices/pci0000:00/0000:00:1d.1/usb2/2-1'
Nov 19 19:23:40 pim udev[26091]: do_number: search '2-1.1' in '/2-1.1', path='/sys/devices/pci0000:00/0000:00:1d.1/usb2/2-1/2-1.1'
Nov 19 19:23:40 pim udev[26091]: do_number: found id '2-1.1', 'video0' becomes 'webcam%n' - owner='', group ='', mode=0
2003-11-21 05:37:01 +03:00
/* parent reads from fds[0] */
2003-10-15 10:32:17 +04:00
close ( fds [ 1 ] ) ;
retval = 0 ;
while ( 1 ) {
res = read ( fds [ 0 ] , buffer , sizeof ( buffer ) - 1 ) ;
if ( res < = 0 )
break ;
buffer [ res ] = ' \0 ' ;
if ( res > len ) {
2003-11-25 09:27:17 +03:00
dbg ( " callout len %d too short " , len ) ;
2003-10-15 10:32:17 +04:00
retval = - 1 ;
}
if ( value_set ) {
dbg ( " callout value already set " ) ;
retval = - 1 ;
} else {
value_set = 1 ;
strncpy ( value , buffer , len ) ;
}
}
2003-11-21 17:48:01 +03:00
dbg ( " callout returned '%s' " , value ) ;
2003-10-15 10:32:17 +04:00
close ( fds [ 0 ] ) ;
res = wait ( & status ) ;
if ( res < 0 ) {
dbg ( " wait failed result %d " , res ) ;
retval = - 1 ;
}
2003-10-23 10:48:55 +04:00
# ifndef __KLIBC__
2003-10-15 10:32:17 +04:00
if ( ! WIFEXITED ( status ) | | ( WEXITSTATUS ( status ) ! = 0 ) ) {
dbg ( " callout program status 0x%x " , status ) ;
retval = - 1 ;
}
2003-10-23 10:48:55 +04:00
# endif
2003-10-15 10:32:17 +04:00
}
return retval ;
}
2003-11-27 04:45:05 +03:00
static int do_callout ( struct sysfs_class_device * class_dev , struct udevice * udev , struct sysfs_device * sysfs_device )
2003-11-12 19:26:08 +03:00
{
struct config_device * dev ;
struct list_head * tmp ;
list_for_each ( tmp , & config_device_list ) {
dev = list_entry ( tmp , struct config_device , node ) ;
if ( dev - > type ! = CALLOUT )
continue ;
2003-11-24 09:25:13 +03:00
2003-11-27 04:45:05 +03:00
if ( sysfs_device ) {
2003-12-03 05:38:30 +03:00
dbg ( " dev->bus='%s' sysfs_device->bus='%s' " , dev - > bus , sysfs_device - > bus ) ;
2003-11-27 04:45:05 +03:00
if ( strcasecmp ( dev - > bus , sysfs_device - > bus ) ! = 0 )
continue ;
}
2003-11-24 09:25:13 +03:00
/* substitute anything that needs to be in the program name */
apply_format ( udev , dev - > exec_program ) ;
if ( exec_callout ( dev , udev - > callout_value , NAME_SIZE ) )
2003-11-12 19:26:08 +03:00
continue ;
2003-12-03 17:22:53 +03:00
if ( strcmp_pattern ( dev - > id , udev - > callout_value ) ! = 0 )
2003-11-12 19:26:08 +03:00
continue ;
2003-11-19 08:39:30 +03:00
strfieldcpy ( udev - > name , dev - > name ) ;
2003-12-07 20:12:07 +03:00
strfieldcpy ( udev - > symlink , dev - > symlink ) ;
2003-12-04 05:33:58 +03:00
dbg ( " callout returned matching value '%s', '%s' becomes '%s' " ,
dev - > id , class_dev - > name , udev - > name ) ;
2003-11-12 19:26:08 +03:00
return 0 ;
}
return - ENODEV ;
}
2003-11-13 16:52:08 +03:00
static int do_label ( struct sysfs_class_device * class_dev , struct udevice * udev , struct sysfs_device * sysfs_device )
{
struct sysfs_attribute * tmpattr = NULL ;
struct config_device * dev ;
struct list_head * tmp ;
2003-12-05 06:21:27 +03:00
char * c ;
2003-11-13 16:52:08 +03:00
list_for_each ( tmp , & config_device_list ) {
dev = list_entry ( tmp , struct config_device , node ) ;
if ( dev - > type ! = LABEL )
continue ;
2003-11-27 04:45:05 +03:00
if ( sysfs_device ) {
2003-12-03 05:38:30 +03:00
dbg ( " dev->bus='%s' sysfs_device->bus='%s' " , dev - > bus , sysfs_device - > bus ) ;
2003-11-27 04:45:05 +03:00
if ( strcasecmp ( dev - > bus , sysfs_device - > bus ) ! = 0 )
continue ;
}
2003-12-03 05:38:30 +03:00
dbg ( " look for device attribute '%s' " , dev - > sysfs_file ) ;
2003-11-13 16:52:08 +03:00
/* try to find the attribute in the class device directory */
tmpattr = sysfs_get_classdev_attr ( class_dev , dev - > sysfs_file ) ;
if ( tmpattr )
goto label_found ;
/* look in the class device directory if present */
if ( sysfs_device ) {
tmpattr = sysfs_get_device_attr ( sysfs_device , dev - > sysfs_file ) ;
if ( tmpattr )
goto label_found ;
}
continue ;
label_found :
2003-12-05 06:21:27 +03:00
c = tmpattr - > value + strlen ( tmpattr - > value ) - 1 ;
if ( * c = = ' \n ' )
* c = 0x00 ;
2003-12-03 05:38:30 +03:00
dbg ( " compare attribute '%s' value '%s' with '%s' " ,
[PATCH] namedev.c whitespace + debug text cleanup
here is mainly a whitespace cleanup for namedev.c. I changed the
dbg_parse() output a bit for better readability:
current:
Nov 19 19:00:59 pim udev[25582]: do_number: NUMBER path='/sys/devices/pci0000:00/0000:00:1d.1/usb2/2-1/2-1.1'
Nov 19 19:00:59 pim udev[25582]: do_number: NUMBER temp='/2-1.1' id='00:07.1'
Nov 19 19:00:59 pim udev[25582]: do_number: NUMBER temp='/2-1' id='00:07.1'
Nov 19 19:00:59 pim udev[25582]: do_number: NUMBER path='/sys/devices/pci0000:00/0000:00:1d.1/usb2/2-1/2-1.1'
Nov 19 19:00:59 pim udev[25582]: do_number: NUMBER temp='/2-1.1' id='00:0b.0'
Nov 19 19:00:59 pim udev[25582]: do_number: NUMBER temp='/2-1' id='00:0b.0'
Nov 19 19:00:59 pim udev[25582]: do_number: NUMBER path='/sys/devices/pci0000:00/0000:00:1d.1/usb2/2-1/2-1.1'
Nov 19 19:00:59 pim udev[25582]: do_number: NUMBER temp='/2-1.1' id='2-1.1'
Nov 19 19:00:59 pim udev[25582]: do_number: device id '2-1.1' becomes 'webcam%n' - owner='', group ='', mode=0
becomes:
Nov 19 19:23:40 pim udev[26091]: do_number: search '00:07.1' in '/2-1.1', path='/sys/devices/pci0000:00/0000:00:1d.1/usb2/2-1/2-1.1'
Nov 19 19:23:40 pim udev[26091]: do_number: search '00:07.1' in '/2-1', path='/sys/devices/pci0000:00/0000:00:1d.1/usb2/2-1'
Nov 19 19:23:40 pim udev[26091]: do_number: search '00:0b.0' in '/2-1.1', path='/sys/devices/pci0000:00/0000:00:1d.1/usb2/2-1/2-1.1'
Nov 19 19:23:40 pim udev[26091]: do_number: search '00:0b.0' in '/2-1', path='/sys/devices/pci0000:00/0000:00:1d.1/usb2/2-1'
Nov 19 19:23:40 pim udev[26091]: do_number: search '2-1.1' in '/2-1.1', path='/sys/devices/pci0000:00/0000:00:1d.1/usb2/2-1/2-1.1'
Nov 19 19:23:40 pim udev[26091]: do_number: found id '2-1.1', 'video0' becomes 'webcam%n' - owner='', group ='', mode=0
2003-11-21 05:37:01 +03:00
dev - > sysfs_file , tmpattr - > value , dev - > sysfs_value ) ;
2003-12-05 06:21:31 +03:00
if ( strcmp_pattern ( dev - > sysfs_value , tmpattr - > value ) ! = 0 )
2003-11-13 16:52:08 +03:00
continue ;
2003-11-19 08:39:30 +03:00
strfieldcpy ( udev - > name , dev - > name ) ;
2003-12-07 20:12:07 +03:00
strfieldcpy ( udev - > symlink , dev - > symlink ) ;
2003-12-04 05:33:58 +03:00
dbg ( " found matching attribute '%s', '%s' becomes '%s' " ,
dev - > sysfs_file , class_dev - > name , udev - > name ) ;
2003-11-13 16:52:08 +03:00
return 0 ;
}
return - ENODEV ;
}
static int do_number ( struct sysfs_class_device * class_dev , struct udevice * udev , struct sysfs_device * sysfs_device )
{
struct config_device * dev ;
struct list_head * tmp ;
char path [ SYSFS_PATH_MAX ] ;
int found ;
char * temp = NULL ;
/* we have to have a sysfs device for NUMBER to work */
if ( ! sysfs_device )
return - ENODEV ;
list_for_each ( tmp , & config_device_list ) {
dev = list_entry ( tmp , struct config_device , node ) ;
if ( dev - > type ! = NUMBER )
continue ;
2003-12-03 05:38:30 +03:00
dbg ( " dev->bus='%s' sysfs_device->bus='%s' " , dev - > bus , sysfs_device - > bus ) ;
2003-11-27 04:45:05 +03:00
if ( strcasecmp ( dev - > bus , sysfs_device - > bus ) ! = 0 )
continue ;
2003-11-13 16:52:08 +03:00
found = 0 ;
2003-11-19 08:39:30 +03:00
strfieldcpy ( path , sysfs_device - > path ) ;
2003-11-13 16:52:08 +03:00
temp = strrchr ( path , ' / ' ) ;
2003-12-03 05:38:30 +03:00
dbg ( " search '%s' in '%s', path='%s' " , dev - > id , temp , path ) ;
2003-11-13 16:52:08 +03:00
if ( strstr ( temp , dev - > id ) ! = NULL ) {
found = 1 ;
} else {
* temp = 0x00 ;
temp = strrchr ( path , ' / ' ) ;
2003-12-03 05:38:30 +03:00
dbg ( " search '%s' in '%s', path='%s' " , dev - > id , temp , path ) ;
2003-11-13 16:52:08 +03:00
if ( strstr ( temp , dev - > id ) ! = NULL )
found = 1 ;
}
if ( ! found )
continue ;
2003-11-19 08:39:30 +03:00
strfieldcpy ( udev - > name , dev - > name ) ;
2003-12-07 20:12:07 +03:00
strfieldcpy ( udev - > symlink , dev - > symlink ) ;
2003-12-04 05:33:58 +03:00
dbg ( " found matching id '%s', '%s' becomes '%s' " ,
dev - > id , class_dev - > name , udev - > name ) ;
2003-11-13 16:52:08 +03:00
return 0 ;
}
return - ENODEV ;
}
2003-11-13 05:08:19 +03:00
static int do_topology ( struct sysfs_class_device * class_dev , struct udevice * udev , struct sysfs_device * sysfs_device )
{
struct config_device * dev ;
struct list_head * tmp ;
char path [ SYSFS_PATH_MAX ] ;
int found ;
char * temp = NULL ;
/* we have to have a sysfs device for TOPOLOGY to work */
if ( ! sysfs_device )
return - ENODEV ;
list_for_each ( tmp , & config_device_list ) {
dev = list_entry ( tmp , struct config_device , node ) ;
if ( dev - > type ! = TOPOLOGY )
continue ;
2003-12-03 05:38:30 +03:00
dbg ( " dev->bus='%s' sysfs_device->bus='%s' " , dev - > bus , sysfs_device - > bus ) ;
2003-11-27 04:45:05 +03:00
if ( strcasecmp ( dev - > bus , sysfs_device - > bus ) ! = 0 )
continue ;
2003-11-13 17:24:09 +03:00
found = 0 ;
2003-11-19 08:39:30 +03:00
strfieldcpy ( path , sysfs_device - > path ) ;
2003-11-13 05:08:19 +03:00
temp = strrchr ( path , ' / ' ) ;
2003-12-03 05:38:30 +03:00
dbg ( " search '%s' in '%s', path='%s' " , dev - > place , temp , path ) ;
2003-11-13 05:08:19 +03:00
if ( strstr ( temp , dev - > place ) ! = NULL ) {
found = 1 ;
} else {
* temp = 0x00 ;
temp = strrchr ( path , ' / ' ) ;
2003-12-03 05:38:30 +03:00
dbg ( " search '%s' in '%s', path='%s' " , dev - > place , temp , path ) ;
2003-11-13 05:08:19 +03:00
if ( strstr ( temp , dev - > place ) ! = NULL )
found = 1 ;
}
if ( ! found )
continue ;
2003-11-19 08:39:30 +03:00
strfieldcpy ( udev - > name , dev - > name ) ;
2003-12-07 20:12:07 +03:00
strfieldcpy ( udev - > symlink , dev - > symlink ) ;
2003-12-04 05:33:58 +03:00
dbg ( " found matching place '%s', '%s' becomes '%s' " ,
dev - > place , class_dev - > name , udev - > name ) ;
2003-11-13 05:08:19 +03:00
return 0 ;
}
return - ENODEV ;
}
2003-11-27 04:45:05 +03:00
static int do_replace ( struct sysfs_class_device * class_dev , struct udevice * udev , struct sysfs_device * sysfs_device )
2003-11-12 19:26:08 +03:00
{
struct config_device * dev ;
struct list_head * tmp ;
list_for_each ( tmp , & config_device_list ) {
dev = list_entry ( tmp , struct config_device , node ) ;
if ( dev - > type ! = REPLACE )
continue ;
2003-12-03 05:38:30 +03:00
dbg ( " compare name '%s' with '%s' " , dev - > kernel_name , class_dev - > name ) ;
2003-12-03 17:22:53 +03:00
if ( strcmp_pattern ( dev - > kernel_name , class_dev - > name ) ! = 0 )
2003-11-12 19:26:08 +03:00
continue ;
2003-11-19 08:39:30 +03:00
strfieldcpy ( udev - > name , dev - > name ) ;
2003-12-07 20:12:07 +03:00
strfieldcpy ( udev - > symlink , dev - > symlink ) ;
2003-12-04 05:33:58 +03:00
dbg ( " found name, '%s' becomes '%s' " , dev - > kernel_name , udev - > name ) ;
2003-11-12 19:26:08 +03:00
return 0 ;
}
return - ENODEV ;
}
2003-11-19 17:19:06 +03:00
static void do_kernelname ( struct sysfs_class_device * class_dev , struct udevice * udev )
{
2003-12-04 05:33:58 +03:00
/* heh, this is pretty simple... */
2003-11-19 17:19:06 +03:00
strfieldcpy ( udev - > name , class_dev - > name ) ;
}
2003-12-03 05:18:21 +03:00
int namedev_name_device ( struct sysfs_class_device * class_dev , struct udevice * udev )
2003-07-19 09:48:28 +04:00
{
2003-11-13 04:38:14 +03:00
struct sysfs_device * sysfs_device = NULL ;
struct sysfs_class_device * class_dev_parent = NULL ;
2003-07-19 09:48:28 +04:00
int retval = 0 ;
2003-11-13 04:38:14 +03:00
char * temp = NULL ;
2003-12-04 05:33:58 +03:00
struct perm_device * perm ;
2003-07-19 09:48:28 +04:00
2003-10-22 09:28:32 +04:00
udev - > mode = 0 ;
2003-11-13 04:38:14 +03:00
/* find the sysfs_device for this class device */
2003-11-13 04:56:26 +03:00
/* Wouldn't it really be nice if libsysfs could do this for us? */
2003-07-24 18:27:06 +04:00
if ( class_dev - > sysdevice ) {
2003-11-13 04:38:14 +03:00
sysfs_device = class_dev - > sysdevice ;
} else {
/* bah, let's go backwards up a level to see if the device is there,
* as block partitions don ' t point to the physical device . Need to fix that
* up in the kernel . . .
*/
if ( strstr ( class_dev - > path , " block " ) ) {
2003-12-03 05:38:30 +03:00
dbg ( " looking at block device " ) ;
2003-11-13 04:38:14 +03:00
if ( isdigit ( class_dev - > path [ strlen ( class_dev - > path ) - 1 ] ) ) {
char path [ SYSFS_PATH_MAX ] ;
2003-12-03 05:38:30 +03:00
dbg ( " really is a partition " ) ;
2003-11-19 08:39:30 +03:00
strfieldcpy ( path , class_dev - > path ) ;
2003-11-13 04:38:14 +03:00
temp = strrchr ( path , ' / ' ) ;
* temp = 0x00 ;
2003-12-03 05:38:30 +03:00
dbg ( " looking for a class device at '%s' " , path ) ;
2003-11-13 04:38:14 +03:00
class_dev_parent = sysfs_open_class_device ( path ) ;
if ( class_dev_parent = = NULL ) {
dbg ( " sysfs_open_class_device at '%s' failed " , path ) ;
} else {
2003-12-03 05:38:30 +03:00
dbg ( " class_dev_parent->name='%s' " , class_dev_parent - > name ) ;
2003-11-13 04:38:14 +03:00
if ( class_dev_parent - > sysdevice )
sysfs_device = class_dev_parent - > sysdevice ;
}
}
}
}
2003-12-05 06:21:27 +03:00
2003-11-13 04:38:14 +03:00
if ( sysfs_device ) {
2003-12-03 05:38:30 +03:00
dbg ( " sysfs_device->path='%s' " , sysfs_device - > path ) ;
dbg ( " sysfs_device->bus_id='%s' " , sysfs_device - > bus_id ) ;
dbg ( " sysfs_device->bus='%s' " , sysfs_device - > bus ) ;
2003-11-24 09:25:13 +03:00
strfieldcpy ( udev - > bus_id , sysfs_device - > bus_id ) ;
2003-07-24 18:27:06 +04:00
} else {
2003-12-03 05:38:30 +03:00
dbg ( " class_dev->name = '%s' " , class_dev - > name ) ;
2003-07-24 18:27:06 +04:00
}
2003-11-12 19:26:08 +03:00
2003-11-24 09:25:13 +03:00
build_kernel_number ( class_dev , udev ) ;
2003-11-12 19:26:08 +03:00
/* rules are looked at in priority order */
2003-11-27 04:45:05 +03:00
retval = do_callout ( class_dev , udev , sysfs_device ) ;
2003-11-12 19:26:08 +03:00
if ( retval = = 0 )
2003-11-19 17:19:06 +03:00
goto found ;
2003-11-12 19:26:08 +03:00
2003-11-13 16:52:08 +03:00
retval = do_label ( class_dev , udev , sysfs_device ) ;
if ( retval = = 0 )
2003-11-19 17:19:06 +03:00
goto found ;
2003-11-13 16:52:08 +03:00
retval = do_number ( class_dev , udev , sysfs_device ) ;
if ( retval = = 0 )
2003-11-19 17:19:06 +03:00
goto found ;
2003-11-13 16:52:08 +03:00
2003-11-13 05:08:19 +03:00
retval = do_topology ( class_dev , udev , sysfs_device ) ;
if ( retval = = 0 )
2003-11-19 17:19:06 +03:00
goto found ;
2003-11-13 05:08:19 +03:00
2003-11-27 04:45:05 +03:00
retval = do_replace ( class_dev , udev , sysfs_device ) ;
2003-11-12 19:26:08 +03:00
if ( retval = = 0 )
2003-11-19 17:19:06 +03:00
goto found ;
2003-11-12 19:26:08 +03:00
2003-11-19 17:19:06 +03:00
do_kernelname ( class_dev , udev ) ;
goto done ;
2003-10-20 08:56:21 +04:00
2003-11-19 17:19:06 +03:00
found :
2003-12-07 20:12:07 +03:00
/* substitute placeholder */
2003-11-24 09:25:13 +03:00
apply_format ( udev , udev - > name ) ;
2003-12-07 20:12:07 +03:00
apply_format ( udev , udev - > symlink ) ;
[PATCH] implement printf-like placeholder support for NAME
> Problem is, if you use the LABEL rule to match a device, like a SCSI
> vendor, then all of the partitions, as well as the main block device,
> will end up with the same name. That's why I added the "add the number"
> hack to the LABEL rule.
>
> So yes, your patch is correct in that we shouldn't always be adding the
> number to any match for LABEL (like for char devices), but if we do
> that, then we break partitions. Your '%' patch fixes this, but I'd just
> like to extend it a bit. Let me see what I can come up with...
Oh, I see. Do you mean something like this:
LABEL, BUS="usb", model="Creative Labs WebCam 3", NAME="webcam%n-%M:%m-test"
results in: "webcam0-81:0-test"
Nov 15 16:51:53 pim udev[16193]: get_class_dev: looking at /sys/class/video4linux/video0
Nov 15 16:51:53 pim udev[16193]: get_class_dev: class_dev->name = video0
Nov 15 16:51:53 pim udev[16193]: get_major_minor: dev = 81:0
Nov 15 16:51:53 pim udev[16193]: get_major_minor: found major = 81, minor = 0
Nov 15 16:51:53 pim udev[16193]: udev_add_device: name = webcam0-81:0-test
Nov 15 16:51:53 pim udev[16193]: create_node: mknod(/udev/webcam0-81:0-test, 020666, 81, 0)
implement printf-like placeholder support for NAME
%n-kernel number, %M-major number, %m-minor number
2003-11-18 11:59:27 +03:00
2003-11-19 17:19:06 +03:00
done :
2003-12-04 05:33:58 +03:00
perm = find_perm ( udev - > name ) ;
if ( perm ) {
udev - > mode = perm - > mode ;
strfieldcpy ( udev - > owner , perm - > owner ) ;
strfieldcpy ( udev - > group , perm - > group ) ;
} else {
/* no matching perms found :( */
2003-10-22 09:28:32 +04:00
udev - > mode = get_default_mode ( class_dev ) ;
udev - > owner [ 0 ] = 0x00 ;
udev - > group [ 0 ] = 0x00 ;
2003-07-25 15:01:48 +04:00
}
2003-12-04 05:33:58 +03:00
dbg ( " name, '%s' is going to have owner='%s', group='%s', mode = %#o " ,
udev - > name , udev - > owner , udev - > group , udev - > mode ) ;
2003-11-13 04:38:14 +03:00
if ( class_dev_parent )
sysfs_close_class_device ( class_dev_parent ) ;
2003-11-12 19:26:08 +03:00
return 0 ;
2003-07-19 09:48:28 +04:00
}
2003-07-17 12:24:51 +04:00
int namedev_init ( void )
{
int retval ;
2003-12-05 06:21:27 +03:00
2003-12-03 12:08:46 +03:00
retval = namedev_init_rules ( ) ;
2003-07-17 12:24:51 +04:00
if ( retval )
return retval ;
retval = namedev_init_permissions ( ) ;
if ( retval )
return retval ;
2003-12-03 05:38:30 +03:00
dump_config_dev_list ( ) ;
2003-12-04 05:33:58 +03:00
dump_perm_dev_list ( ) ;
2003-07-17 12:24:51 +04:00
return retval ;
}