diff --git a/usr.sbin/installboot/installboot.c b/usr.sbin/installboot/installboot.c index c4e6a7a0e..f3867a9c7 100644 --- a/usr.sbin/installboot/installboot.c +++ b/usr.sbin/installboot/installboot.c @@ -245,13 +245,13 @@ main(int argc, char *argv[]) mode = O_RDWR; } - if (minixfs3_is_minix_partition(params->filesystem)) { + if (minixfs3_is_minix_partition(params)) { /* Old setups has just 1 sector for bootblock, * but bootxx_minixfs is ~8Kb, so we require new setups * to have 32 sectors before the first subpartition. * This prevents from overwriting FS on old setups. */ - if (!minixfs3_has_bootblock_space(params->filesystem)) { + if (!minixfs3_has_bootblock_space(params)) { err(1, "No space for bootxx, you should have 32 sectors" " before the first subpartition on %s", params->filesystem); diff --git a/usr.sbin/installboot/installboot.h b/usr.sbin/installboot/installboot.h index c66fc2ec9..f12ec8e9b 100644 --- a/usr.sbin/installboot/installboot.h +++ b/usr.sbin/installboot/installboot.h @@ -166,8 +166,8 @@ void install_master(const char *device, char *masterboot, char **guide); int isoption(const char *option, const char *test); /* minixfs3.c */ -int minixfs3_is_minix_partition(const char* partition); -int minixfs3_has_bootblock_space(const char* partition); +int minixfs3_is_minix_partition(ib_params *params); +int minixfs3_has_bootblock_space(ib_params *params); /* machines.c */ @@ -178,9 +178,6 @@ extern struct ib_mach ib_mach_ews4800mips; extern struct ib_mach ib_mach_hp300; extern struct ib_mach ib_mach_hp700; extern struct ib_mach ib_mach_i386; -#ifdef __minix -extern struct ib_mach ib_mach_i386; -#endif extern struct ib_mach ib_mach_landisk; extern struct ib_mach ib_mach_macppc; extern struct ib_mach ib_mach_news68k; diff --git a/usr.sbin/installboot/minixfs3.c b/usr.sbin/installboot/minixfs3.c index 1951b89bf..8009e5a89 100644 --- a/usr.sbin/installboot/minixfs3.c +++ b/usr.sbin/installboot/minixfs3.c @@ -16,7 +16,14 @@ #define MFS_FIRST_SUBP_OFFSET 32 -static int minixfs3_read_mbr(const char* device, char* buf) +enum { + TYPE_BAD, + TYPE_PART, + TYPE_DISK +}; + +static int +minixfs3_read_mbr(const char* device, char* buf) { int fd; int bytes; @@ -56,30 +63,48 @@ static int minixfs3_read_mbr(const char* device, char* buf) return 0; } +static int +minixfs3_get_dev_type(const char *device, ib_params *params) +{ + int len, type; -int minixfs3_is_minix_partition(const char* partition) + /* + * Unless the -f flag is given, we expect to be provided with a primary + * partition. That is, a device name that ends with "pN", N being 0-3. + * If the -f flag is given, we assume that anything else is a whole + * disk. If we were given a subpartition, it will fail the subsequent + * MBR signature test, so we need not check this explicitly. + */ + len = strlen(device); + + if (len > 2 && device[len-2] == 'p' && + (unsigned) (device[len-1] - '0') <= 3) { + type = TYPE_PART; + } else { + type = TYPE_DISK; + } + + if (type != TYPE_PART && !(params->flags & IB_FORCE)) { + fprintf(stderr, "Wrong device %s, must be /.../cxdyp[0-3]\n", + device); + return TYPE_BAD; + } + + return type; +} + +int +minixfs3_is_minix_partition(ib_params *params) { char buf[DFL_SECSIZE]; /* part table + signature */ - int name_length = strlen(partition); - /* partition must be 0-3 */ - if (atol(&partition[name_length-1]) >= 4) { - fprintf(stderr, "Wrong device %s, must be /.../cxdyp[0-3]\n", - partition); + if (minixfs3_get_dev_type(params->filesystem, params) == TYPE_BAD) return 0; - } - - /* it should be partition device, not disk */ - if (partition[name_length-2] != 'p') { - fprintf(stderr, "Wrong device %s, must be /.../cxdyp[0-3]\n", - partition); - return 0; - } /* MINIX 3 partition with current scheme *must* have subpartitions, * thus MBR has signature. minixfs3_read_mbr checks the signature. */ - if (minixfs3_read_mbr(partition, buf)) + if (minixfs3_read_mbr(params->filesystem, buf)) return 0; return 1; } @@ -89,52 +114,55 @@ int minixfs3_is_minix_partition(const char* partition) * to install bootxx_minixfs3. New installation should have 16Kb before * the first subpartition. */ -int minixfs3_has_bootblock_space(const char* partition) +int +minixfs3_has_bootblock_space(ib_params *params) { + const char *device; char buf[DFL_SECSIZE]; /* part table + signature */ - char disk[NAME_MAX]; + char parent_name[NAME_MAX]; struct mbr_partition *part; uint32_t first_subpartition = (uint32_t) ~0; - uint32_t parent_partition = 0; - int i; - int name_length = strlen(partition); + uint32_t parent_partition; + int i, len, type = 0; - /* partition must be 0-3 */ - if (atol(&partition[name_length-1]) >= 4) { - fprintf(stderr, "Wrong device %s, must be /.../cxdyp[0-3]\n", - partition); - exit(1); - } - /* it should be partition device, not disk */ - if (partition[name_length-2] != 'p') { - fprintf(stderr, "Wrong device %s, must be /.../cxdyp[0-3]\n", - partition); - exit(1); - } + device = params->filesystem; - if (minixfs3_read_mbr(partition, buf)) + if ((type = minixfs3_get_dev_type(device, params)) == TYPE_BAD) + exit(1); + + if (minixfs3_read_mbr(device, buf)) exit(1); part = (struct mbr_partition *) buf; for (i = 0; i < 4; i++) { - if (part[i].mbrp_size && part[i].mbrp_start < first_subpartition) + if (part[i].mbrp_size && + part[i].mbrp_start < first_subpartition) first_subpartition = part[i].mbrp_start; } - strncpy(disk, partition, name_length - 2); - disk[name_length - 2] = '\0'; + if (type == TYPE_PART) { + /* The target is a partition. Look up its starting offset. */ + len = strlen(device); + strncpy(parent_name, device, len - 2); + parent_name[len - 2] = '\0'; - if (minixfs3_read_mbr(disk, buf)) - exit(1); + if (minixfs3_read_mbr(parent_name, buf)) + exit(1); - for (i = 0; i < 4; i++) { - struct mbr_partition *p = &part[i]; - if (p->mbrp_size && p->mbrp_start <= first_subpartition - && (p->mbrp_start + p->mbrp_size) > first_subpartition) { - parent_partition = p->mbrp_start; - break; + parent_partition = 0; + for (i = 0; i < 4; i++) { + struct mbr_partition *p = &part[i]; + if (p->mbrp_size && p->mbrp_start <= first_subpartition + && (p->mbrp_start + p->mbrp_size) > + first_subpartition) { + parent_partition = p->mbrp_start; + break; + } } + } else { + /* The target is a whole disk. The starting offset is 0. */ + parent_partition = 0; } if ((first_subpartition - parent_partition) < MFS_FIRST_SUBP_OFFSET)