sunlabel.c revision 113538
1218466Sjilles/*- 2218466Sjilles * Copyright (c) 2003 Jake Burkholder. 3218466Sjilles * All rights reserved. 4218466Sjilles * 5218466Sjilles * Redistribution and use in source and binary forms, with or without 6218466Sjilles * modification, are permitted provided that the following conditions 7218466Sjilles * are met: 8218466Sjilles * 1. Redistributions of source code must retain the above copyright 9218466Sjilles * notice, this list of conditions and the following disclaimer. 10218466Sjilles * 2. Redistributions in binary form must reproduce the above copyright 11218466Sjilles * notice, this list of conditions and the following disclaimer in the 12218466Sjilles * documentation and/or other materials provided with the distribution. 13218466Sjilles * 14218466Sjilles * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15218466Sjilles * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16218466Sjilles * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17218466Sjilles * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18218466Sjilles * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19218466Sjilles * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20218466Sjilles * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21218466Sjilles * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22218466Sjilles * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23218466Sjilles * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24218466Sjilles * SUCH DAMAGE. 25218466Sjilles */ 26218466Sjilles/* 27218466Sjilles * Copyright (c) 1994, 1995 Gordon W. Ross 28218466Sjilles * Copyright (c) 1994 Theo de Raadt 29218466Sjilles * All rights reserved. 30218466Sjilles * Copyright (c) 1987, 1993 31218466Sjilles * The Regents of the University of California. All rights reserved. 32218466Sjilles * 33218466Sjilles * This code is derived from software contributed to Berkeley by 34218466Sjilles * Symmetric Computer Systems. 35218466Sjilles * 36218466Sjilles * Redistribution and use in source and binary forms, with or without 37218466Sjilles * modification, are permitted provided that the following conditions 38223580Sjilles * are met: 39218466Sjilles * 1. Redistributions of source code must retain the above copyright 40218466Sjilles * notice, this list of conditions and the following disclaimer. 41218466Sjilles * 2. Redistributions in binary form must reproduce the above copyright 42218466Sjilles * notice, this list of conditions and the following disclaimer in the 43218466Sjilles * documentation and/or other materials provided with the distribution. 44218466Sjilles * 3. All advertising materials mentioning features or use of this software 45218466Sjilles * must display the following acknowledgement: 46218466Sjilles * This product includes software developed by the University of 47218466Sjilles * California, Berkeley and its contributors. 48218466Sjilles * This product includes software developed by Theo de Raadt. 49218466Sjilles * 4. Neither the name of the University nor the names of its contributors 50218466Sjilles * may be used to endorse or promote products derived from this software 51218466Sjilles * without specific prior written permission. 52218466Sjilles * 53218466Sjilles * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 54218466Sjilles * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 55218466Sjilles * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 56218466Sjilles * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 57218466Sjilles * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 58218466Sjilles * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 59218466Sjilles * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 60218466Sjilles * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 61218466Sjilles * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 62218466Sjilles * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 63218466Sjilles * SUCH DAMAGE. 64218466Sjilles * 65218466Sjilles * from: $NetBSD: disksubr.c,v 1.13 2000/12/17 22:39:18 pk $ 66218466Sjilles */ 67218466Sjilles 68218466Sjilles#include <sys/cdefs.h> 69218466Sjilles__FBSDID("$FreeBSD: head/sbin/sunlabel/sunlabel.c 113538 2003-04-15 23:46:19Z jake $"); 70218466Sjilles 71218466Sjilles#include <sys/types.h> 72218466Sjilles#include <sys/param.h> 73218466Sjilles#include <sys/disk.h> 74218466Sjilles#include <sys/ioctl.h> 75218466Sjilles#include <sys/sun_disklabel.h> 76218466Sjilles#include <sys/wait.h> 77218466Sjilles 78218466Sjilles#include <err.h> 79218466Sjilles#include <fcntl.h> 80218466Sjilles#include <inttypes.h> 81218466Sjilles#include <paths.h> 82218466Sjilles#include <stdio.h> 83218466Sjilles#include <stdlib.h> 84218466Sjilles#include <string.h> 85218466Sjilles#include <unistd.h> 86218466Sjilles 87218466Sjilles#define _PATH_TMPFILE "/tmp/EdDk.XXXXXXXXXX" 88218466Sjilles#define _PATH_BOOT "/boot/boot1" 89218466Sjilles 90218466Sjillesstatic int bflag; 91218466Sjillesstatic int Bflag; 92218466Sjillesstatic int eflag; 93218466Sjillesstatic int nflag; 94218466Sjillesstatic int rflag = 1; 95218466Sjillesstatic int Rflag; 96218466Sjillesstatic int wflag; 97218466Sjilles 98218466Sjillesstatic int check_label(struct sun_disklabel *sl); 99218466Sjillesstatic void read_label(struct sun_disklabel *sl, const char *disk); 100221463Sjillesstatic void write_label(struct sun_disklabel *sl, const char *disk, 101221463Sjilles const char *bootpath); 102218466Sjillesstatic int edit_label(struct sun_disklabel *sl, const char *disk, 103218466Sjilles const char *bootpath); 104218466Sjillesstatic int parse_label(struct sun_disklabel *sl, const char *file); 105218466Sjillesstatic void print_label(struct sun_disklabel *sl, const char *disk, FILE *out); 106218466Sjilles 107218466Sjillesstatic uint16_t checksum(struct sun_disklabel *sl); 108218466Sjilles 109218466Sjillesstatic int parse_size(struct sun_disklabel *sl, int part, char *size); 110218466Sjillesstatic int parse_offset(struct sun_disklabel *sl, int part, char *offset); 111218466Sjilles 112218466Sjillesstatic void usage(void); 113218466Sjilles 114218466Sjillesextern char *__progname; 115218466Sjilles 116218466Sjilles/* 117218466Sjilles * Disk label editor for sun disklabels. 118218466Sjilles */ 119218466Sjillesint 120218466Sjillesmain(int ac, char **av) 121218466Sjilles{ 122218466Sjilles struct sun_disklabel sl; 123218466Sjilles const char *bootpath; 124218466Sjilles const char *proto; 125218466Sjilles const char *disk; 126218466Sjilles int ch; 127218466Sjilles 128218466Sjilles bootpath = _PATH_BOOT; 129218466Sjilles while ((ch = getopt(ac, av, "b:BenrRw")) != -1) 130218626Sjilles switch (ch) { 131218626Sjilles case 'b': 132218466Sjilles bflag = 1; 133218466Sjilles bootpath = optarg; 134227369Sjilles break; 135218466Sjilles case 'B': 136227369Sjilles Bflag = 1; 137218466Sjilles break; 138227369Sjilles case 'e': 139218466Sjilles eflag = 1; 140218466Sjilles break; 141218466Sjilles case 'n': 142218466Sjilles nflag = 1; 143218466Sjilles break; 144218466Sjilles case 'r': 145218466Sjilles rflag = 1; 146218466Sjilles break; 147218466Sjilles case 'R': 148218466Sjilles Rflag = 1; 149218466Sjilles break; 150218466Sjilles case 'w': 151218466Sjilles wflag = 1; 152218466Sjilles break; 153218466Sjilles default: 154218466Sjilles usage(); 155218466Sjilles break; 156218466Sjilles } 157218466Sjilles if (bflag && !Bflag) 158218466Sjilles usage(); 159218466Sjilles if (nflag && !(Bflag || eflag || Rflag || wflag)) 160218466Sjilles usage(); 161218466Sjilles if (eflag && (Rflag || wflag)) 162218466Sjilles usage(); 163218466Sjilles ac -= optind; 164218466Sjilles av += optind; 165218466Sjilles if (ac == 0) 166218466Sjilles usage(); 167218466Sjilles bzero(&sl, sizeof(sl)); 168218466Sjilles disk = av[0]; 169218466Sjilles if (wflag) { 170218466Sjilles if (ac != 2 || strcmp(av[1], "auto") != 0) 171218466Sjilles usage(); 172218466Sjilles read_label(&sl, disk); 173218466Sjilles bzero(sl.sl_part, sizeof(sl.sl_part)); 174218466Sjilles sl.sl_part[2].sdkp_cyloffset = 0; 175218466Sjilles sl.sl_part[2].sdkp_nsectors = sl.sl_ncylinders * 176218466Sjilles sl.sl_ntracks * sl.sl_nsectors; 177218466Sjilles write_label(&sl, disk, bootpath); 178218466Sjilles } else if (eflag) { 179218466Sjilles if (ac != 1) 180218466Sjilles usage(); 181218466Sjilles read_label(&sl, disk); 182218466Sjilles if (sl.sl_magic != SUN_DKMAGIC) 183218466Sjilles errx(1, "%s%s has no sun disklabel", _PATH_DEV, disk); 184218466Sjilles while (edit_label(&sl, disk, bootpath) != 0) 185218466Sjilles ; 186218466Sjilles } else if (Rflag) { 187218466Sjilles if (ac != 2) 188218466Sjilles usage(); 189218466Sjilles proto = av[1]; 190218466Sjilles read_label(&sl, disk); 191218466Sjilles if (parse_label(&sl, proto) != 0) 192218466Sjilles errx(1, "%s: invalid label", proto); 193218466Sjilles write_label(&sl, disk, bootpath); 194218466Sjilles } else if (Bflag) { 195218466Sjilles read_label(&sl, disk); 196218466Sjilles if (sl.sl_magic != SUN_DKMAGIC) 197218466Sjilles errx(1, "%s%s has no sun disklabel", _PATH_DEV, disk); 198218466Sjilles write_label(&sl, disk, bootpath); 199218466Sjilles } else { 200218466Sjilles read_label(&sl, disk); 201218466Sjilles if (sl.sl_magic != SUN_DKMAGIC) 202218466Sjilles errx(1, "%s%s has no sun disklabel", _PATH_DEV, disk); 203219306Sjilles print_label(&sl, disk, stdout); 204218466Sjilles } 205218466Sjilles return (0); 206218466Sjilles} 207218466Sjilles 208218466Sjillesstatic int 209218466Sjillescheck_label(struct sun_disklabel *sl) 210218466Sjilles{ 211218466Sjilles uint64_t nsectors; 212218466Sjilles uint64_t ostart; 213218466Sjilles uint64_t start; 214218466Sjilles uint64_t oend; 215218466Sjilles uint64_t end; 216218466Sjilles int i; 217218466Sjilles int j; 218218466Sjilles 219218466Sjilles nsectors = sl->sl_ncylinders * sl->sl_ntracks * sl->sl_nsectors; 220218466Sjilles if (sl->sl_part[2].sdkp_cyloffset != 0 || 221218466Sjilles sl->sl_part[2].sdkp_nsectors != nsectors) { 222218466Sjilles warnx("partition c is incorrect, must start at 0 and cover " 223218466Sjilles "whole disk"); 224218466Sjilles return (1); 225218466Sjilles } 226219306Sjilles for (i = 0; i < 8; i++) { 227218466Sjilles if (i == 2 || sl->sl_part[i].sdkp_nsectors == 0) 228218466Sjilles continue; 229218466Sjilles start = (uint64_t)sl->sl_part[i].sdkp_cyloffset * 230218466Sjilles sl->sl_ntracks * sl->sl_nsectors; 231218466Sjilles end = start + sl->sl_part[i].sdkp_nsectors; 232218466Sjilles if (end > nsectors) { 233218466Sjilles warnx("partition %c extends past end of disk", 234218466Sjilles 'a' + i); 235218466Sjilles return (1); 236218466Sjilles } 237218466Sjilles for (j = 0; j < 8; j++) { 238218466Sjilles if (j == 2 || j == i || 239218466Sjilles sl->sl_part[j].sdkp_nsectors == 0) 240218466Sjilles continue; 241218466Sjilles ostart = (uint64_t)sl->sl_part[j].sdkp_cyloffset * 242218466Sjilles sl->sl_ntracks * sl->sl_nsectors; 243218466Sjilles oend = ostart + sl->sl_part[j].sdkp_nsectors; 244218466Sjilles if ((start <= ostart && end >= oend) || 245218466Sjilles (start > ostart && start < oend) || 246218466Sjilles (end > ostart && end < oend)) { 247218466Sjilles warnx("partition %c overlaps partition %c", 248218466Sjilles 'a' + i, 'a' + j); 249218466Sjilles return (1); 250218466Sjilles } 251218466Sjilles } 252218466Sjilles } 253218466Sjilles return (0); 254218466Sjilles} 255218466Sjilles 256218466Sjillesstatic void 257218466Sjillesread_label(struct sun_disklabel *sl, const char *disk) 258218466Sjilles{ 259218466Sjilles char path[MAXPATHLEN]; 260218466Sjilles uint32_t sectorsize; 261218466Sjilles uint32_t fwsectors; 262218466Sjilles uint32_t fwheads; 263218466Sjilles off_t mediasize; 264218466Sjilles int fd; 265218466Sjilles 266218466Sjilles snprintf(path, sizeof(path), "%s%s", _PATH_DEV, disk); 267218466Sjilles if ((fd = open(path, O_RDONLY)) < 0) 268218466Sjilles err(1, "open %s", path); 269218466Sjilles if (read(fd, sl, sizeof(*sl)) != sizeof(*sl)) 270218466Sjilles err(1, "read"); 271218466Sjilles if (sl->sl_magic != SUN_DKMAGIC || checksum(sl) != sl->sl_cksum) { 272218466Sjilles bzero(sl, sizeof(*sl)); 273218466Sjilles if (ioctl(fd, DIOCGMEDIASIZE, &mediasize) != 0) 274218466Sjilles err(1, "%s: ioctl(DIOCGMEDIASIZE) failed", disk); 275218466Sjilles if (ioctl(fd, DIOCGSECTORSIZE, §orsize) != 0) 276218466Sjilles err(1, "%s: DIOCGSECTORSIZE failed", disk); 277218466Sjilles if (ioctl(fd, DIOCGFWSECTORS, &fwsectors) != 0) 278218466Sjilles fwsectors = 63; 279218466Sjilles if (ioctl(fd, DIOCGFWHEADS, &fwheads) != 0) { 280218466Sjilles if (mediasize <= 63 * 1024 * sectorsize) 281218466Sjilles fwheads = 1; 282218466Sjilles else if (mediasize <= 63 * 16 * 1024 * sectorsize) 283218466Sjilles fwheads = 16; 284218466Sjilles else 285218466Sjilles fwheads = 255; 286218466Sjilles } 287218466Sjilles sl->sl_rpm = 3600; 288218466Sjilles sl->sl_pcylinders = mediasize / (fwsectors * fwheads * 289218466Sjilles sectorsize); 290218466Sjilles sl->sl_sparespercyl = 0; 291218466Sjilles sl->sl_interleave = 1; 292218466Sjilles sl->sl_ncylinders = sl->sl_pcylinders - 2; 293218466Sjilles sl->sl_acylinders = 2; 294218466Sjilles sl->sl_nsectors = fwsectors; 295218466Sjilles sl->sl_ntracks = fwheads; 296218466Sjilles sl->sl_part[2].sdkp_cyloffset = 0; 297218466Sjilles sl->sl_part[2].sdkp_nsectors = sl->sl_ncylinders * 298218466Sjilles sl->sl_ntracks * sl->sl_nsectors; 299218466Sjilles if (mediasize > 4999L * 1024L * 1024L) { 300218466Sjilles sprintf(sl->sl_text, 301218466Sjilles "FreeBSD%luG cyl %u alt %u hd %u sec %u", 302218466Sjilles (mediasize + 512 * 1024 * 1024) / 303218466Sjilles (1024 * 1024 * 1024), 304218466Sjilles sl->sl_ncylinders, sl->sl_acylinders, 305218466Sjilles sl->sl_ntracks, sl->sl_nsectors); 306218466Sjilles } else { 307218466Sjilles sprintf(sl->sl_text, 308218466Sjilles "FreeBSD%luM cyl %u alt %u hd %u sec %u", 309218466Sjilles (mediasize + 512 * 1024) / (1024 * 1024), 310218466Sjilles sl->sl_ncylinders, sl->sl_acylinders, 311218466Sjilles sl->sl_ntracks, sl->sl_nsectors); 312218466Sjilles } 313218466Sjilles } 314218466Sjilles close(fd); 315218466Sjilles} 316218466Sjilles 317218466Sjillesstatic void 318218466Sjilleswrite_label(struct sun_disklabel *sl, const char *disk, const char *bootpath) 319218466Sjilles{ 320218466Sjilles char path[MAXPATHLEN]; 321218466Sjilles char boot[16 * 512]; 322218466Sjilles off_t off; 323218466Sjilles int bfd; 324218466Sjilles int fd; 325218466Sjilles int i; 326218466Sjilles 327218466Sjilles sl->sl_magic = SUN_DKMAGIC; 328218466Sjilles sl->sl_cksum = checksum(sl); 329218466Sjilles 330218466Sjilles if (check_label(sl) != 0) 331218466Sjilles errx(1, "invalid label"); 332218466Sjilles 333218466Sjilles if (nflag) { 334218466Sjilles print_label(sl, disk, stdout); 335218466Sjilles } else if (rflag) { 336218466Sjilles snprintf(path, sizeof(path), "%s%s", _PATH_DEV, disk); 337218466Sjilles if ((fd = open(path, O_RDWR)) < 0) 338218466Sjilles err(1, "open %s", path); 339218466Sjilles if (Bflag) { 340218466Sjilles if ((bfd = open(bootpath, O_RDONLY)) < 0) 341218466Sjilles err(1, "open %s", bootpath); 342218466Sjilles if (read(bfd, boot, sizeof(boot)) != sizeof(boot)) 343218466Sjilles err(1, "read"); 344218466Sjilles close(bfd); 345218466Sjilles for (i = 0; i < 8; i++) { 346218466Sjilles if (sl->sl_part[i].sdkp_nsectors == 0) 347222386Sjilles continue; 348218466Sjilles off = sl->sl_part[i].sdkp_cyloffset * 349218466Sjilles sl->sl_ntracks * sl->sl_nsectors * 512; 350218466Sjilles if (lseek(fd, off, SEEK_SET) < 0) 351218466Sjilles err(1, "lseek"); 352218466Sjilles if (write(fd, boot, sizeof(boot)) != 353218466Sjilles sizeof(boot)) 354218466Sjilles err(1, "write"); 355218466Sjilles } 356218466Sjilles } 357218466Sjilles if (lseek(fd, 0, SEEK_SET) < 0) 358218466Sjilles err(1, "lseek"); 359218466Sjilles if (write(fd, sl, sizeof(*sl)) != sizeof(*sl)) 360218466Sjilles err(1, "write"); 361218466Sjilles close(fd); 362218466Sjilles } else 363218466Sjilles err(1, "implement!"); 364218466Sjilles} 365218466Sjilles 366218466Sjillesstatic int 367218466Sjillesedit_label(struct sun_disklabel *sl, const char *disk, const char *bootpath) 368218466Sjilles{ 369218466Sjilles char tmpfil[] = _PATH_TMPFILE; 370218466Sjilles const char *editor; 371218466Sjilles int status; 372218466Sjilles FILE *fp; 373218466Sjilles pid_t pid; 374218466Sjilles pid_t r; 375218466Sjilles int fd; 376218466Sjilles int c; 377218466Sjilles 378218466Sjilles if ((fd = mkstemp(tmpfil)) < 0) 379218466Sjilles err(1, "mkstemp"); 380218466Sjilles if ((fp = fdopen(fd, "w")) == NULL) 381 err(1, "fdopen"); 382 print_label(sl, disk, fp); 383 fflush(fp); 384 if ((pid = fork()) < 0) 385 err(1, "fork"); 386 if (pid == 0) { 387 if ((editor = getenv("EDITOR")) == NULL) 388 editor = _PATH_VI; 389 execlp(editor, editor, tmpfil, NULL); 390 err(1, "execlp %s", editor); 391 } 392 status = 0; 393 while ((r = wait(&status)) > 0 && r != pid) 394 ; 395 if (WIFEXITED(status)) { 396 if (parse_label(sl, tmpfil) == 0) { 397 fclose(fp); 398 unlink(tmpfil); 399 write_label(sl, disk, bootpath); 400 return (0); 401 } 402 printf("re-edit the label? [y]: "); 403 fflush(stdout); 404 c = getchar(); 405 if (c != EOF && c != '\n') 406 while (getchar() != '\n') 407 ; 408 if (c == 'n') { 409 fclose(fp); 410 unlink(tmpfil); 411 return (0); 412 } 413 } 414 fclose(fp); 415 unlink(tmpfil); 416 return (1); 417} 418 419static int 420parse_label(struct sun_disklabel *sl, const char *file) 421{ 422 char offset[32]; 423 char size[32]; 424 char buf[128]; 425 uint8_t part; 426 FILE *fp; 427 int line; 428 429 line = 0; 430 if ((fp = fopen(file, "r")) == NULL) 431 err(1, "fopen"); 432 bzero(sl->sl_part, sizeof(sl->sl_part)); 433 while (fgets(buf, sizeof(buf), fp) != NULL) { 434 if (buf[0] != ' ' || buf[1] != ' ') 435 continue; 436 if (sscanf(buf, " %c: %s %s\n", &part, size, offset) != 3 || 437 parse_size(sl, part - 'a', size) || 438 parse_offset(sl, part - 'a', offset)) { 439 warnx("%s: syntex error on line %d", 440 file, line); 441 fclose(fp); 442 return (1); 443 } 444 line++; 445 } 446 fclose(fp); 447 return (check_label(sl)); 448} 449 450static int 451parse_size(struct sun_disklabel *sl, int part, char *size) 452{ 453 uintmax_t nsectors; 454 uintmax_t total; 455 uintmax_t n; 456 char *p; 457 int i; 458 459 nsectors = 0; 460 n = strtoumax(size, &p, 10); 461 if (*p != '\0') { 462 if (strcmp(size, "*") == 0) { 463 total = sl->sl_ncylinders * sl->sl_ntracks * 464 sl->sl_nsectors; 465 for (i = 0; i < part; i++) { 466 if (i == 2) 467 continue; 468 nsectors += sl->sl_part[i].sdkp_nsectors; 469 } 470 n = total - nsectors; 471 } else if (p[1] == '\0' && (p[0] == 'K' || p[0] == 'k')) { 472 n = roundup((n * 1024) / 512, 473 sl->sl_ntracks * sl->sl_nsectors); 474 } else if (p[1] == '\0' && (p[0] == 'M' || p[0] == 'm')) { 475 n = roundup((n * 1024 * 1024) / 512, 476 sl->sl_ntracks * sl->sl_nsectors); 477 } else if (p[1] == '\0' && (p[0] == 'G' || p[0] == 'g')) { 478 n = roundup((n * 1024 * 1024 * 1024) / 512, 479 sl->sl_ntracks * sl->sl_nsectors); 480 } else 481 return (-1); 482 } 483 sl->sl_part[part].sdkp_nsectors = n; 484 return (0); 485} 486 487static uint16_t 488checksum(struct sun_disklabel *sl) 489{ 490 uint16_t cksum; 491 uint16_t *sp1; 492 uint16_t *sp2; 493 494 sp1 = (u_short *)sl; 495 sp2 = (u_short *)(sl + 1) - 1; 496 cksum = 0; 497 while (sp1 < sp2) 498 cksum ^= *sp1++; 499 return (cksum); 500} 501 502static int 503parse_offset(struct sun_disklabel *sl, int part, char *offset) 504{ 505 uintmax_t nsectors; 506 uintmax_t n; 507 char *p; 508 int i; 509 510 nsectors = 0; 511 n = strtoumax(offset, &p, 10); 512 if (*p != '\0') { 513 if (strcmp(offset, "*") == 0) { 514 for (i = 0; i < part; i++) { 515 if (i == 2) 516 continue; 517 nsectors += sl->sl_part[i].sdkp_nsectors; 518 } 519 n = nsectors / (sl->sl_nsectors * sl->sl_ntracks); 520 } else 521 return (-1); 522 } 523 sl->sl_part[part].sdkp_cyloffset = n; 524 return (0); 525} 526 527static void 528print_label(struct sun_disklabel *sl, const char *disk, FILE *out) 529{ 530 int i; 531 532 fprintf(out, 533"# /dev/%s:\n" 534"text: %s\n" 535"bytes/sectors: 512\n" 536"sectors/cylinder: %d\n" 537"sectors/unit: %d\n" 538"\n" 539"8 partitions:\n" 540"#\n" 541"# Size is in sectors, use %%dK, %%dM or %%dG to specify in kilobytes,\n" 542"# megabytes or gigabytes respectively, or '*' to specify rest of disk.\n" 543"# Offset is in cylinders, use '*' to calculate offsets automatically.\n" 544"#\n" 545"# size offset\n" 546"# ---------- ----------\n", 547 disk, 548 sl->sl_text, 549 sl->sl_nsectors * sl->sl_ntracks, 550 sl->sl_nsectors * sl->sl_ntracks * sl->sl_ncylinders); 551 for (i = 0; i < 8; i++) { 552 if (sl->sl_part[i].sdkp_nsectors == 0) 553 continue; 554 fprintf(out, " %c: %10u %10u\n", 555 'a' + i, 556 sl->sl_part[i].sdkp_nsectors, 557 sl->sl_part[i].sdkp_cyloffset); 558 } 559} 560 561static void 562usage(void) 563{ 564 565 fprintf(stderr, "usage:" 566"\t%s [-r] disk\n" 567"\t\t(to read label)\n" 568"\t%s -B [-b boot1] [-n] disk\n" 569"\t\t(to install boot program only)\n" 570"\t%s -R [-B [-b boot1]] [-r] [-n] disk protofile\n" 571"\t\t(to restore label)\n" 572"\t%s -e [-B [-b boot1]] [-r] [-n] disk\n" 573"\t\t(to edit label)\n" 574"\t%s -w [-B [-b boot1]] [-r] [-n] disk type\n" 575"\t\t(to write default label)\n", 576 __progname, 577 __progname, 578 __progname, 579 __progname, 580 __progname); 581 exit(1); 582} 583