diff options
Diffstat (limited to 'mdk-stage1')
-rw-r--r-- | mdk-stage1/disk.c | 103 | ||||
-rw-r--r-- | mdk-stage1/mount.c | 2 | ||||
-rw-r--r-- | mdk-stage1/mount.h | 4 | ||||
-rw-r--r-- | mdk-stage1/stage1.c | 2 |
4 files changed, 107 insertions, 4 deletions
diff --git a/mdk-stage1/disk.c b/mdk-stage1/disk.c index ec9e1a97f..515b95395 100644 --- a/mdk-stage1/disk.c +++ b/mdk-stage1/disk.c @@ -37,6 +37,100 @@ #include "disk.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]; + int 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 } }, + { "Linux Swap", { 4086, "SWAPSPACE2" }, { 0, NULL } }, + { "Ext2", { 0x438, "\x53\xEF" }, { 0, NULL } }, + { "ReiserFS", { 0x10034, "ReIsErFs" }, { 0, NULL } }, + { "ReiserFS", { 0x10034, "ReIsEr2Fs" }, { 0, NULL } }, + { "XFS", { 0, "XFSB" }, { 0x200, "XAGF" }, { 0x400, "XAGI" } }, + { "JFS", { 0x8000, "JFS1" }, { 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; + + 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); + + if ((fd = open(device_fullname, O_RDONLY, 0)) < 0) { + log_perror("open"); + return NULL; + } + + 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: + return partitions_signatures[i].name; + } + + detect_partition_type_end: + close(fd); + return NULL; +} + static char * disk_extract_list_directory(char * direct) { char ** full = list_directory(direct); @@ -84,9 +178,14 @@ static enum return_type try_with_device(char *dev_name) bzero(name, 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); - parts_comments[i] = (char *) malloc(sizeof(char) * 25); - snprintf(parts_comments[i], 24, "size: %d Mbytes", blocks >> 10); + parts_comments[i] = (char *) malloc(sizeof(char) * 100); + sprintf(parts_comments[i], "size: %d Mbytes", blocks >> 10); + if (partition_type) { + strcat(parts_comments[i], ", type: "); + strcat(parts_comments[i], partition_type); + } i++; } } diff --git a/mdk-stage1/mount.c b/mdk-stage1/mount.c index b41604cfe..257638421 100644 --- a/mdk-stage1/mount.c +++ b/mdk-stage1/mount.c @@ -34,7 +34,7 @@ #ifndef DISABLE_MEDIAS /* WARNING: this won't work if the argument is not /dev/ based */ -static int ensure_dev_exists(char *dev) +int ensure_dev_exists(char *dev) { int major, minor; int type = S_IFBLK; /* my default type is block. don't forget to change for chars */ diff --git a/mdk-stage1/mount.h b/mdk-stage1/mount.h index 992796bde..82795462f 100644 --- a/mdk-stage1/mount.h +++ b/mdk-stage1/mount.h @@ -28,4 +28,8 @@ int my_mount(char *dev, char *location, char *fs, int force_rw); +#ifndef DISABLE_MEDIAS +int ensure_dev_exists(char *dev); +#endif + #endif diff --git a/mdk-stage1/stage1.c b/mdk-stage1/stage1.c index b8c6914ce..de9bffd2f 100644 --- a/mdk-stage1/stage1.c +++ b/mdk-stage1/stage1.c @@ -324,7 +324,7 @@ static enum return_type method_select_and_prepare(void) results = ask_from_list_auto("Please choose the installation method.", means, &choice, "method", means_auto); if (results != RETURN_OK) - return method_select_and_prepare(); + return method_select_and_prepare(); results = RETURN_ERROR; |