diff options
author | jake <jake@FreeBSD.org> | 2003-04-15 23:46:19 +0000 |
---|---|---|
committer | jake <jake@FreeBSD.org> | 2003-04-15 23:46:19 +0000 |
commit | 2d089db7c2761e4d82397bf1d6ea627161ce201e (patch) | |
tree | 0bdc242f4f395a903ce5a568168b2ca922125b5f /sbin/sunlabel | |
parent | 89e06191dd10c7ac4039f086ceb7233ac1f3b442 (diff) | |
download | FreeBSD-src-2d089db7c2761e4d82397bf1d6ea627161ce201e.zip FreeBSD-src-2d089db7c2761e4d82397bf1d6ea627161ce201e.tar.gz |
- Use read(2) to get the existing sunlabel on a disk, instead of parsing
kern.geom.conftxt, which md disks don't show up in. If the magic and
the checksum are right assume its a valid sunlabel, otherwise use the
DIOC ioctls to get the disk parameters and whip up a label out of thin
air.
- Don't just silently create or correct invalid c partitions, warn about
invalid ones in label proto files.
- Split checksumming into a function since we do it a couple times. Also
don't include the sl_cksum field in the checksum, which avoids needing
to clear it first.
This is makes sunlabel a suitable replacement for disklabel in make release.
Diffstat (limited to 'sbin/sunlabel')
-rw-r--r-- | sbin/sunlabel/sunlabel.c | 158 |
1 files changed, 81 insertions, 77 deletions
diff --git a/sbin/sunlabel/sunlabel.c b/sbin/sunlabel/sunlabel.c index 06aab9b..99a2620 100644 --- a/sbin/sunlabel/sunlabel.c +++ b/sbin/sunlabel/sunlabel.c @@ -70,7 +70,8 @@ __FBSDID("$FreeBSD$"); #include <sys/types.h> #include <sys/param.h> -#include <sys/sysctl.h> +#include <sys/disk.h> +#include <sys/ioctl.h> #include <sys/sun_disklabel.h> #include <sys/wait.h> @@ -103,6 +104,8 @@ static int edit_label(struct sun_disklabel *sl, const char *disk, static int parse_label(struct sun_disklabel *sl, const char *file); static void print_label(struct sun_disklabel *sl, const char *disk, FILE *out); +static uint16_t checksum(struct sun_disklabel *sl); + static int parse_size(struct sun_disklabel *sl, int part, char *size); static int parse_offset(struct sun_disklabel *sl, int part, char *offset); @@ -185,6 +188,8 @@ main(int ac, char **av) usage(); proto = av[1]; read_label(&sl, disk); + if (parse_label(&sl, proto) != 0) + errx(1, "%s: invalid label", proto); write_label(&sl, disk, bootpath); } else if (Bflag) { read_label(&sl, disk); @@ -212,6 +217,12 @@ check_label(struct sun_disklabel *sl) int j; nsectors = sl->sl_ncylinders * sl->sl_ntracks * sl->sl_nsectors; + if (sl->sl_part[2].sdkp_cyloffset != 0 || + sl->sl_part[2].sdkp_nsectors != nsectors) { + warnx("partition c is incorrect, must start at 0 and cover " + "whole disk"); + return (1); + } for (i = 0; i < 8; i++) { if (i == 2 || sl->sl_part[i].sdkp_nsectors == 0) continue; @@ -245,72 +256,62 @@ check_label(struct sun_disklabel *sl) static void read_label(struct sun_disklabel *sl, const char *disk) { - uint32_t bytepercyl; - uint32_t bytepersec; - uint32_t acylinders; - uint32_t nsectors; - uint32_t ntracks; - uintmax_t offset; - uintmax_t size; - char name[64]; - char *text; - char *p, *s; - size_t len; - int i; - int n; - - if (sysctlbyname("kern.geom.conftxt", NULL, &len, NULL, 0) < 0) - err(1, "sysctlbyname"); - if ((text = malloc(len)) == NULL) - err(1, "malloc"); - if (sysctlbyname("kern.geom.conftxt", text, &len, NULL, 0) < 0) - err(1, "sysctlbyname"); - bytepercyl = 0; - for (p = text; (s = strsep(&p, "\n")) != NULL;) { - n = sscanf(s, "%*u DISK %s %ju %u hd %u sc %u\n", name, &size, - &bytepersec, &ntracks, &nsectors); - if (n == 5) { - if (strncmp(name, disk, strlen(disk)) != 0) - continue; - bytepercyl = ntracks * nsectors * bytepersec; - sl->sl_pcylinders = size / bytepercyl; - sl->sl_acylinders = 2; - sl->sl_nsectors = nsectors; - sl->sl_ntracks = ntracks; - continue; + char path[MAXPATHLEN]; + uint32_t sectorsize; + uint32_t fwsectors; + uint32_t fwheads; + off_t mediasize; + int fd; + + snprintf(path, sizeof(path), "%s%s", _PATH_DEV, disk); + if ((fd = open(path, O_RDONLY)) < 0) + err(1, "open %s", path); + if (read(fd, sl, sizeof(*sl)) != sizeof(*sl)) + err(1, "read"); + if (sl->sl_magic != SUN_DKMAGIC || checksum(sl) != sl->sl_cksum) { + bzero(sl, sizeof(*sl)); + if (ioctl(fd, DIOCGMEDIASIZE, &mediasize) != 0) + err(1, "%s: ioctl(DIOCGMEDIASIZE) failed", disk); + if (ioctl(fd, DIOCGSECTORSIZE, §orsize) != 0) + err(1, "%s: DIOCGSECTORSIZE failed", disk); + if (ioctl(fd, DIOCGFWSECTORS, &fwsectors) != 0) + fwsectors = 63; + if (ioctl(fd, DIOCGFWHEADS, &fwheads) != 0) { + if (mediasize <= 63 * 1024 * sectorsize) + fwheads = 1; + else if (mediasize <= 63 * 16 * 1024 * sectorsize) + fwheads = 16; + else + fwheads = 255; } - n = sscanf(s, - "%*u SUN %s %ju %*u i %u o %ju sc %*u hd %*u alt %u", - name, &size, &i, &offset, &acylinders); - if (n == 5) { - if (strncmp(name, disk, strlen(disk)) != 0) - continue; - sl->sl_acylinders = acylinders; - sl->sl_part[i].sdkp_cyloffset = offset / bytepercyl; - sl->sl_part[i].sdkp_nsectors = size / bytepersec; - sl->sl_magic = SUN_DKMAGIC; - continue; + sl->sl_rpm = 3600; + sl->sl_pcylinders = mediasize / (fwsectors * fwheads * + sectorsize); + sl->sl_sparespercyl = 0; + sl->sl_interleave = 1; + sl->sl_ncylinders = sl->sl_pcylinders - 2; + sl->sl_acylinders = 2; + sl->sl_nsectors = fwsectors; + sl->sl_ntracks = fwheads; + sl->sl_part[2].sdkp_cyloffset = 0; + sl->sl_part[2].sdkp_nsectors = sl->sl_ncylinders * + sl->sl_ntracks * sl->sl_nsectors; + if (mediasize > 4999L * 1024L * 1024L) { + sprintf(sl->sl_text, + "FreeBSD%luG cyl %u alt %u hd %u sec %u", + (mediasize + 512 * 1024 * 1024) / + (1024 * 1024 * 1024), + sl->sl_ncylinders, sl->sl_acylinders, + sl->sl_ntracks, sl->sl_nsectors); + } else { + sprintf(sl->sl_text, + "FreeBSD%luM cyl %u alt %u hd %u sec %u", + (mediasize + 512 * 1024) / (1024 * 1024), + sl->sl_ncylinders, sl->sl_acylinders, + sl->sl_ntracks, sl->sl_nsectors); } } - if (bytepercyl == 0) - errx(1, "disk %s not found", disk); - sl->sl_ncylinders = sl->sl_pcylinders - - sl->sl_acylinders; - sl->sl_interleave = 1; - sl->sl_sparespercyl = 0; - sl->sl_rpm = 3600; - size = (uint64_t)sl->sl_ncylinders * sl->sl_ntracks * sl->sl_nsectors; - if (size > 4999 * 1024 * 2) { - sprintf(sl->sl_text, "FreeBSD%luG cyl %u alt %u hd %u sec %u", - (size + 1024 * 1024) / (2 * 1024 * 1024), - sl->sl_ncylinders, sl->sl_acylinders, - sl->sl_ntracks, sl->sl_nsectors); - } else { - sprintf(sl->sl_text, "FreeBSD%luM cyl %u alt %u hd %u sec %u", - (size + 1024) / (2 * 1024), - sl->sl_ncylinders, sl->sl_acylinders, - sl->sl_ntracks, sl->sl_nsectors); - } + close(fd); } static void @@ -318,22 +319,13 @@ write_label(struct sun_disklabel *sl, const char *disk, const char *bootpath) { char path[MAXPATHLEN]; char boot[16 * 512]; - uint16_t cksum; - uint16_t *sp1; - uint16_t *sp2; off_t off; int bfd; int fd; int i; sl->sl_magic = SUN_DKMAGIC; - - sp1 = (u_short *)sl; - sp2 = (u_short *)(sl + 1); - cksum = 0; - while (sp1 < sp2) - cksum ^= *sp1++; - sl->sl_cksum = cksum; + sl->sl_cksum = checksum(sl); if (check_label(sl) != 0) errx(1, "invalid label"); @@ -452,9 +444,6 @@ parse_label(struct sun_disklabel *sl, const char *file) line++; } fclose(fp); - sl->sl_part[2].sdkp_cyloffset = 0; - sl->sl_part[2].sdkp_nsectors = sl->sl_ncylinders * - sl->sl_ntracks * sl->sl_nsectors; return (check_label(sl)); } @@ -495,6 +484,21 @@ parse_size(struct sun_disklabel *sl, int part, char *size) return (0); } +static uint16_t +checksum(struct sun_disklabel *sl) +{ + uint16_t cksum; + uint16_t *sp1; + uint16_t *sp2; + + sp1 = (u_short *)sl; + sp2 = (u_short *)(sl + 1) - 1; + cksum = 0; + while (sp1 < sp2) + cksum ^= *sp1++; + return (cksum); +} + static int parse_offset(struct sun_disklabel *sl, int part, char *offset) { |