diff options
Diffstat (limited to 'mdk-stage1/disk.c')
| -rw-r--r-- | mdk-stage1/disk.c | 283 | 
1 files changed, 146 insertions, 137 deletions
| diff --git a/mdk-stage1/disk.c b/mdk-stage1/disk.c index 0a15f0e67..51a033639 100644 --- a/mdk-stage1/disk.c +++ b/mdk-stage1/disk.c @@ -1,7 +1,7 @@  /* - * Guillaume Cottenceau (gc@mandrakesoft.com) + * Guillaume Cottenceau (gc)   * - * Copyright 2000 MandrakeSoft + * Copyright 2000 Mandriva   *   * This software may be freely redistributed under the terms of the GNU   * public license. @@ -19,192 +19,200 @@   *   */ +#define _GNU_SOURCE         /* We want the non segfaulting my_dirname() -- See dirname(3) */ +#include <string.h>  #include <stdlib.h>  #include <unistd.h>  #include <stdio.h> -#include <string.h>  #include <sys/mount.h>  #include <sys/stat.h>  #include <fcntl.h> +#include <libgen.h>  #include "stage1.h"  #include "frontend.h"  #include "modules.h"  #include "probing.h"  #include "log.h" +#include "tools.h" +#include "utils.h"  #include "mount.h" -#include "lomount.h"  #include "automatic.h" +#include "directory.h" +#include "partition.h"  #include "disk.h" -static char * disk_extract_list_directory(char * direct) +static enum return_type try_automatic_with_partition(char *dev) { +	enum return_type results; +	int mounted; +	char *dir= get_auto_value("directory"); +	char location_full[500]; +	strcpy(location_full, MEDIA_LOCATION); +	if (dir) { +		strcat(location_full, "/"); +		strcat(location_full, dir); +	} +	wait_message("Trying to access " DISTRIB_NAME " disk (partition %s)", dev); +	mounted = !try_mount(dev, MEDIA_LOCATION); +	remove_wait_message(); +	if (mounted) { +		create_IMAGE_LOCATION(MEDIA_LOCATION); +		if (image_has_stage2()) { +			results = try_with_directory(MEDIA_LOCATION, "disk", "disk-iso"); +		} else { +			results = try_with_directory(location_full, "disk", "disk-iso"); +		} +		if (results == RETURN_OK) { +			if (!KEEP_MOUNTED) +				umount(MEDIA_LOCATION); +			return RETURN_OK; +		} +	} +	if (mounted) +		umount(MEDIA_LOCATION); +	return RETURN_ERROR; +} + +static enum return_type try_automatic_with_disk(char *disk, char *model) { +	char * parts[50]; +	char * parts_comments[50]; +	enum return_type results; +	char **dev; +	char *part = get_auto_value("partition"); +	wait_message("Trying to access " DISTRIB_NAME " disk (drive %s)", model); +	if (list_partitions(disk, parts, parts_comments)) { +		stg1_error_message("Could not read partitions information."); +		return RETURN_ERROR; +	} +	remove_wait_message(); +	dev = parts; +	while (dev && *dev) { +		if (part && strcmp(part, *dev) != 0) +			goto next; +		results = try_automatic_with_partition(*dev); +		if (results == RETURN_OK) { +			return RETURN_OK; +		} +	next: +		dev++; +	} +	return RETURN_ERROR; +} + +static enum return_type try_automatic(char ** medias, char ** medias_models)  { -	char ** full = list_directory(direct); -	char tmp[2000] = ""; -	int i; -	for (i=0; i<5 ; i++) { -		if (!full || !*full) -			break; -		strcat(tmp, *full); -		strcat(tmp, "\n"); -		full++; +	char ** model = medias_models; +	char ** ptr = medias; +	char *disk = get_auto_value("disk"); +	while (ptr && *ptr) { +		enum return_type results; +		if (disk && strcmp(disk, *ptr) != 0) +			goto next; +		results = try_automatic_with_disk(*ptr, *model); +		if (results == RETURN_OK) +			return RETURN_OK; +	next: +		ptr++; +		model++;  	} -	return strdup(tmp); +	return RETURN_ERROR;  }  static enum return_type try_with_device(char *dev_name)  { -	char * questions_location[] = { "Directory or ISO image", NULL }; +	char * questions_location[] = { "Directory or ISO images directory or ISO image", NULL };  	char * questions_location_auto[] = { "directory", NULL };  	static char ** answers_location = NULL; -	char device_fullname[50];  	char location_full[500]; -	char * disk_own_mount = "/tmp/hdimage"; - -	int major, minor, blocks; -	char name[100]; - -	char buf[512]; -	FILE * f;  	char * parts[50];  	char * parts_comments[50]; -	struct stat statbuf; -	int i = 0;  	enum return_type results;  	char * choice; - -	if (!(f = fopen("/proc/partitions", "rb")) || !fgets(buf, sizeof(buf), f) || !fgets(buf, sizeof(buf), f)) { -		log_perror(dev_name); -		error_message("Could not read partitions information."); -		return RETURN_ERROR; -	} - -	while (fgets(buf, sizeof(buf), f)) { -		sscanf(buf, " %d %d %d %s", &major, &minor, &blocks, name); -		if ((strstr(name, dev_name) == name) && (blocks > 1) && (name[strlen(dev_name)] != '\0')) { -			parts[i] = strdup(name); -			parts_comments[i] = (char *) malloc(sizeof(char) * 25); -			snprintf(parts_comments[i], 24, "size: %d Mbytes", blocks >> 10); -			i++; -		} -	} -	parts[i] = NULL; -	fclose(f); - -	if (parts[0] == NULL) { -		error_message("No partitions found."); +         +        if (list_partitions(dev_name, parts, parts_comments)) { +		stg1_error_message("Could not read partitions information.");  		return RETURN_ERROR; -	} - -	results = ask_from_list_comments_auto("Please choose the partition where is copied the " DISTRIB_NAME " Distribution.", -					      parts, parts_comments, &choice, "partition", parts); -	if (results != RETURN_OK) -		return results; - -	strcpy(device_fullname, "/dev/"); -	strcat(device_fullname, choice); - -	if (my_mount(device_fullname, disk_own_mount, "ext2") == -1 && -	    my_mount(device_fullname, disk_own_mount, "vfat") == -1 && -	    my_mount(device_fullname, disk_own_mount, "reiserfs") == -1) { -		error_message("I can't find a valid filesystem."); +        } + +        /* uglyness to allow auto starting with devfs */ +        if (!IS_AUTOMATIC || streq((choice = get_auto_value("partition")), "")) { +                if (parts[0] == NULL) { +                        stg1_error_message("No partition found."); +                        return RETURN_ERROR; +                } + +                results = ask_from_list_comments_auto("Please select the partition containing the copy of the " +						      DISTRIB_NAME " Distribution install source.", +                                                      parts, parts_comments, &choice, "partition", parts); +                if (results != RETURN_OK) +                        return results; +        } + +	/* in testing mode, assume the partition is already mounted on MEDIA_LOCATION */ +        if (!IS_TESTING && try_mount(choice, MEDIA_LOCATION)) { +		stg1_error_message("I can't find a valid filesystem (tried: ext4, vfat, ntfs, reiserfs). " +                                   "Make sure the partition has been cleanly unmounted.");  		return try_with_device(dev_name);  	} -	if (ask_from_entries_auto("Please enter the directory (or ISO image file) containing the " DISTRIB_NAME " Distribution.", + ask_dir: +	if (ask_from_entries_auto("Please enter the directory (or ISO image file) containing the " +				  DISTRIB_NAME " Distribution install source.",  				  questions_location, &answers_location, 24, questions_location_auto, NULL) != RETURN_OK) { -		umount(disk_own_mount); +		umount(MEDIA_LOCATION);  		return try_with_device(dev_name);  	} -	strcpy(location_full, disk_own_mount); +	strcpy(location_full, MEDIA_LOCATION);  	strcat(location_full, "/");  	strcat(location_full, answers_location[0]);  	if (access(location_full, R_OK)) { -		error_message("Directory or ISO image file could not be found on partition.\n" -			      "Here's a short extract of the files in the root of the partition:\n" -			      "%s", disk_extract_list_directory(disk_own_mount)); -		umount(disk_own_mount); -		return try_with_device(dev_name); +		char * path = strdup(answers_location[0]); +		stg1_error_message("Directory or ISO image file could not be found on partition.\n" +			      "Here's a short extract of the files in the directory %s:\n" +			      "%s", my_dirname(path), extract_list_directory(my_dirname(location_full))); +		free(path); +		goto ask_dir;  	} -	unlink(IMAGE_LOCATION); - -	if (!stat(location_full, &statbuf) && !S_ISDIR(statbuf.st_mode)) { -		log_message("%s exists and is not a directory, assuming this is an ISO image", location_full); -		if (lomount(location_full, IMAGE_LOCATION)) { -			error_message("Could not mount file %s as an ISO image of the " DISTRIB_NAME " Distribution.", answers_location[0]); -			umount(disk_own_mount); -			return try_with_device(dev_name); -		} -	} else -		symlink(location_full, IMAGE_LOCATION); - -	if (IS_SPECIAL_STAGE2 || ramdisk_possible()) { -		/* RAMDISK install */ -		if (access(IMAGE_LOCATION RAMDISK_LOCATION, R_OK)) { -			error_message("I can't find the " DISTRIB_NAME " Distribution in the specified directory. " -				      "(I need the subdirectory " RAMDISK_LOCATION ")\n" -				      "Here's a short extract of the files in the directory:\n" -				      "%s", disk_extract_list_directory(IMAGE_LOCATION)); -			umount(disk_own_mount); -			return try_with_device(dev_name); -		} -		if (load_ramdisk() != RETURN_OK) { -			error_message("Could not load program into memory."); -			umount(disk_own_mount); -			return try_with_device(dev_name); -		} -	} else { -		/* LIVE install */ -		char p; -		if (access(IMAGE_LOCATION LIVE_LOCATION, R_OK)) { -			error_message("I can't find the " DISTRIB_NAME " Distribution in the specified directory. " -				      "(I need the subdirectory " LIVE_LOCATION ")\n" -				      "Here's a short extract of the files in the directory:\n" -				      "%s", disk_extract_list_directory(IMAGE_LOCATION)); -			umount(disk_own_mount); -			return try_with_device(dev_name); -		} -		if (readlink(IMAGE_LOCATION LIVE_LOCATION "/usr/bin/runinstall2", &p, 1) != 1) { -			error_message("The " DISTRIB_NAME " Distribution seems to be copied on a Windows partition. " -				      "You need more memory to perform an installation from a Windows partition. " -				      "Another solution if to copy the " DISTRIB_NAME " Distribution on a Linux partition."); -			umount(disk_own_mount); -			return try_with_device(dev_name); -		} -		log_message("found the " DISTRIB_NAME " Installation, good news!"); +	results = try_with_directory(location_full, "disk", "disk-iso"); +	if (results != RETURN_OK) { +		goto ask_dir;  	} -	if (IS_RESCUE) -		umount(IMAGE_LOCATION); +	if (!KEEP_MOUNTED) +		umount(MEDIA_LOCATION); -	method_name = strdup("disk");  	return RETURN_OK;  }  enum return_type disk_prepare(void)  { -	char ** medias, ** ptr, ** medias_models; +	char ** medias, ** medias_models;  	char * choice; -	int i, count = 0; +	int i;  	enum return_type results; +	static int already_probed_ide_generic = 0; -	my_insmod("sd_mod", ANY_DRIVER_TYPE, NULL); -	 -	get_medias(DISK, &medias, &medias_models); +        int count = get_disks(&medias, &medias_models); -	ptr = medias; -	while (ptr && *ptr) { -		count++; -		ptr++; -	} +	if (IS_AUTOMATIC) { +		results = try_automatic(medias, medias_models); +		if (results != RETURN_ERROR) +			return results; +		unset_automatic(); +        }  	if (count == 0) { -		error_message("No DISK drive found."); -		i = ask_insmod(SCSI_ADAPTERS); +		if (!already_probed_ide_generic) { +			already_probed_ide_generic = 1; +			my_modprobe("ide_generic", ANY_DRIVER_TYPE, NULL); +			return disk_prepare(); +		} +		stg1_error_message("No DISK drive found."); +		i = ask_insmod(MEDIA_ADAPTERS);  		if (i == RETURN_BACK)  			return RETURN_BACK;  		return disk_prepare(); @@ -212,24 +220,25 @@ enum return_type disk_prepare(void)  	if (count == 1) {  		results = try_with_device(*medias); -		if (results == RETURN_OK) -			return RETURN_OK; -		i = ask_insmod(SCSI_ADAPTERS); +		if (results != RETURN_ERROR) +			return results; +		i = ask_insmod(MEDIA_ADAPTERS);  		if (i == RETURN_BACK)  			return RETURN_BACK;  		return disk_prepare();  	} -	results = ask_from_list_comments_auto("Please choose the DISK drive on which you copied the " DISTRIB_NAME " Distribution.", +	results = ask_from_list_comments_auto("Please select the disk containing the copy of the " +					      DISTRIB_NAME " Distribution install source.",  					      medias, medias_models, &choice, "disk", medias);  	if (results != RETURN_OK)  		return results;  	results = try_with_device(choice); -	if (results == RETURN_OK) -		return RETURN_OK; -	i = ask_insmod(SCSI_ADAPTERS); +	if (results != RETURN_ERROR) +		return results; +	i = ask_insmod(MEDIA_ADAPTERS);  	if (i == RETURN_BACK)  		return RETURN_BACK;  	return disk_prepare(); | 
