summaryrefslogtreecommitdiffstats
path: root/mdk-stage1/disk.c
diff options
context:
space:
mode:
Diffstat (limited to 'mdk-stage1/disk.c')
-rw-r--r--mdk-stage1/disk.c272
1 files changed, 100 insertions, 172 deletions
diff --git a/mdk-stage1/disk.c b/mdk-stage1/disk.c
index 8318bb6f4..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,171 +19,103 @@
*
*/
+#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 <string.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 "disk.h"
#include "directory.h"
+#include "partition.h"
-struct partition_detection_anchor {
- off_t offset;
- const char * anchor;
-};
-
-static int seek_and_compare(int fd, struct partition_detection_anchor anch)
-{
- char buf[500];
- size_t count;
- if (lseek(fd, anch.offset, SEEK_SET) == (off_t)-1) {
- log_perror("seek failed");
- return -1;
- }
- count = read(fd, buf, strlen(anch.anchor));
- if (count != strlen(anch.anchor)) {
- log_perror("read failed");
- return -1;
- }
- buf[count] = '\0';
- if (strcmp(anch.anchor, buf))
- return 1;
- return 0;
-}
-
-static const char * detect_partition_type(char * dev)
-{
- struct partition_detection_info {
- const char * name;
- struct partition_detection_anchor anchor0;
- struct partition_detection_anchor anchor1;
- struct partition_detection_anchor anchor2;
- };
- struct partition_detection_info partitions_signatures[] = {
- { "Linux Swap", { 4086, "SWAP-SPACE" }, { 0, NULL }, { 0, NULL } },
- { "Linux Swap", { 4086, "SWAPSPACE2" }, { 0, NULL }, { 0, NULL } },
- { "Ext2", { 0x438, "\x53\xEF" }, { 0, NULL }, { 0, NULL } },
- { "ReiserFS", { 0x10034, "ReIsErFs" }, { 0, NULL }, { 0, NULL } },
- { "ReiserFS", { 0x10034, "ReIsEr2Fs" }, { 0, NULL }, { 0, NULL } },
- { "XFS", { 0, "XFSB" }, { 0x200, "XAGF" }, { 0x400, "XAGI" } },
- { "JFS", { 0x8000, "JFS1" }, { 0, NULL }, { 0, NULL } },
- { "NTFS", { 0x1FE, "\x55\xAA" }, { 0x3, "NTFS" }, { 0, NULL } },
- { "FAT32", { 0x1FE, "\x55\xAA" }, { 0x52, "FAT32" }, { 0, NULL } },
- { "FAT", { 0x1FE, "\x55\xAA" }, { 0x36, "FAT" }, { 0, NULL } },
- { "Linux LVM", { 0, "HM\1\0" }, { 0, NULL }, { 0, NULL } }
- };
- int partitions_signatures_nb = sizeof(partitions_signatures) / sizeof(struct partition_detection_info);
- int i;
- int fd;
- const char *part_type = NULL;
-
- char device_fullname[50];
- strcpy(device_fullname, "/dev/");
- strcat(device_fullname, dev);
-
- if (ensure_dev_exists(device_fullname))
- return NULL;
- log_message("guessing type of %s", device_fullname);
+#include "disk.h"
- if ((fd = open(device_fullname, O_RDONLY, 0)) < 0) {
- log_perror("open");
- return NULL;
+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);
}
-
- for (i=0; i<partitions_signatures_nb; i++) {
- int results = seek_and_compare(fd, partitions_signatures[i].anchor0);
- if (results == -1)
- goto detect_partition_type_end;
- if (results == 1)
- continue;
- if (!partitions_signatures[i].anchor1.anchor)
- goto detect_partition_found_it;
-
- results = seek_and_compare(fd, partitions_signatures[i].anchor1);
- if (results == -1)
- goto detect_partition_type_end;
- if (results == 1)
- continue;
- if (!partitions_signatures[i].anchor2.anchor)
- goto detect_partition_found_it;
-
- results = seek_and_compare(fd, partitions_signatures[i].anchor2);
- if (results == -1)
- goto detect_partition_type_end;
- if (results == 1)
- continue;
-
- detect_partition_found_it:
- part_type = partitions_signatures[i].name;
- break;
+ 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;
+ }
}
-
- detect_partition_type_end:
- close(fd);
- return part_type;
+ if (mounted)
+ umount(MEDIA_LOCATION);
+ return RETURN_ERROR;
}
-static int list_partitions(char * dev_name, char ** parts, char ** comments)
-{
- int major, minor, blocks;
- char name[100];
- FILE * f;
- int i = 0;
- char buf[512];
-
- if (!(f = fopen("/proc/partitions", "rb")) || !fgets(buf, sizeof(buf), f) || !fgets(buf, sizeof(buf), f)) {
- log_perror(dev_name);
- return 1;
+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;
}
-
- while (fgets(buf, sizeof(buf), f)) {
- memset(name, 0, sizeof(name));
- sscanf(buf, " %d %d %d %s", &major, &minor, &blocks, name);
- if ((strstr(name, dev_name) == name) && (blocks > 1) && (name[strlen(dev_name)] != '\0')) {
- const char * partition_type = detect_partition_type(name);
- parts[i] = strdup(name);
- comments[i] = (char *) malloc(sizeof(char) * 100);
- sprintf(comments[i], "size: %d Mbytes", blocks >> 10);
- if (partition_type) {
- strcat(comments[i], ", type: ");
- strcat(comments[i], partition_type);
- }
- i++;
+ 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++;
}
- parts[i] = NULL;
- fclose(f);
-
- return 0;
+ return RETURN_ERROR;
}
-static int try_mount(char * dev, char * location)
+static enum return_type try_automatic(char ** medias, char ** medias_models)
{
- char device_fullname[50];
- strcpy(device_fullname, "/dev/");
- strcat(device_fullname, dev);
-
- if (my_mount(device_fullname, location, "ext2", 0) == -1 &&
- my_mount(device_fullname, location, "vfat", 0) == -1 &&
- my_mount(device_fullname, location, "ntfs", 0) == -1 &&
- my_mount(device_fullname, location, "reiserfs", 0) == -1) {
- return 1;
- }
-
- return 0;
+ 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 RETURN_ERROR;
}
static enum return_type try_with_device(char *dev_name)
@@ -193,8 +125,6 @@ static enum return_type try_with_device(char *dev_name)
static char ** answers_location = NULL;
char location_full[500];
- char * disk_own_mount = IMAGE_LOCATION_DIR "hdimage";
-
char * parts[50];
char * parts_comments[50];
enum return_type results;
@@ -208,7 +138,7 @@ static enum return_type try_with_device(char *dev_name)
/* uglyness to allow auto starting with devfs */
if (!IS_AUTOMATIC || streq((choice = get_auto_value("partition")), "")) {
if (parts[0] == NULL) {
- stg1_error_message("No partitions found.");
+ stg1_error_message("No partition found.");
return RETURN_ERROR;
}
@@ -219,9 +149,10 @@ static enum return_type try_with_device(char *dev_name)
return results;
}
- /* in testing mode, assume the partition is already mounted on IMAGE_LOCATION_DIR "hdimage" */
- if (!IS_TESTING && try_mount(choice, disk_own_mount)) {
- stg1_error_message("I can't find a valid filesystem (tried: ext2, vfat, ntfs, reiserfs).");
+ /* 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);
}
@@ -229,18 +160,20 @@ static enum return_type try_with_device(char *dev_name)
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)) {
+ 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", dirname(answers_location[0]), extract_list_directory(dirname(location_full)));
+ "%s", my_dirname(path), extract_list_directory(my_dirname(location_full)));
+ free(path);
goto ask_dir;
}
@@ -249,42 +182,37 @@ static enum return_type try_with_device(char *dev_name)
goto ask_dir;
}
- if (IS_RESCUE)
- umount(disk_own_mount);
+ if (!KEEP_MOUNTED)
+ umount(MEDIA_LOCATION);
return RETURN_OK;
}
-static int get_disks(char *** names, char *** models)
-{
- char ** ptr;
- int count = 0;
-
- my_insmod("sd_mod", ANY_DRIVER_TYPE, NULL, 0);
-
- get_medias(DISK, names, models, BUS_ANY);
-
- ptr = *names;
- while (ptr && *ptr) {
- count++;
- ptr++;
- }
-
- return count;
-}
-
enum return_type disk_prepare(void)
{
char ** medias, ** medias_models;
char * choice;
int i;
enum return_type results;
+ static int already_probed_ide_generic = 0;
int count = get_disks(&medias, &medias_models);
+ if (IS_AUTOMATIC) {
+ results = try_automatic(medias, medias_models);
+ if (results != RETURN_ERROR)
+ return results;
+ unset_automatic();
+ }
+
if (count == 0) {
+ 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(SCSI_ADAPTERS);
+ i = ask_insmod(MEDIA_ADAPTERS);
if (i == RETURN_BACK)
return RETURN_BACK;
return disk_prepare();
@@ -294,7 +222,7 @@ enum return_type disk_prepare(void)
results = try_with_device(*medias);
if (results != RETURN_ERROR)
return results;
- i = ask_insmod(SCSI_ADAPTERS);
+ i = ask_insmod(MEDIA_ADAPTERS);
if (i == RETURN_BACK)
return RETURN_BACK;
return disk_prepare();
@@ -310,7 +238,7 @@ enum return_type disk_prepare(void)
results = try_with_device(choice);
if (results != RETURN_ERROR)
return results;
- i = ask_insmod(SCSI_ADAPTERS);
+ i = ask_insmod(MEDIA_ADAPTERS);
if (i == RETURN_BACK)
return RETURN_BACK;
return disk_prepare();