1110130Sjake/*- 2110130Sjake * Copyright (c) 2003 Jake Burkholder. 3144328Sjoerg * Copyright (c) 2004,2005 Joerg Wunsch. 4110130Sjake * All rights reserved. 5110130Sjake * 6110130Sjake * Redistribution and use in source and binary forms, with or without 7110130Sjake * modification, are permitted provided that the following conditions 8110130Sjake * are met: 9110130Sjake * 1. Redistributions of source code must retain the above copyright 10110130Sjake * notice, this list of conditions and the following disclaimer. 11110130Sjake * 2. Redistributions in binary form must reproduce the above copyright 12110130Sjake * notice, this list of conditions and the following disclaimer in the 13110130Sjake * documentation and/or other materials provided with the distribution. 14110130Sjake * 15110130Sjake * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16110130Sjake * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17110130Sjake * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18110130Sjake * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19110130Sjake * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20110130Sjake * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21110130Sjake * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22110130Sjake * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23110130Sjake * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24110130Sjake * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25110130Sjake * SUCH DAMAGE. 26110130Sjake */ 27110130Sjake/* 28110130Sjake * Copyright (c) 1994, 1995 Gordon W. Ross 29110130Sjake * Copyright (c) 1994 Theo de Raadt 30110130Sjake * All rights reserved. 31110130Sjake * Copyright (c) 1987, 1993 32110130Sjake * The Regents of the University of California. All rights reserved. 33110130Sjake * 34110130Sjake * This code is derived from software contributed to Berkeley by 35110130Sjake * Symmetric Computer Systems. 36110130Sjake * 37110130Sjake * Redistribution and use in source and binary forms, with or without 38110130Sjake * modification, are permitted provided that the following conditions 39110130Sjake * are met: 40110130Sjake * 1. Redistributions of source code must retain the above copyright 41110130Sjake * notice, this list of conditions and the following disclaimer. 42110130Sjake * 2. Redistributions in binary form must reproduce the above copyright 43110130Sjake * notice, this list of conditions and the following disclaimer in the 44110130Sjake * documentation and/or other materials provided with the distribution. 45110130Sjake * 3. All advertising materials mentioning features or use of this software 46110130Sjake * must display the following acknowledgement: 47110130Sjake * This product includes software developed by the University of 48110130Sjake * California, Berkeley and its contributors. 49110130Sjake * This product includes software developed by Theo de Raadt. 50110130Sjake * 4. Neither the name of the University nor the names of its contributors 51110130Sjake * may be used to endorse or promote products derived from this software 52110130Sjake * without specific prior written permission. 53110130Sjake * 54110130Sjake * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 55110130Sjake * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 56110130Sjake * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 57110130Sjake * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 58110130Sjake * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 59110130Sjake * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 60110130Sjake * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 61110130Sjake * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 62110130Sjake * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 63110130Sjake * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 64110130Sjake * SUCH DAMAGE. 65110130Sjake * 66110130Sjake * from: $NetBSD: disksubr.c,v 1.13 2000/12/17 22:39:18 pk $ 67110130Sjake */ 68110130Sjake 69110130Sjake#include <sys/cdefs.h> 70110130Sjake__FBSDID("$FreeBSD$"); 71110130Sjake 72110130Sjake#include <sys/types.h> 73110130Sjake#include <sys/param.h> 74113538Sjake#include <sys/disk.h> 75113538Sjake#include <sys/ioctl.h> 76110130Sjake#include <sys/sun_disklabel.h> 77110130Sjake#include <sys/wait.h> 78110130Sjake 79128916Sjoerg#include <ctype.h> 80110130Sjake#include <err.h> 81110130Sjake#include <fcntl.h> 82110130Sjake#include <inttypes.h> 83113896Sphk#include <libgeom.h> 84110130Sjake#include <paths.h> 85110130Sjake#include <stdio.h> 86110130Sjake#include <stdlib.h> 87110130Sjake#include <string.h> 88110130Sjake#include <unistd.h> 89110130Sjake 90110130Sjake#define _PATH_TMPFILE "/tmp/EdDk.XXXXXXXXXX" 91110130Sjake#define _PATH_BOOT "/boot/boot1" 92110130Sjake 93110130Sjakestatic int bflag; 94110130Sjakestatic int Bflag; 95129965Sjoergstatic int cflag; 96110130Sjakestatic int eflag; 97129965Sjoergstatic int hflag; 98110130Sjakestatic int nflag; 99110130Sjakestatic int Rflag; 100110130Sjakestatic int wflag; 101110130Sjake 102129965Sjoergstatic off_t mediasize; 103129965Sjoergstatic uint32_t sectorsize; 104129965Sjoerg 105129965Sjoergstruct tags { 106129965Sjoerg const char *name; 107129965Sjoerg unsigned int id; 108129965Sjoerg}; 109129965Sjoerg 110110130Sjakestatic int check_label(struct sun_disklabel *sl); 111110130Sjakestatic void read_label(struct sun_disklabel *sl, const char *disk); 112110130Sjakestatic void write_label(struct sun_disklabel *sl, const char *disk, 113110130Sjake const char *bootpath); 114129965Sjoergstatic void edit_label(struct sun_disklabel *sl, const char *disk, 115110130Sjake const char *bootpath); 116110130Sjakestatic int parse_label(struct sun_disklabel *sl, const char *file); 117110130Sjakestatic void print_label(struct sun_disklabel *sl, const char *disk, FILE *out); 118110130Sjake 119110130Sjakestatic int parse_size(struct sun_disklabel *sl, int part, char *size); 120110130Sjakestatic int parse_offset(struct sun_disklabel *sl, int part, char *offset); 121110130Sjake 122129965Sjoergstatic const char *flagname(unsigned int tag); 123129965Sjoergstatic const char *tagname(unsigned int tag); 124129965Sjoergstatic unsigned int parse_flag(struct sun_disklabel *sl, int part, 125129965Sjoerg const char *flag); 126129965Sjoergstatic unsigned int parse_tag(struct sun_disklabel *sl, int part, 127129965Sjoerg const char *tag); 128129965Sjoergstatic const char *make_h_number(uintmax_t u); 129129965Sjoerg 130110130Sjakestatic void usage(void); 131110130Sjake 132110130Sjakeextern char *__progname; 133110130Sjake 134129965Sjoergstatic struct tags knowntags[] = { 135129965Sjoerg { "unassigned", VTOC_UNASSIGNED }, 136129965Sjoerg { "boot", VTOC_BOOT }, 137129965Sjoerg { "root", VTOC_ROOT }, 138129965Sjoerg { "swap", VTOC_SWAP }, 139129965Sjoerg { "usr", VTOC_USR }, 140129965Sjoerg { "backup", VTOC_BACKUP }, 141129965Sjoerg { "stand", VTOC_STAND }, 142129965Sjoerg { "var", VTOC_VAR }, 143129965Sjoerg { "home", VTOC_HOME }, 144129965Sjoerg { "altsctr", VTOC_ALTSCTR }, 145129965Sjoerg { "cache", VTOC_CACHE }, 146129965Sjoerg { "VxVM_pub", VTOC_VXVM_PUB }, 147129965Sjoerg { "VxVM_priv", VTOC_VXVM_PRIV }, 148129965Sjoerg}; 149129965Sjoerg 150129965Sjoergstatic struct tags knownflags[] = { 151129965Sjoerg { "wm", 0 }, 152129965Sjoerg { "wu", VTOC_UNMNT }, 153129965Sjoerg { "rm", VTOC_RONLY }, 154129965Sjoerg { "ru", VTOC_UNMNT | VTOC_RONLY }, 155129965Sjoerg}; 156129965Sjoerg 157110130Sjake/* 158110130Sjake * Disk label editor for sun disklabels. 159110130Sjake */ 160110130Sjakeint 161110130Sjakemain(int ac, char **av) 162110130Sjake{ 163110130Sjake struct sun_disklabel sl; 164110130Sjake const char *bootpath; 165110130Sjake const char *proto; 166110130Sjake const char *disk; 167110130Sjake int ch; 168110130Sjake 169110130Sjake bootpath = _PATH_BOOT; 170129965Sjoerg while ((ch = getopt(ac, av, "b:BcehnrRw")) != -1) 171110130Sjake switch (ch) { 172110130Sjake case 'b': 173110130Sjake bflag = 1; 174110130Sjake bootpath = optarg; 175110130Sjake break; 176110130Sjake case 'B': 177110130Sjake Bflag = 1; 178110130Sjake break; 179129965Sjoerg case 'c': 180129965Sjoerg cflag = 1; 181129965Sjoerg break; 182110130Sjake case 'e': 183110130Sjake eflag = 1; 184110130Sjake break; 185129965Sjoerg case 'h': 186129965Sjoerg hflag = 1; 187129965Sjoerg break; 188110130Sjake case 'n': 189110130Sjake nflag = 1; 190110130Sjake break; 191110130Sjake case 'r': 192113896Sphk fprintf(stderr, "Obsolete -r flag ignored\n"); 193110130Sjake break; 194110130Sjake case 'R': 195110130Sjake Rflag = 1; 196110130Sjake break; 197110130Sjake case 'w': 198110130Sjake wflag = 1; 199110130Sjake break; 200110130Sjake default: 201110130Sjake usage(); 202110130Sjake break; 203110130Sjake } 204110130Sjake if (bflag && !Bflag) 205110130Sjake usage(); 206110130Sjake if (nflag && !(Bflag || eflag || Rflag || wflag)) 207110130Sjake usage(); 208110130Sjake if (eflag && (Rflag || wflag)) 209110130Sjake usage(); 210129965Sjoerg if (eflag) 211129965Sjoerg hflag = 0; 212110130Sjake ac -= optind; 213110130Sjake av += optind; 214110130Sjake if (ac == 0) 215110130Sjake usage(); 216110130Sjake bzero(&sl, sizeof(sl)); 217110130Sjake disk = av[0]; 218110130Sjake if (wflag) { 219110130Sjake if (ac != 2 || strcmp(av[1], "auto") != 0) 220110130Sjake usage(); 221110130Sjake read_label(&sl, disk); 222110130Sjake bzero(sl.sl_part, sizeof(sl.sl_part)); 223113824Sphk sl.sl_part[SUN_RAWPART].sdkp_cyloffset = 0; 224113824Sphk sl.sl_part[SUN_RAWPART].sdkp_nsectors = sl.sl_ncylinders * 225110130Sjake sl.sl_ntracks * sl.sl_nsectors; 226110130Sjake write_label(&sl, disk, bootpath); 227110130Sjake } else if (eflag) { 228110130Sjake if (ac != 1) 229110130Sjake usage(); 230110130Sjake read_label(&sl, disk); 231110130Sjake if (sl.sl_magic != SUN_DKMAGIC) 232110130Sjake errx(1, "%s%s has no sun disklabel", _PATH_DEV, disk); 233129965Sjoerg edit_label(&sl, disk, bootpath); 234110130Sjake } else if (Rflag) { 235110130Sjake if (ac != 2) 236110130Sjake usage(); 237110130Sjake proto = av[1]; 238110130Sjake read_label(&sl, disk); 239113538Sjake if (parse_label(&sl, proto) != 0) 240113538Sjake errx(1, "%s: invalid label", proto); 241110130Sjake write_label(&sl, disk, bootpath); 242110130Sjake } else if (Bflag) { 243110130Sjake read_label(&sl, disk); 244110130Sjake if (sl.sl_magic != SUN_DKMAGIC) 245110130Sjake errx(1, "%s%s has no sun disklabel", _PATH_DEV, disk); 246110130Sjake write_label(&sl, disk, bootpath); 247110130Sjake } else { 248110130Sjake read_label(&sl, disk); 249110130Sjake if (sl.sl_magic != SUN_DKMAGIC) 250110130Sjake errx(1, "%s%s has no sun disklabel", _PATH_DEV, disk); 251110130Sjake print_label(&sl, disk, stdout); 252110130Sjake } 253110130Sjake return (0); 254110130Sjake} 255110130Sjake 256110130Sjakestatic int 257110130Sjakecheck_label(struct sun_disklabel *sl) 258110130Sjake{ 259110130Sjake uint64_t nsectors; 260110130Sjake uint64_t ostart; 261110130Sjake uint64_t start; 262110130Sjake uint64_t oend; 263110130Sjake uint64_t end; 264129965Sjoerg int havevtoc; 265129965Sjoerg int warnonly; 266110130Sjake int i; 267110130Sjake int j; 268110130Sjake 269129965Sjoerg havevtoc = sl->sl_vtoc_sane == SUN_VTOC_SANE; 270129965Sjoerg 271110130Sjake nsectors = sl->sl_ncylinders * sl->sl_ntracks * sl->sl_nsectors; 272113824Sphk if (sl->sl_part[SUN_RAWPART].sdkp_cyloffset != 0 || 273113824Sphk sl->sl_part[SUN_RAWPART].sdkp_nsectors != nsectors) { 274113538Sjake warnx("partition c is incorrect, must start at 0 and cover " 275113538Sjake "whole disk"); 276113538Sjake return (1); 277113538Sjake } 278129965Sjoerg if (havevtoc && sl->sl_vtoc_map[2].svtoc_tag != VTOC_BACKUP) { 279129965Sjoerg warnx("partition c must have tag \"backup\""); 280129965Sjoerg return (1); 281129965Sjoerg } 282113824Sphk for (i = 0; i < SUN_NPART; i++) { 283110130Sjake if (i == 2 || sl->sl_part[i].sdkp_nsectors == 0) 284110130Sjake continue; 285110130Sjake start = (uint64_t)sl->sl_part[i].sdkp_cyloffset * 286110130Sjake sl->sl_ntracks * sl->sl_nsectors; 287110130Sjake end = start + sl->sl_part[i].sdkp_nsectors; 288110130Sjake if (end > nsectors) { 289110130Sjake warnx("partition %c extends past end of disk", 290110130Sjake 'a' + i); 291110130Sjake return (1); 292110130Sjake } 293129965Sjoerg if (havevtoc) { 294129965Sjoerg if (sl->sl_vtoc_map[i].svtoc_tag == VTOC_BACKUP) { 295129965Sjoerg warnx("only partition c is allowed to have " 296130692Sjoerg "tag \"backup\""); 297129965Sjoerg return (1); 298129965Sjoerg } 299129965Sjoerg } 300113824Sphk for (j = 0; j < SUN_NPART; j++) { 301129965Sjoerg /* 302129965Sjoerg * Overlaps for unmountable partitions are 303129965Sjoerg * non-fatal but will be warned anyway. 304129965Sjoerg */ 305129965Sjoerg warnonly = havevtoc && 306129965Sjoerg ((sl->sl_vtoc_map[i].svtoc_flag & VTOC_UNMNT) != 0 || 307129965Sjoerg (sl->sl_vtoc_map[j].svtoc_flag & VTOC_UNMNT) != 0); 308129965Sjoerg 309110130Sjake if (j == 2 || j == i || 310110130Sjake sl->sl_part[j].sdkp_nsectors == 0) 311110130Sjake continue; 312110130Sjake ostart = (uint64_t)sl->sl_part[j].sdkp_cyloffset * 313110130Sjake sl->sl_ntracks * sl->sl_nsectors; 314110130Sjake oend = ostart + sl->sl_part[j].sdkp_nsectors; 315110130Sjake if ((start <= ostart && end >= oend) || 316110130Sjake (start > ostart && start < oend) || 317110130Sjake (end > ostart && end < oend)) { 318110130Sjake warnx("partition %c overlaps partition %c", 319110130Sjake 'a' + i, 'a' + j); 320129965Sjoerg if (!warnonly) 321129965Sjoerg return (1); 322110130Sjake } 323110130Sjake } 324110130Sjake } 325110130Sjake return (0); 326110130Sjake} 327110130Sjake 328110130Sjakestatic void 329110130Sjakeread_label(struct sun_disklabel *sl, const char *disk) 330110130Sjake{ 331113538Sjake char path[MAXPATHLEN]; 332113538Sjake uint32_t fwsectors; 333113538Sjake uint32_t fwheads; 334113824Sphk char buf[SUN_SIZE]; 335113824Sphk int fd, error; 336110130Sjake 337113538Sjake snprintf(path, sizeof(path), "%s%s", _PATH_DEV, disk); 338113538Sjake if ((fd = open(path, O_RDONLY)) < 0) 339113538Sjake err(1, "open %s", path); 340113824Sphk if (read(fd, buf, sizeof(buf)) != sizeof(buf)) 341113538Sjake err(1, "read"); 342113824Sphk error = sunlabel_dec(buf, sl); 343129965Sjoerg if (ioctl(fd, DIOCGMEDIASIZE, &mediasize) != 0) 344129965Sjoerg if (error) 345129965Sjoerg err(1, "%s: ioctl(DIOCGMEDIASIZE) failed", disk); 346129965Sjoerg if (ioctl(fd, DIOCGSECTORSIZE, §orsize) != 0) { 347129965Sjoerg if (error) 348129965Sjoerg err(1, "%s: DIOCGSECTORSIZE failed", disk); 349129965Sjoerg else 350129965Sjoerg sectorsize = 512; 351129965Sjoerg } 352113824Sphk if (error) { 353113538Sjake bzero(sl, sizeof(*sl)); 354113538Sjake if (ioctl(fd, DIOCGFWSECTORS, &fwsectors) != 0) 355113538Sjake fwsectors = 63; 356113538Sjake if (ioctl(fd, DIOCGFWHEADS, &fwheads) != 0) { 357113538Sjake if (mediasize <= 63 * 1024 * sectorsize) 358113538Sjake fwheads = 1; 359113538Sjake else if (mediasize <= 63 * 16 * 1024 * sectorsize) 360113538Sjake fwheads = 16; 361113538Sjake else 362113538Sjake fwheads = 255; 363110130Sjake } 364113538Sjake sl->sl_rpm = 3600; 365113538Sjake sl->sl_pcylinders = mediasize / (fwsectors * fwheads * 366113538Sjake sectorsize); 367113538Sjake sl->sl_sparespercyl = 0; 368113538Sjake sl->sl_interleave = 1; 369113538Sjake sl->sl_ncylinders = sl->sl_pcylinders - 2; 370113538Sjake sl->sl_acylinders = 2; 371113538Sjake sl->sl_nsectors = fwsectors; 372113538Sjake sl->sl_ntracks = fwheads; 373113824Sphk sl->sl_part[SUN_RAWPART].sdkp_cyloffset = 0; 374113824Sphk sl->sl_part[SUN_RAWPART].sdkp_nsectors = sl->sl_ncylinders * 375113538Sjake sl->sl_ntracks * sl->sl_nsectors; 376113688Sphk if (mediasize > (off_t)4999L * 1024L * 1024L) { 377113538Sjake sprintf(sl->sl_text, 378113688Sphk "FreeBSD%jdG cyl %u alt %u hd %u sec %u", 379113688Sphk (intmax_t)(mediasize + 512 * 1024 * 1024) / 380113538Sjake (1024 * 1024 * 1024), 381113538Sjake sl->sl_ncylinders, sl->sl_acylinders, 382113538Sjake sl->sl_ntracks, sl->sl_nsectors); 383113538Sjake } else { 384113538Sjake sprintf(sl->sl_text, 385113688Sphk "FreeBSD%jdM cyl %u alt %u hd %u sec %u", 386113688Sphk (intmax_t)(mediasize + 512 * 1024) / (1024 * 1024), 387113538Sjake sl->sl_ncylinders, sl->sl_acylinders, 388113538Sjake sl->sl_ntracks, sl->sl_nsectors); 389110130Sjake } 390110130Sjake } 391113538Sjake close(fd); 392110130Sjake} 393110130Sjake 394110130Sjakestatic void 395110130Sjakewrite_label(struct sun_disklabel *sl, const char *disk, const char *bootpath) 396110130Sjake{ 397110130Sjake char path[MAXPATHLEN]; 398113896Sphk char boot[SUN_BOOTSIZE]; 399113824Sphk char buf[SUN_SIZE]; 400113896Sphk const char *errstr; 401110130Sjake off_t off; 402110130Sjake int bfd; 403110130Sjake int fd; 404110130Sjake int i; 405113896Sphk struct gctl_req *grq; 406110130Sjake 407110130Sjake sl->sl_magic = SUN_DKMAGIC; 408110130Sjake 409110130Sjake if (check_label(sl) != 0) 410110130Sjake errx(1, "invalid label"); 411110130Sjake 412113896Sphk bzero(buf, sizeof(buf)); 413113896Sphk sunlabel_enc(buf, sl); 414113896Sphk 415110130Sjake if (nflag) { 416110130Sjake print_label(sl, disk, stdout); 417113896Sphk return; 418113896Sphk } 419113896Sphk if (Bflag) { 420113896Sphk if ((bfd = open(bootpath, O_RDONLY)) < 0) 421113896Sphk err(1, "open %s", bootpath); 422113896Sphk i = read(bfd, boot, sizeof(boot)); 423113896Sphk if (i < 0) 424113896Sphk err(1, "read"); 425113896Sphk else if (i != sizeof (boot)) 426113896Sphk errx(1, "read wrong size boot code (%d)", i); 427113896Sphk close(bfd); 428113896Sphk } 429113896Sphk snprintf(path, sizeof(path), "%s%s", _PATH_DEV, disk); 430113896Sphk fd = open(path, O_RDWR); 431113896Sphk if (fd < 0) { 432115624Sphk grq = gctl_get_handle(); 433115624Sphk gctl_ro_param(grq, "verb", -1, "write label"); 434113896Sphk gctl_ro_param(grq, "class", -1, "SUN"); 435113896Sphk gctl_ro_param(grq, "geom", -1, disk); 436113896Sphk gctl_ro_param(grq, "label", sizeof buf, buf); 437113896Sphk errstr = gctl_issue(grq); 438113896Sphk if (errstr != NULL) 439113896Sphk errx(1, "%s", errstr); 440113896Sphk gctl_free(grq); 441110130Sjake if (Bflag) { 442115624Sphk grq = gctl_get_handle(); 443115624Sphk gctl_ro_param(grq, "verb", -1, "write bootcode"); 444113896Sphk gctl_ro_param(grq, "class", -1, "SUN"); 445113896Sphk gctl_ro_param(grq, "geom", -1, disk); 446113896Sphk gctl_ro_param(grq, "bootcode", sizeof boot, boot); 447113896Sphk errstr = gctl_issue(grq); 448113896Sphk if (errstr != NULL) 449113896Sphk errx(1, "%s", errstr); 450113896Sphk gctl_free(grq); 451113896Sphk } 452113896Sphk } else { 453113896Sphk if (lseek(fd, 0, SEEK_SET) < 0) 454113896Sphk err(1, "lseek"); 455113896Sphk if (write(fd, buf, sizeof(buf)) != sizeof(buf)) 456113896Sphk err (1, "write"); 457113896Sphk if (Bflag) { 458113824Sphk for (i = 0; i < SUN_NPART; i++) { 459110130Sjake if (sl->sl_part[i].sdkp_nsectors == 0) 460110130Sjake continue; 461110130Sjake off = sl->sl_part[i].sdkp_cyloffset * 462110130Sjake sl->sl_ntracks * sl->sl_nsectors * 512; 463113896Sphk /* 464113896Sphk * Ignore first SUN_SIZE bytes of boot code to 465113896Sphk * avoid overwriting the label. 466113896Sphk */ 467113896Sphk if (lseek(fd, off + SUN_SIZE, SEEK_SET) < 0) 468110130Sjake err(1, "lseek"); 469113896Sphk if (write(fd, boot + SUN_SIZE, 470113896Sphk sizeof(boot) - SUN_SIZE) != 471113896Sphk sizeof(boot) - SUN_SIZE) 472110130Sjake err(1, "write"); 473110130Sjake } 474110130Sjake } 475110130Sjake close(fd); 476113896Sphk } 477113896Sphk exit(0); 478110130Sjake} 479110130Sjake 480129965Sjoergstatic void 481110130Sjakeedit_label(struct sun_disklabel *sl, const char *disk, const char *bootpath) 482110130Sjake{ 483110130Sjake char tmpfil[] = _PATH_TMPFILE; 484110130Sjake const char *editor; 485110130Sjake int status; 486110130Sjake FILE *fp; 487110130Sjake pid_t pid; 488110130Sjake pid_t r; 489110130Sjake int fd; 490110130Sjake int c; 491110130Sjake 492110130Sjake if ((fd = mkstemp(tmpfil)) < 0) 493110130Sjake err(1, "mkstemp"); 494110130Sjake if ((fp = fdopen(fd, "w")) == NULL) 495110130Sjake err(1, "fdopen"); 496110130Sjake print_label(sl, disk, fp); 497110130Sjake fflush(fp); 498129965Sjoerg for (;;) { 499129965Sjoerg if ((pid = fork()) < 0) 500129965Sjoerg err(1, "fork"); 501129965Sjoerg if (pid == 0) { 502129965Sjoerg if ((editor = getenv("EDITOR")) == NULL) 503129965Sjoerg editor = _PATH_VI; 504129965Sjoerg execlp(editor, editor, tmpfil, (char *)NULL); 505129965Sjoerg err(1, "execlp %s", editor); 506110130Sjake } 507129965Sjoerg status = 0; 508129965Sjoerg while ((r = wait(&status)) > 0 && r != pid) 509129965Sjoerg ; 510129965Sjoerg if (WIFEXITED(status)) { 511129965Sjoerg if (parse_label(sl, tmpfil) == 0) { 512129965Sjoerg fclose(fp); 513129965Sjoerg unlink(tmpfil); 514129965Sjoerg write_label(sl, disk, bootpath); 515129965Sjoerg return; 516129965Sjoerg } 517129965Sjoerg printf("re-edit the label? [y]: "); 518129965Sjoerg fflush(stdout); 519129965Sjoerg c = getchar(); 520129965Sjoerg if (c != EOF && c != '\n') 521129965Sjoerg while (getchar() != '\n') 522129965Sjoerg ; 523129965Sjoerg if (c == 'n') { 524129965Sjoerg fclose(fp); 525129965Sjoerg unlink(tmpfil); 526129965Sjoerg return; 527129965Sjoerg } 528110130Sjake } 529110130Sjake } 530110130Sjake fclose(fp); 531110130Sjake unlink(tmpfil); 532129965Sjoerg return; 533110130Sjake} 534110130Sjake 535110130Sjakestatic int 536110130Sjakeparse_label(struct sun_disklabel *sl, const char *file) 537110130Sjake{ 538110130Sjake char offset[32]; 539110130Sjake char size[32]; 540129965Sjoerg char flag[32]; 541129965Sjoerg char tag[32]; 542110130Sjake char buf[128]; 543129965Sjoerg char text[128]; 544144328Sjoerg char volname[SUN_VOLNAME_LEN + 1]; 545129965Sjoerg struct sun_disklabel sl1; 546128916Sjoerg char *bp; 547129965Sjoerg const char *what; 548110130Sjake uint8_t part; 549110130Sjake FILE *fp; 550110130Sjake int line; 551129965Sjoerg int rv; 552129965Sjoerg int wantvtoc; 553129965Sjoerg unsigned alt, cyl, hd, nr, sec; 554110130Sjake 555129965Sjoerg line = wantvtoc = 0; 556110130Sjake if ((fp = fopen(file, "r")) == NULL) 557110130Sjake err(1, "fopen"); 558129965Sjoerg sl1 = *sl; 559129965Sjoerg bzero(&sl1.sl_part, sizeof(sl1.sl_part)); 560110130Sjake while (fgets(buf, sizeof(buf), fp) != NULL) { 561128916Sjoerg /* 562128916Sjoerg * In order to recognize a partition entry, we search 563128916Sjoerg * for lines starting with a single letter followed by 564128916Sjoerg * a colon as their first non-white characters. We 565128916Sjoerg * silently ignore any other lines, so any comment etc. 566128916Sjoerg * lines in the label template will be ignored. 567128916Sjoerg * 568128916Sjoerg * XXX We should probably also recognize the geometry 569128916Sjoerg * fields on top, and allow changing the geometry 570128916Sjoerg * emulated by this disk. 571128916Sjoerg */ 572128916Sjoerg for (bp = buf; isspace(*bp); bp++) 573128916Sjoerg ; 574129965Sjoerg if (strncmp(bp, "text:", strlen("text:")) == 0) { 575129965Sjoerg bp += strlen("text:"); 576129965Sjoerg rv = sscanf(bp, 577130692Sjoerg " %s cyl %u alt %u hd %u sec %u", 578130692Sjoerg text, &cyl, &alt, &hd, &sec); 579129965Sjoerg if (rv != 5) { 580129965Sjoerg warnx("%s, line %d: text label does not " 581130692Sjoerg "contain required fields", 582130692Sjoerg file, line + 1); 583129965Sjoerg fclose(fp); 584129965Sjoerg return (1); 585129965Sjoerg } 586129965Sjoerg if (alt != 2) { 587129965Sjoerg warnx("%s, line %d: # alt must be equal 2", 588130692Sjoerg file, line + 1); 589129965Sjoerg fclose(fp); 590129965Sjoerg return (1); 591129965Sjoerg } 592129965Sjoerg if (cyl == 0 || cyl > USHRT_MAX) { 593129965Sjoerg what = "cyl"; 594129965Sjoerg nr = cyl; 595129965Sjoerg unreasonable: 596129965Sjoerg warnx("%s, line %d: # %s %d unreasonable", 597130692Sjoerg file, line + 1, what, nr); 598129965Sjoerg fclose(fp); 599129965Sjoerg return (1); 600129965Sjoerg } 601129965Sjoerg if (hd == 0 || hd > USHRT_MAX) { 602129965Sjoerg what = "hd"; 603129965Sjoerg nr = hd; 604129965Sjoerg goto unreasonable; 605129965Sjoerg } 606129965Sjoerg if (sec == 0 || sec > USHRT_MAX) { 607129965Sjoerg what = "sec"; 608129965Sjoerg nr = sec; 609129965Sjoerg goto unreasonable; 610129965Sjoerg } 611129965Sjoerg if (mediasize == 0) 612129965Sjoerg warnx("unit size unknown, no sector count " 613130692Sjoerg "check could be done"); 614129965Sjoerg else if ((uintmax_t)(cyl + alt) * sec * hd > 615129965Sjoerg (uintmax_t)mediasize / sectorsize) { 616129965Sjoerg warnx("%s, line %d: sector count %ju exceeds " 617130692Sjoerg "unit size %ju", 618130692Sjoerg file, line + 1, 619130692Sjoerg (uintmax_t)(cyl + alt) * sec * hd, 620130692Sjoerg (uintmax_t)mediasize / sectorsize); 621129965Sjoerg fclose(fp); 622129965Sjoerg return (1); 623129965Sjoerg } 624129965Sjoerg sl1.sl_pcylinders = cyl + alt; 625129965Sjoerg sl1.sl_ncylinders = cyl; 626129965Sjoerg sl1.sl_acylinders = alt; 627129965Sjoerg sl1.sl_nsectors = sec; 628129965Sjoerg sl1.sl_ntracks = hd; 629129965Sjoerg memset(sl1.sl_text, 0, sizeof(sl1.sl_text)); 630129965Sjoerg snprintf(sl1.sl_text, sizeof(sl1.sl_text), 631130692Sjoerg "%s cyl %u alt %u hd %u sec %u", 632130692Sjoerg text, cyl, alt, hd, sec); 633129965Sjoerg continue; 634129965Sjoerg } 635144328Sjoerg if (strncmp(bp, "volume name:", strlen("volume name:")) == 0) { 636144328Sjoerg wantvtoc = 1; /* Volume name requires VTOC. */ 637144328Sjoerg bp += strlen("volume name:"); 638144328Sjoerg#if SUN_VOLNAME_LEN != 8 639144328Sjoerg# error "scanf field width does not match SUN_VOLNAME_LEN" 640144328Sjoerg#endif 641144328Sjoerg /* 642144328Sjoerg * We set the field length to one more than 643144328Sjoerg * SUN_VOLNAME_LEN to allow detecting an 644144328Sjoerg * overflow. 645144328Sjoerg */ 646144328Sjoerg memset(volname, 0, sizeof volname); 647144328Sjoerg rv = sscanf(bp, " %9[^\n]", volname); 648144328Sjoerg if (rv != 1) { 649144328Sjoerg /* Clear the volume name. */ 650144328Sjoerg memset(sl1.sl_vtoc_volname, 0, 651144328Sjoerg SUN_VOLNAME_LEN); 652144328Sjoerg } else { 653144328Sjoerg memcpy(sl1.sl_vtoc_volname, volname, 654144328Sjoerg SUN_VOLNAME_LEN); 655144328Sjoerg if (volname[SUN_VOLNAME_LEN] != '\0') 656144328Sjoerg warnx( 657144328Sjoerg"%s, line %d: volume name longer than %d characters, truncating", 658144328Sjoerg file, line + 1, SUN_VOLNAME_LEN); 659144328Sjoerg } 660144328Sjoerg continue; 661144328Sjoerg } 662128916Sjoerg if (strlen(bp) < 2 || bp[1] != ':') { 663128916Sjoerg line++; 664110130Sjake continue; 665128916Sjoerg } 666129965Sjoerg rv = sscanf(bp, "%c: %30s %30s %30s %30s", 667130692Sjoerg &part, size, offset, tag, flag); 668129965Sjoerg if (rv < 3) { 669129965Sjoerg syntaxerr: 670128916Sjoerg warnx("%s: syntax error on line %d", 671128916Sjoerg file, line + 1); 672110130Sjake fclose(fp); 673110130Sjake return (1); 674110130Sjake } 675129965Sjoerg if (parse_size(&sl1, part - 'a', size) || 676129965Sjoerg parse_offset(&sl1, part - 'a', offset)) 677129965Sjoerg goto syntaxerr; 678129965Sjoerg if (rv > 3) { 679129965Sjoerg wantvtoc = 1; 680129965Sjoerg if (rv == 5 && parse_flag(&sl1, part - 'a', flag)) 681129965Sjoerg goto syntaxerr; 682129965Sjoerg if (parse_tag(&sl1, part - 'a', tag)) 683129965Sjoerg goto syntaxerr; 684129965Sjoerg } 685110130Sjake line++; 686110130Sjake } 687110130Sjake fclose(fp); 688129965Sjoerg if (wantvtoc) { 689129965Sjoerg sl1.sl_vtoc_sane = SUN_VTOC_SANE; 690129965Sjoerg sl1.sl_vtoc_vers = SUN_VTOC_VERSION; 691129965Sjoerg sl1.sl_vtoc_nparts = SUN_NPART; 692129965Sjoerg } else { 693129965Sjoerg sl1.sl_vtoc_sane = 0; 694129965Sjoerg sl1.sl_vtoc_vers = 0; 695129965Sjoerg sl1.sl_vtoc_nparts = 0; 696129965Sjoerg bzero(&sl1.sl_vtoc_map, sizeof(sl1.sl_vtoc_map)); 697129965Sjoerg } 698129965Sjoerg *sl = sl1; 699110130Sjake return (check_label(sl)); 700110130Sjake} 701110130Sjake 702110130Sjakestatic int 703110130Sjakeparse_size(struct sun_disklabel *sl, int part, char *size) 704110130Sjake{ 705110130Sjake uintmax_t nsectors; 706110130Sjake uintmax_t total; 707110130Sjake uintmax_t n; 708110130Sjake char *p; 709110130Sjake int i; 710110130Sjake 711110130Sjake nsectors = 0; 712110130Sjake n = strtoumax(size, &p, 10); 713110130Sjake if (*p != '\0') { 714110130Sjake if (strcmp(size, "*") == 0) { 715110130Sjake total = sl->sl_ncylinders * sl->sl_ntracks * 716110130Sjake sl->sl_nsectors; 717110130Sjake for (i = 0; i < part; i++) { 718110130Sjake if (i == 2) 719110130Sjake continue; 720110130Sjake nsectors += sl->sl_part[i].sdkp_nsectors; 721110130Sjake } 722110130Sjake n = total - nsectors; 723129965Sjoerg } else if (p[1] == '\0' && (p[0] == 'C' || p[0] == 'c')) { 724129965Sjoerg n = n * sl->sl_ntracks * sl->sl_nsectors; 725110130Sjake } else if (p[1] == '\0' && (p[0] == 'K' || p[0] == 'k')) { 726110130Sjake n = roundup((n * 1024) / 512, 727110130Sjake sl->sl_ntracks * sl->sl_nsectors); 728110130Sjake } else if (p[1] == '\0' && (p[0] == 'M' || p[0] == 'm')) { 729110130Sjake n = roundup((n * 1024 * 1024) / 512, 730110130Sjake sl->sl_ntracks * sl->sl_nsectors); 731129965Sjoerg } else if (p[1] == '\0' && (p[0] == 'S' || p[0] == 's')) { 732129965Sjoerg /* size in sectors, no action neded */ 733110130Sjake } else if (p[1] == '\0' && (p[0] == 'G' || p[0] == 'g')) { 734110130Sjake n = roundup((n * 1024 * 1024 * 1024) / 512, 735110130Sjake sl->sl_ntracks * sl->sl_nsectors); 736110130Sjake } else 737110130Sjake return (-1); 738129965Sjoerg } else if (cflag) { 739129965Sjoerg n = n * sl->sl_ntracks * sl->sl_nsectors; 740110130Sjake } 741110130Sjake sl->sl_part[part].sdkp_nsectors = n; 742110130Sjake return (0); 743110130Sjake} 744110130Sjake 745110130Sjakestatic int 746110130Sjakeparse_offset(struct sun_disklabel *sl, int part, char *offset) 747110130Sjake{ 748110130Sjake uintmax_t nsectors; 749110130Sjake uintmax_t n; 750110130Sjake char *p; 751110130Sjake int i; 752110130Sjake 753110130Sjake nsectors = 0; 754110130Sjake n = strtoumax(offset, &p, 10); 755110130Sjake if (*p != '\0') { 756110130Sjake if (strcmp(offset, "*") == 0) { 757110130Sjake for (i = 0; i < part; i++) { 758110130Sjake if (i == 2) 759110130Sjake continue; 760110130Sjake nsectors += sl->sl_part[i].sdkp_nsectors; 761110130Sjake } 762110130Sjake n = nsectors / (sl->sl_nsectors * sl->sl_ntracks); 763110130Sjake } else 764110130Sjake return (-1); 765110130Sjake } 766110130Sjake sl->sl_part[part].sdkp_cyloffset = n; 767110130Sjake return (0); 768110130Sjake} 769110130Sjake 770110130Sjakestatic void 771110130Sjakeprint_label(struct sun_disklabel *sl, const char *disk, FILE *out) 772110130Sjake{ 773144328Sjoerg int i, j; 774129965Sjoerg int havevtoc; 775129965Sjoerg uintmax_t secpercyl; 776144328Sjoerg /* Long enough to hex-encode each character. */ 777144328Sjoerg char volname[4 * SUN_VOLNAME_LEN + 1]; 778110130Sjake 779129965Sjoerg havevtoc = sl->sl_vtoc_sane == SUN_VTOC_SANE; 780129965Sjoerg secpercyl = sl->sl_nsectors * sl->sl_ntracks; 781129965Sjoerg 782110130Sjake fprintf(out, 783110130Sjake"# /dev/%s:\n" 784110130Sjake"text: %s\n" 785141956Sobrien"bytes/sector: %d\n" 786129965Sjoerg"sectors/cylinder: %ju\n", 787129965Sjoerg disk, 788129965Sjoerg sl->sl_text, 789129965Sjoerg sectorsize, 790129965Sjoerg secpercyl); 791129965Sjoerg if (eflag) 792129965Sjoerg fprintf(out, 793130692Sjoerg "# max sectors/unit (including alt cylinders): %ju\n", 794130692Sjoerg (uintmax_t)mediasize / sectorsize); 795129965Sjoerg fprintf(out, 796144328Sjoerg"sectors/unit: %ju\n", 797144328Sjoerg secpercyl * sl->sl_ncylinders); 798144328Sjoerg if (havevtoc && sl->sl_vtoc_volname[0] != '\0') { 799144328Sjoerg for (i = j = 0; i < SUN_VOLNAME_LEN; i++) { 800144328Sjoerg if (sl->sl_vtoc_volname[i] == '\0') 801144328Sjoerg break; 802144328Sjoerg if (isprint(sl->sl_vtoc_volname[i])) 803144328Sjoerg volname[j++] = sl->sl_vtoc_volname[i]; 804144328Sjoerg else 805144328Sjoerg j += sprintf(volname + j, "\\x%02X", 806144328Sjoerg sl->sl_vtoc_volname[i]); 807144328Sjoerg } 808144328Sjoerg volname[j] = '\0'; 809144328Sjoerg fprintf(out, "volume name: %s\n", volname); 810144328Sjoerg } 811144328Sjoerg fprintf(out, 812110130Sjake"\n" 813113824Sphk"%d partitions:\n" 814129965Sjoerg"#\n", 815129965Sjoerg SUN_NPART); 816129965Sjoerg if (!hflag) { 817129965Sjoerg fprintf(out, "# Size is in %s.", cflag? "cylinders": "sectors"); 818129965Sjoerg if (eflag) 819129965Sjoerg fprintf(out, 820129965Sjoerg" Use %%d%c, %%dK, %%dM or %%dG to specify in %s,\n" 821129965Sjoerg"# kilobytes, megabytes or gigabytes respectively, or '*' to specify rest of\n" 822129965Sjoerg"# disk.\n", 823130692Sjoerg cflag? 's': 'c', 824130692Sjoerg cflag? "sectors": "cylinders"); 825129965Sjoerg else 826129965Sjoerg putc('\n', out); 827129965Sjoerg fprintf(out, "# Offset is in cylinders."); 828129965Sjoerg if (eflag) 829129965Sjoerg fprintf(out, 830129965Sjoerg" Use '*' to calculate offsets automatically.\n" 831129965Sjoerg"#\n"); 832129965Sjoerg else 833129965Sjoerg putc('\n', out); 834129965Sjoerg } 835129965Sjoerg if (havevtoc) 836129965Sjoerg fprintf(out, 837129965Sjoerg"# size offset tag flag\n" 838129965Sjoerg"# ---------- ---------- ---------- ----\n" 839129965Sjoerg ); 840129965Sjoerg else 841129965Sjoerg fprintf(out, 842110130Sjake"# size offset\n" 843129965Sjoerg"# ---------- ----------\n" 844129965Sjoerg ); 845129965Sjoerg 846113824Sphk for (i = 0; i < SUN_NPART; i++) { 847110130Sjake if (sl->sl_part[i].sdkp_nsectors == 0) 848110130Sjake continue; 849129965Sjoerg if (hflag) { 850129965Sjoerg fprintf(out, " %c: %10s", 851130692Sjoerg 'a' + i, 852130692Sjoerg make_h_number((uintmax_t) 853130692Sjoerg sl->sl_part[i].sdkp_nsectors * 512)); 854129965Sjoerg fprintf(out, " %10s", 855130692Sjoerg make_h_number((uintmax_t) 856130692Sjoerg sl->sl_part[i].sdkp_cyloffset * 512 857130692Sjoerg * secpercyl)); 858129965Sjoerg } else { 859129965Sjoerg fprintf(out, " %c: %10ju %10u", 860130692Sjoerg 'a' + i, 861130692Sjoerg sl->sl_part[i].sdkp_nsectors / (cflag? secpercyl: 1), 862130692Sjoerg sl->sl_part[i].sdkp_cyloffset); 863129965Sjoerg } 864129965Sjoerg if (havevtoc) 865129965Sjoerg fprintf(out, " %11s %5s", 866130692Sjoerg tagname(sl->sl_vtoc_map[i].svtoc_tag), 867130692Sjoerg flagname(sl->sl_vtoc_map[i].svtoc_flag)); 868129965Sjoerg putc('\n', out); 869110130Sjake } 870110130Sjake} 871110130Sjake 872110130Sjakestatic void 873110130Sjakeusage(void) 874110130Sjake{ 875110130Sjake 876110130Sjake fprintf(stderr, "usage:" 877129965Sjoerg"\t%s [-r] [-c | -h] disk\n" 878110130Sjake"\t\t(to read label)\n" 879110130Sjake"\t%s -B [-b boot1] [-n] disk\n" 880110130Sjake"\t\t(to install boot program only)\n" 881129965Sjoerg"\t%s -R [-B [-b boot1]] [-r] [-n] [-c] disk protofile\n" 882110130Sjake"\t\t(to restore label)\n" 883129965Sjoerg"\t%s -e [-B [-b boot1]] [-r] [-n] [-c] disk\n" 884110130Sjake"\t\t(to edit label)\n" 885110130Sjake"\t%s -w [-B [-b boot1]] [-r] [-n] disk type\n" 886110130Sjake"\t\t(to write default label)\n", 887110130Sjake __progname, 888110130Sjake __progname, 889110130Sjake __progname, 890110130Sjake __progname, 891110130Sjake __progname); 892110130Sjake exit(1); 893110130Sjake} 894129965Sjoerg 895129965Sjoerg/* 896129965Sjoerg * Return VTOC tag and flag names for tag or flag ID, resp. 897129965Sjoerg */ 898129965Sjoergstatic const char * 899129965Sjoergtagname(unsigned int tag) 900129965Sjoerg{ 901129965Sjoerg static char buf[32]; 902129965Sjoerg size_t i; 903129965Sjoerg struct tags *tp; 904129965Sjoerg 905129965Sjoerg for (i = 0, tp = knowntags; 906129965Sjoerg i < sizeof(knowntags) / sizeof(struct tags); 907129965Sjoerg i++, tp++) 908129965Sjoerg if (tp->id == tag) 909129965Sjoerg return (tp->name); 910129965Sjoerg 911129965Sjoerg sprintf(buf, "%u", tag); 912129965Sjoerg 913129965Sjoerg return (buf); 914129965Sjoerg} 915129965Sjoerg 916129965Sjoergstatic const char * 917129965Sjoergflagname(unsigned int flag) 918129965Sjoerg{ 919129965Sjoerg static char buf[32]; 920129965Sjoerg size_t i; 921129965Sjoerg struct tags *tp; 922129965Sjoerg 923129965Sjoerg for (i = 0, tp = knownflags; 924129965Sjoerg i < sizeof(knownflags) / sizeof(struct tags); 925129965Sjoerg i++, tp++) 926129965Sjoerg if (tp->id == flag) 927129965Sjoerg return (tp->name); 928129965Sjoerg 929129965Sjoerg sprintf(buf, "%u", flag); 930129965Sjoerg 931129965Sjoerg return (buf); 932129965Sjoerg} 933129965Sjoerg 934129965Sjoergstatic unsigned int 935129965Sjoergparse_tag(struct sun_disklabel *sl, int part, const char *tag) 936129965Sjoerg{ 937129965Sjoerg struct tags *tp; 938129965Sjoerg char *endp; 939129965Sjoerg size_t i; 940129965Sjoerg unsigned long l; 941129965Sjoerg 942129965Sjoerg for (i = 0, tp = knowntags; 943129965Sjoerg i < sizeof(knowntags) / sizeof(struct tags); 944129965Sjoerg i++, tp++) 945129965Sjoerg if (strcmp(tp->name, tag) == 0) { 946129965Sjoerg sl->sl_vtoc_map[part].svtoc_tag = (uint16_t)tp->id; 947129965Sjoerg return (0); 948129965Sjoerg } 949129965Sjoerg 950129965Sjoerg l = strtoul(tag, &endp, 0); 951129965Sjoerg if (*tag != '\0' && *endp == '\0') { 952129965Sjoerg sl->sl_vtoc_map[part].svtoc_tag = (uint16_t)l; 953129965Sjoerg return (0); 954129965Sjoerg } 955129965Sjoerg 956129965Sjoerg return (-1); 957129965Sjoerg} 958129965Sjoerg 959129965Sjoergstatic unsigned int 960129965Sjoergparse_flag(struct sun_disklabel *sl, int part, const char *flag) 961129965Sjoerg{ 962129965Sjoerg struct tags *tp; 963129965Sjoerg char *endp; 964129965Sjoerg size_t i; 965129965Sjoerg unsigned long l; 966129965Sjoerg 967129965Sjoerg for (i = 0, tp = knownflags; 968129965Sjoerg i < sizeof(knownflags) / sizeof(struct tags); 969129965Sjoerg i++, tp++) 970129965Sjoerg if (strcmp(tp->name, flag) == 0) { 971129965Sjoerg sl->sl_vtoc_map[part].svtoc_flag = (uint16_t)tp->id; 972129965Sjoerg return (0); 973129965Sjoerg } 974129965Sjoerg 975129965Sjoerg l = strtoul(flag, &endp, 0); 976129965Sjoerg if (*flag != '\0' && *endp == '\0') { 977129965Sjoerg sl->sl_vtoc_map[part].svtoc_flag = (uint16_t)l; 978129965Sjoerg return (0); 979129965Sjoerg } 980129965Sjoerg 981129965Sjoerg return (-1); 982129965Sjoerg} 983129965Sjoerg 984129965Sjoerg/* 985129965Sjoerg * Convert argument into `human readable' byte number form. 986129965Sjoerg */ 987129965Sjoergstatic const char * 988129965Sjoergmake_h_number(uintmax_t u) 989129965Sjoerg{ 990129965Sjoerg static char buf[32]; 991129965Sjoerg double d; 992129965Sjoerg 993129965Sjoerg if (u == 0) { 994129965Sjoerg strcpy(buf, "0B"); 995129965Sjoerg } else if (u > 2000000000UL) { 996129965Sjoerg d = (double)u / 1e9; 997129965Sjoerg sprintf(buf, "%.1fG", d); 998129965Sjoerg } else if (u > 2000000UL) { 999129965Sjoerg d = (double)u / 1e6; 1000129965Sjoerg sprintf(buf, "%.1fM", d); 1001129965Sjoerg } else { 1002129965Sjoerg d = (double)u / 1e3; 1003129965Sjoerg sprintf(buf, "%.1fK", d); 1004129965Sjoerg } 1005129965Sjoerg 1006129965Sjoerg return (buf); 1007129965Sjoerg} 1008