2004-03-02 12:30:38 +03:00
/*
* udevstart . c
*
* Copyright ( C ) 2004 Greg Kroah - Hartman < greg @ kroah . com >
*
* Quick and dirty way to populate a / dev with udev if your system
* does not have access to a shell . Based originally on a patch to udev
* from Harald Hoyer < harald @ redhat . 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 <stdlib.h>
# include <string.h>
# include <stdio.h>
# include <errno.h>
# include <ctype.h>
# include <dirent.h>
# include <sys/wait.h>
2004-04-01 11:03:07 +04:00
# include <sys/types.h>
# include <unistd.h>
2004-03-02 12:30:38 +03:00
# include "logging.h"
2004-04-01 12:59:58 +04:00
# include "udev_lib.h"
2004-03-02 12:30:38 +03:00
# ifdef LOG
2004-03-04 11:57:29 +03:00
unsigned char logname [ LOGNAME_SIZE ] ;
2004-03-02 12:30:38 +03:00
void log_message ( int level , const char * format , . . . )
{
va_list args ;
va_start ( args , format ) ;
vsyslog ( level , format , args ) ;
va_end ( args ) ;
}
# endif
2004-03-03 09:15:20 +03:00
# define MAX_PATHLEN 1024
# define SYSBLOCK " / sys / block"
# define SYSCLASS " / sys / class"
# define UDEV_BIN " / sbin / udev"
2004-03-02 12:30:38 +03:00
2004-03-03 09:15:20 +03:00
static void udev_exec ( const char * path , const char * subsystem )
2004-03-02 12:30:38 +03:00
{
pid_t pid ;
2004-03-03 09:15:20 +03:00
char action [ ] = " ACTION=add " ;
char devpath [ MAX_PATHLEN ] ;
char nosleep [ ] = " UDEV_NO_SLEEP=1 " ;
char * env [ ] = { action , devpath , nosleep , NULL } ;
2004-04-03 04:58:57 +04:00
strcpy ( devpath , " DEVPATH= " ) ;
strfieldcat ( devpath , path ) ;
2004-03-03 09:15:20 +03:00
2004-03-02 12:30:38 +03:00
pid = fork ( ) ;
2004-03-03 09:15:20 +03:00
switch ( pid ) {
2004-03-02 12:30:38 +03:00
case 0 :
/* child */
2004-03-03 09:15:20 +03:00
execle ( UDEV_BIN , " udev " , subsystem , NULL , env ) ;
dbg ( " exec of child failed " ) ;
2004-03-02 12:30:38 +03:00
exit ( 1 ) ;
2004-03-03 09:15:20 +03:00
break ;
2004-03-02 12:30:38 +03:00
case - 1 :
2004-03-03 09:15:20 +03:00
dbg ( " fork of child failed " ) ;
break ;
2004-03-02 12:30:38 +03:00
default :
2004-03-03 09:15:20 +03:00
wait ( NULL ) ;
2004-03-02 12:30:38 +03:00
}
}
2004-03-05 06:10:02 +03:00
static void udev_scan ( void )
2004-03-02 12:30:38 +03:00
{
2004-03-03 09:15:20 +03:00
char * devpath ;
DIR * dir ;
struct dirent * dent ;
2004-03-02 12:30:38 +03:00
2004-06-26 12:08:47 +04:00
/*
* We want to scan the class tree first as lvm and dm needs to be able
* to have access to the char control device when probing the block
* devices .
*/
devpath = " class " ;
dir = opendir ( SYSCLASS ) ;
2004-03-03 09:15:20 +03:00
if ( dir ! = NULL ) {
for ( dent = readdir ( dir ) ; dent ! = NULL ; dent = readdir ( dir ) ) {
char dirname [ MAX_PATHLEN ] ;
DIR * dir2 ;
struct dirent * dent2 ;
if ( ( strcmp ( dent - > d_name , " . " ) = = 0 ) | |
( strcmp ( dent - > d_name , " .. " ) = = 0 ) )
2004-03-02 12:30:38 +03:00
continue ;
2004-06-26 12:08:47 +04:00
snprintf ( dirname , MAX_PATHLEN , " %s/%s " , SYSCLASS , dent - > d_name ) ;
dirname [ MAX_PATHLEN ] = ' \0 ' ;
2004-03-02 12:30:38 +03:00
dir2 = opendir ( dirname ) ;
2004-03-03 09:15:20 +03:00
if ( dir2 ! = NULL ) {
for ( dent2 = readdir ( dir2 ) ; dent2 ! = NULL ; dent2 = readdir ( dir2 ) ) {
2004-06-26 12:08:47 +04:00
char dirname2 [ MAX_PATHLEN - 1 ] ;
2004-03-03 09:15:20 +03:00
DIR * dir3 ;
struct dirent * dent3 ;
2004-03-02 12:30:38 +03:00
if ( ( strcmp ( dent2 - > d_name , " . " ) = = 0 ) | |
( strcmp ( dent2 - > d_name , " .. " ) = = 0 ) )
continue ;
snprintf ( dirname2 , MAX_PATHLEN , " %s/%s " , dirname , dent2 - > d_name ) ;
2004-03-03 09:15:20 +03:00
dirname2 [ MAX_PATHLEN - 1 ] = ' \0 ' ;
2004-03-02 12:30:38 +03:00
dir3 = opendir ( dirname2 ) ;
2004-03-03 09:15:20 +03:00
if ( dir3 ! = NULL ) {
for ( dent3 = readdir ( dir3 ) ; dent3 ! = NULL ; dent3 = readdir ( dir3 ) ) {
2004-03-02 12:30:38 +03:00
char filename [ MAX_PATHLEN ] ;
if ( strcmp ( dent3 - > d_name , " dev " ) = = 0 ) {
2004-06-26 12:08:47 +04:00
snprintf ( filename , MAX_PATHLEN , " /class/%s/%s " ,
2004-03-03 09:15:20 +03:00
dent - > d_name , dent2 - > d_name ) ;
filename [ MAX_PATHLEN - 1 ] = ' \0 ' ;
2004-06-26 12:08:47 +04:00
udev_exec ( filename , dent - > d_name ) ;
2004-03-02 12:30:38 +03:00
}
}
2004-04-24 08:55:57 +04:00
closedir ( dir3 ) ;
2004-03-02 12:30:38 +03:00
}
}
2004-04-24 08:55:57 +04:00
closedir ( dir2 ) ;
2004-03-02 12:30:38 +03:00
}
}
2004-04-24 08:55:57 +04:00
closedir ( dir ) ;
2004-03-02 12:30:38 +03:00
}
2004-06-26 12:08:47 +04:00
devpath = " block " ;
dir = opendir ( SYSBLOCK ) ;
2004-03-03 09:15:20 +03:00
if ( dir ! = NULL ) {
for ( dent = readdir ( dir ) ; dent ! = NULL ; dent = readdir ( dir ) ) {
char dirname [ MAX_PATHLEN ] ;
DIR * dir2 ;
struct dirent * dent2 ;
if ( ( strcmp ( dent - > d_name , " . " ) = = 0 ) | |
( strcmp ( dent - > d_name , " .. " ) = = 0 ) )
2004-03-02 12:30:38 +03:00
continue ;
2004-06-26 12:08:47 +04:00
snprintf ( dirname , MAX_PATHLEN , " /block/%s " , dent - > d_name ) ;
dirname [ MAX_PATHLEN - 1 ] = ' \0 ' ;
udev_exec ( dirname , " block " ) ;
snprintf ( dirname , MAX_PATHLEN , " %s/%s " , SYSBLOCK , dent - > d_name ) ;
2004-03-02 12:30:38 +03:00
dir2 = opendir ( dirname ) ;
2004-03-03 09:15:20 +03:00
if ( dir2 ! = NULL ) {
for ( dent2 = readdir ( dir2 ) ; dent2 ! = NULL ; dent2 = readdir ( dir2 ) ) {
2004-06-26 12:08:47 +04:00
char dirname2 [ MAX_PATHLEN ] ;
2004-03-03 09:15:20 +03:00
DIR * dir3 ;
struct dirent * dent3 ;
2004-03-02 12:30:38 +03:00
2004-03-03 09:15:20 +03:00
if ( ( strcmp ( dent2 - > d_name , " . " ) = = 0 ) | |
( strcmp ( dent2 - > d_name , " .. " ) = = 0 ) )
2004-03-02 12:30:38 +03:00
continue ;
snprintf ( dirname2 , MAX_PATHLEN , " %s/%s " , dirname , dent2 - > d_name ) ;
2004-03-03 09:15:20 +03:00
dirname2 [ MAX_PATHLEN - 1 ] = ' \0 ' ;
2004-03-02 12:30:38 +03:00
dir3 = opendir ( dirname2 ) ;
2004-03-03 09:15:20 +03:00
if ( dir3 ! = NULL ) {
for ( dent3 = readdir ( dir3 ) ; dent3 ! = NULL ; dent3 = readdir ( dir3 ) ) {
char filename [ MAX_PATHLEN ] ;
2004-03-02 12:30:38 +03:00
if ( strcmp ( dent3 - > d_name , " dev " ) = = 0 ) {
2004-06-26 12:08:47 +04:00
snprintf ( filename , MAX_PATHLEN , " /block/%s/%s " ,
2004-03-03 09:15:20 +03:00
dent - > d_name , dent2 - > d_name ) ;
filename [ MAX_PATHLEN - 1 ] = ' \0 ' ;
2004-06-26 12:08:47 +04:00
udev_exec ( filename , " block " ) ;
2004-03-02 12:30:38 +03:00
}
}
2004-04-24 08:55:57 +04:00
closedir ( dir3 ) ;
2004-03-02 12:30:38 +03:00
}
}
2004-04-24 08:55:57 +04:00
closedir ( dir2 ) ;
2004-03-02 12:30:38 +03:00
}
}
2004-04-24 08:55:57 +04:00
closedir ( dir ) ;
2004-03-02 12:30:38 +03:00
}
}
2004-03-04 11:57:29 +03:00
int main ( int argc , char * argv [ ] , char * envp [ ] )
2004-03-02 12:30:38 +03:00
{
init_logging ( " udevstart " ) ;
2004-03-05 06:10:02 +03:00
udev_scan ( ) ;
return 0 ;
2004-03-02 12:30:38 +03:00
}