130715Sbostic /* 235983Sbostic * Copyright (c) 1987 The Regents of the University of California. 335983Sbostic * All rights reserved. 435983Sbostic * 535983Sbostic * This code is derived from software contributed to Berkeley by 635983Sbostic * Symmetric Computer Systems. 735983Sbostic * 835983Sbostic * Redistribution and use in source and binary forms are permitted 935983Sbostic * provided that the above copyright notice and this paragraph are 1035983Sbostic * duplicated in all such forms and that any documentation, 1135983Sbostic * advertising materials, and other materials related to such 1235983Sbostic * distribution and use acknowledge that the software was developed 1335983Sbostic * by the University of California, Berkeley. The name of the 1435983Sbostic * University may not be used to endorse or promote products derived 1535983Sbostic * from this software without specific prior written permission. 1635983Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1735983Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1835983Sbostic * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1930715Sbostic */ 2030715Sbostic 2130418Skarels #ifndef lint 2235983Sbostic char copyright[] = 2335983Sbostic "@(#) Copyright (c) 1987 The Regents of the University of California.\n\ 2435983Sbostic All rights reserved.\n"; 2535983Sbostic #endif /* not lint */ 2635983Sbostic 2735983Sbostic #ifndef lint 28*42042Sbostic static char sccsid[] = "@(#)disklabel.c 5.18 (Berkeley) 05/15/90"; 2930418Skarels /* from static char sccsid[] = "@(#)disklabel.c 1.2 (Symmetric) 11/28/85"; */ 3035983Sbostic #endif /* not lint */ 3130418Skarels 3230418Skarels #include <sys/param.h> 3330715Sbostic #include <sys/signal.h> 3430418Skarels #include <sys/errno.h> 3530418Skarels #include <sys/file.h> 3630715Sbostic #include <sys/ioctl.h> 3738505Sbostic #include <ufs/fs.h> 38*42042Sbostic #include <string.h> 3930418Skarels #define DKTYPENAMES 4030418Skarels #include <sys/disklabel.h> 4137261Sbostic #include <stdio.h> 4237261Sbostic #include <ctype.h> 4337261Sbostic #include "pathnames.h" 4430418Skarels 4530418Skarels /* 4630418Skarels * Disklabel: read and write disklabels. 4730418Skarels * The label is usually placed on one of the first sectors of the disk. 4830418Skarels * Many machines (VAX 11/750) also place a bootstrap in the same area, 4930418Skarels * in which case the label is embedded in the bootstrap. 5030418Skarels * The bootstrap source must leave space at the proper offset 5130418Skarels * for the label on such machines. 5230418Skarels */ 5330418Skarels 5430677Skarels #ifdef vax 5530677Skarels #define RAWPARTITION 'c' 5630677Skarels #else 5730677Skarels #define RAWPARTITION 'a' 5830677Skarels #endif 5930677Skarels 6030677Skarels #ifndef BBSIZE 6130418Skarels #define BBSIZE 8192 /* size of boot area, with label */ 6230677Skarels #endif 6330418Skarels 6430418Skarels #ifdef vax 6530418Skarels #define BOOT /* also have bootstrap in "boot area" */ 6637261Sbostic #define BOOTDIR _PATH_BOOTDIR /* source of boot binaries */ 6730677Skarels #else 6830677Skarels #ifdef lint 6930677Skarels #define BOOT 7030418Skarels #endif 7130677Skarels #endif 7230418Skarels 7338505Sbostic #define DEFEDITOR _PATH_VI 7430715Sbostic #define streq(a,b) (strcmp(a,b) == 0) 7530715Sbostic 7630715Sbostic #ifdef BOOT 7730418Skarels char *xxboot; 7830418Skarels char *bootxx; 7930715Sbostic #endif 8031617Skarels 8131617Skarels char *dkname; 8230418Skarels char *specname; 8337945Sbostic char tmpfil[] = _PATH_TMP; 8430418Skarels 8530418Skarels extern int errno; 8630418Skarels char namebuf[BBSIZE], *np = namebuf; 8731617Skarels struct disklabel lab; 8831617Skarels struct disklabel *readlabel(), *makebootarea(); 8930418Skarels char bootarea[BBSIZE]; 9034032Skarels char boot0[MAXPATHLEN]; 9134032Skarels char boot1[MAXPATHLEN]; 9230418Skarels 9334032Skarels enum { UNSPEC, EDIT, NOWRITE, READ, RESTORE, WRITE, WRITEABLE } op = UNSPEC; 9430418Skarels 9530677Skarels int rflag; 9630677Skarels 9734032Skarels #ifdef DEBUG 9834032Skarels int debug; 9934032Skarels #endif 10034032Skarels 10130418Skarels main(argc, argv) 10230418Skarels int argc; 10330418Skarels char *argv[]; 10430418Skarels { 10534032Skarels extern int optind; 10630418Skarels register struct disklabel *lp; 10734032Skarels FILE *t; 10834641Skarels int ch, f, error = 0; 10930715Sbostic char *name = 0, *type; 11030418Skarels 11134032Skarels while ((ch = getopt(argc, argv, "NRWerw")) != EOF) 11234032Skarels switch (ch) { 11334032Skarels case 'N': 11434032Skarels if (op != UNSPEC) 11534032Skarels usage(); 11634032Skarels op = NOWRITE; 11734032Skarels break; 11830715Sbostic case 'R': 11934032Skarels if (op != UNSPEC) 12034032Skarels usage(); 12130715Sbostic op = RESTORE; 12230715Sbostic break; 12334032Skarels case 'W': 12434032Skarels if (op != UNSPEC) 12534032Skarels usage(); 12634032Skarels op = WRITEABLE; 12734032Skarels break; 12830715Sbostic case 'e': 12934032Skarels if (op != UNSPEC) 13034032Skarels usage(); 13130715Sbostic op = EDIT; 13230715Sbostic break; 13330715Sbostic case 'r': 13430715Sbostic ++rflag; 13530715Sbostic break; 13630715Sbostic case 'w': 13734032Skarels if (op != UNSPEC) 13834032Skarels usage(); 13930715Sbostic op = WRITE; 14030715Sbostic break; 14134032Skarels #ifdef DEBUG 14234032Skarels case 'd': 14334032Skarels debug++; 14434032Skarels break; 14534032Skarels #endif 14630715Sbostic case '?': 14730715Sbostic default: 14830715Sbostic usage(); 14930715Sbostic } 15030715Sbostic argc -= optind; 15130715Sbostic argv += optind; 15234032Skarels if (op == UNSPEC) 15334032Skarels op = READ; 15430715Sbostic if (argc < 1) 15530715Sbostic usage(); 15630715Sbostic 15730715Sbostic dkname = argv[0]; 15830418Skarels if (dkname[0] != '/') { 15937945Sbostic (void)sprintf(np, "%s/r%s%c", _PATH_DEV, dkname, RAWPARTITION); 16030418Skarels specname = np; 16130418Skarels np += strlen(specname) + 1; 16230418Skarels } else 16330418Skarels specname = dkname; 16430418Skarels f = open(specname, op == READ ? O_RDONLY : O_RDWR); 16530418Skarels if (f < 0 && errno == ENOENT && dkname[0] != '/') { 16637945Sbostic (void)sprintf(specname, "%s/r%s", _PATH_DEV, dkname); 16730418Skarels np = namebuf + strlen(specname) + 1; 16830418Skarels f = open(specname, op == READ ? O_RDONLY : O_RDWR); 16930418Skarels } 17030418Skarels if (f < 0) 17130418Skarels Perror(specname); 17230418Skarels 17330715Sbostic switch(op) { 17430715Sbostic case EDIT: 17530715Sbostic if (argc != 1) 17630715Sbostic usage(); 17734032Skarels lp = readlabel(f); 17834641Skarels error = edit(lp, f); 17930715Sbostic break; 18034032Skarels case NOWRITE: { 18134032Skarels int flag = 0; 18234032Skarels if (ioctl(f, DIOCWLABEL, (char *)&flag) < 0) 18334032Skarels Perror("ioctl DIOCWLABEL"); 18434032Skarels break; 18534032Skarels } 18630418Skarels case READ: 18730715Sbostic if (argc != 1) 18830715Sbostic usage(); 18934032Skarels lp = readlabel(f); 19030418Skarels display(stdout, lp); 19134641Skarels error = checklabel(lp); 19230418Skarels break; 19330715Sbostic case RESTORE: 19430715Sbostic #ifdef BOOT 19534032Skarels if (rflag) { 19634032Skarels if (argc == 4) { /* [ priboot secboot ] */ 19734032Skarels xxboot = argv[2]; 19834032Skarels bootxx = argv[3]; 19934032Skarels lab.d_secsize = DEV_BSIZE; /* XXX */ 20034032Skarels lab.d_bbsize = BBSIZE; /* XXX */ 20134032Skarels } 20234032Skarels else if (argc == 3) /* [ disktype ] */ 20334032Skarels makelabel(argv[2], (char *)NULL, &lab); 20434032Skarels else { 20534032Skarels fprintf(stderr, 20634032Skarels "Must specify either disktype or bootfiles with -r flag of RESTORE option\n"); 20734032Skarels exit(1); 20834032Skarels } 20934032Skarels } 21034032Skarels else 21131617Skarels #endif 21230715Sbostic if (argc != 2) 21330715Sbostic usage(); 21431617Skarels lp = makebootarea(bootarea, &lab); 21530715Sbostic if (!(t = fopen(argv[1],"r"))) 21630715Sbostic Perror(argv[1]); 21730715Sbostic if (getasciilabel(t, lp)) 21834641Skarels error = writelabel(f, bootarea, lp); 21930418Skarels break; 22030418Skarels case WRITE: 22130715Sbostic type = argv[1]; 22230715Sbostic #ifdef BOOT 22330715Sbostic if (argc > 5 || argc < 2) 22430715Sbostic usage(); 22530715Sbostic if (argc > 3) { 22630715Sbostic bootxx = argv[--argc]; 22730715Sbostic xxboot = argv[--argc]; 22830715Sbostic } 22930715Sbostic #else 23030715Sbostic if (argc > 3 || argc < 2) 23130715Sbostic usage(); 23230715Sbostic #endif 23330715Sbostic if (argc > 2) 23430715Sbostic name = argv[--argc]; 23530418Skarels makelabel(type, name, &lab); 23631617Skarels lp = makebootarea(bootarea, &lab); 23730418Skarels *lp = lab; 23830715Sbostic if (checklabel(lp) == 0) 23934641Skarels error = writelabel(f, bootarea, lp); 24030418Skarels break; 24134032Skarels case WRITEABLE: { 24234032Skarels int flag = 1; 24334032Skarels if (ioctl(f, DIOCWLABEL, (char *)&flag) < 0) 24434032Skarels Perror("ioctl DIOCWLABEL"); 24534032Skarels break; 24630418Skarels } 24734032Skarels } 24834641Skarels exit(error); 24930418Skarels } 25030418Skarels 25134032Skarels /* 25234032Skarels * Construct a prototype disklabel from /etc/disktab. As a side 25334032Skarels * effect, set the names of the primary and secondary boot files 25434032Skarels * if specified. 25534032Skarels */ 25630418Skarels makelabel(type, name, lp) 25730418Skarels char *type, *name; 25830418Skarels register struct disklabel *lp; 25930418Skarels { 26030418Skarels register struct disklabel *dp; 26134032Skarels char *strcpy(); 26230418Skarels 26330418Skarels dp = getdiskbyname(type); 26430418Skarels if (dp == NULL) { 26530418Skarels fprintf(stderr, "%s: unknown disk type\n", type); 26630418Skarels exit(1); 26730418Skarels } 26830418Skarels *lp = *dp; 26934032Skarels #ifdef BOOT 27034032Skarels /* 27134032Skarels * Check if disktab specifies the bootstraps (b0 or b1). 27234032Skarels */ 27334032Skarels if (!xxboot && lp->d_boot0) { 27434032Skarels if (*lp->d_boot0 != '/') 27534032Skarels (void)sprintf(boot0, "%s/%s", BOOTDIR, lp->d_boot0); 27634032Skarels else 27734032Skarels (void)strcpy(boot0, lp->d_boot0); 27834032Skarels xxboot = boot0; 27934032Skarels } 28034032Skarels if (!bootxx && lp->d_boot1) { 28134032Skarels if (*lp->d_boot1 != '/') 28234032Skarels (void)sprintf(boot1, "%s/%s", BOOTDIR, lp->d_boot1); 28334032Skarels else 28434032Skarels (void)strcpy(boot1, lp->d_boot1); 28534032Skarels bootxx = boot1; 28634032Skarels } 28734032Skarels /* 28834032Skarels * If bootstraps not specified anywhere, makebootarea() 28934032Skarels * will choose ones based on the name of the disk special 29034032Skarels * file. E.g. /dev/ra0 -> raboot, bootra 29134032Skarels */ 29234032Skarels #endif /*BOOT*/ 29334032Skarels /* d_packname is union d_boot[01], so zero */ 29434032Skarels bzero(lp->d_packname, sizeof(lp->d_packname)); 29530418Skarels if (name) 29634032Skarels (void)strncpy(lp->d_packname, name, sizeof(lp->d_packname)); 29730418Skarels } 29830418Skarels 29930418Skarels writelabel(f, boot, lp) 30030418Skarels int f; 30130418Skarels char *boot; 30230418Skarels register struct disklabel *lp; 30330418Skarels { 30430715Sbostic register int i; 30534032Skarels int flag; 30634032Skarels off_t lseek(); 30730418Skarels 30830418Skarels lp->d_magic = DISKMAGIC; 30930418Skarels lp->d_magic2 = DISKMAGIC; 31030418Skarels lp->d_checksum = 0; 31130418Skarels lp->d_checksum = dkcksum(lp); 31230677Skarels if (rflag) { 31334032Skarels /* 31434032Skarels * First set the kernel disk label, 31534032Skarels * then write a label to the raw disk. 31634032Skarels * If the SDINFO ioctl fails because it is unimplemented, 31734032Skarels * keep going; otherwise, the kernel consistency checks 31834032Skarels * may prevent us from changing the current (in-core) 31934032Skarels * label. 32034032Skarels */ 32134032Skarels if (ioctl(f, DIOCSDINFO, lp) < 0 && 32234641Skarels errno != ENODEV && errno != ENOTTY) { 32334641Skarels l_perror("ioctl DIOCSDINFO"); 32434641Skarels return (1); 32534641Skarels } 32631617Skarels (void)lseek(f, (off_t)0, L_SET); 32734032Skarels /* 32834032Skarels * write enable label sector before write (if necessary), 32934032Skarels * disable after writing. 33034032Skarels */ 33134032Skarels flag = 1; 33234032Skarels if (ioctl(f, DIOCWLABEL, &flag) < 0) 33334032Skarels perror("ioctl DIOCWLABEL"); 33434641Skarels if (write(f, boot, lp->d_bbsize) != lp->d_bbsize) { 33534641Skarels perror("write"); 33634641Skarels return (1); 33734641Skarels } 33834032Skarels flag = 0; 33934032Skarels (void) ioctl(f, DIOCWLABEL, &flag); 34034641Skarels } else if (ioctl(f, DIOCWDINFO, lp) < 0) { 34134641Skarels l_perror("ioctl DIOCWDINFO"); 34234641Skarels return (1); 34334641Skarels } 34434032Skarels #ifdef vax 34530677Skarels if (lp->d_type == DTYPE_SMD && lp->d_flags & D_BADSECT) { 34630677Skarels daddr_t alt; 34730677Skarels 34830677Skarels alt = lp->d_ncylinders * lp->d_secpercyl - lp->d_nsectors; 34930677Skarels for (i = 1; i < 11 && i < lp->d_nsectors; i += 2) { 35030715Sbostic (void)lseek(f, (off_t)((alt + i) * lp->d_secsize), L_SET); 35130677Skarels if (write(f, boot, lp->d_secsize) < lp->d_secsize) { 35230677Skarels int oerrno = errno; 35330677Skarels fprintf(stderr, "alternate label %d ", i/2); 35430677Skarels errno = oerrno; 35530677Skarels perror("write"); 35630677Skarels } 35730418Skarels } 35830418Skarels } 35930419Skarels #endif 36034641Skarels return (0); 36130418Skarels } 36230418Skarels 36334641Skarels l_perror(s) 36434641Skarels char *s; 36534641Skarels { 36634641Skarels int saverrno = errno; 36734641Skarels 36834641Skarels fprintf(stderr, "disklabel: %s: ", s); 36934641Skarels 37034641Skarels switch (saverrno) { 37134641Skarels 37234641Skarels case ESRCH: 37334641Skarels fprintf(stderr, "No disk label on disk;\n"); 37434641Skarels fprintf(stderr, 37534641Skarels "use \"disklabel -r\" to install initial label\n"); 37634641Skarels break; 37734641Skarels 37834641Skarels case EINVAL: 37934641Skarels fprintf(stderr, "Label magic number or checksum is wrong!\n"); 38034641Skarels fprintf(stderr, "(disklabel or kernel is out of date?)\n"); 38134641Skarels break; 38234641Skarels 38334641Skarels case EBUSY: 38434641Skarels fprintf(stderr, "Open partition would move or shrink\n"); 38534641Skarels break; 38634641Skarels 38734641Skarels case EXDEV: 38834641Skarels fprintf(stderr, 38934641Skarels "Labeled partition or 'a' partition must start at beginning of disk\n"); 39034641Skarels break; 39134641Skarels 39234641Skarels default: 39334641Skarels errno = saverrno; 39434641Skarels perror((char *)NULL); 39534641Skarels break; 39634641Skarels } 39734641Skarels } 39834641Skarels 39930418Skarels /* 40031617Skarels * Fetch disklabel for disk. 40131617Skarels * Use ioctl to get label unless -r flag is given. 40230418Skarels */ 40330418Skarels struct disklabel * 40434032Skarels readlabel(f) 40534032Skarels int f; 40630418Skarels { 40730418Skarels register struct disklabel *lp; 40830418Skarels 40934032Skarels if (rflag) { 41031617Skarels if (read(f, bootarea, BBSIZE) < BBSIZE) 41131401Skarels Perror(specname); 41231617Skarels for (lp = (struct disklabel *)bootarea; 41331617Skarels lp <= (struct disklabel *)(bootarea + BBSIZE - sizeof(*lp)); 41430677Skarels lp = (struct disklabel *)((char *)lp + 16)) 41530677Skarels if (lp->d_magic == DISKMAGIC && 41630677Skarels lp->d_magic2 == DISKMAGIC) 41730677Skarels break; 41831617Skarels if (lp > (struct disklabel *)(bootarea+BBSIZE-sizeof(*lp)) || 41930677Skarels lp->d_magic != DISKMAGIC || lp->d_magic2 != DISKMAGIC || 42030677Skarels dkcksum(lp) != 0) { 42130677Skarels fprintf(stderr, 42230418Skarels "Bad pack magic number (label is damaged, or pack is unlabeled)\n"); 42334032Skarels /* lp = (struct disklabel *)(bootarea + LABELOFFSET); */ 42434032Skarels exit (1); 42530677Skarels } 42634032Skarels } else { 42734032Skarels lp = &lab; 42834032Skarels if (ioctl(f, DIOCGDINFO, lp) < 0) 42934032Skarels Perror("ioctl DIOCGDINFO"); 43030418Skarels } 43130418Skarels return (lp); 43230418Skarels } 43330418Skarels 43430418Skarels struct disklabel * 43531617Skarels makebootarea(boot, dp) 43630418Skarels char *boot; 43730418Skarels register struct disklabel *dp; 43830418Skarels { 43930418Skarels struct disklabel *lp; 44030418Skarels register char *p; 44130418Skarels int b; 44230418Skarels #ifdef BOOT 44330715Sbostic char *dkbasename; 44434032Skarels #endif /*BOOT*/ 44530715Sbostic 44634032Skarels lp = (struct disklabel *)(boot + (LABELSECTOR * dp->d_secsize) + 44734032Skarels LABELOFFSET); 44834032Skarels #ifdef BOOT 44934032Skarels if (!rflag) 45034032Skarels return (lp); 45134032Skarels 45234032Skarels if (xxboot == NULL || bootxx == NULL) { 45330418Skarels dkbasename = np; 45430418Skarels if ((p = rindex(dkname, '/')) == NULL) 45530418Skarels p = dkname; 45630418Skarels else 45730418Skarels p++; 45830418Skarels while (*p && !isdigit(*p)) 45930418Skarels *np++ = *p++; 46030418Skarels *np++ = '\0'; 46130418Skarels 46234032Skarels if (xxboot == NULL) { 46334032Skarels (void)sprintf(np, "%s/%sboot", BOOTDIR, dkbasename); 46434032Skarels if (access(np, F_OK) < 0 && dkbasename[0] == 'r') 46534032Skarels dkbasename++; 46634032Skarels xxboot = np; 46734032Skarels (void)sprintf(xxboot, "%s/%sboot", BOOTDIR, dkbasename); 46834032Skarels np += strlen(xxboot) + 1; 46934032Skarels } 47034032Skarels if (bootxx == NULL) { 47134032Skarels (void)sprintf(np, "%s/boot%s", BOOTDIR, dkbasename); 47234032Skarels if (access(np, F_OK) < 0 && dkbasename[0] == 'r') 47334032Skarels dkbasename++; 47434032Skarels bootxx = np; 47534032Skarels (void)sprintf(bootxx, "%s/boot%s", BOOTDIR, dkbasename); 47634032Skarels np += strlen(bootxx) + 1; 47734032Skarels } 47830418Skarels } 47934032Skarels #ifdef DEBUG 48034032Skarels if (debug) 48134032Skarels fprintf(stderr, "bootstraps: xxboot = %s, bootxx = %s\n", 48234032Skarels xxboot, bootxx); 48334032Skarels #endif 48430418Skarels 48530418Skarels b = open(xxboot, O_RDONLY); 48630418Skarels if (b < 0) 48730418Skarels Perror(xxboot); 48830715Sbostic if (read(b, boot, (int)dp->d_secsize) < 0) 48930418Skarels Perror(xxboot); 49030418Skarels close(b); 49130418Skarels b = open(bootxx, O_RDONLY); 49230418Skarels if (b < 0) 49330418Skarels Perror(bootxx); 49430715Sbostic if (read(b, &boot[dp->d_secsize], (int)(dp->d_bbsize-dp->d_secsize)) < 0) 49530418Skarels Perror(bootxx); 49630715Sbostic (void)close(b); 49734032Skarels #endif /*BOOT*/ 49830418Skarels 49930418Skarels for (p = (char *)lp; p < (char *)lp + sizeof(struct disklabel); p++) 50030418Skarels if (*p) { 50130418Skarels fprintf(stderr, 50230418Skarels "Bootstrap doesn't leave room for disk label\n"); 50330418Skarels exit(2); 50430418Skarels } 50530418Skarels return (lp); 50630418Skarels } 50730418Skarels 50830418Skarels display(f, lp) 50930418Skarels FILE *f; 51030418Skarels register struct disklabel *lp; 51130418Skarels { 51230715Sbostic register int i, j; 51330418Skarels register struct partition *pp; 51430418Skarels 51530418Skarels fprintf(f, "# %s:\n", specname); 51630418Skarels if ((unsigned) lp->d_type < DKMAXTYPES) 51730418Skarels fprintf(f, "type: %s\n", dktypenames[lp->d_type]); 51830418Skarels else 51930418Skarels fprintf(f, "type: %d\n", lp->d_type); 52030418Skarels fprintf(f, "disk: %.*s\n", sizeof(lp->d_typename), lp->d_typename); 52134032Skarels fprintf(f, "label: %.*s\n", sizeof(lp->d_packname), lp->d_packname); 52231401Skarels fprintf(f, "flags:"); 52330418Skarels if (lp->d_flags & D_REMOVABLE) 52431401Skarels fprintf(f, " removeable"); 52530418Skarels if (lp->d_flags & D_ECC) 52631401Skarels fprintf(f, " ecc"); 52730418Skarels if (lp->d_flags & D_BADSECT) 52831401Skarels fprintf(f, " badsect"); 52930418Skarels fprintf(f, "\n"); 53030418Skarels fprintf(f, "bytes/sector: %d\n", lp->d_secsize); 53130418Skarels fprintf(f, "sectors/track: %d\n", lp->d_nsectors); 53230418Skarels fprintf(f, "tracks/cylinder: %d\n", lp->d_ntracks); 53331386Skarels fprintf(f, "sectors/cylinder: %d\n", lp->d_secpercyl); 53430418Skarels fprintf(f, "cylinders: %d\n", lp->d_ncylinders); 53530715Sbostic fprintf(f, "rpm: %d\n", lp->d_rpm); 53630418Skarels fprintf(f, "interleave: %d\n", lp->d_interleave); 53730418Skarels fprintf(f, "trackskew: %d\n", lp->d_trackskew); 53830418Skarels fprintf(f, "cylinderskew: %d\n", lp->d_cylskew); 53930418Skarels fprintf(f, "headswitch: %d\t\t# milliseconds\n", lp->d_headswitch); 54030418Skarels fprintf(f, "track-to-track seek: %d\t# milliseconds\n", lp->d_trkseek); 54130418Skarels fprintf(f, "drivedata: "); 54230418Skarels for (i = NDDATA - 1; i >= 0; i--) 54330418Skarels if (lp->d_drivedata[i]) 54430418Skarels break; 54530418Skarels if (i < 0) 54630418Skarels i = 0; 54730418Skarels for (j = 0; j <= i; j++) 54830418Skarels fprintf(f, "%d ", lp->d_drivedata[j]); 54930418Skarels fprintf(f, "\n\n%d partitions:\n", lp->d_npartitions); 55030863Skarels fprintf(f, 55130863Skarels "# size offset fstype [fsize bsize cpg]\n"); 55230418Skarels pp = lp->d_partitions; 55330418Skarels for (i = 0; i < lp->d_npartitions; i++, pp++) { 55430418Skarels if (pp->p_size) { 55530863Skarels fprintf(f, " %c: %8d %8d ", 'a' + i, 55630863Skarels pp->p_size, pp->p_offset); 55730418Skarels if ((unsigned) pp->p_fstype < FSMAXTYPES) 55830418Skarels fprintf(f, "%8.8s", fstypenames[pp->p_fstype]); 55930418Skarels else 56030418Skarels fprintf(f, "%8d", pp->p_fstype); 56130863Skarels switch (pp->p_fstype) { 56230863Skarels 56330863Skarels case FS_UNUSED: /* XXX */ 56430863Skarels fprintf(f, " %5d %5d %5.5s ", 56530863Skarels pp->p_fsize, pp->p_fsize * pp->p_frag, ""); 56630863Skarels break; 56730863Skarels 56830863Skarels case FS_BSDFFS: 56930863Skarels fprintf(f, " %5d %5d %5d ", 57030863Skarels pp->p_fsize, pp->p_fsize * pp->p_frag, 57130863Skarels pp->p_cpg); 57230863Skarels break; 57330863Skarels 57430863Skarels default: 57530863Skarels fprintf(f, "%20.20s", ""); 57630863Skarels break; 57730863Skarels } 57830418Skarels fprintf(f, "\t# (Cyl. %4d", 57930418Skarels pp->p_offset / lp->d_secpercyl); 58030418Skarels if (pp->p_offset % lp->d_secpercyl) 58130418Skarels putc('*', f); 58230418Skarels else 58330418Skarels putc(' ', f); 58430418Skarels fprintf(f, "- %d", 58530418Skarels (pp->p_offset + 58630418Skarels pp->p_size + lp->d_secpercyl - 1) / 58730418Skarels lp->d_secpercyl - 1); 58830418Skarels if (pp->p_size % lp->d_secpercyl) 58930418Skarels putc('*', f); 59030863Skarels fprintf(f, ")\n"); 59130418Skarels } 59230418Skarels } 59332121Stef fflush(f); 59430418Skarels } 59530418Skarels 59634641Skarels edit(lp, f) 59730715Sbostic struct disklabel *lp; 59834641Skarels int f; 59930418Skarels { 60030715Sbostic register int c; 60130715Sbostic struct disklabel label; 60230715Sbostic FILE *fd; 60330715Sbostic char *mktemp(); 60430715Sbostic 60530715Sbostic (void) mktemp(tmpfil); 60630715Sbostic fd = fopen(tmpfil, "w"); 60730715Sbostic if (fd == NULL) { 60830715Sbostic fprintf(stderr, "%s: Can't create\n", tmpfil); 60934641Skarels return (1); 61030715Sbostic } 61130715Sbostic (void)fchmod(fd, 0600); 61230715Sbostic display(fd, lp); 61330715Sbostic fclose(fd); 61430715Sbostic for (;;) { 61530715Sbostic if (!editit()) 61630715Sbostic break; 61730715Sbostic fd = fopen(tmpfil, "r"); 61830715Sbostic if (fd == NULL) { 61934032Skarels fprintf(stderr, "%s: Can't reopen for reading\n", 62034032Skarels tmpfil); 62130715Sbostic break; 62230715Sbostic } 62330863Skarels bzero((char *)&label, sizeof(label)); 62430715Sbostic if (getasciilabel(fd, &label)) { 62530715Sbostic *lp = label; 62634641Skarels if (writelabel(f, bootarea, lp) == 0) { 62734641Skarels (void) unlink(tmpfil); 62834641Skarels return (0); 62934641Skarels } 63030715Sbostic } 63130715Sbostic printf("re-edit the label? [y]: "); fflush(stdout); 63230715Sbostic c = getchar(); 63330715Sbostic if (c != EOF && c != (int)'\n') 63430715Sbostic while (getchar() != (int)'\n') 63530715Sbostic ; 63630715Sbostic if (c == (int)'n') 63730715Sbostic break; 63830715Sbostic } 63930715Sbostic (void) unlink(tmpfil); 64034641Skarels return (1); 64130418Skarels } 64230418Skarels 64330715Sbostic editit() 64430715Sbostic { 64530715Sbostic register int pid, xpid; 64630715Sbostic int stat, omask; 64730715Sbostic extern char *getenv(); 64830418Skarels 64930715Sbostic omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGHUP)); 65030715Sbostic while ((pid = fork()) < 0) { 65130715Sbostic extern int errno; 65230715Sbostic 65330715Sbostic if (errno == EPROCLIM) { 65430715Sbostic fprintf(stderr, "You have too many processes\n"); 65530715Sbostic return(0); 65630715Sbostic } 65730715Sbostic if (errno != EAGAIN) { 65830715Sbostic perror("fork"); 65930715Sbostic return(0); 66030715Sbostic } 66130715Sbostic sleep(1); 66230715Sbostic } 66330715Sbostic if (pid == 0) { 66430715Sbostic register char *ed; 66530715Sbostic 66630715Sbostic sigsetmask(omask); 66730715Sbostic setgid(getgid()); 66830715Sbostic setuid(getuid()); 66930715Sbostic if ((ed = getenv("EDITOR")) == (char *)0) 67030715Sbostic ed = DEFEDITOR; 67130715Sbostic execlp(ed, ed, tmpfil, 0); 67230715Sbostic perror(ed); 67330715Sbostic exit(1); 67430715Sbostic } 67530715Sbostic while ((xpid = wait(&stat)) >= 0) 67630715Sbostic if (xpid == pid) 67730715Sbostic break; 67830715Sbostic sigsetmask(omask); 67930715Sbostic return(!stat); 68030715Sbostic } 68130715Sbostic 68230715Sbostic char * 68330715Sbostic skip(cp) 68430715Sbostic register char *cp; 68530715Sbostic { 68630715Sbostic 68730715Sbostic while (*cp != '\0' && isspace(*cp)) 68830715Sbostic cp++; 68930715Sbostic if (*cp == '\0' || *cp == '#') 69030715Sbostic return ((char *)NULL); 69130715Sbostic return (cp); 69230715Sbostic } 69330715Sbostic 69430715Sbostic char * 69530715Sbostic word(cp) 69630715Sbostic register char *cp; 69730715Sbostic { 69830715Sbostic register char c; 69930715Sbostic 70031401Skarels while (*cp != '\0' && !isspace(*cp) && *cp != '#') 70131401Skarels cp++; 70230715Sbostic if ((c = *cp) != '\0') { 70330715Sbostic *cp++ = '\0'; 70430715Sbostic if (c != '#') 70530715Sbostic return (skip(cp)); 70630715Sbostic } 70730715Sbostic return ((char *)NULL); 70830715Sbostic } 70930715Sbostic 71030418Skarels /* 71130418Skarels * Read an ascii label in from fd f, 71230418Skarels * in the same format as that put out by display(), 71330418Skarels * and fill in lp. 71430418Skarels */ 71530418Skarels getasciilabel(f, lp) 71630715Sbostic FILE *f; 71730418Skarels register struct disklabel *lp; 71830418Skarels { 71930715Sbostic register char **cpp, *cp; 72030863Skarels register struct partition *pp; 72130715Sbostic char *tp, *s, line[BUFSIZ]; 72230715Sbostic int v, lineno = 0, errors = 0; 72330715Sbostic 72430715Sbostic lp->d_bbsize = BBSIZE; /* XXX */ 72530715Sbostic lp->d_sbsize = SBSIZE; /* XXX */ 72630715Sbostic while (fgets(line, sizeof(line) - 1, f)) { 72730715Sbostic lineno++; 72830715Sbostic if (cp = index(line,'\n')) 72930715Sbostic *cp = '\0'; 73030715Sbostic cp = skip(line); 73130715Sbostic if (cp == NULL) 73230715Sbostic continue; 73330715Sbostic tp = index(cp, ':'); 73430715Sbostic if (tp == NULL) { 73530715Sbostic fprintf(stderr, "line %d: syntax error\n", lineno); 73630715Sbostic errors++; 73730715Sbostic continue; 73830715Sbostic } 73930715Sbostic *tp++ = '\0', tp = skip(tp); 74030715Sbostic if (streq(cp, "type")) { 74130715Sbostic if (tp == NULL) 74230715Sbostic tp = "unknown"; 74330715Sbostic cpp = dktypenames; 74430715Sbostic for (; cpp < &dktypenames[DKMAXTYPES]; cpp++) 74530715Sbostic if ((s = *cpp) && streq(s, tp)) { 74630715Sbostic lp->d_type = cpp - dktypenames; 74730715Sbostic goto next; 74830715Sbostic } 74930715Sbostic v = atoi(tp); 75030715Sbostic if ((unsigned)v >= DKMAXTYPES) 75130715Sbostic fprintf(stderr, "line %d:%s %d\n", lineno, 75230715Sbostic "Warning, unknown disk type", v); 75330715Sbostic lp->d_type = v; 75430715Sbostic continue; 75530715Sbostic } 75630715Sbostic if (streq(cp, "flags")) { 75734032Skarels for (v = 0; (cp = tp) && *cp != '\0';) { 75834032Skarels tp = word(cp); 75930715Sbostic if (streq(cp, "removeable")) 76030715Sbostic v |= D_REMOVABLE; 76130715Sbostic else if (streq(cp, "ecc")) 76230715Sbostic v |= D_ECC; 76330715Sbostic else if (streq(cp, "badsect")) 76430715Sbostic v |= D_BADSECT; 76530715Sbostic else { 76630715Sbostic fprintf(stderr, 76730715Sbostic "line %d: %s: bad flag\n", 76830715Sbostic lineno, cp); 76930715Sbostic errors++; 77030715Sbostic } 77130715Sbostic } 77230715Sbostic lp->d_flags = v; 77330715Sbostic continue; 77430715Sbostic } 77530715Sbostic if (streq(cp, "drivedata")) { 77630715Sbostic register int i; 77730715Sbostic 77831386Skarels for (i = 0; (cp = tp) && *cp != '\0' && i < NDDATA;) { 77930715Sbostic lp->d_drivedata[i++] = atoi(cp); 78031386Skarels tp = word(cp); 78130715Sbostic } 78230715Sbostic continue; 78330715Sbostic } 78430715Sbostic if (sscanf(cp, "%d partitions", &v) == 1) { 78530863Skarels if (v == 0 || (unsigned)v > MAXPARTITIONS) { 78630715Sbostic fprintf(stderr, 78730715Sbostic "line %d: bad # of partitions\n", lineno); 78830863Skarels lp->d_npartitions = MAXPARTITIONS; 78930863Skarels errors++; 79030863Skarels } else 79130715Sbostic lp->d_npartitions = v; 79230715Sbostic continue; 79330715Sbostic } 79430715Sbostic if (tp == NULL) 79530715Sbostic tp = ""; 79630715Sbostic if (streq(cp, "disk")) { 79730715Sbostic strncpy(lp->d_typename, tp, sizeof (lp->d_typename)); 79830715Sbostic continue; 79930715Sbostic } 80030715Sbostic if (streq(cp, "label")) { 80134032Skarels strncpy(lp->d_packname, tp, sizeof (lp->d_packname)); 80230715Sbostic continue; 80330715Sbostic } 80430715Sbostic if (streq(cp, "bytes/sector")) { 80530715Sbostic v = atoi(tp); 80630715Sbostic if (v <= 0 || (v % 512) != 0) { 80730715Sbostic fprintf(stderr, 80830715Sbostic "line %d: %s: bad sector size\n", 80930715Sbostic lineno, tp); 81030715Sbostic errors++; 81130715Sbostic } else 81230715Sbostic lp->d_secsize = v; 81330715Sbostic continue; 81430715Sbostic } 81530715Sbostic if (streq(cp, "sectors/track")) { 81630715Sbostic v = atoi(tp); 81730715Sbostic if (v <= 0) { 81830715Sbostic fprintf(stderr, "line %d: %s: bad %s\n", 81930715Sbostic lineno, tp, cp); 82030715Sbostic errors++; 82130715Sbostic } else 82230715Sbostic lp->d_nsectors = v; 82330715Sbostic continue; 82430715Sbostic } 82531386Skarels if (streq(cp, "sectors/cylinder")) { 82631386Skarels v = atoi(tp); 82731386Skarels if (v <= 0) { 82831386Skarels fprintf(stderr, "line %d: %s: bad %s\n", 82931386Skarels lineno, tp, cp); 83031386Skarels errors++; 83131386Skarels } else 83231386Skarels lp->d_secpercyl = v; 83331386Skarels continue; 83431386Skarels } 83530715Sbostic if (streq(cp, "tracks/cylinder")) { 83630715Sbostic v = atoi(tp); 83730715Sbostic if (v <= 0) { 83830715Sbostic fprintf(stderr, "line %d: %s: bad %s\n", 83930715Sbostic lineno, tp, cp); 84030715Sbostic errors++; 84130715Sbostic } else 84230715Sbostic lp->d_ntracks = v; 84330715Sbostic continue; 84430715Sbostic } 84530715Sbostic if (streq(cp, "cylinders")) { 84630715Sbostic v = atoi(tp); 84730715Sbostic if (v <= 0) { 84830715Sbostic fprintf(stderr, "line %d: %s: bad %s\n", 84930715Sbostic lineno, tp, cp); 85030715Sbostic errors++; 85130715Sbostic } else 85230715Sbostic lp->d_ncylinders = v; 85330715Sbostic continue; 85430715Sbostic } 85530715Sbostic if (streq(cp, "rpm")) { 85630715Sbostic v = atoi(tp); 85730715Sbostic if (v <= 0) { 85830715Sbostic fprintf(stderr, "line %d: %s: bad %s\n", 85930715Sbostic lineno, tp, cp); 86030715Sbostic errors++; 86130715Sbostic } else 86230715Sbostic lp->d_rpm = v; 86330715Sbostic continue; 86430715Sbostic } 86530715Sbostic if (streq(cp, "interleave")) { 86630715Sbostic v = atoi(tp); 86730715Sbostic if (v <= 0) { 86830715Sbostic fprintf(stderr, "line %d: %s: bad %s\n", 86930715Sbostic lineno, tp, cp); 87030715Sbostic errors++; 87130715Sbostic } else 87230715Sbostic lp->d_interleave = v; 87330715Sbostic continue; 87430715Sbostic } 87530715Sbostic if (streq(cp, "trackskew")) { 87630715Sbostic v = atoi(tp); 87730715Sbostic if (v < 0) { 87830715Sbostic fprintf(stderr, "line %d: %s: bad %s\n", 87930715Sbostic lineno, tp, cp); 88030715Sbostic errors++; 88130715Sbostic } else 88230715Sbostic lp->d_trackskew = v; 88330715Sbostic continue; 88430715Sbostic } 88530715Sbostic if (streq(cp, "cylinderskew")) { 88630715Sbostic v = atoi(tp); 88730715Sbostic if (v < 0) { 88830715Sbostic fprintf(stderr, "line %d: %s: bad %s\n", 88930715Sbostic lineno, tp, cp); 89030715Sbostic errors++; 89130715Sbostic } else 89230715Sbostic lp->d_cylskew = v; 89330715Sbostic continue; 89430715Sbostic } 89530715Sbostic if (streq(cp, "headswitch")) { 89630715Sbostic v = atoi(tp); 89730715Sbostic if (v < 0) { 89830715Sbostic fprintf(stderr, "line %d: %s: bad %s\n", 89930715Sbostic lineno, tp, cp); 90030715Sbostic errors++; 90130715Sbostic } else 90230715Sbostic lp->d_headswitch = v; 90330715Sbostic continue; 90430715Sbostic } 90530715Sbostic if (streq(cp, "track-to-track seek")) { 90630715Sbostic v = atoi(tp); 90730715Sbostic if (v < 0) { 90830715Sbostic fprintf(stderr, "line %d: %s: bad %s\n", 90930715Sbostic lineno, tp, cp); 91030715Sbostic errors++; 91130715Sbostic } else 91230715Sbostic lp->d_trkseek = v; 91330715Sbostic continue; 91430715Sbostic } 91530715Sbostic if ('a' <= *cp && *cp <= 'z' && cp[1] == '\0') { 91630863Skarels unsigned part = *cp - 'a'; 91730715Sbostic 91830863Skarels if (part > lp->d_npartitions) { 91930715Sbostic fprintf(stderr, 92030715Sbostic "line %d: bad partition name\n", lineno); 92130715Sbostic errors++; 92230715Sbostic continue; 92330715Sbostic } 92430863Skarels pp = &lp->d_partitions[part]; 92530863Skarels #define NXTNUM(n) { \ 92630863Skarels cp = tp, tp = word(cp); \ 92730863Skarels if (tp == NULL) \ 92830863Skarels tp = cp; \ 92930863Skarels (n) = atoi(cp); \ 93030863Skarels } 93130863Skarels 93230863Skarels NXTNUM(v); 93330715Sbostic if (v < 0) { 93430715Sbostic fprintf(stderr, 93530715Sbostic "line %d: %s: bad partition size\n", 93630715Sbostic lineno, cp); 93730715Sbostic errors++; 93830715Sbostic } else 93930863Skarels pp->p_size = v; 94030863Skarels NXTNUM(v); 94130715Sbostic if (v < 0) { 94230715Sbostic fprintf(stderr, 94330715Sbostic "line %d: %s: bad partition offset\n", 94430715Sbostic lineno, cp); 94530715Sbostic errors++; 94630715Sbostic } else 94730863Skarels pp->p_offset = v; 94830715Sbostic cp = tp, tp = word(cp); 94930715Sbostic cpp = fstypenames; 95030715Sbostic for (; cpp < &fstypenames[FSMAXTYPES]; cpp++) 95130715Sbostic if ((s = *cpp) && streq(s, cp)) { 95230863Skarels pp->p_fstype = cpp - fstypenames; 95330863Skarels goto gottype; 95430715Sbostic } 95534032Skarels if (isdigit(*cp)) 95634032Skarels v = atoi(cp); 95734032Skarels else 95834032Skarels v = FSMAXTYPES; 95934032Skarels if ((unsigned)v >= FSMAXTYPES) { 96030715Sbostic fprintf(stderr, "line %d: %s %s\n", lineno, 96130715Sbostic "Warning, unknown filesystem type", cp); 96234032Skarels v = FS_UNUSED; 96334032Skarels } 96430863Skarels pp->p_fstype = v; 96530863Skarels gottype: 96630863Skarels 96730863Skarels switch (pp->p_fstype) { 96830863Skarels 96930863Skarels case FS_UNUSED: /* XXX */ 97030863Skarels NXTNUM(pp->p_fsize); 97130863Skarels if (pp->p_fsize == 0) 97230863Skarels break; 97330863Skarels NXTNUM(v); 97430863Skarels pp->p_frag = v / pp->p_fsize; 97530863Skarels break; 97630863Skarels 97730863Skarels case FS_BSDFFS: 97830863Skarels NXTNUM(pp->p_fsize); 97930863Skarels if (pp->p_fsize == 0) 98030863Skarels break; 98130863Skarels NXTNUM(v); 98230863Skarels pp->p_frag = v / pp->p_fsize; 98330863Skarels NXTNUM(pp->p_cpg); 98430863Skarels break; 98530863Skarels 98630863Skarels default: 98730863Skarels break; 98830863Skarels } 98930715Sbostic continue; 99030715Sbostic } 99130715Sbostic fprintf(stderr, "line %d: %s: Unknown disklabel field\n", 99230715Sbostic lineno, cp); 99330715Sbostic errors++; 99430715Sbostic next: 99530715Sbostic ; 99630715Sbostic } 99730715Sbostic errors += checklabel(lp); 99830715Sbostic return (errors == 0); 99930418Skarels } 100030418Skarels 100130715Sbostic /* 100230715Sbostic * Check disklabel for errors and fill in 100330715Sbostic * derived fields according to supplied values. 100430715Sbostic */ 100530715Sbostic checklabel(lp) 100630715Sbostic register struct disklabel *lp; 100730418Skarels { 100830715Sbostic register struct partition *pp; 100930715Sbostic int i, errors = 0; 101030715Sbostic char part; 101130418Skarels 101230715Sbostic if (lp->d_secsize == 0) { 101330715Sbostic fprintf(stderr, "sector size %d\n", lp->d_secsize); 101430715Sbostic return (1); 101530715Sbostic } 101630715Sbostic if (lp->d_nsectors == 0) { 101730715Sbostic fprintf(stderr, "sectors/track %d\n", lp->d_nsectors); 101830715Sbostic return (1); 101930715Sbostic } 102030715Sbostic if (lp->d_ntracks == 0) { 102130715Sbostic fprintf(stderr, "tracks/cylinder %d\n", lp->d_ntracks); 102230715Sbostic return (1); 102330715Sbostic } 102430715Sbostic if (lp->d_ncylinders == 0) { 102530715Sbostic fprintf(stderr, "cylinders/unit %d\n", lp->d_ncylinders); 102630715Sbostic errors++; 102730715Sbostic } 102830715Sbostic if (lp->d_rpm == 0) 102930715Sbostic Warning("revolutions/minute %d\n", lp->d_rpm); 103030715Sbostic if (lp->d_secpercyl == 0) 103130715Sbostic lp->d_secpercyl = lp->d_nsectors * lp->d_ntracks; 103230715Sbostic if (lp->d_secperunit == 0) 103330715Sbostic lp->d_secperunit = lp->d_secpercyl * lp->d_ncylinders; 103430715Sbostic if (lp->d_bbsize == 0) { 103530715Sbostic fprintf(stderr, "boot block size %d\n", lp->d_bbsize); 103630715Sbostic errors++; 103730715Sbostic } else if (lp->d_bbsize % lp->d_secsize) 103830715Sbostic Warning("boot block size %% sector-size != 0\n"); 103930715Sbostic if (lp->d_sbsize == 0) { 104030715Sbostic fprintf(stderr, "super block size %d\n", lp->d_sbsize); 104130715Sbostic errors++; 104230715Sbostic } else if (lp->d_sbsize % lp->d_secsize) 104330715Sbostic Warning("super block size %% sector-size != 0\n"); 104430715Sbostic if (lp->d_npartitions > MAXPARTITIONS) 104530715Sbostic Warning("number of partitions (%d) > MAXPARTITIONS (%d)\n", 104630715Sbostic lp->d_npartitions, MAXPARTITIONS); 104730715Sbostic for (i = 0; i < lp->d_npartitions; i++) { 104830715Sbostic part = 'a' + i; 104930715Sbostic pp = &lp->d_partitions[i]; 105030715Sbostic if (pp->p_size == 0 && pp->p_offset != 0) 105130715Sbostic Warning("partition %c: size 0, but offset %d\n", 105230715Sbostic part, pp->p_offset); 105330715Sbostic #ifdef notdef 105430715Sbostic if (pp->p_size % lp->d_secpercyl) 105530715Sbostic Warning("partition %c: size %% cylinder-size != 0\n", 105630715Sbostic part); 105730715Sbostic if (pp->p_offset % lp->d_secpercyl) 105830715Sbostic Warning("partition %c: offset %% cylinder-size != 0\n", 105930715Sbostic part); 106030715Sbostic #endif 106130715Sbostic if (pp->p_offset > lp->d_secperunit) { 106230715Sbostic fprintf(stderr, 106330715Sbostic "partition %c: offset past end of unit\n", part); 106430715Sbostic errors++; 106530715Sbostic } 106630715Sbostic if (pp->p_offset + pp->p_size > lp->d_secperunit) { 106730715Sbostic fprintf(stderr, 106830715Sbostic "partition %c: partition extends past end of unit\n", 106930715Sbostic part); 107030715Sbostic errors++; 107130715Sbostic } 107230715Sbostic } 107330715Sbostic for (; i < MAXPARTITIONS; i++) { 107430715Sbostic part = 'a' + i; 107530715Sbostic pp = &lp->d_partitions[i]; 107630715Sbostic if (pp->p_size || pp->p_offset) 107730715Sbostic Warning("unused partition %c: size %d offset %d\n", 107834032Skarels 'a' + i, pp->p_size, pp->p_offset); 107930715Sbostic } 108030715Sbostic return (errors); 108130715Sbostic } 108230715Sbostic 108330715Sbostic /*VARARGS1*/ 108430715Sbostic Warning(fmt, a1, a2, a3, a4, a5) 108530715Sbostic char *fmt; 108630715Sbostic { 108730715Sbostic 108830715Sbostic fprintf(stderr, "Warning, "); 108930715Sbostic fprintf(stderr, fmt, a1, a2, a3, a4, a5); 109030715Sbostic fprintf(stderr, "\n"); 109130715Sbostic } 109230715Sbostic 109330715Sbostic Perror(str) 109430715Sbostic char *str; 109530715Sbostic { 109630715Sbostic fputs("disklabel: ", stderr); perror(str); 109730418Skarels exit(4); 109830418Skarels } 109930715Sbostic 110030715Sbostic usage() 110130715Sbostic { 110230715Sbostic #ifdef BOOT 110334032Skarels fprintf(stderr, "%-62s%s\n%-62s%s\n%-62s%s\n%-62s%s\n%-62s%s\n", 110430715Sbostic "usage: disklabel [-r] disk", "(to read label)", 110530715Sbostic "or disklabel -w [-r] disk type [ packid ] [ xxboot bootxx ]", "(to write label)", 110630715Sbostic "or disklabel -e [-r] disk", "(to edit label)", 110734032Skarels "or disklabel -R [-r] disk protofile [ type | xxboot bootxx ]", "(to restore label)", 110834032Skarels "or disklabel [-NW] disk", "(to write disable/enable label)"); 110930715Sbostic #else 111034032Skarels fprintf(stderr, "%-43s%s\n%-43s%s\n%-43s%s\n%-43s%s\n%-43s%s\n", 111130715Sbostic "usage: disklabel [-r] disk", "(to read label)", 111230715Sbostic "or disklabel -w [-r] disk type [ packid ]", "(to write label)", 111330715Sbostic "or disklabel -e [-r] disk", "(to edit label)", 111434032Skarels "or disklabel -R [-r] disk protofile", "(to restore label)", 111534032Skarels "or disklabel [-NW] disk", "(to write disable/enable label)"); 111630715Sbostic #endif 111730715Sbostic exit(1); 111830715Sbostic } 1119