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
*
*/
2008-04-10 14:35:23 +04:00
# include <sys/types.h>
# include <sys/stat.h>
2004-01-20 21:32:43 +03:00
# include <stdlib.h>
# include <unistd.h>
# include <string.h>
# include <stdio.h>
# include <sys/mount.h>
2013-03-15 22:13:28 +04:00
# include <ctype.h>
2004-01-20 21:32:43 +03:00
# include "stage1.h"
# include "frontend.h"
# include "modules.h"
# include "probing.h"
# include "log.h"
# include "mount.h"
# include "cdrom.h"
2016-05-16 19:57:12 +03:00
# include "init.h"
2004-01-20 21:32:43 +03:00
2016-05-16 19:57:12 +03:00
extern char * udevtrigger_add [ ] ;
2007-08-02 20:45:59 +04:00
extern char version [ ] ;
2004-01-20 21:32:43 +03:00
2013-08-21 18:25:48 +04:00
static int mount_iso9660 ( char * dev_name )
{
return my_mount ( dev_name , IMAGE_LOCATION , " iso9660 " , 0 ) ;
}
2004-01-20 21:32:43 +03:00
static int mount_that_cd_device ( char * dev_name )
{
2013-03-15 22:13:28 +04:00
char device_fullname [ 64 ] = " /dev/ " ;
2015-03-06 20:53:50 +03:00
strcat ( device_fullname , dev_name ) ;
2004-01-20 21:32:43 +03:00
2015-03-06 20:53:50 +03:00
char * p = device_fullname + strlen ( device_fullname ) ;
2013-08-21 18:25:48 +04:00
if ( islower ( p [ - 1 ] ) ) {
2013-03-15 22:13:28 +04:00
int ret ;
2013-08-21 18:25:48 +04:00
p [ 0 ] = ' 1 ' ;
p [ 1 ] = ' \0 ' ;
ret = mount_iso9660 ( device_fullname ) ;
2013-03-15 22:13:28 +04:00
if ( ret ! = - 1 )
return ret ;
2013-08-21 18:25:48 +04:00
p [ 0 ] = ' \0 ' ;
2013-03-15 22:13:28 +04:00
}
2004-01-20 21:32:43 +03:00
2013-08-21 18:25:48 +04:00
return mount_iso9660 ( device_fullname ) ;
2004-01-20 21:32:43 +03:00
}
2014-04-19 10:50:25 +04:00
/* test_that_cd() returns 0 on success */
static int test_that_cd ( int no_digest )
2004-01-20 21:32:43 +03:00
{
2014-04-23 01:38:54 +04:00
if ( IS_VERIFICATION & & ! no_digest )
return verify_ramdisk_digest ( get_ramdisk_path ( NULL ) ,
get_param_valued ( " hash " ) ) = = RETURN_ERROR ;
2007-08-02 20:45:59 +04:00
log_message ( " test file on cd: %s \n " , get_ramdisk_path ( NULL ) ) ;
2004-12-13 01:22:50 +03:00
return access ( get_ramdisk_path ( NULL ) , R_OK ) ;
2004-01-20 21:32:43 +03:00
}
static enum return_type try_with_device ( char * dev_name , char * dev_model ) ;
static enum return_type do_with_device ( char * dev_name , char * dev_model )
{
2008-04-10 14:35:23 +04:00
struct stat st ;
2007-08-02 20:45:59 +04:00
char msg [ 256 ] ;
2008-04-10 14:35:23 +04:00
char * ramdisk_path ;
2014-04-19 10:50:25 +04:00
if ( test_that_cd ( 0 ) ) {
2004-01-20 21:32:43 +03:00
enum return_type results ;
umount ( IMAGE_LOCATION ) ;
2014-04-19 10:50:25 +04:00
if ( IS_VERIFICATION )
2014-04-19 12:48:01 +04:00
snprintf ( msg , sizeof ( msg ) , " ISO on /dev/%s does not seem to contain proper %s "
" media: \n hash verification failed. \n Try another media in that drive? " , dev_name , version ) ;
2014-04-19 10:50:25 +04:00
else
snprintf ( msg , sizeof ( msg ) , " That ISO does not seem like proper %s "
2014-04-19 12:48:01 +04:00
" media. \n Try another media in that drive? " , version ) ;
2007-08-02 20:45:59 +04:00
results = ask_yes_no ( msg ) ;
2004-01-20 21:32:43 +03:00
if ( results = = RETURN_OK )
return try_with_device ( dev_name , dev_model ) ;
return results ;
}
2011-12-16 14:27:46 +04:00
log_message ( " found %s ISO9660 media, good news! " , version ) ;
2004-01-20 21:32:43 +03:00
if ( IS_RESCUE ) {
2005-03-05 18:26:22 +03:00
load_ramdisk ( NULL ) ;
2004-01-20 21:32:43 +03:00
umount ( IMAGE_LOCATION ) ;
}
2005-01-26 16:43:53 +03:00
2008-04-10 14:35:23 +04:00
ramdisk_path = get_ramdisk_path ( NULL ) ;
stat ( ramdisk_path , & st ) ;
if ( S_ISDIR ( st . st_mode ) ) {
mount ( ramdisk_path , STAGE2_LOCATION , NULL , MS_BIND , NULL ) ;
} else {
do_losetup ( LIVE_DEVICE , ramdisk_path ) ;
my_mount ( LIVE_DEVICE , STAGE2_LOCATION , ( IS_LIVE ) ? LIVEFS : STAGE2FS , 0 ) ;
}
2005-02-03 18:38:15 +03:00
2004-01-20 21:32:43 +03:00
method_name = strdup ( " cdrom " ) ;
2005-01-26 16:43:53 +03:00
add_to_env ( " METHOD " , method_name ) ;
add_to_env ( " PREFIX " , " / " ) ;
2004-01-20 21:32:43 +03:00
return RETURN_OK ;
}
static enum return_type try_with_device ( char * dev_name , char * dev_model )
{
2011-12-16 14:27:46 +04:00
wait_message ( " Trying to access media in drive %s " , dev_model ) ;
2004-01-20 21:32:43 +03:00
if ( mount_that_cd_device ( dev_name ) = = - 1 ) {
enum return_type results ;
char msg [ 500 ] ;
unset_param ( MODE_AUTOMATIC ) ; /* we are in a fallback mode */
remove_wait_message ( ) ;
2011-12-16 14:27:46 +04:00
snprintf ( msg , sizeof ( msg ) , " I can't access %s media in drive %s. \n Retry? " , version , dev_model ) ;
2004-01-20 21:32:43 +03:00
results = ask_yes_no ( msg ) ;
if ( results = = RETURN_OK )
return try_with_device ( dev_name , dev_model ) ;
return results ;
}
remove_wait_message ( ) ;
return do_with_device ( dev_name , dev_model ) ;
}
2014-12-17 19:48:24 +03:00
# define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
2011-12-16 14:27:46 +04:00
int try_automatic ( char * * medias , char * * medias_models )
{
static char * already_tried [ 50 ] = { NULL } ;
char * * model = medias_models ;
char * * ptr = medias ;
int i = 0 ;
2014-12-17 19:48:24 +03:00
if ( ! medias ) {
for ( ; i < ARRAY_SIZE ( already_tried ) ; + + i ) {
if ( ! already_tried [ i ] )
break ;
free ( already_tried [ i ] ) ;
already_tried [ i ] = NULL ;
}
return - 1 ;
}
2011-12-16 14:27:46 +04:00
while ( ptr & & * ptr ) {
char * * p ;
for ( p = already_tried ; p & & * p ; p + + )
if ( streq ( * p , * ptr ) )
goto try_automatic_already_tried ;
* p = strdup ( * ptr ) ;
* ( p + 1 ) = NULL ;
wait_message ( " Trying to access media in drive %s " , * model ) ;
if ( mount_that_cd_device ( * ptr ) ! = - 1 ) {
2014-04-19 10:50:25 +04:00
if ( ! test_that_cd ( 1 ) ) {
2011-12-16 14:27:46 +04:00
remove_wait_message ( ) ;
return i ;
}
else
umount ( IMAGE_LOCATION ) ;
}
remove_wait_message ( ) ;
try_automatic_already_tried :
ptr + + ;
model + + ;
i + + ;
}
return - 1 ;
}
2004-01-20 21:32:43 +03:00
enum return_type cdrom_prepare ( void )
{
char * * medias , * * ptr , * * medias_models ;
char * choice ;
int i , count = 0 ;
enum return_type results ;
2015-03-10 01:26:53 +03:00
int timeout = 32 ;
int period = 5 ;
2010-11-20 19:20:08 +03:00
2010-12-01 13:22:58 +03:00
update_splash ( " prepare " ) ;
2010-11-20 19:20:08 +03:00
fprintf ( stderr , " %c[1A " , 27 ) ;
for ( i = 0 ; i < timeout ; i + + ) {
2016-05-16 19:57:12 +03:00
if ( i % period = = 0 ) {
spawn ( udevtrigger_add ) ;
}
2010-11-20 19:20:08 +03:00
sleep ( 1 ) ;
if ( opendir ( " /dev/disk/ " ) ) break ;
fprintf ( stderr , " \r waiting for /dev/disk/ %d... " , i ) ;
}
2010-11-22 19:56:35 +03:00
update_splash ( " wait_media " ) ;
2004-01-20 21:32:43 +03:00
get_medias ( CDROM , & medias , & medias_models ) ;
if ( IS_AUTOMATIC ) {
2014-12-17 19:48:24 +03:00
unsigned int j ;
for ( j = 0 ; j < 5 ; + + j ) {
if ( j ) {
wait_message ( " Waiting %d second%s for CD/DVD/Pendrive media to appear " ,
j , j > 1 ? " s " : " " ) ;
sleep ( 1 ) ;
/* drop medias */
for ( ptr = medias ; * ptr ; + + ptr )
free ( * ptr ) ;
free ( medias ) ;
/* drop medias_models */
for ( ptr = medias_models ; * ptr ; + + ptr )
free ( * ptr ) ;
free ( medias_models ) ;
/* drop already_tried */
try_automatic ( NULL , NULL ) ;
/* refill medias and medias_models;
note that get_medias ( ) leaks memory */
get_medias ( CDROM , & medias , & medias_models ) ;
2015-02-26 20:06:47 +03:00
remove_wait_message ( ) ;
2014-12-17 19:48:24 +03:00
}
if ( ( i = try_automatic ( medias , medias_models ) ) ! = - 1 ) {
if ( j ) {
log_message ( " found /dev/%s %s after %d seconds of waiting " ,
medias [ i ] , medias_models [ i ] , j ) ;
remove_wait_message ( ) ;
}
return do_with_device ( medias [ i ] , medias_models [ i ] ) ;
}
}
2004-01-20 21:32:43 +03:00
ptr = medias ;
while ( ptr & & * ptr ) {
2011-12-16 14:27:46 +04:00
count + + ;
2004-01-20 21:32:43 +03:00
ptr + + ;
}
2011-12-16 14:27:46 +04:00
if ( count = = 0 ) {
2014-12-17 19:48:24 +03:00
stg1_error_message ( " No CD/DVD/Pendrive found. " ) ;
2011-12-16 14:27:46 +04:00
i = ask_insmod ( ) ;
if ( i = = RETURN_BACK )
return RETURN_BACK ;
return cdrom_prepare ( ) ;
}
if ( count = = 1 ) {
results = try_with_device ( * medias , * medias_models ) ;
if ( results = = RETURN_OK )
return RETURN_OK ;
i = ask_insmod ( ) ;
if ( i = = RETURN_BACK )
return RETURN_BACK ;
return cdrom_prepare ( ) ;
}
unset_param ( MODE_AUTOMATIC ) ;
2004-01-20 21:32:43 +03:00
}
2015-03-27 10:41:24 +03:00
results = ask_from_list_comments ( " Please choose the drive to boot from. " , medias , medias_models , & choice ) ;
2011-12-16 14:27:46 +04:00
if ( results = = RETURN_OK ) {
char * * model = medias_models ;
ptr = medias ;
while ( ptr & & * ptr & & model & & * model ) {
if ( ! strcmp ( * ptr , choice ) )
break ;
ptr + + ;
model + + ;
}
results = try_with_device ( choice , * model ) ;
} else
return results ;
2004-01-20 21:32:43 +03:00
if ( results = = RETURN_OK )
2005-04-21 15:06:44 +04:00
{
2010-12-01 13:22:58 +03:00
update_splash ( " found_media " ) ;
2004-01-20 21:32:43 +03:00
return RETURN_OK ;
2005-04-21 15:06:44 +04:00
}
2004-01-20 21:32:43 +03:00
if ( results = = RETURN_BACK )
return cdrom_prepare ( ) ;
2008-02-29 20:05:35 +03:00
i = ask_insmod ( ) ;
2004-01-20 21:32:43 +03:00
if ( i = = RETURN_BACK )
return RETURN_BACK ;
return cdrom_prepare ( ) ;
}