2003-10-17 12:40:02 +04:00
/*
2004-11-12 08:32:19 +03:00
* udev_db . c
2003-10-17 12:40:02 +04:00
*
* Userspace devfs
*
* Copyright ( C ) 2003 Greg Kroah - Hartman < greg @ kroah . com >
2005-02-21 15:48:10 +03:00
* Copyright ( C ) 2004 - 2005 Kay Sievers < kay . sievers @ vrfy . org >
2003-10-17 12:40:02 +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 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 .
*
*/
2004-11-06 16:28:01 +03:00
2003-08-06 10:57:23 +04:00
# include <stdlib.h>
# include <stdio.h>
2004-03-02 10:47:59 +03:00
# include <string.h>
2004-03-23 09:22:20 +03:00
# include <stddef.h>
2005-03-06 14:16:32 +03:00
# include <unistd.h>
2003-08-06 10:57:23 +04:00
# include <fcntl.h>
# include <string.h>
# include <errno.h>
2004-11-06 16:28:01 +03:00
# include <dirent.h>
2003-08-06 10:57:23 +04:00
2004-02-24 06:07:25 +03:00
# include "libsysfs/sysfs/libsysfs.h"
2005-03-07 06:29:43 +03:00
# include "udev_libc_wrapper.h"
2003-10-16 10:50:13 +04:00
# include "udev.h"
2004-11-25 04:44:38 +03:00
# include "udev_utils.h"
[PATCH] add udev logging to info log
On Thu, Jan 15, 2004 at 05:14:16AM +0100, Kay Sievers wrote:
> On Wed, Jan 14, 2004 at 01:10:43PM -0800, Greg KH wrote:
> > On Wed, Jan 14, 2004 at 02:34:26PM -0600, Clay Haapala wrote:
> > > On Wed, 14 Jan 2004, Chris Friesen spake thusly:
> > > >
> > > > Maybe for ones with a matching rule, you could print something like:
> > > >
> > > >
> > > Is the act of printing/syslogging a rule in an of itself?
> >
> > No, as currently the only way stuff ends up in the syslog is if
> > DEBUG=true is used on the build line.
> >
> > But it's sounding like we might want to change that... :)
>
> How about this in the syslog after connect/disconnect?
>
> Jan 15 05:07:45 pim udev[28007]: configured rule in '/etc/udev/udev.rules' at line 17 applied, 'video*' becomes 'video/webcam%n'
> Jan 15 05:07:45 pim udev[28007]: creating device node '/udev/video/webcam0'
> Jan 15 05:07:47 pim udev[28015]: removing device node '/udev/video/webcam0'
Here is a slightly better version. I've created a logging.h file and
moved the debug macros from udev.h in there.
If you type:
'make' - you will get a binary that prints one or two lines to syslog
if a device node is created or deleted
'make LOG=false' - you get a binary that prints asolutely nothing
'make DEBUG=true' - the same as today, it will print all debug lines
2004-01-16 08:53:20 +03:00
# include "logging.h"
2004-11-12 08:32:19 +03:00
# include "udev_db.h"
2003-08-06 10:57:23 +04:00
2004-11-06 16:28:01 +03:00
# define PATH_TO_NAME_CHAR '@'
2005-02-21 15:48:10 +03:00
static int get_db_filename ( const char * devpath , char * filename , int len )
2004-11-06 16:28:01 +03:00
{
2005-03-07 06:29:43 +03:00
char temp [ PATH_SIZE ] ;
2004-11-06 16:28:01 +03:00
char * pos ;
/* replace '/' to transform path into a filename */
2005-03-07 06:29:43 +03:00
strlcpy ( temp , devpath , sizeof ( temp ) ) ;
2005-02-21 15:48:10 +03:00
pos = strchr ( & temp [ 1 ] , ' / ' ) ;
2004-11-06 16:28:01 +03:00
while ( pos ) {
pos [ 0 ] = PATH_TO_NAME_CHAR ;
pos = strchr ( & pos [ 1 ] , ' / ' ) ;
}
2005-02-21 15:48:10 +03:00
snprintf ( filename , len , " %s%s " , udev_db_path , temp ) ;
2004-11-06 16:28:01 +03:00
filename [ len - 1 ] = ' \0 ' ;
return 0 ;
}
2003-10-18 10:32:17 +04:00
2004-11-12 08:32:19 +03:00
int udev_db_add_device ( struct udevice * udev )
2003-10-18 10:32:17 +04:00
{
2005-03-07 06:29:43 +03:00
char filename [ PATH_SIZE ] ;
2005-03-05 07:35:31 +03:00
struct name_entry * name_loop ;
2004-11-06 16:28:01 +03:00
FILE * f ;
2003-10-18 10:32:17 +04:00
2004-10-19 06:28:39 +04:00
if ( udev - > test_run )
return 0 ;
2005-03-07 06:29:43 +03:00
get_db_filename ( udev - > devpath , filename , sizeof ( filename ) ) ;
2004-11-06 16:28:01 +03:00
create_path ( filename ) ;
f = fopen ( filename , " w " ) ;
if ( f = = NULL ) {
dbg ( " unable to create db file '%s' " , filename ) ;
2004-10-14 10:13:26 +04:00
return - 1 ;
2004-11-06 16:28:01 +03:00
}
dbg ( " storing data for device '%s' in '%s' " , udev - > devpath , filename ) ;
2004-10-14 10:13:26 +04:00
2004-11-06 16:28:01 +03:00
fprintf ( f , " P:%s \n " , udev - > devpath ) ;
fprintf ( f , " N:%s \n " , udev - > name ) ;
2005-03-05 07:35:31 +03:00
list_for_each_entry ( name_loop , & udev - > symlink_list , node )
fprintf ( f , " S:%s \n " , name_loop - > name ) ;
2005-02-21 15:44:39 +03:00
fprintf ( f , " M:%u:%u \n " , major ( udev - > devt ) , minor ( udev - > devt ) ) ;
2004-11-13 16:43:24 +03:00
fprintf ( f , " A:%u \n " , udev - > partitions ) ;
fprintf ( f , " R:%u \n " , udev - > ignore_remove ) ;
2003-11-25 09:27:17 +03:00
2004-11-06 16:28:01 +03:00
fclose ( f ) ;
2004-02-13 09:51:44 +03:00
2004-11-06 16:28:01 +03:00
return 0 ;
2003-10-18 10:32:17 +04:00
}
2004-11-06 16:28:01 +03:00
static int parse_db_file ( struct udevice * udev , const char * filename )
2003-08-06 10:57:23 +04:00
{
2005-03-07 06:29:43 +03:00
char line [ PATH_SIZE ] ;
2005-02-21 15:44:39 +03:00
unsigned int major , minor ;
2004-11-06 16:28:01 +03:00
char * bufline ;
char * buf ;
size_t bufsize ;
size_t cur ;
size_t count ;
if ( file_map ( filename , & buf , & bufsize ) ! = 0 ) {
dbg ( " unable to read db file '%s' " , filename ) ;
2004-10-14 10:13:26 +04:00
return - 1 ;
2004-11-06 16:28:01 +03:00
}
2004-10-14 10:13:26 +04:00
2004-11-06 16:28:01 +03:00
cur = 0 ;
while ( cur < bufsize ) {
count = buf_get_line ( buf , bufsize , cur ) ;
bufline = & buf [ cur ] ;
cur + = count + 1 ;
switch ( bufline [ 0 ] ) {
case ' P ' :
2005-03-07 06:29:43 +03:00
if ( count > sizeof ( udev - > devpath ) )
count = sizeof ( udev - > devpath ) - 1 ;
strlcpy ( udev - > devpath , & bufline [ 2 ] , count - 2 ) ;
2004-11-06 16:28:01 +03:00
break ;
case ' N ' :
2005-03-07 06:29:43 +03:00
if ( count > sizeof ( udev - > name ) )
count = sizeof ( udev - > name ) - 1 ;
strlcpy ( udev - > name , & bufline [ 2 ] , count - 2 ) ;
2004-11-06 16:28:01 +03:00
break ;
2005-02-18 05:30:03 +03:00
case ' M ' :
2005-03-07 06:29:43 +03:00
if ( count > sizeof ( line ) )
count = sizeof ( line ) - 1 ;
strlcpy ( line , & bufline [ 2 ] , count - 2 ) ;
sscanf ( line , " %u:%u " , & major , & minor ) ;
2005-02-21 15:44:39 +03:00
udev - > devt = makedev ( major , minor ) ;
2005-02-18 05:30:03 +03:00
break ;
2004-11-06 16:28:01 +03:00
case ' S ' :
2005-03-07 06:29:43 +03:00
if ( count > sizeof ( line ) )
count = sizeof ( line ) - 1 ;
strlcpy ( line , & bufline [ 2 ] , count - 2 ) ;
name_list_add ( & udev - > symlink_list , line , 0 ) ;
2004-11-06 16:28:01 +03:00
break ;
case ' A ' :
2005-03-07 06:29:43 +03:00
if ( count > sizeof ( line ) )
count = sizeof ( line ) - 1 ;
strlcpy ( line , & bufline [ 2 ] , count - 2 ) ;
2004-11-06 16:28:01 +03:00
udev - > partitions = atoi ( line ) ;
break ;
2004-11-13 16:43:24 +03:00
case ' R ' :
2005-03-07 06:29:43 +03:00
if ( count > sizeof ( line ) )
count = sizeof ( line ) - 1 ;
strlcpy ( line , & bufline [ 2 ] , count - 2 ) ;
2004-11-13 16:43:24 +03:00
udev - > ignore_remove = atoi ( line ) ;
break ;
2004-11-06 16:28:01 +03:00
}
}
2005-03-05 04:33:31 +03:00
file_unmap ( buf , bufsize ) ;
2003-11-25 09:27:17 +03:00
2004-11-06 16:28:01 +03:00
if ( udev - > name [ 0 ] = = ' \0 ' )
return - 1 ;
2004-10-19 06:11:51 +04:00
2003-12-20 05:29:01 +03:00
return 0 ;
2003-08-06 10:57:23 +04:00
}
2005-02-21 15:48:10 +03:00
int udev_db_delete_device ( struct udevice * udev )
2003-08-06 10:57:23 +04:00
{
2005-03-07 06:29:43 +03:00
char filename [ PATH_SIZE ] ;
2003-10-21 07:28:42 +04:00
2005-03-07 06:29:43 +03:00
get_db_filename ( udev - > devpath , filename , sizeof ( filename ) ) ;
2005-02-21 15:48:10 +03:00
unlink ( filename ) ;
2003-10-21 07:28:42 +04:00
2005-02-21 15:48:10 +03:00
return 0 ;
2003-10-21 07:28:42 +04:00
}
2005-03-05 07:35:31 +03:00
int udev_db_get_device ( struct udevice * udev , const char * devpath )
2003-10-15 10:20:53 +04:00
{
2005-03-07 06:29:43 +03:00
char filename [ PATH_SIZE ] ;
2004-11-06 16:28:01 +03:00
2005-03-07 06:29:43 +03:00
get_db_filename ( devpath , filename , sizeof ( filename ) ) ;
2003-10-15 10:20:53 +04:00
2005-03-05 07:35:31 +03:00
if ( parse_db_file ( udev , filename ) ! = 0 )
return - 1 ;
return 0 ;
2003-10-15 10:20:53 +04:00
}
2003-12-31 09:31:37 +03:00
2005-03-05 07:35:31 +03:00
int udev_db_search_name ( char * devpath , size_t len , const char * name )
2003-12-31 09:31:37 +03:00
{
2004-11-06 16:28:01 +03:00
DIR * dir ;
dir = opendir ( udev_db_path ) ;
if ( dir = = NULL ) {
dbg ( " unable to udev db '%s' " , udev_db_path ) ;
return - 1 ;
2004-01-13 12:01:19 +03:00
}
2004-11-06 16:28:01 +03:00
while ( 1 ) {
2005-03-05 13:55:59 +03:00
struct dirent * ent ;
2005-03-07 06:29:43 +03:00
char filename [ PATH_SIZE ] ;
char path [ PATH_SIZE ] ;
char nodename [ PATH_SIZE ] ;
2005-03-05 07:35:31 +03:00
char * bufline ;
char * buf ;
size_t bufsize ;
size_t cur ;
size_t count ;
2004-11-06 16:28:01 +03:00
ent = readdir ( dir ) ;
if ( ent = = NULL | | ent - > d_name [ 0 ] = = ' \0 ' )
break ;
2004-01-13 12:01:19 +03:00
2004-11-06 16:28:01 +03:00
if ( ent - > d_name [ 0 ] = = ' . ' )
continue ;
2004-01-13 12:01:19 +03:00
2005-03-07 06:29:43 +03:00
snprintf ( filename , sizeof ( filename ) , " %s/%s " , udev_db_path , ent - > d_name ) ;
filename [ sizeof ( filename ) - 1 ] = ' \0 ' ;
2005-03-05 07:35:31 +03:00
dbg ( " looking at '%s' " , filename ) ;
2004-01-20 06:40:32 +03:00
2005-03-05 07:35:31 +03:00
if ( file_map ( filename , & buf , & bufsize ) ! = 0 ) {
dbg ( " unable to read db file '%s' " , filename ) ;
continue ;
}
2004-01-20 06:40:32 +03:00
2005-03-05 07:35:31 +03:00
cur = 0 ;
while ( cur < bufsize ) {
count = buf_get_line ( buf , bufsize , cur ) ;
bufline = & buf [ cur ] ;
cur + = count + 1 ;
switch ( bufline [ 0 ] ) {
case ' P ' :
2005-03-07 06:29:43 +03:00
if ( count > sizeof ( path ) )
count = sizeof ( path ) - 1 ;
strlcpy ( path , & bufline [ 2 ] , count - 2 ) ;
2005-03-05 07:35:31 +03:00
break ;
case ' N ' :
case ' S ' :
2005-03-07 06:29:43 +03:00
if ( count > sizeof ( nodename ) )
count = sizeof ( nodename ) - 1 ;
strlcpy ( nodename , & bufline [ 2 ] , count - 2 ) ;
2005-03-05 07:35:31 +03:00
dbg ( " compare '%s' '%s' " , nodename , name ) ;
if ( strcmp ( nodename , name ) = = 0 ) {
2005-03-07 06:29:43 +03:00
strlcpy ( devpath , path , len ) ;
2005-03-05 07:35:31 +03:00
file_unmap ( buf , bufsize ) ;
closedir ( dir ) ;
return 0 ;
}
break ;
default :
continue ;
2004-11-06 16:28:01 +03:00
}
}
2005-03-05 07:35:31 +03:00
file_unmap ( buf , bufsize ) ;
2004-01-20 06:40:32 +03:00
}
2004-03-04 05:16:35 +03:00
2004-11-06 16:28:01 +03:00
closedir ( dir ) ;
return - 1 ;
2004-01-20 06:40:32 +03:00
}
2005-02-25 09:40:14 +03:00
2005-03-05 13:55:59 +03:00
int udev_db_dump_names ( int ( * handler_function ) ( const char * path , const char * name ) )
2005-02-25 09:40:14 +03:00
{
DIR * dir ;
dir = opendir ( udev_db_path ) ;
if ( dir = = NULL ) {
dbg ( " unable to udev db '%s' " , udev_db_path ) ;
return - 1 ;
}
while ( 1 ) {
2005-03-05 13:55:59 +03:00
struct dirent * ent ;
2005-03-07 06:29:43 +03:00
char filename [ PATH_SIZE ] ;
char path [ PATH_SIZE ] ;
char nodename [ PATH_SIZE ] ;
2005-03-05 13:55:59 +03:00
char * bufline ;
char * buf ;
size_t bufsize ;
size_t cur ;
size_t count ;
2005-02-25 09:40:14 +03:00
ent = readdir ( dir ) ;
if ( ent = = NULL | | ent - > d_name [ 0 ] = = ' \0 ' )
break ;
if ( ent - > d_name [ 0 ] = = ' . ' )
continue ;
2005-03-07 06:29:43 +03:00
snprintf ( filename , sizeof ( filename ) , " %s/%s " , udev_db_path , ent - > d_name ) ;
filename [ sizeof ( filename ) - 1 ] = ' \0 ' ;
2005-03-05 13:55:59 +03:00
dbg ( " looking at '%s' " , filename ) ;
if ( file_map ( filename , & buf , & bufsize ) ! = 0 ) {
dbg ( " unable to read db file '%s' " , filename ) ;
continue ;
}
2005-02-25 09:40:14 +03:00
2005-03-05 13:55:59 +03:00
path [ 0 ] = ' \0 ' ;
nodename [ 0 ] = ' \0 ' ;
cur = 0 ;
while ( cur < bufsize ) {
count = buf_get_line ( buf , bufsize , cur ) ;
bufline = & buf [ cur ] ;
cur + = count + 1 ;
2005-03-05 07:35:31 +03:00
2005-03-05 13:55:59 +03:00
switch ( bufline [ 0 ] ) {
case ' P ' :
2005-03-07 06:29:43 +03:00
if ( count > sizeof ( path ) )
count = sizeof ( path ) - 1 ;
strlcpy ( path , & bufline [ 2 ] , count - 2 ) ;
2005-02-25 09:40:14 +03:00
break ;
2005-03-05 13:55:59 +03:00
case ' N ' :
2005-03-07 06:29:43 +03:00
if ( count > sizeof ( nodename ) )
count = sizeof ( nodename ) - 1 ;
strlcpy ( nodename , & bufline [ 2 ] , count - 2 ) ;
2005-03-05 13:55:59 +03:00
break ;
default :
continue ;
}
2005-02-25 09:40:14 +03:00
}
2005-03-05 13:55:59 +03:00
file_unmap ( buf , bufsize ) ;
if ( path [ 0 ] = = ' \0 ' | | nodename [ 0 ] = = ' \0 ' )
continue ;
if ( handler_function ( path , nodename ) ! = 0 )
break ;
2005-02-25 09:40:14 +03:00
}
closedir ( dir ) ;
return 0 ;
}