2004-01-20 21:32:43 +03:00
/*
* Guillaume Cottenceau ( gc @ mandrakesoft . com )
*
* Copyright 2000 MandrakeSoft
*
* This software may be freely redistributed under the terms of the GNU
* public license .
*
* 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 .
*
*/
/*
* Portions from Erik Troan ( ewt @ redhat . com )
*
* Copyright 1996 Red Hat Software
*
*/
/*
* This contains stuff related to probing :
* ( 1 ) any ( actually only SCSI , NET , CPQ , USB Controllers ) devices ( autoprobe for PCI and USB )
* ( 2 ) IDE media
* ( 3 ) SCSI media
* ( 4 ) ETH devices
*/
# include <stdlib.h>
# include <unistd.h>
# include <stdio.h>
# include <string.h>
# include <sys/types.h>
# include <sys/stat.h>
2008-03-15 23:59:16 +03:00
# include <sys/socket.h>
2004-01-20 21:32:43 +03:00
# include <fcntl.h>
# include <net/if.h>
# include <sys/ioctl.h>
# include <sys/mount.h>
2007-02-27 16:11:49 +03:00
# include <dirent.h>
2004-01-20 21:32:43 +03:00
# include "stage1.h"
# include "log.h"
# include "frontend.h"
# include "modules.h"
# include "probing.h"
struct media_info {
char * name ;
char * model ;
enum media_type type ;
} ;
# ifndef DISABLE_NETWORK
struct net_description_elem
{
char * intf_name ;
char * intf_description ;
} ;
static struct net_description_elem net_descriptions [ 50 ] ;
static int net_descr_number = 0 ;
static char * intf_descr_for_discover = NULL ;
static char * net_intf_too_early_name [ 50 ] ; /* for modules providing more than one net intf */
static int net_intf_too_early_number = 0 ;
static int net_intf_too_early_ptr = 0 ;
void net_discovered_interface ( char * intf_name )
{
if ( ! intf_descr_for_discover ) {
net_intf_too_early_name [ net_intf_too_early_number + + ] = strdup ( intf_name ) ;
return ;
}
if ( ! intf_name ) {
if ( net_intf_too_early_ptr > = net_intf_too_early_number ) {
log_message ( " NET: was expecting another network interface (broken net module?) " ) ;
return ;
}
net_descriptions [ net_descr_number ] . intf_name = net_intf_too_early_name [ net_intf_too_early_ptr + + ] ;
}
else
net_descriptions [ net_descr_number ] . intf_name = strdup ( intf_name ) ;
net_descriptions [ net_descr_number ] . intf_description = strdup ( intf_descr_for_discover ) ;
intf_descr_for_discover = NULL ;
net_descr_number + + ;
}
char * get_net_intf_description ( char * intf_name )
{
2008-02-29 20:09:32 +03:00
char dev [ SYSFS_PATH_MAX ] ;
char drv [ SYSFS_PATH_MAX ] ;
ssize_t i ;
snprintf ( dev , SYSFS_PATH_MAX , " /sys/class/net/%s/device/driver " , intf_name ) ;
if ( ( i = readlink ( dev , drv , SYSFS_PATH_MAX ) ) > 0 ) {
drv [ i ] = ' \0 ' ;
2008-03-01 19:16:25 +03:00
return strdup ( strrchr ( drv , ' / ' ) + 1 ) ;
2008-02-29 20:09:32 +03:00
} else {
return strdup ( " unknown " ) ;
}
2004-01-20 21:32:43 +03:00
}
# endif
# ifndef DISABLE_MEDIAS
static struct media_info * medias = NULL ;
2007-03-01 19:25:26 +03:00
static void find_media ( void )
2007-02-27 16:11:49 +03:00
{
2007-03-01 19:25:26 +03:00
FILE * f ;
2007-02-27 16:11:49 +03:00
DIR * dir = NULL ;
struct dirent * dirent = NULL ;
struct stat st ;
2007-03-01 19:25:26 +03:00
struct media_info tmp [ 50 ] ;
2007-02-27 16:11:49 +03:00
char path [ SYSFS_PATH_MAX ] ;
2007-03-01 19:25:26 +03:00
char buf [ 512 ] ;
2007-02-27 16:11:49 +03:00
char * s ;
2007-03-01 19:25:26 +03:00
int count = 0 ;
2008-02-29 18:14:39 +03:00
if ( medias )
2007-03-01 19:25:26 +03:00
free ( medias ) ; /* that does not free the strings, by the way */
2007-02-27 16:11:49 +03:00
if ( ( dir = opendir ( " /sys/block " ) ) = = NULL ) {
log_message ( " failed to open /sys/block directory " ) ;
return ;
}
while ( ( dirent = readdir ( dir ) ) ! = NULL ) {
2007-03-01 19:25:26 +03:00
if ( ! strcmp ( dirent - > d_name , " . " ) | |
! strcmp ( dirent - > d_name , " .. " ) ) continue ;
2007-02-27 16:11:49 +03:00
memset ( path , 0 , SYSFS_PATH_MAX ) ;
strcpy ( path , " /sys/block/ " ) ;
strcat ( path , dirent - > d_name ) ;
s = path + strlen ( path ) ;
2004-01-20 21:32:43 +03:00
2007-03-01 19:25:26 +03:00
/* probe for scsi type */
strcat ( path , " /device/type " ) ;
if ( lstat ( path , & st ) = = 0 & & S_ISREG ( st . st_mode ) ) {
tmp [ count ] . name = strdup ( dirent - > d_name ) ;
tmp [ count ] . type = UNKNOWN_MEDIA ;
if ( ( f = fopen ( path , " r " ) ) ! = NULL ) {
int type ;
2008-03-15 23:59:16 +03:00
if ( fgets ( buf , sizeof ( buf ) , f ) & & sscanf ( buf , " %d " , & type ) ) {
2007-03-01 19:25:26 +03:00
if ( type = = SCSI_TYPE_DISK ) tmp [ count ] . type = DISK ;
else if ( type = = SCSI_TYPE_ROM ) tmp [ count ] . type = CDROM ;
else if ( type = = SCSI_TYPE_TAPE ) tmp [ count ] . type = TAPE ;
}
fclose ( f ) ;
}
2004-01-20 21:32:43 +03:00
2007-03-01 19:25:26 +03:00
* s = 0 ;
strcat ( path , " /device/model " ) ;
if ( ( f = fopen ( path , " r " ) ) ! = NULL ) {
if ( fgets ( buf , sizeof ( buf ) , f ) ) {
2007-08-02 20:08:13 +04:00
if ( buf [ strlen ( buf ) - 1 ] = = ' \n ' )
buf [ strlen ( buf ) - 1 ] = 0 ;
2007-03-01 19:25:26 +03:00
tmp [ count ] . model = strdup ( buf ) ;
}
fclose ( f ) ;
} else {
tmp [ count ] . model = strdup ( " (unknown) " ) ;
}
2004-01-20 21:32:43 +03:00
2007-03-01 19:25:26 +03:00
log_message ( " SCSI/%d: %s is a %s " , tmp [ count ] . type , tmp [ count ] . name , tmp [ count ] . model ) ;
count + + ;
2004-01-20 21:32:43 +03:00
continue ;
}
2007-03-01 19:25:26 +03:00
/* assume ide */
* s = 0 ;
strcat ( s , " /device/media " ) ;
if ( lstat ( path , & st ) = = 0 & & S_ISREG ( st . st_mode ) ) {
tmp [ count ] . name = strdup ( dirent - > d_name ) ;
2004-01-20 21:32:43 +03:00
tmp [ count ] . type = UNKNOWN_MEDIA ;
2007-03-01 19:25:26 +03:00
log_message ( " IDE: name: %s " , dirent - > d_name ) ;
if ( ( f = fopen ( path , " r " ) ) ! = NULL ) {
if ( fgets ( buf , sizeof ( buf ) , f ) ) {
log_message ( " IDE: type: %s " , buf ) ;
if ( ! strncmp ( " disk " , buf , 4 ) )
2004-01-20 21:32:43 +03:00
tmp [ count ] . type = DISK ;
2007-03-01 19:25:26 +03:00
else if ( ! strncmp ( " cdrom " , buf , 5 ) )
tmp [ count ] . type = CDROM ;
else if ( ! strncmp ( " tape " , buf , 4 ) )
tmp [ count ] . type = TAPE ;
else if ( ! strncmp ( " floppy " , buf , 6 ) )
tmp [ count ] . type = FLOPPY ;
2004-01-20 21:32:43 +03:00
}
2007-03-01 19:25:26 +03:00
fclose ( f ) ;
2004-01-20 21:32:43 +03:00
}
2007-03-01 19:25:26 +03:00
/* grab model */
strcpy ( path , " /proc/ide/ " ) ;
strcat ( path , dirent - > d_name ) ;
strcat ( path , " /model " ) ;
if ( ( f = fopen ( path , " r " ) ) ! = NULL ) {
if ( fgets ( buf , sizeof ( buf ) , f ) ) {
2007-08-02 20:08:13 +04:00
if ( buf [ strlen ( buf ) - 1 ] = = ' \n ' )
buf [ strlen ( buf ) - 1 ] = 0 ;
2007-03-01 19:25:26 +03:00
tmp [ count ] . model = strdup ( buf ) ;
2004-01-20 21:32:43 +03:00
}
2007-03-01 19:25:26 +03:00
fclose ( f ) ;
} else {
tmp [ count ] . model = strdup ( " (none) " ) ;
2004-01-20 21:32:43 +03:00
}
2007-03-01 19:25:26 +03:00
log_message ( " IDE/%d: %s is a %s " , tmp [ count ] . type , tmp [ count ] . name , tmp [ count ] . model ) ;
count + + ;
2004-01-20 21:32:43 +03:00
}
}
2007-03-01 19:25:26 +03:00
closedir ( dir ) ;
2004-01-20 21:32:43 +03:00
tmp [ count ] . name = NULL ;
count + + ;
medias = memdup ( tmp , sizeof ( struct media_info ) * count ) ;
}
/* Finds by media */
void get_medias ( enum media_type media , char * * * names , char * * * models )
{
struct media_info * m ;
char * tmp_names [ 50 ] ;
char * tmp_models [ 50 ] ;
int count ;
find_media ( ) ;
m = medias ;
count = 0 ;
while ( m & & m - > name ) {
if ( m - > type = = media ) {
tmp_names [ count ] = strdup ( m - > name ) ;
tmp_models [ count + + ] = strdup ( m - > model ) ;
}
m + + ;
}
tmp_names [ count ] = NULL ;
tmp_models [ count + + ] = NULL ;
* names = memdup ( tmp_names , sizeof ( char * ) * count ) ;
* models = memdup ( tmp_models , sizeof ( char * ) * count ) ;
}
# endif /* DISABLE_MEDIAS */
# ifndef DISABLE_NETWORK
2008-02-29 18:14:39 +03:00
static int net_device_available ( char * device )
2004-11-22 16:47:29 +03:00
{
2004-01-20 21:32:43 +03:00
struct ifreq req ;
int s ;
s = socket ( AF_INET , SOCK_DGRAM , 0 ) ;
if ( s < 0 ) {
log_perror ( device ) ;
return 0 ;
}
strcpy ( req . ifr_name , device ) ;
if ( ioctl ( s , SIOCGIFFLAGS , & req ) ) {
/* if we can't get the flags, the networking device isn't available */
close ( s ) ;
return 0 ;
}
close ( s ) ;
return 1 ;
}
char * * get_net_devices ( void )
{
char * devices [ ] = {
" eth0 " , " eth1 " , " eth2 " , " eth3 " , " eth4 " , " eth5 " ,
" tr0 " ,
" fddi0 " ,
# ifdef ENABLE_USBNET
" usb0 " , " usb1 " , " usb2 " , " usb3 " ,
# endif
NULL
} ;
char * * ptr = devices ;
char * tmp [ 50 ] ;
int i = 0 ;
while ( ptr & & * ptr ) {
if ( net_device_available ( * ptr ) )
tmp [ i + + ] = strdup ( * ptr ) ;
ptr + + ;
}
tmp [ i + + ] = NULL ;
return memdup ( tmp , sizeof ( char * ) * i ) ;
}
# endif /* DISABLE_NETWORK */