sunlabel.c revision 113538
1110130Sjake/*- 2110130Sjake * Copyright (c) 2003 Jake Burkholder. 3110130Sjake * All rights reserved. 4110130Sjake * 5110130Sjake * Redistribution and use in source and binary forms, with or without 6110130Sjake * modification, are permitted provided that the following conditions 7110130Sjake * are met: 8110130Sjake * 1. Redistributions of source code must retain the above copyright 9110130Sjake * notice, this list of conditions and the following disclaimer. 10110130Sjake * 2. Redistributions in binary form must reproduce the above copyright 11110130Sjake * notice, this list of conditions and the following disclaimer in the 12110130Sjake * documentation and/or other materials provided with the distribution. 13110130Sjake * 14110130Sjake * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15110130Sjake * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16110130Sjake * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17110130Sjake * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18110130Sjake * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19110130Sjake * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20110130Sjake * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21110130Sjake * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22110130Sjake * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23110130Sjake * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24110130Sjake * SUCH DAMAGE. 25110130Sjake */ 26110130Sjake/* 27110130Sjake * Copyright (c) 1994, 1995 Gordon W. Ross 28110130Sjake * Copyright (c) 1994 Theo de Raadt 29110130Sjake * All rights reserved. 30110130Sjake * Copyright (c) 1987, 1993 31110130Sjake * The Regents of the University of California. All rights reserved. 32110130Sjake * 33110130Sjake * This code is derived from software contributed to Berkeley by 34110130Sjake * Symmetric Computer Systems. 35110130Sjake * 36110130Sjake * Redistribution and use in source and binary forms, with or without 37110130Sjake * modification, are permitted provided that the following conditions 38110130Sjake * are met: 39110130Sjake * 1. Redistributions of source code must retain the above copyright 40110130Sjake * notice, this list of conditions and the following disclaimer. 41110130Sjake * 2. Redistributions in binary form must reproduce the above copyright 42110130Sjake * notice, this list of conditions and the following disclaimer in the 43110130Sjake * documentation and/or other materials provided with the distribution. 44110130Sjake * 3. All advertising materials mentioning features or use of this software 45110130Sjake * must display the following acknowledgement: 46110130Sjake * This product includes software developed by the University of 47110130Sjake * California, Berkeley and its contributors. 48110130Sjake * This product includes software developed by Theo de Raadt. 49110130Sjake * 4. Neither the name of the University nor the names of its contributors 50110130Sjake * may be used to endorse or promote products derived from this software 51110130Sjake * without specific prior written permission. 52110130Sjake * 53110130Sjake * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 54110130Sjake * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 55110130Sjake * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 56110130Sjake * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 57110130Sjake * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 58110130Sjake * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 59110130Sjake * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 60110130Sjake * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 61110130Sjake * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 62110130Sjake * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 63110130Sjake * SUCH DAMAGE. 64110130Sjake * 65110130Sjake * from: $NetBSD: disksubr.c,v 1.13 2000/12/17 22:39:18 pk $ 66110130Sjake */ 67110130Sjake 68110130Sjake#include <sys/cdefs.h> 69110130Sjake__FBSDID("$FreeBSD: head/sbin/sunlabel/sunlabel.c 113538 2003-04-15 23:46:19Z jake $"); 70110130Sjake 71110130Sjake#include <sys/types.h> 72110130Sjake#include <sys/param.h> 73113538Sjake#include <sys/disk.h> 74113538Sjake#include <sys/ioctl.h> 75110130Sjake#include <sys/sun_disklabel.h> 76110130Sjake#include <sys/wait.h> 77110130Sjake 78110130Sjake#include <err.h> 79110130Sjake#include <fcntl.h> 80110130Sjake#include <inttypes.h> 81110130Sjake#include <paths.h> 82110130Sjake#include <stdio.h> 83110130Sjake#include <stdlib.h> 84110130Sjake#include <string.h> 85110130Sjake#include <unistd.h> 86110130Sjake 87110130Sjake#define _PATH_TMPFILE "/tmp/EdDk.XXXXXXXXXX" 88110130Sjake#define _PATH_BOOT "/boot/boot1" 89110130Sjake 90110130Sjakestatic int bflag; 91110130Sjakestatic int Bflag; 92110130Sjakestatic int eflag; 93110130Sjakestatic int nflag; 94110130Sjakestatic int rflag = 1; 95110130Sjakestatic int Rflag; 96110130Sjakestatic int wflag; 97110130Sjake 98110130Sjakestatic int check_label(struct sun_disklabel *sl); 99110130Sjakestatic void read_label(struct sun_disklabel *sl, const char *disk); 100110130Sjakestatic void write_label(struct sun_disklabel *sl, const char *disk, 101110130Sjake const char *bootpath); 102110130Sjakestatic int edit_label(struct sun_disklabel *sl, const char *disk, 103110130Sjake const char *bootpath); 104110130Sjakestatic int parse_label(struct sun_disklabel *sl, const char *file); 105110130Sjakestatic void print_label(struct sun_disklabel *sl, const char *disk, FILE *out); 106110130Sjake 107113538Sjakestatic uint16_t checksum(struct sun_disklabel *sl); 108113538Sjake 109110130Sjakestatic int parse_size(struct sun_disklabel *sl, int part, char *size); 110110130Sjakestatic int parse_offset(struct sun_disklabel *sl, int part, char *offset); 111110130Sjake 112110130Sjakestatic void usage(void); 113110130Sjake 114110130Sjakeextern char *__progname; 115110130Sjake 116110130Sjake/* 117110130Sjake * Disk label editor for sun disklabels. 118110130Sjake */ 119110130Sjakeint 120110130Sjakemain(int ac, char **av) 121110130Sjake{ 122110130Sjake struct sun_disklabel sl; 123110130Sjake const char *bootpath; 124110130Sjake const char *proto; 125110130Sjake const char *disk; 126110130Sjake int ch; 127110130Sjake 128110130Sjake bootpath = _PATH_BOOT; 129110130Sjake while ((ch = getopt(ac, av, "b:BenrRw")) != -1) 130110130Sjake switch (ch) { 131110130Sjake case 'b': 132110130Sjake bflag = 1; 133110130Sjake bootpath = optarg; 134110130Sjake break; 135110130Sjake case 'B': 136110130Sjake Bflag = 1; 137110130Sjake break; 138110130Sjake case 'e': 139110130Sjake eflag = 1; 140110130Sjake break; 141110130Sjake case 'n': 142110130Sjake nflag = 1; 143110130Sjake break; 144110130Sjake case 'r': 145110130Sjake rflag = 1; 146110130Sjake break; 147110130Sjake case 'R': 148110130Sjake Rflag = 1; 149110130Sjake break; 150110130Sjake case 'w': 151110130Sjake wflag = 1; 152110130Sjake break; 153110130Sjake default: 154110130Sjake usage(); 155110130Sjake break; 156110130Sjake } 157110130Sjake if (bflag && !Bflag) 158110130Sjake usage(); 159110130Sjake if (nflag && !(Bflag || eflag || Rflag || wflag)) 160110130Sjake usage(); 161110130Sjake if (eflag && (Rflag || wflag)) 162110130Sjake usage(); 163110130Sjake ac -= optind; 164110130Sjake av += optind; 165110130Sjake if (ac == 0) 166110130Sjake usage(); 167110130Sjake bzero(&sl, sizeof(sl)); 168110130Sjake disk = av[0]; 169110130Sjake if (wflag) { 170110130Sjake if (ac != 2 || strcmp(av[1], "auto") != 0) 171110130Sjake usage(); 172110130Sjake read_label(&sl, disk); 173110130Sjake bzero(sl.sl_part, sizeof(sl.sl_part)); 174110130Sjake sl.sl_part[2].sdkp_cyloffset = 0; 175110130Sjake sl.sl_part[2].sdkp_nsectors = sl.sl_ncylinders * 176110130Sjake sl.sl_ntracks * sl.sl_nsectors; 177110130Sjake write_label(&sl, disk, bootpath); 178110130Sjake } else if (eflag) { 179110130Sjake if (ac != 1) 180110130Sjake usage(); 181110130Sjake read_label(&sl, disk); 182110130Sjake if (sl.sl_magic != SUN_DKMAGIC) 183110130Sjake errx(1, "%s%s has no sun disklabel", _PATH_DEV, disk); 184110130Sjake while (edit_label(&sl, disk, bootpath) != 0) 185110130Sjake ; 186110130Sjake } else if (Rflag) { 187110130Sjake if (ac != 2) 188110130Sjake usage(); 189110130Sjake proto = av[1]; 190110130Sjake read_label(&sl, disk); 191113538Sjake if (parse_label(&sl, proto) != 0) 192113538Sjake errx(1, "%s: invalid label", proto); 193110130Sjake write_label(&sl, disk, bootpath); 194110130Sjake } else if (Bflag) { 195110130Sjake read_label(&sl, disk); 196110130Sjake if (sl.sl_magic != SUN_DKMAGIC) 197110130Sjake errx(1, "%s%s has no sun disklabel", _PATH_DEV, disk); 198110130Sjake write_label(&sl, disk, bootpath); 199110130Sjake } else { 200110130Sjake read_label(&sl, disk); 201110130Sjake if (sl.sl_magic != SUN_DKMAGIC) 202110130Sjake errx(1, "%s%s has no sun disklabel", _PATH_DEV, disk); 203110130Sjake print_label(&sl, disk, stdout); 204110130Sjake } 205110130Sjake return (0); 206110130Sjake} 207110130Sjake 208110130Sjakestatic int 209110130Sjakecheck_label(struct sun_disklabel *sl) 210110130Sjake{ 211110130Sjake uint64_t nsectors; 212110130Sjake uint64_t ostart; 213110130Sjake uint64_t start; 214110130Sjake uint64_t oend; 215110130Sjake uint64_t end; 216110130Sjake int i; 217110130Sjake int j; 218110130Sjake 219110130Sjake nsectors = sl->sl_ncylinders * sl->sl_ntracks * sl->sl_nsectors; 220113538Sjake if (sl->sl_part[2].sdkp_cyloffset != 0 || 221113538Sjake sl->sl_part[2].sdkp_nsectors != nsectors) { 222113538Sjake warnx("partition c is incorrect, must start at 0 and cover " 223113538Sjake "whole disk"); 224113538Sjake return (1); 225113538Sjake } 226110130Sjake for (i = 0; i < 8; i++) { 227110130Sjake if (i == 2 || sl->sl_part[i].sdkp_nsectors == 0) 228110130Sjake continue; 229110130Sjake start = (uint64_t)sl->sl_part[i].sdkp_cyloffset * 230110130Sjake sl->sl_ntracks * sl->sl_nsectors; 231110130Sjake end = start + sl->sl_part[i].sdkp_nsectors; 232110130Sjake if (end > nsectors) { 233110130Sjake warnx("partition %c extends past end of disk", 234110130Sjake 'a' + i); 235110130Sjake return (1); 236110130Sjake } 237110130Sjake for (j = 0; j < 8; j++) { 238110130Sjake if (j == 2 || j == i || 239110130Sjake sl->sl_part[j].sdkp_nsectors == 0) 240110130Sjake continue; 241110130Sjake ostart = (uint64_t)sl->sl_part[j].sdkp_cyloffset * 242110130Sjake sl->sl_ntracks * sl->sl_nsectors; 243110130Sjake oend = ostart + sl->sl_part[j].sdkp_nsectors; 244110130Sjake if ((start <= ostart && end >= oend) || 245110130Sjake (start > ostart && start < oend) || 246110130Sjake (end > ostart && end < oend)) { 247110130Sjake warnx("partition %c overlaps partition %c", 248110130Sjake 'a' + i, 'a' + j); 249110130Sjake return (1); 250110130Sjake } 251110130Sjake } 252110130Sjake } 253110130Sjake return (0); 254110130Sjake} 255110130Sjake 256110130Sjakestatic void 257110130Sjakeread_label(struct sun_disklabel *sl, const char *disk) 258110130Sjake{ 259113538Sjake char path[MAXPATHLEN]; 260113538Sjake uint32_t sectorsize; 261113538Sjake uint32_t fwsectors; 262113538Sjake uint32_t fwheads; 263113538Sjake off_t mediasize; 264113538Sjake int fd; 265110130Sjake 266113538Sjake snprintf(path, sizeof(path), "%s%s", _PATH_DEV, disk); 267113538Sjake if ((fd = open(path, O_RDONLY)) < 0) 268113538Sjake err(1, "open %s", path); 269113538Sjake if (read(fd, sl, sizeof(*sl)) != sizeof(*sl)) 270113538Sjake err(1, "read"); 271113538Sjake if (sl->sl_magic != SUN_DKMAGIC || checksum(sl) != sl->sl_cksum) { 272113538Sjake bzero(sl, sizeof(*sl)); 273113538Sjake if (ioctl(fd, DIOCGMEDIASIZE, &mediasize) != 0) 274113538Sjake err(1, "%s: ioctl(DIOCGMEDIASIZE) failed", disk); 275113538Sjake if (ioctl(fd, DIOCGSECTORSIZE, §orsize) != 0) 276113538Sjake err(1, "%s: DIOCGSECTORSIZE failed", disk); 277113538Sjake if (ioctl(fd, DIOCGFWSECTORS, &fwsectors) != 0) 278113538Sjake fwsectors = 63; 279113538Sjake if (ioctl(fd, DIOCGFWHEADS, &fwheads) != 0) { 280113538Sjake if (mediasize <= 63 * 1024 * sectorsize) 281113538Sjake fwheads = 1; 282113538Sjake else if (mediasize <= 63 * 16 * 1024 * sectorsize) 283113538Sjake fwheads = 16; 284113538Sjake else 285113538Sjake fwheads = 255; 286110130Sjake } 287113538Sjake sl->sl_rpm = 3600; 288113538Sjake sl->sl_pcylinders = mediasize / (fwsectors * fwheads * 289113538Sjake sectorsize); 290113538Sjake sl->sl_sparespercyl = 0; 291113538Sjake sl->sl_interleave = 1; 292113538Sjake sl->sl_ncylinders = sl->sl_pcylinders - 2; 293113538Sjake sl->sl_acylinders = 2; 294113538Sjake sl->sl_nsectors = fwsectors; 295113538Sjake sl->sl_ntracks = fwheads; 296113538Sjake sl->sl_part[2].sdkp_cyloffset = 0; 297113538Sjake sl->sl_part[2].sdkp_nsectors = sl->sl_ncylinders * 298113538Sjake sl->sl_ntracks * sl->sl_nsectors; 299113538Sjake if (mediasize > 4999L * 1024L * 1024L) { 300113538Sjake sprintf(sl->sl_text, 301113538Sjake "FreeBSD%luG cyl %u alt %u hd %u sec %u", 302113538Sjake (mediasize + 512 * 1024 * 1024) / 303113538Sjake (1024 * 1024 * 1024), 304113538Sjake sl->sl_ncylinders, sl->sl_acylinders, 305113538Sjake sl->sl_ntracks, sl->sl_nsectors); 306113538Sjake } else { 307113538Sjake sprintf(sl->sl_text, 308113538Sjake "FreeBSD%luM cyl %u alt %u hd %u sec %u", 309113538Sjake (mediasize + 512 * 1024) / (1024 * 1024), 310113538Sjake sl->sl_ncylinders, sl->sl_acylinders, 311113538Sjake sl->sl_ntracks, sl->sl_nsectors); 312110130Sjake } 313110130Sjake } 314113538Sjake close(fd); 315110130Sjake} 316110130Sjake 317110130Sjakestatic void 318110130Sjakewrite_label(struct sun_disklabel *sl, const char *disk, const char *bootpath) 319110130Sjake{ 320110130Sjake char path[MAXPATHLEN]; 321110130Sjake char boot[16 * 512]; 322110130Sjake off_t off; 323110130Sjake int bfd; 324110130Sjake int fd; 325110130Sjake int i; 326110130Sjake 327110130Sjake sl->sl_magic = SUN_DKMAGIC; 328113538Sjake sl->sl_cksum = checksum(sl); 329110130Sjake 330110130Sjake if (check_label(sl) != 0) 331110130Sjake errx(1, "invalid label"); 332110130Sjake 333110130Sjake if (nflag) { 334110130Sjake print_label(sl, disk, stdout); 335110130Sjake } else if (rflag) { 336110130Sjake snprintf(path, sizeof(path), "%s%s", _PATH_DEV, disk); 337110130Sjake if ((fd = open(path, O_RDWR)) < 0) 338110130Sjake err(1, "open %s", path); 339110130Sjake if (Bflag) { 340110130Sjake if ((bfd = open(bootpath, O_RDONLY)) < 0) 341110130Sjake err(1, "open %s", bootpath); 342110130Sjake if (read(bfd, boot, sizeof(boot)) != sizeof(boot)) 343110130Sjake err(1, "read"); 344110130Sjake close(bfd); 345110130Sjake for (i = 0; i < 8; i++) { 346110130Sjake if (sl->sl_part[i].sdkp_nsectors == 0) 347110130Sjake continue; 348110130Sjake off = sl->sl_part[i].sdkp_cyloffset * 349110130Sjake sl->sl_ntracks * sl->sl_nsectors * 512; 350110130Sjake if (lseek(fd, off, SEEK_SET) < 0) 351110130Sjake err(1, "lseek"); 352110130Sjake if (write(fd, boot, sizeof(boot)) != 353110130Sjake sizeof(boot)) 354110130Sjake err(1, "write"); 355110130Sjake } 356110130Sjake } 357110130Sjake if (lseek(fd, 0, SEEK_SET) < 0) 358110130Sjake err(1, "lseek"); 359110130Sjake if (write(fd, sl, sizeof(*sl)) != sizeof(*sl)) 360110130Sjake err(1, "write"); 361110130Sjake close(fd); 362110130Sjake } else 363110130Sjake err(1, "implement!"); 364110130Sjake} 365110130Sjake 366110130Sjakestatic int 367110130Sjakeedit_label(struct sun_disklabel *sl, const char *disk, const char *bootpath) 368110130Sjake{ 369110130Sjake char tmpfil[] = _PATH_TMPFILE; 370110130Sjake const char *editor; 371110130Sjake int status; 372110130Sjake FILE *fp; 373110130Sjake pid_t pid; 374110130Sjake pid_t r; 375110130Sjake int fd; 376110130Sjake int c; 377110130Sjake 378110130Sjake if ((fd = mkstemp(tmpfil)) < 0) 379110130Sjake err(1, "mkstemp"); 380110130Sjake if ((fp = fdopen(fd, "w")) == NULL) 381110130Sjake err(1, "fdopen"); 382110130Sjake print_label(sl, disk, fp); 383110130Sjake fflush(fp); 384110130Sjake if ((pid = fork()) < 0) 385110130Sjake err(1, "fork"); 386110130Sjake if (pid == 0) { 387110130Sjake if ((editor = getenv("EDITOR")) == NULL) 388110130Sjake editor = _PATH_VI; 389110130Sjake execlp(editor, editor, tmpfil, NULL); 390110130Sjake err(1, "execlp %s", editor); 391110130Sjake } 392110130Sjake status = 0; 393110130Sjake while ((r = wait(&status)) > 0 && r != pid) 394110130Sjake ; 395110130Sjake if (WIFEXITED(status)) { 396110130Sjake if (parse_label(sl, tmpfil) == 0) { 397110130Sjake fclose(fp); 398110130Sjake unlink(tmpfil); 399110130Sjake write_label(sl, disk, bootpath); 400110130Sjake return (0); 401110130Sjake } 402110130Sjake printf("re-edit the label? [y]: "); 403110130Sjake fflush(stdout); 404110130Sjake c = getchar(); 405110130Sjake if (c != EOF && c != '\n') 406110130Sjake while (getchar() != '\n') 407110130Sjake ; 408110130Sjake if (c == 'n') { 409110130Sjake fclose(fp); 410110130Sjake unlink(tmpfil); 411110130Sjake return (0); 412110130Sjake } 413110130Sjake } 414110130Sjake fclose(fp); 415110130Sjake unlink(tmpfil); 416110130Sjake return (1); 417110130Sjake} 418110130Sjake 419110130Sjakestatic int 420110130Sjakeparse_label(struct sun_disklabel *sl, const char *file) 421110130Sjake{ 422110130Sjake char offset[32]; 423110130Sjake char size[32]; 424110130Sjake char buf[128]; 425110130Sjake uint8_t part; 426110130Sjake FILE *fp; 427110130Sjake int line; 428110130Sjake 429110130Sjake line = 0; 430110130Sjake if ((fp = fopen(file, "r")) == NULL) 431110130Sjake err(1, "fopen"); 432110130Sjake bzero(sl->sl_part, sizeof(sl->sl_part)); 433110130Sjake while (fgets(buf, sizeof(buf), fp) != NULL) { 434110130Sjake if (buf[0] != ' ' || buf[1] != ' ') 435110130Sjake continue; 436110130Sjake if (sscanf(buf, " %c: %s %s\n", &part, size, offset) != 3 || 437110130Sjake parse_size(sl, part - 'a', size) || 438110130Sjake parse_offset(sl, part - 'a', offset)) { 439110130Sjake warnx("%s: syntex error on line %d", 440110130Sjake file, line); 441110130Sjake fclose(fp); 442110130Sjake return (1); 443110130Sjake } 444110130Sjake line++; 445110130Sjake } 446110130Sjake fclose(fp); 447110130Sjake return (check_label(sl)); 448110130Sjake} 449110130Sjake 450110130Sjakestatic int 451110130Sjakeparse_size(struct sun_disklabel *sl, int part, char *size) 452110130Sjake{ 453110130Sjake uintmax_t nsectors; 454110130Sjake uintmax_t total; 455110130Sjake uintmax_t n; 456110130Sjake char *p; 457110130Sjake int i; 458110130Sjake 459110130Sjake nsectors = 0; 460110130Sjake n = strtoumax(size, &p, 10); 461110130Sjake if (*p != '\0') { 462110130Sjake if (strcmp(size, "*") == 0) { 463110130Sjake total = sl->sl_ncylinders * sl->sl_ntracks * 464110130Sjake sl->sl_nsectors; 465110130Sjake for (i = 0; i < part; i++) { 466110130Sjake if (i == 2) 467110130Sjake continue; 468110130Sjake nsectors += sl->sl_part[i].sdkp_nsectors; 469110130Sjake } 470110130Sjake n = total - nsectors; 471110130Sjake } else if (p[1] == '\0' && (p[0] == 'K' || p[0] == 'k')) { 472110130Sjake n = roundup((n * 1024) / 512, 473110130Sjake sl->sl_ntracks * sl->sl_nsectors); 474110130Sjake } else if (p[1] == '\0' && (p[0] == 'M' || p[0] == 'm')) { 475110130Sjake n = roundup((n * 1024 * 1024) / 512, 476110130Sjake sl->sl_ntracks * sl->sl_nsectors); 477110130Sjake } else if (p[1] == '\0' && (p[0] == 'G' || p[0] == 'g')) { 478110130Sjake n = roundup((n * 1024 * 1024 * 1024) / 512, 479110130Sjake sl->sl_ntracks * sl->sl_nsectors); 480110130Sjake } else 481110130Sjake return (-1); 482110130Sjake } 483110130Sjake sl->sl_part[part].sdkp_nsectors = n; 484110130Sjake return (0); 485110130Sjake} 486110130Sjake 487113538Sjakestatic uint16_t 488113538Sjakechecksum(struct sun_disklabel *sl) 489113538Sjake{ 490113538Sjake uint16_t cksum; 491113538Sjake uint16_t *sp1; 492113538Sjake uint16_t *sp2; 493113538Sjake 494113538Sjake sp1 = (u_short *)sl; 495113538Sjake sp2 = (u_short *)(sl + 1) - 1; 496113538Sjake cksum = 0; 497113538Sjake while (sp1 < sp2) 498113538Sjake cksum ^= *sp1++; 499113538Sjake return (cksum); 500113538Sjake} 501113538Sjake 502110130Sjakestatic int 503110130Sjakeparse_offset(struct sun_disklabel *sl, int part, char *offset) 504110130Sjake{ 505110130Sjake uintmax_t nsectors; 506110130Sjake uintmax_t n; 507110130Sjake char *p; 508110130Sjake int i; 509110130Sjake 510110130Sjake nsectors = 0; 511110130Sjake n = strtoumax(offset, &p, 10); 512110130Sjake if (*p != '\0') { 513110130Sjake if (strcmp(offset, "*") == 0) { 514110130Sjake for (i = 0; i < part; i++) { 515110130Sjake if (i == 2) 516110130Sjake continue; 517110130Sjake nsectors += sl->sl_part[i].sdkp_nsectors; 518110130Sjake } 519110130Sjake n = nsectors / (sl->sl_nsectors * sl->sl_ntracks); 520110130Sjake } else 521110130Sjake return (-1); 522110130Sjake } 523110130Sjake sl->sl_part[part].sdkp_cyloffset = n; 524110130Sjake return (0); 525110130Sjake} 526110130Sjake 527110130Sjakestatic void 528110130Sjakeprint_label(struct sun_disklabel *sl, const char *disk, FILE *out) 529110130Sjake{ 530110130Sjake int i; 531110130Sjake 532110130Sjake fprintf(out, 533110130Sjake"# /dev/%s:\n" 534110130Sjake"text: %s\n" 535110130Sjake"bytes/sectors: 512\n" 536110130Sjake"sectors/cylinder: %d\n" 537110130Sjake"sectors/unit: %d\n" 538110130Sjake"\n" 539110130Sjake"8 partitions:\n" 540110130Sjake"#\n" 541110130Sjake"# Size is in sectors, use %%dK, %%dM or %%dG to specify in kilobytes,\n" 542110130Sjake"# megabytes or gigabytes respectively, or '*' to specify rest of disk.\n" 543110130Sjake"# Offset is in cylinders, use '*' to calculate offsets automatically.\n" 544110130Sjake"#\n" 545110130Sjake"# size offset\n" 546110130Sjake"# ---------- ----------\n", 547110130Sjake disk, 548110130Sjake sl->sl_text, 549110130Sjake sl->sl_nsectors * sl->sl_ntracks, 550110130Sjake sl->sl_nsectors * sl->sl_ntracks * sl->sl_ncylinders); 551110130Sjake for (i = 0; i < 8; i++) { 552110130Sjake if (sl->sl_part[i].sdkp_nsectors == 0) 553110130Sjake continue; 554110130Sjake fprintf(out, " %c: %10u %10u\n", 555110130Sjake 'a' + i, 556110130Sjake sl->sl_part[i].sdkp_nsectors, 557110130Sjake sl->sl_part[i].sdkp_cyloffset); 558110130Sjake } 559110130Sjake} 560110130Sjake 561110130Sjakestatic void 562110130Sjakeusage(void) 563110130Sjake{ 564110130Sjake 565110130Sjake fprintf(stderr, "usage:" 566110130Sjake"\t%s [-r] disk\n" 567110130Sjake"\t\t(to read label)\n" 568110130Sjake"\t%s -B [-b boot1] [-n] disk\n" 569110130Sjake"\t\t(to install boot program only)\n" 570110130Sjake"\t%s -R [-B [-b boot1]] [-r] [-n] disk protofile\n" 571110130Sjake"\t\t(to restore label)\n" 572110130Sjake"\t%s -e [-B [-b boot1]] [-r] [-n] disk\n" 573110130Sjake"\t\t(to edit label)\n" 574110130Sjake"\t%s -w [-B [-b boot1]] [-r] [-n] disk type\n" 575110130Sjake"\t\t(to write default label)\n", 576110130Sjake __progname, 577110130Sjake __progname, 578110130Sjake __progname, 579110130Sjake __progname, 580110130Sjake __progname); 581110130Sjake exit(1); 582110130Sjake} 583