From 747375caa2fb534e2fab929e745054fcf53ef80a Mon Sep 17 00:00:00 2001 From: lukem Date: Sun, 24 Dec 2000 13:57:37 +0000 Subject: [PATCH] i got sick of the brain damage that mbrlabel used to do, and had gotten bitten by mbrlabel trashing my incore disklabel to a point where the machine wasn't usable, so I reworked it: * only update the incore (and on-disk) label if `-f' is given. by default, the proposed disklabel will be printed but no changes will occur * add -q, to make the default operation a bit more quiet. * leave existing `used' in-core partition slots alone, and only add entries to the incore label if: - there's not an existing partition of the same size and offset (even of a different type) - there's a free partition slot (`unused', with size == 0) * use DIOCWDINFO instead of DIOCSDINFO, to update the incore as well as the on-disk label * use showpartitions() from ../disklabel/printlabel.c this should make mbrlabel a *lot* more useful. --- sbin/mbrlabel/Makefile | 4 +- sbin/mbrlabel/mbrlabel.8 | 74 ++++++------ sbin/mbrlabel/mbrlabel.c | 252 +++++++++++++++++++++++++-------------- 3 files changed, 202 insertions(+), 128 deletions(-) diff --git a/sbin/mbrlabel/Makefile b/sbin/mbrlabel/Makefile index f10fcc1ba62b..a642d24c5578 100644 --- a/sbin/mbrlabel/Makefile +++ b/sbin/mbrlabel/Makefile @@ -1,8 +1,8 @@ -# $NetBSD: Makefile,v 1.2 2000/03/15 11:55:04 fvdl Exp $ +# $NetBSD: Makefile,v 1.3 2000/12/24 13:57:37 lukem Exp $ DISKLABELPATH= ${.CURDIR}/../../sbin/disklabel PROG= mbrlabel -SRCS= mbrlabel.c dkcksum.c +SRCS= mbrlabel.c dkcksum.c printlabel.c CPPFLAGS+= -I${DISKLABELPATH} MAN= mbrlabel.8 LDADD+= -lutil diff --git a/sbin/mbrlabel/mbrlabel.8 b/sbin/mbrlabel/mbrlabel.8 index 2b40f3ceadc0..c88ae652ea4b 100644 --- a/sbin/mbrlabel/mbrlabel.8 +++ b/sbin/mbrlabel/mbrlabel.8 @@ -27,63 +27,63 @@ .\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF .\" ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.\" $NetBSD: mbrlabel.8,v 1.5 2000/11/14 11:06:20 abs Exp $ +.\" $NetBSD: mbrlabel.8,v 1.6 2000/12/24 13:57:37 lukem Exp $ .\" -.Dd November 15, 1998 +.Dd December 24, 2000 .Dt MBRLABEL 8 .Os .Sh NAME .Nm mbrlabel -.Nd generate incore disklabel from MBR label(s) +.Nd generate incore disk label from MBR label(s) .Sh SYNOPSIS .Nm +.Op Fl fq .Ar device .Sh DESCRIPTION .Nm -is used to generate an incore disklabel from the MBR label(s) found +is used to update an incore +.Nx +disk label from the Master Boot Record (MBR) label(s) found on disks that were previously used on DOS/Windows systems (or other MBR using systems). .Pp -The .Nm -utility generates an incore label from the MBR contained in the very first -block of the disk, then walking through every extended partition found -and generating additional partition entries for the disk from the -MBRs found in those extended partitions. -The partitions are sequentially entered into the constructed disklabel -as partitions -.Em a , b -and so on until no more MBR partitions are found or all available -entries in the disklabel are used up. +scans the MBR contained in the very first block of the disk, +then walks through every extended partition found and generating +additional partition entries for the disk from the MBRs found in +those extended partitions. +.Pp +Each MBR partition which does not have an equivalent partition in incore +disk label (equivalent in having the same size and offset) is added to +the first free partition slot in the incore disk label. A free +partition slot is defined as one with an +.Dv fstype +of +.Sq Li unused +and a +.Dv size +of zero +.Pq Sq 0 . +If there are not enough free slots in the incore disk label, a warning +will be issued. +.Pp The raw partition (typically partition .Em c , but .Em d -on i386) is left alone during this process. -The resulting disklabel is then placed as the incore disklabel for -this disk. -.Sh BUGS -Due to the way disk drivers currently work in -.Nx , -any incore disklabel is forgotten whenever the last partition of a -disk is closed. -Since typically you wouldn't have a partition open on a disk while -running -.Nm -this lossage will most likely happen, if -.Nm -is used naively. +on i386 and some othe platforms) is left alone during this process. .Pp -The workaround until the disk drivers are fixed is to keep the -raw partition open until you access the partition(s) of the -disk via e.g. -.Xr mount 8 . +If +.Fl f +is given, then the incore disk label is updated. +Otherwise, the proposed changed disk label will be displayed and no +update will occur. .Pp -E.g. you could use -.Dl sleep 100 #ifndef lint -__RCSID("$NetBSD: mbrlabel.c,v 1.10 2000/12/24 01:54:20 wiz Exp $"); +__RCSID("$NetBSD: mbrlabel.c,v 1.11 2000/12/24 13:57:37 lukem Exp $"); #endif /* not lint */ #include @@ -44,20 +44,22 @@ __RCSID("$NetBSD: mbrlabel.c,v 1.10 2000/12/24 01:54:20 wiz Exp $"); #include #include +#define FSTYPENAMES #include #include #include #include "dkcksum.h" +#include "extern.h" #define FIRSTPART 0 -int main(int, char **); -void usage(void); -void getlabel(int); -void setlabel(int); -int getparts(int, int, u_int32_t, u_int32_t); -int nbsdtype(int); +int main(int, char **); +void usage(void); +void getlabel(int); +void setlabel(int); +int getparts(int, int, u_int32_t, u_int32_t, int); +int nbsdtype(int); u_int32_t getlong(void *p); struct disklabel label; @@ -65,15 +67,11 @@ struct disklabel label; void getlabel(int sd) { - struct partition save; if (ioctl(sd, DIOCGDINFO, &label) < 0) { perror("get label"); exit(1); } - save = label.d_partitions[RAW_PART]; - memset(label.d_partitions, 0, sizeof label.d_partitions); - label.d_partitions[RAW_PART] = save; /* * Some ports seem to not set the number of partitions * correctly, albeit they seem to set the raw partiton ok! @@ -85,9 +83,10 @@ getlabel(int sd) void setlabel(int sd) { + label.d_checksum = 0; label.d_checksum = dkcksum(&label); - if (ioctl(sd, DIOCSDINFO, &label) < 0) { + if (ioctl(sd, DIOCWDINFO, &label) < 0) { perror("set label"); exit(1); } @@ -97,16 +96,17 @@ static struct typetab { int mbrtype; int nbsdtype; } typetable[] = { - { MBR_PTYPE_NETBSD, FS_BSDFFS }, - { MBR_PTYPE_386BSD, FS_BSDFFS }, - { MBR_PTYPE_FAT12, FS_MSDOS }, - { MBR_PTYPE_FAT16S, FS_MSDOS }, - { MBR_PTYPE_FAT16B, FS_MSDOS }, - { MBR_PTYPE_FAT32, FS_MSDOS }, - { MBR_PTYPE_FAT32L, FS_MSDOS }, - { MBR_PTYPE_FAT16L, FS_MSDOS }, - { MBR_PTYPE_NTFS, FS_NTFS }, - { MBR_PTYPE_LNXEXT2, FS_EX2FS }, + { MBR_PTYPE_386BSD, FS_BSDFFS }, + { MBR_PTYPE_FAT12, FS_MSDOS }, + { MBR_PTYPE_FAT16B, FS_MSDOS }, + { MBR_PTYPE_FAT16L, FS_MSDOS }, + { MBR_PTYPE_FAT16S, FS_MSDOS }, + { MBR_PTYPE_FAT32, FS_MSDOS }, + { MBR_PTYPE_FAT32L, FS_MSDOS }, + { MBR_PTYPE_LNXEXT2, FS_EX2FS }, + { MBR_PTYPE_LNXSWAP, FS_SWAP }, + { MBR_PTYPE_NETBSD, FS_BSDFFS }, + { MBR_PTYPE_NTFS, FS_NTFS }, { 0, 0 } }; @@ -117,8 +117,8 @@ nbsdtype(int type) for (tt = typetable; tt->mbrtype; tt++) if (tt->mbrtype == type) - return tt->nbsdtype; - return FS_OTHER; + return (tt->nbsdtype); + return (FS_OTHER); } u_int32_t @@ -126,17 +126,19 @@ getlong(void *p) { unsigned char *cp = p; - return cp[0] | (cp[1] << 8) | (cp[2] << 16) | (cp[3] << 24); + return (cp[0] | (cp[1] << 8) | (cp[2] << 16) | (cp[3] << 24)); } int -getparts(int sd, int np, u_int32_t off, u_int32_t eoff) +getparts(int sd, int np, u_int32_t off, u_int32_t extoff, int verbose) { - unsigned char buf[DEV_BSIZE]; - struct mbr_partition parts[NMBRPART]; - off_t loff = 0; /* XXX this nonsense shuts up GCC 2.7.2.2 */ - int i; + unsigned char buf[DEV_BSIZE]; + struct mbr_partition parts[NMBRPART]; + struct partition npe; + off_t loff; + int i, j, unused, changed; + changed = 0; loff = (off_t)off * DEV_BSIZE; if (lseek(sd, loff, SEEK_SET) != loff) { @@ -148,91 +150,163 @@ getparts(int sd, int np, u_int32_t off, u_int32_t eoff) exit(1); } if (buf[0x1fe] != 0x55 || buf[0x1ff] != 0xaa) - return np; + return (changed); memcpy(parts, buf + MBR_PARTOFF, sizeof parts); + + /* scan partition table */ for (i = 0; i < NMBRPART; i++) { - switch (parts[i].mbrp_typ) { - case 0: - /* Nothing to do */ - break; - case MBR_PTYPE_EXT: - case MBR_PTYPE_EXT_LBA: - case MBR_PTYPE_EXT_LNX: - /* Will be handled below */ - break; - default: - label.d_partitions[np].p_size = getlong(&parts[i].mbrp_size); - label.d_partitions[np].p_offset = getlong(&parts[i].mbrp_start) + off; - label.d_partitions[np].p_fstype = nbsdtype(parts[i].mbrp_typ); - switch (label.d_partitions[np].p_fstype) { - case FS_BSDFFS: - label.d_partitions[np].p_size = 16384; - label.d_partitions[np].p_fsize = 1024; - label.d_partitions[np].p_frag = 8; - label.d_partitions[np].p_cpg = 16; - break; -#ifdef __does_not_happen__ - case FS_BSDLFS: - label.d_partitions[np].p_size = 16384; - label.d_partitions[np].p_fsize = 1024; - label.d_partitions[np].p_frag = 8; - label.d_partitions[np].p_sgs = XXX; - break; + if (parts[i].mbrp_typ == 0 || + /* extended partitions are handled below */ + MBR_IS_EXTENDED(parts[i].mbrp_typ)) + continue; + + memset((void *)&npe, 0, sizeof(npe)); + npe.p_size = getlong(&parts[i].mbrp_size); + npe.p_offset = getlong(&parts[i].mbrp_start) + off; + npe.p_fstype = nbsdtype(parts[i].mbrp_typ); + + /* find existing entry, or first free slot */ + unused = -1; /* flag as no free slot */ + if (verbose) + printf("Found %s partition at %d, size %d\n", + fstypenames[npe.p_fstype], npe.p_offset, + npe.p_size); + for (j = 0; j < label.d_npartitions; j++) { + struct partition *lpe; + + if (j == RAW_PART) + continue; + lpe = &label.d_partitions[j]; + if (lpe->p_size == npe.p_size && + lpe->p_offset == npe.p_offset +#ifdef notyet + && (lpe->p_fstype == npe.p_fstype || + lpe->p_fstype == FS_UNUSED) */ #endif + ) { + if (verbose) + printf( + " skipping existing %s partition at slot %c.\n", + fstypenames[lpe->p_fstype], + j + 'a'); + unused = -2; /* flag as existing */ + break; } - np++; - break; + if (unused == -1 && lpe->p_size == 0 && + lpe->p_fstype == FS_UNUSED) + unused = j; } - if (np >MAXPARTITIONS) - return np; - if (np == RAW_PART) - np++; + if (unused == -2) + continue; /* entry exists, skip... */ + if (unused == -1) { + if (label.d_npartitions < MAXPARTITIONS) { + unused = label.d_npartitions; + label.d_npartitions++; + } else { + printf( + " WARNING: no slots free for %s partition.\n", + fstypenames[npe.p_fstype]); + continue; + } + } + + if (verbose) + printf(" adding %s partition to slot %c.\n", + fstypenames[npe.p_fstype], unused + 'a'); + switch (npe.p_fstype) { + case FS_BSDFFS: + npe.p_size = 16384; /* XXX */ + npe.p_fsize = 1024; + npe.p_frag = 8; + npe.p_cpg = 16; + break; +#ifdef __does_not_happen__ + case FS_BSDLFS: + npe.p_size = 16384; /* XXX */ + npe.p_fsize = 1024; + npe.p_frag = 8; + npe.p_sgs = XXX; + break; +#endif + } + changed++; + label.d_partitions[unused] = npe; } + + /* recursively scan extended partitions */ for (i = 0; i < NMBRPART; i++) { u_int32_t poff; - switch (parts[i].mbrp_typ) { - case MBR_PTYPE_EXT: - case MBR_PTYPE_EXT_LBA: - case MBR_PTYPE_EXT_LNX: - poff = getlong(&parts[i].mbrp_start) + eoff; - np = getparts(sd, np, poff, eoff ? eoff : poff); - break; - default: - break; + if (MBR_IS_EXTENDED(parts[i].mbrp_typ)) { + poff = getlong(&parts[i].mbrp_start) + extoff; + changed += getparts(sd, np, poff, + extoff ? extoff : poff, verbose); } - if (np >MAXPARTITIONS) - return np; } - return np; + return (changed); } void usage(void) { - fprintf(stderr, "usage: mbrlabel rawdisk\n"); + extern char *__progname; + + fprintf(stderr, "usage: %s [-fq] rawdisk\n", __progname); exit(1); } + int main(int argc, char **argv) { - int sd; - int np; - char name[MAXPATHLEN]; + int sd, ch, changed; + char name[MAXPATHLEN]; + int force; /* force label update */ + int verbose; /* verbose output */ - if (argc != 2) + force = 0; + verbose = 1; + while ((ch = getopt(argc, argv, "fq")) != -1) { + switch (ch) { + case 'f': + force = 1; + break; + case 'q': + verbose = 0; + break; + default: + usage(); + } + } + argc -= optind; + argv += optind; + if (argc != 1) usage(); - if ((sd = opendisk(*++argv, O_RDWR, name, MAXPATHLEN, 0)) < 0) { - perror(*argv); + if ((sd = opendisk(argv[0], O_RDWR, name, MAXPATHLEN, 0)) < 0) { + perror(argv[0]); exit(1); } getlabel(sd); - np = getparts(sd, FIRSTPART, MBR_BBSECTOR, 0); - if (np > label.d_npartitions) - label.d_npartitions = np; - setlabel(sd); + changed = getparts(sd, FIRSTPART, MBR_BBSECTOR, 0, verbose); + + if (verbose) { + putchar('\n'); + if (0) showinfo(stdout, &label, name); + showpartitions(stdout, &label, 0); + putchar('\n'); + } + if (force) { + if (! changed) + printf("No change; not updating disk label.\n"); + else { + if (verbose) + printf("Updating disk label.\n"); + setlabel(sd); + } + } else { + printf("Not updating disk label.\n"); + } close(sd); - return 0; + return (0); }