1*498920cdSkrw /* $OpenBSD: disklabel.c,v 1.254 2023/07/03 15:27:07 krw Exp $ */
2df930be7Sderaadt
3df930be7Sderaadt /*
4df930be7Sderaadt * Copyright (c) 1987, 1993
5df930be7Sderaadt * The Regents of the University of California. All rights reserved.
6df930be7Sderaadt *
7df930be7Sderaadt * This code is derived from software contributed to Berkeley by
8df930be7Sderaadt * Symmetric Computer Systems.
9df930be7Sderaadt *
10df930be7Sderaadt * Redistribution and use in source and binary forms, with or without
11df930be7Sderaadt * modification, are permitted provided that the following conditions
12df930be7Sderaadt * are met:
13df930be7Sderaadt * 1. Redistributions of source code must retain the above copyright
14df930be7Sderaadt * notice, this list of conditions and the following disclaimer.
15df930be7Sderaadt * 2. Redistributions in binary form must reproduce the above copyright
16df930be7Sderaadt * notice, this list of conditions and the following disclaimer in the
17df930be7Sderaadt * documentation and/or other materials provided with the distribution.
181ef0d710Smillert * 3. Neither the name of the University nor the names of its contributors
19df930be7Sderaadt * may be used to endorse or promote products derived from this software
20df930be7Sderaadt * without specific prior written permission.
21df930be7Sderaadt *
22df930be7Sderaadt * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23df930be7Sderaadt * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24df930be7Sderaadt * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25df930be7Sderaadt * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26df930be7Sderaadt * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27df930be7Sderaadt * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28df930be7Sderaadt * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29df930be7Sderaadt * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30df930be7Sderaadt * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31df930be7Sderaadt * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32df930be7Sderaadt * SUCH DAMAGE.
33df930be7Sderaadt */
34df930be7Sderaadt
3578eb0b7eSderaadt #include <sys/param.h> /* DEV_BSIZE */
36e384f6efSderaadt #include <sys/sysctl.h>
37df930be7Sderaadt #include <sys/ioctl.h>
3891f4f7d8Sdlg #include <sys/dkio.h>
39df930be7Sderaadt #include <sys/stat.h>
40df930be7Sderaadt #include <sys/wait.h>
41df930be7Sderaadt #define DKTYPENAMES
42df930be7Sderaadt #include <sys/disklabel.h>
43df930be7Sderaadt
44df930be7Sderaadt #include <ufs/ffs/fs.h>
45df930be7Sderaadt
46df930be7Sderaadt #include <ctype.h>
47df930be7Sderaadt #include <err.h>
48df930be7Sderaadt #include <errno.h>
4901a83688Smillert #include <fcntl.h>
5018ec52beSotto #include <limits.h>
51df930be7Sderaadt #include <signal.h>
52df930be7Sderaadt #include <string.h>
53df930be7Sderaadt #include <stdio.h>
54df930be7Sderaadt #include <stdlib.h>
55df930be7Sderaadt #include <unistd.h>
563e34b74fSdownsj #include <util.h>
572b7ecb54Skrw #include <fstab.h>
58df930be7Sderaadt #include "pathnames.h"
59a12b0823Sderaadt #include "extern.h"
60df930be7Sderaadt
61df930be7Sderaadt /*
62df930be7Sderaadt * Disklabel: read and write disklabels.
63df930be7Sderaadt * The label is usually placed on one of the first sectors of the disk.
64df930be7Sderaadt * Many machines also place a bootstrap in the same area,
65df930be7Sderaadt * in which case the label is embedded in the bootstrap.
66df930be7Sderaadt * The bootstrap source must leave space at the proper offset
67df930be7Sderaadt * for the label on such machines.
68df930be7Sderaadt */
69df930be7Sderaadt
70df930be7Sderaadt #ifndef BBSIZE
71df930be7Sderaadt #define BBSIZE 8192 /* size of boot area, with label */
72df930be7Sderaadt #endif
73df930be7Sderaadt
7434ae4198Skrw char *dkname, *specname, *fstabfile;
755641d43aSmillert char tmpfil[] = _PATH_TMPFILE;
7634ae4198Skrw char *mountpoints[MAXPARTITIONS];
77df930be7Sderaadt struct disklabel lab;
78df930be7Sderaadt enum {
79ad383930Smiod UNSPEC, EDIT, EDITOR, READ, RESTORE, WRITE
80df930be7Sderaadt } op = UNSPEC;
81df930be7Sderaadt
82557f712bSkrw int aflag;
831b8b78b5Smillert int cflag;
845362a395Smillert int dflag;
85b8778baaSmillert int tflag;
86d6d80bb0Skrw int uidflag;
87625b9b20Sderaadt int verbose;
884bf1fc9dSotto int quiet;
89625b9b20Sderaadt int donothing;
90df930be7Sderaadt
91c72b5b24Smillert void makedisktab(FILE *, struct disklabel *);
927831279eSkrw int checklabel(struct disklabel *);
937831279eSkrw void readlabel(int);
94ccd9f552Skrw void parsefstab(void);
95ccd9f552Skrw void parsedisktab(char *, struct disklabel *);
96c72b5b24Smillert int edit(struct disklabel *, int);
97ba7e2ebaSray int editit(const char *);
98c72b5b24Smillert char *skip(char *);
99c72b5b24Smillert char *word(char *);
100c72b5b24Smillert int getasciilabel(FILE *, struct disklabel *);
101c72b5b24Smillert int cmplabel(struct disklabel *, struct disklabel *);
102c72b5b24Smillert void usage(void);
1031e0ad43cSotto u_int64_t getnum(char *, u_int64_t, u_int64_t, const char **);
104df930be7Sderaadt
105e384f6efSderaadt int64_t physmem;
106e384f6efSderaadt
107e384f6efSderaadt void
getphysmem(void)108e384f6efSderaadt getphysmem(void)
109e384f6efSderaadt {
110e384f6efSderaadt size_t sz = sizeof(physmem);
111e384f6efSderaadt int mib[] = { CTL_HW, HW_PHYSMEM64 };
112e384f6efSderaadt
113e384f6efSderaadt if (sysctl(mib, 2, &physmem, &sz, NULL, (size_t)0) == -1)
114e384f6efSderaadt errx(4, "can't get mem size");
115e384f6efSderaadt }
116e384f6efSderaadt
117df930be7Sderaadt int
main(int argc,char * argv[])1188809fabbSderaadt main(int argc, char *argv[])
119df930be7Sderaadt {
120df930be7Sderaadt FILE *t;
121a2c1f847Shenning char *autotable = NULL;
1228e58de64Skrw int ch, f, error = 0;
1238e58de64Skrw char print_unit = '\0';
124df930be7Sderaadt
125e384f6efSderaadt getphysmem();
126e384f6efSderaadt
127ad383930Smiod while ((ch = getopt(argc, argv, "AEf:F:hRcdenp:tT:vw")) != -1)
128df930be7Sderaadt switch (ch) {
129557f712bSkrw case 'A':
1303579491dSderaadt aflag = 1;
131557f712bSkrw break;
132df930be7Sderaadt case 'R':
133df930be7Sderaadt if (op != UNSPEC)
134df930be7Sderaadt usage();
135df930be7Sderaadt op = RESTORE;
136df930be7Sderaadt break;
1371b8b78b5Smillert case 'c':
1383579491dSderaadt cflag = 1;
1391b8b78b5Smillert break;
1405362a395Smillert case 'd':
1413579491dSderaadt dflag = 1;
1425362a395Smillert break;
143df930be7Sderaadt case 'e':
144df930be7Sderaadt if (op != UNSPEC)
145df930be7Sderaadt usage();
146df930be7Sderaadt op = EDIT;
147df930be7Sderaadt break;
1485362a395Smillert case 'E':
1495362a395Smillert if (op != UNSPEC)
1505362a395Smillert usage();
1515362a395Smillert op = EDITOR;
152fa8ace58Smillert break;
153d09f3941Smillert case 'f':
154bd6726faSmillert fstabfile = optarg;
155d6d80bb0Skrw uidflag = 0;
156d6d80bb0Skrw break;
157d6d80bb0Skrw case 'F':
158d6d80bb0Skrw fstabfile = optarg;
1593579491dSderaadt uidflag = 1;
160bd6726faSmillert break;
161352d199bSkrw case 'h':
162352d199bSkrw print_unit = '*';
163352d199bSkrw break;
164b8778baaSmillert case 't':
1653579491dSderaadt tflag = 1;
166b8778baaSmillert break;
167a2c1f847Shenning case 'T':
168a2c1f847Shenning autotable = optarg;
169a2c1f847Shenning break;
170df930be7Sderaadt case 'w':
171df930be7Sderaadt if (op != UNSPEC)
172df930be7Sderaadt usage();
173df930be7Sderaadt op = WRITE;
174df930be7Sderaadt break;
17529c2f9a4Stedu case 'p':
1764b3a8141Stedu if (strchr("bckmgtBCKMGT", optarg[0]) == NULL ||
1774b3a8141Stedu optarg[1] != '\0') {
1784b3a8141Stedu fprintf(stderr, "Valid units are bckmgt\n");
17982b1057eStb return 1;
1804b3a8141Stedu }
181025f5691Sderaadt print_unit = tolower((unsigned char)optarg[0]);
18229c2f9a4Stedu break;
183625b9b20Sderaadt case 'n':
1843579491dSderaadt donothing = 1;
185df930be7Sderaadt break;
186625b9b20Sderaadt case 'v':
1873579491dSderaadt verbose = 1;
188625b9b20Sderaadt break;
189df930be7Sderaadt default:
190df930be7Sderaadt usage();
191df930be7Sderaadt }
192df930be7Sderaadt argc -= optind;
193df930be7Sderaadt argv += optind;
194df930be7Sderaadt
19582b1057eStb if (op == UNSPEC)
19682b1057eStb op = READ;
19782b1057eStb
19882b1057eStb if (argc < 1 || (fstabfile && !(op == EDITOR || op == RESTORE ||
19982b1057eStb aflag)))
20082b1057eStb usage();
20182b1057eStb
2027f5e2aa5Sbeck if (argv[0] == NULL)
2037f5e2aa5Sbeck usage();
204ae95b2a9Sbeck dkname = argv[0];
205ae95b2a9Sbeck f = opendev(dkname, (op == READ ? O_RDONLY : O_RDWR), OPENDEV_PART,
206ae95b2a9Sbeck &specname);
207df69c215Sderaadt if (f == -1)
208ae95b2a9Sbeck err(4, "%s", specname);
209ae95b2a9Sbeck
210ed5b94b5Stb if (op != WRITE || aflag || dflag) {
21182b1057eStb readlabel(f);
21282b1057eStb
213e2af7730Skrw if (op == EDIT || op == EDITOR || aflag) {
214ed5b94b5Stb if (pledge("stdio rpath wpath cpath disklabel proc "
215ed5b94b5Stb "exec", NULL) == -1)
216e384f6efSderaadt err(1, "pledge");
2179de32208Sjsg } else if (fstabfile) {
218ed5b94b5Stb if (pledge("stdio rpath wpath cpath disklabel", NULL)
219ed5b94b5Stb == -1)
2209de32208Sjsg err(1, "pledge");
221e384f6efSderaadt } else {
222e384f6efSderaadt if (pledge("stdio rpath wpath disklabel", NULL) == -1)
223e384f6efSderaadt err(1, "pledge");
224e384f6efSderaadt }
225e384f6efSderaadt
226ed5b94b5Stb if (autotable != NULL)
227ed5b94b5Stb parse_autotable(autotable);
228ccd9f552Skrw parsefstab();
229ccd9f552Skrw error = aflag ? editor_allocspace(&lab) : 0;
230ccd9f552Skrw if (op == WRITE && error)
231185664b4Sotto errx(1, "autoalloc failed");
232ed5b94b5Stb } else if (argc == 2 || argc == 3) {
233ed5b94b5Stb /* Ensure f is a disk device before pledging. */
23490b0764fSkrw if (ioctl(f, DIOCGDINFO, &lab) == -1)
23590b0764fSkrw err(4, "DIOCGDINFO");
236ed5b94b5Stb
237ed5b94b5Stb if (pledge("stdio rpath wpath disklabel", NULL) == -1)
238ed5b94b5Stb err(1, "pledge");
239ed5b94b5Stb
240ccd9f552Skrw parsedisktab(argv[1], &lab);
241ccd9f552Skrw if (argc == 3)
242ccd9f552Skrw strncpy(lab.d_packname, argv[2], sizeof(lab.d_packname));
243ed5b94b5Stb } else
244ed5b94b5Stb usage();
245ed5b94b5Stb
246df930be7Sderaadt switch (op) {
247df930be7Sderaadt case EDIT:
248df930be7Sderaadt if (argc != 1)
249df930be7Sderaadt usage();
25077a43662Skrw error = edit(&lab, f);
251df930be7Sderaadt break;
2526fe57b42Smillert case EDITOR:
2536fe57b42Smillert if (argc != 1)
2546fe57b42Smillert usage();
255d6d80bb0Skrw error = editor(f);
2566fe57b42Smillert break;
257df930be7Sderaadt case READ:
258df930be7Sderaadt if (argc != 1)
259df930be7Sderaadt usage();
260c6798c7bSderaadt
261c6798c7bSderaadt if (pledge("stdio", NULL) == -1)
262c6798c7bSderaadt err(1, "pledge");
263c6798c7bSderaadt
264b8778baaSmillert if (tflag)
26577a43662Skrw makedisktab(stdout, &lab);
266b8778baaSmillert else
26777a43662Skrw display(stdout, &lab, print_unit, 1);
26877a43662Skrw error = checklabel(&lab);
269df930be7Sderaadt break;
270df930be7Sderaadt case RESTORE:
271df930be7Sderaadt if (argc < 2 || argc > 3)
272df930be7Sderaadt usage();
273df930be7Sderaadt if (!(t = fopen(argv[1], "r")))
274df930be7Sderaadt err(4, "%s", argv[1]);
27540bba581Skrw error = getasciilabel(t, &lab);
276c816a80fSkrw if (error == 0) {
27740bba581Skrw memset(&lab.d_uid, 0, sizeof(lab.d_uid));
27840bba581Skrw error = writelabel(f, &lab);
279038e2c8cSkrw }
28076216654Sderaadt fclose(t);
281df930be7Sderaadt break;
282df930be7Sderaadt case WRITE:
283f52242c6Skrw error = checklabel(&lab);
284f52242c6Skrw if (error == 0)
28540bba581Skrw error = writelabel(f, &lab);
286df930be7Sderaadt break;
287a4df0321Sderaadt default:
288a4df0321Sderaadt break;
289df930be7Sderaadt }
29082b1057eStb return error;
291df930be7Sderaadt }
292df930be7Sderaadt
293df930be7Sderaadt /*
294ccd9f552Skrw * Construct a prototype disklabel from /etc/disktab.
295df930be7Sderaadt */
296df930be7Sderaadt void
parsedisktab(char * type,struct disklabel * lp)297ccd9f552Skrw parsedisktab(char *type, struct disklabel *lp)
298df930be7Sderaadt {
299df930be7Sderaadt struct disklabel *dp;
300df930be7Sderaadt
301df930be7Sderaadt dp = getdiskbyname(type);
302df930be7Sderaadt if (dp == NULL)
303df930be7Sderaadt errx(1, "unknown disk type: %s", type);
304df930be7Sderaadt *lp = *dp;
305df930be7Sderaadt }
306df930be7Sderaadt
307df930be7Sderaadt int
writelabel(int f,struct disklabel * lp)30840bba581Skrw writelabel(int f, struct disklabel *lp)
309df930be7Sderaadt {
310df930be7Sderaadt lp->d_magic = DISKMAGIC;
311df930be7Sderaadt lp->d_magic2 = DISKMAGIC;
312c9b3503cSderaadt lp->d_checksum = 0;
313df930be7Sderaadt lp->d_checksum = dkcksum(lp);
31403f3b153Skrw
315f7c5575eSderaadt if (!donothing) {
31603f3b153Skrw /* Write new label to disk. */
31703f3b153Skrw if (ioctl(f, DIOCWDINFO, lp) == -1) {
31803f3b153Skrw warn("DIOCWDINFO");
319bb12209fSkrw return 1;
320df930be7Sderaadt }
321df930be7Sderaadt
32203f3b153Skrw /* Refresh our copy of the on-disk current label to get UID. */
32390b0764fSkrw if (ioctl(f, DIOCGDINFO, &lab) == -1)
32490b0764fSkrw err(4, "DIOCGDINFO");
32503f3b153Skrw
32603f3b153Skrw /* Finally, write out any mount point information. */
327af9b7167Skrw mpsave(lp);
328d6d80bb0Skrw }
329af9b7167Skrw
330bb12209fSkrw return 0;
331df930be7Sderaadt }
332df930be7Sderaadt
333df930be7Sderaadt /*
33477a43662Skrw * Fetch requested disklabel into 'lab' using ioctl.
335df930be7Sderaadt */
33677a43662Skrw void
readlabel(int f)3378809fabbSderaadt readlabel(int f)
338df930be7Sderaadt {
339ba275c17Skrw struct disklabel dl;
340cce39710Sjsing
34190b0764fSkrw if (cflag && ioctl(f, DIOCRLDINFO) == -1)
34290b0764fSkrw err(4, "DIOCRLDINFO");
34334ae4198Skrw
344c130ef84Skrw if ((op == RESTORE) || dflag || aflag) {
34590b0764fSkrw if (ioctl(f, DIOCGPDINFO, &lab) == -1)
34690b0764fSkrw err(4, "DIOCGPDINFO");
347df930be7Sderaadt } else {
34890b0764fSkrw if (ioctl(f, DIOCGDINFO, &lab) == -1)
34990b0764fSkrw err(4, "DIOCGDINFO");
350ba275c17Skrw if (ioctl(f, DIOCGPDINFO, &dl) == -1)
351ba275c17Skrw err(4, "DIOCGPDINFO");
352ba275c17Skrw lab.d_secsize = dl.d_secsize;
353ba275c17Skrw lab.d_nsectors = dl.d_nsectors;
354ba275c17Skrw lab.d_ntracks = dl.d_ntracks;
355ba275c17Skrw lab.d_secpercyl = dl.d_secpercyl;
356ba275c17Skrw lab.d_ncylinders = dl.d_ncylinders;
3571cc333d2Skrw lab.d_type = dl.d_type;
358df930be7Sderaadt }
359ed5b94b5Stb }
360ed5b94b5Stb
361ccd9f552Skrw void
parsefstab(void)362ccd9f552Skrw parsefstab(void)
363ed5b94b5Stb {
364ed5b94b5Stb char *partname, *partduid;
365ed5b94b5Stb struct fstab *fsent;
366ed5b94b5Stb int i;
367a0cc7d63Skrw
368aa48e8d1Smillert i = asprintf(&partname, "/dev/%s%c", dkname, 'a');
369aa48e8d1Smillert if (i == -1)
370b7cc13deSkrw err(1, NULL);
371aa48e8d1Smillert i = asprintf(&partduid,
37269a6ffbcSjsing "%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx.a",
373cce39710Sjsing lab.d_uid[0], lab.d_uid[1], lab.d_uid[2], lab.d_uid[3],
374cce39710Sjsing lab.d_uid[4], lab.d_uid[5], lab.d_uid[6], lab.d_uid[7]);
375aa48e8d1Smillert if (i == -1)
376b7cc13deSkrw err(1, NULL);
377cce39710Sjsing setfsent();
378cce39710Sjsing for (i = 0; i < MAXPARTITIONS; i++) {
379cce39710Sjsing partname[strlen(dkname) + 5] = 'a' + i;
38069a6ffbcSjsing partduid[strlen(partduid) - 1] = 'a' + i;
381cce39710Sjsing fsent = getfsspec(partname);
382cce39710Sjsing if (fsent == NULL)
38369a6ffbcSjsing fsent = getfsspec(partduid);
384cce39710Sjsing if (fsent)
385cce39710Sjsing mountpoints[i] = strdup(fsent->fs_file);
386cce39710Sjsing }
387cce39710Sjsing endfsent();
38869a6ffbcSjsing free(partduid);
389cce39710Sjsing free(partname);
390df930be7Sderaadt }
391df930be7Sderaadt
392b8778baaSmillert void
makedisktab(FILE * f,struct disklabel * lp)3938809fabbSderaadt makedisktab(FILE *f, struct disklabel *lp)
394b8778baaSmillert {
395d09f3941Smillert int i;
396b8778baaSmillert struct partition *pp;
397b8778baaSmillert
398b8778baaSmillert if (lp->d_packname[0])
399a4df0321Sderaadt (void)fprintf(f, "%.*s|", (int)sizeof(lp->d_packname),
400b8778baaSmillert lp->d_packname);
401b8778baaSmillert if (lp->d_typename[0])
402a4df0321Sderaadt (void)fprintf(f, "%.*s|", (int)sizeof(lp->d_typename),
403b8778baaSmillert lp->d_typename);
404b8778baaSmillert (void)fputs("Automatically generated label:\\\n\t:dt=", f);
405394552ccSderaadt if (lp->d_type < DKMAXTYPES)
406b8778baaSmillert (void)fprintf(f, "%s:", dktypenames[lp->d_type]);
407b8778baaSmillert else
408b8778baaSmillert (void)fprintf(f, "unknown%d:", lp->d_type);
409b8778baaSmillert
410d5475bf8Smillert (void)fprintf(f, "se#%u:", lp->d_secsize);
411d5475bf8Smillert (void)fprintf(f, "ns#%u:", lp->d_nsectors);
412d5475bf8Smillert (void)fprintf(f, "nt#%u:", lp->d_ntracks);
413d5475bf8Smillert (void)fprintf(f, "nc#%u:", lp->d_ncylinders);
414d5475bf8Smillert (void)fprintf(f, "sc#%u:", lp->d_secpercyl);
41534af67a3Sotto (void)fprintf(f, "su#%llu:", DL_GETDSIZE(lp));
416b8778baaSmillert
4176534e983Sderaadt /*
4186534e983Sderaadt * XXX We do not print have disktab information yet for
4196534e983Sderaadt * XXX DL_GETBSTART DL_GETBEND
4206534e983Sderaadt */
421b8778baaSmillert pp = lp->d_partitions;
422b8778baaSmillert for (i = 0; i < lp->d_npartitions; i++, pp++) {
4231e0ad43cSotto if (DL_GETPSIZE(pp)) {
424b8778baaSmillert char c = 'a' + i;
425b8778baaSmillert
426b8778baaSmillert (void)fprintf(f, "\\\n\t:");
4271e0ad43cSotto (void)fprintf(f, "p%c#%llu:", c, DL_GETPSIZE(pp));
4281e0ad43cSotto (void)fprintf(f, "o%c#%llu:", c, DL_GETPOFFSET(pp));
429b8778baaSmillert if (pp->p_fstype != FS_UNUSED) {
430394552ccSderaadt if (pp->p_fstype < FSMAXTYPES)
431b8778baaSmillert (void)fprintf(f, "t%c=%s:", c,
432b8778baaSmillert fstypenames[pp->p_fstype]);
433b8778baaSmillert else
434b8778baaSmillert (void)fprintf(f, "t%c=unknown%d:",
435b8778baaSmillert c, pp->p_fstype);
436b8778baaSmillert }
437b8778baaSmillert switch (pp->p_fstype) {
438b8778baaSmillert
439b8778baaSmillert case FS_UNUSED:
440b8778baaSmillert break;
441b8778baaSmillert
442b8778baaSmillert case FS_BSDFFS:
443d5475bf8Smillert (void)fprintf(f, "b%c#%u:", c,
444ddfcbf38Sotto DISKLABELV1_FFS_BSIZE(pp->p_fragblock));
445ddfcbf38Sotto (void)fprintf(f, "f%c#%u:", c,
446ddfcbf38Sotto DISKLABELV1_FFS_FSIZE(pp->p_fragblock));
447b8778baaSmillert break;
448b8778baaSmillert
449b8778baaSmillert default:
450b8778baaSmillert break;
451b8778baaSmillert }
452b8778baaSmillert }
453b8778baaSmillert }
454b8778baaSmillert (void)fputc('\n', f);
455b8778baaSmillert (void)fflush(f);
456b8778baaSmillert }
457b8778baaSmillert
4585b19a791Sotto double
scale(u_int64_t sz,char unit,const struct disklabel * lp)45943ba7787Skrw scale(u_int64_t sz, char unit, const struct disklabel *lp)
4605b19a791Sotto {
4615b19a791Sotto double fsz;
4625b19a791Sotto
4635b19a791Sotto fsz = (double)sz * lp->d_secsize;
4645b19a791Sotto
4655b19a791Sotto switch (unit) {
4665b19a791Sotto case 'B':
4675b19a791Sotto return fsz;
4685b19a791Sotto case 'C':
4695b19a791Sotto return fsz / lp->d_secsize / lp->d_secpercyl;
4705b19a791Sotto case 'K':
4715b19a791Sotto return fsz / 1024;
4725b19a791Sotto case 'M':
4735b19a791Sotto return fsz / (1024 * 1024);
4745b19a791Sotto case 'G':
4755b19a791Sotto return fsz / (1024 * 1024 * 1024);
4761e0ad43cSotto case 'T':
4771e0ad43cSotto return fsz / (1024ULL * 1024 * 1024 * 1024);
4785b19a791Sotto default:
4795b19a791Sotto return -1.0;
4805b19a791Sotto }
4815b19a791Sotto }
4825b19a791Sotto
483258c7339Smillert /*
484dd195068Smarco * Display a particular partition.
485258c7339Smillert */
486df930be7Sderaadt void
display_partition(FILE * f,const struct disklabel * lp,int i,char unit)48743ba7787Skrw display_partition(FILE *f, const struct disklabel *lp, int i, char unit)
488df930be7Sderaadt {
48943ba7787Skrw const struct partition *pp = &lp->d_partitions[i];
4903f756be8Skrw double p_size;
4916fe57b42Smillert
4921e0ad43cSotto p_size = scale(DL_GETPSIZE(pp), unit, lp);
4931e0ad43cSotto if (DL_GETPSIZE(pp)) {
494ddfcbf38Sotto u_int32_t frag = DISKLABELV1_FFS_FRAG(pp->p_fragblock);
495ddfcbf38Sotto u_int32_t fsize = DISKLABELV1_FFS_FSIZE(pp->p_fragblock);
49661deb337Sderaadt
4976fe57b42Smillert if (p_size < 0)
4987a529b87Sderaadt fprintf(f, " %c: %16llu %16llu ", 'a' + i,
4991e0ad43cSotto DL_GETPSIZE(pp), DL_GETPOFFSET(pp));
5006fe57b42Smillert else
5013f756be8Skrw fprintf(f, " %c: %15.*f%c %16llu ", 'a' + i,
502f21a098bSotto unit == 'B' ? 0 : 1, p_size, unit,
5033f756be8Skrw DL_GETPOFFSET(pp));
504394552ccSderaadt if (pp->p_fstype < FSMAXTYPES)
505ce47867fSotto fprintf(f, "%7.7s", fstypenames[pp->p_fstype]);
506df930be7Sderaadt else
507ce47867fSotto fprintf(f, "%7d", pp->p_fstype);
5086f093b5dSkrw
509df930be7Sderaadt switch (pp->p_fstype) {
510df930be7Sderaadt case FS_BSDFFS:
511a95dd767Sotto fprintf(f, " %5u %5u %5hu ",
512ddfcbf38Sotto fsize, fsize * frag,
513df930be7Sderaadt pp->p_cpg);
514df930be7Sderaadt break;
515df930be7Sderaadt default:
516821416f1Sbluhm fprintf(f, "%20.20s", "");
517df930be7Sderaadt break;
518df930be7Sderaadt }
5196f093b5dSkrw
52034ae4198Skrw if (mountpoints[i] != NULL)
52134ae4198Skrw fprintf(f, "# %s", mountpoints[i]);
522258c7339Smillert putc('\n', f);
523df930be7Sderaadt }
524df930be7Sderaadt }
525258c7339Smillert
526352d199bSkrw char
canonical_unit(const struct disklabel * lp,char unit)52743ba7787Skrw canonical_unit(const struct disklabel *lp, char unit)
528352d199bSkrw {
52943ba7787Skrw const struct partition *pp;
530eafadddfSkrw u_int64_t small;
531352d199bSkrw int i;
532352d199bSkrw
533352d199bSkrw if (unit == '*') {
534352d199bSkrw small = DL_GETDSIZE(lp);
535352d199bSkrw pp = &lp->d_partitions[0];
536352d199bSkrw for (i = 0; i < lp->d_npartitions; i++, pp++)
537352d199bSkrw if (DL_GETPSIZE(pp) > 0 && DL_GETPSIZE(pp) < small)
538352d199bSkrw small = DL_GETPSIZE(pp);
539352d199bSkrw if (small < DL_BLKTOSEC(lp, MEG(1)))
540352d199bSkrw unit = 'K';
541352d199bSkrw else if (small < DL_BLKTOSEC(lp, MEG(1024)))
542352d199bSkrw unit = 'M';
543352d199bSkrw else if (small < DL_BLKTOSEC(lp, GIG(1024)))
544352d199bSkrw unit = 'G';
545352d199bSkrw else
546352d199bSkrw unit = 'T';
547352d199bSkrw }
548025f5691Sderaadt unit = toupper((unsigned char)unit);
549352d199bSkrw
550bb12209fSkrw return unit;
551352d199bSkrw }
552352d199bSkrw
553258c7339Smillert void
display(FILE * f,const struct disklabel * lp,char unit,int all)55443ba7787Skrw display(FILE *f, const struct disklabel *lp, char unit, int all)
555258c7339Smillert {
556a2fe6e2dSkrw int i;
5575b19a791Sotto double d;
558258c7339Smillert
559352d199bSkrw unit = canonical_unit(lp, unit);
560352d199bSkrw
561e303d4a0Skrw fprintf(f, "# %s:\n", specname);
56295fa422dSderaadt
563394552ccSderaadt if (lp->d_type < DKMAXTYPES)
564258c7339Smillert fprintf(f, "type: %s\n", dktypenames[lp->d_type]);
565258c7339Smillert else
566258c7339Smillert fprintf(f, "type: %d\n", lp->d_type);
567ac4d310fSjsing fprintf(f, "disk: %.*s\n", (int)sizeof(lp->d_typename),
568ac4d310fSjsing lp->d_typename);
569ac4d310fSjsing fprintf(f, "label: %.*s\n", (int)sizeof(lp->d_packname),
570ac4d310fSjsing lp->d_packname);
57169a6ffbcSjsing fprintf(f, "duid: %02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx\n",
572f6ad9e2dSjsing lp->d_uid[0], lp->d_uid[1], lp->d_uid[2], lp->d_uid[3],
573f6ad9e2dSjsing lp->d_uid[4], lp->d_uid[5], lp->d_uid[6], lp->d_uid[7]);
574258c7339Smillert fprintf(f, "flags:");
575fc1a4cc6Sderaadt if (lp->d_flags & D_VENDOR)
576fc1a4cc6Sderaadt fprintf(f, " vendor");
577258c7339Smillert putc('\n', f);
578aff3f969Sotto
57918ec52beSotto fprintf(f, "bytes/sector: %u\n", lp->d_secsize);
58018ec52beSotto fprintf(f, "sectors/track: %u\n", lp->d_nsectors);
58118ec52beSotto fprintf(f, "tracks/cylinder: %u\n", lp->d_ntracks);
58218ec52beSotto fprintf(f, "sectors/cylinder: %u\n", lp->d_secpercyl);
58318ec52beSotto fprintf(f, "cylinders: %u\n", lp->d_ncylinders);
5843f756be8Skrw fprintf(f, "total sectors: %llu", DL_GETDSIZE(lp));
5851e0ad43cSotto d = scale(DL_GETDSIZE(lp), unit, lp);
5863f756be8Skrw if (d > 0)
5873f756be8Skrw fprintf(f, " # total bytes: %.*f%c", unit == 'B' ? 0 : 1,
5885b19a791Sotto d, unit);
5893f756be8Skrw fprintf(f, "\n");
5905b19a791Sotto
5916534e983Sderaadt fprintf(f, "boundstart: %llu\n", DL_GETBSTART(lp));
5926534e983Sderaadt fprintf(f, "boundend: %llu\n", DL_GETBEND(lp));
59395fa422dSderaadt if (all) {
5945b19a791Sotto fprintf(f, "\n%hu partitions:\n", lp->d_npartitions);
5957a529b87Sderaadt fprintf(f, "# %16.16s %16.16s fstype [fsize bsize cpg]\n",
596f21a098bSotto "size", "offset");
597258c7339Smillert for (i = 0; i < lp->d_npartitions; i++)
59834ae4198Skrw display_partition(f, lp, i, unit);
599aff3f969Sotto }
600df930be7Sderaadt fflush(f);
601df930be7Sderaadt }
602df930be7Sderaadt
603df930be7Sderaadt int
edit(struct disklabel * lp,int f)6048809fabbSderaadt edit(struct disklabel *lp, int f)
605df930be7Sderaadt {
606f52242c6Skrw int first, ch, fd, error = 0;
607df930be7Sderaadt struct disklabel label;
60834ac054bSderaadt FILE *fp;
609df930be7Sderaadt
610625b9b20Sderaadt if ((fd = mkstemp(tmpfil)) == -1 || (fp = fdopen(fd, "w")) == NULL) {
611ffb4dd05Sguenther warn("%s", tmpfil);
612979a4437Sderaadt if (fd != -1)
613979a4437Sderaadt close(fd);
614bb12209fSkrw return 1;
615df930be7Sderaadt }
61634ae4198Skrw display(fp, lp, 0, 1);
617979a4437Sderaadt fprintf(fp, "\n# Notes:\n");
618979a4437Sderaadt fprintf(fp,
619979a4437Sderaadt "# Up to 16 partitions are valid, named from 'a' to 'p'. Partition 'a' is\n"
620979a4437Sderaadt "# your root filesystem, 'b' is your swap, and 'c' should cover your whole\n"
621979a4437Sderaadt "# disk. Any other partition is free for any use. 'size' and 'offset' are\n"
622979a4437Sderaadt "# in 512-byte blocks. fstype should be '4.2BSD', 'swap', or 'none' or some\n"
6233c92d7f2Stedu "# other values. fsize/bsize/cpg should typically be '2048 16384 16' for a\n"
6245e61eb4aSmiod "# 4.2BSD filesystem (or '512 4096 16' except on alpha, sun4, ...)\n");
62534ac054bSderaadt fclose(fp);
626df930be7Sderaadt for (;;) {
627ba7e2ebaSray if (editit(tmpfil) == -1)
628df930be7Sderaadt break;
62934ac054bSderaadt fp = fopen(tmpfil, "r");
63034ac054bSderaadt if (fp == NULL) {
631df930be7Sderaadt warn("%s", tmpfil);
632df930be7Sderaadt break;
633df930be7Sderaadt }
6346bdbf715Skrw /* Start with the kernel's idea of the default label. */
63590b0764fSkrw if (ioctl(f, DIOCGPDINFO, &label) == -1)
63690b0764fSkrw err(4, "DIOCGPDINFO");
637f52242c6Skrw error = getasciilabel(fp, &label);
638f52242c6Skrw if (error == 0) {
6395362a395Smillert if (cmplabel(lp, &label) == 0) {
6405362a395Smillert puts("No changes.");
6415362a395Smillert fclose(fp);
6425362a395Smillert (void) unlink(tmpfil);
643bb12209fSkrw return 0;
6445362a395Smillert }
645df930be7Sderaadt *lp = label;
64640bba581Skrw if (writelabel(f, lp) == 0) {
64734ac054bSderaadt fclose(fp);
648df930be7Sderaadt (void) unlink(tmpfil);
649bb12209fSkrw return 0;
650df930be7Sderaadt }
651df930be7Sderaadt }
65234ac054bSderaadt fclose(fp);
653df930be7Sderaadt printf("re-edit the label? [y]: ");
654df930be7Sderaadt fflush(stdout);
655df930be7Sderaadt first = ch = getchar();
656df930be7Sderaadt while (ch != '\n' && ch != EOF)
657df930be7Sderaadt ch = getchar();
658df930be7Sderaadt if (first == 'n' || first == 'N')
659df930be7Sderaadt break;
660df930be7Sderaadt }
661df930be7Sderaadt (void)unlink(tmpfil);
662bb12209fSkrw return 1;
663df930be7Sderaadt }
664df930be7Sderaadt
665dcb1730eSray /*
666dcb1730eSray * Execute an editor on the specified pathname, which is interpreted
667dcb1730eSray * from the shell. This means flags may be included.
668dcb1730eSray *
669dcb1730eSray * Returns -1 on error, or the exit value on success.
670dcb1730eSray */
671df930be7Sderaadt int
editit(const char * pathname)672ba7e2ebaSray editit(const char *pathname)
673df930be7Sderaadt {
674ba7e2ebaSray char *argp[] = {"sh", "-c", NULL, NULL}, *ed, *p;
67543316b18Sderaadt sig_t sighup, sigint, sigquit, sigchld;
67621bb9853Sderaadt pid_t pid;
67743316b18Sderaadt int saved_errno, st, ret = -1;
6781bfae893Sderaadt
679ba7e2ebaSray ed = getenv("VISUAL");
680ba7e2ebaSray if (ed == NULL || ed[0] == '\0')
681ba7e2ebaSray ed = getenv("EDITOR");
682ba7e2ebaSray if (ed == NULL || ed[0] == '\0')
683625b9b20Sderaadt ed = _PATH_VI;
684ba7e2ebaSray if (asprintf(&p, "%s %s", ed, pathname) == -1)
685bb12209fSkrw return -1;
686b5043781Sderaadt argp[2] = p;
687df930be7Sderaadt
688ba7e2ebaSray sighup = signal(SIGHUP, SIG_IGN);
689ba7e2ebaSray sigint = signal(SIGINT, SIG_IGN);
690ba7e2ebaSray sigquit = signal(SIGQUIT, SIG_IGN);
69143316b18Sderaadt sigchld = signal(SIGCHLD, SIG_DFL);
692dcb1730eSray if ((pid = fork()) == -1)
693dcb1730eSray goto fail;
694df930be7Sderaadt if (pid == 0) {
695b5043781Sderaadt execv(_PATH_BSHELL, argp);
696b5043781Sderaadt _exit(127);
697df930be7Sderaadt }
698dcb1730eSray while (waitpid(pid, &st, 0) == -1)
699ba7e2ebaSray if (errno != EINTR)
700dcb1730eSray goto fail;
70143316b18Sderaadt if (!WIFEXITED(st))
702dcb1730eSray errno = EINTR;
70343316b18Sderaadt else
70443316b18Sderaadt ret = WEXITSTATUS(st);
705dcb1730eSray
706dcb1730eSray fail:
707dcb1730eSray saved_errno = errno;
708dcb1730eSray (void)signal(SIGHUP, sighup);
709dcb1730eSray (void)signal(SIGINT, sigint);
710dcb1730eSray (void)signal(SIGQUIT, sigquit);
71143316b18Sderaadt (void)signal(SIGCHLD, sigchld);
712dcb1730eSray free(p);
713dcb1730eSray errno = saved_errno;
714bb12209fSkrw return ret;
715df930be7Sderaadt }
716df930be7Sderaadt
717df930be7Sderaadt char *
skip(char * cp)7188809fabbSderaadt skip(char *cp)
719df930be7Sderaadt {
720df930be7Sderaadt
721df930be7Sderaadt cp += strspn(cp, " \t");
722df930be7Sderaadt if (*cp == '\0')
723bb12209fSkrw return NULL;
724bb12209fSkrw return cp;
725df930be7Sderaadt }
726df930be7Sderaadt
727df930be7Sderaadt char *
word(char * cp)7288809fabbSderaadt word(char *cp)
729df930be7Sderaadt {
730df930be7Sderaadt
731df930be7Sderaadt cp += strcspn(cp, " \t");
732df930be7Sderaadt if (*cp == '\0')
733bb12209fSkrw return NULL;
734df930be7Sderaadt *cp++ = '\0';
735df930be7Sderaadt cp += strspn(cp, " \t");
736df930be7Sderaadt if (*cp == '\0')
737bb12209fSkrw return NULL;
738bb12209fSkrw return cp;
739df930be7Sderaadt }
740df930be7Sderaadt
74118ec52beSotto /* Base the max value on the sizeof of the value we are reading */
74218ec52beSotto #define GETNUM(field, nptr, min, errstr) \
74318ec52beSotto getnum((nptr), (min), \
7441e0ad43cSotto sizeof(field) == 8 ? LLONG_MAX : \
7451e0ad43cSotto (sizeof(field) == 4 ? UINT_MAX : \
7461e0ad43cSotto (sizeof(field) == 2 ? USHRT_MAX : UCHAR_MAX)), (errstr))
74718ec52beSotto
7481e0ad43cSotto u_int64_t
getnum(char * nptr,u_int64_t min,u_int64_t max,const char ** errstr)7491e0ad43cSotto getnum(char *nptr, u_int64_t min, u_int64_t max, const char **errstr)
75018ec52beSotto {
75118ec52beSotto char *p, c;
7521e0ad43cSotto u_int64_t ret;
75318ec52beSotto
754025f5691Sderaadt for (p = nptr; *p != '\0' && !isspace((unsigned char)*p); p++)
75518ec52beSotto ;
75618ec52beSotto c = *p;
75718ec52beSotto *p = '\0';
75818ec52beSotto ret = strtonum(nptr, min, max, errstr);
75918ec52beSotto *p = c;
760bb12209fSkrw return ret;
76118ec52beSotto }
76218ec52beSotto
76335a55a91Sjsing int
duid_parse(struct disklabel * lp,char * s)76469a6ffbcSjsing duid_parse(struct disklabel *lp, char *s)
76535a55a91Sjsing {
76669a6ffbcSjsing u_char duid[8];
76735a55a91Sjsing char c;
76835a55a91Sjsing int i;
76935a55a91Sjsing
77035a55a91Sjsing if (strlen(s) != 16)
77135a55a91Sjsing return -1;
77235a55a91Sjsing
77354bd9d93Skrw memset(duid, 0, sizeof(duid));
77435a55a91Sjsing for (i = 0; i < 16; i++) {
77535a55a91Sjsing c = s[i];
77635a55a91Sjsing if (c >= '0' && c <= '9')
77735a55a91Sjsing c -= '0';
77835a55a91Sjsing else if (c >= 'a' && c <= 'f')
77935a55a91Sjsing c -= ('a' - 10);
780b2fee82fShalex else if (c >= 'A' && c <= 'F')
781b2fee82fShalex c -= ('A' - 10);
78235a55a91Sjsing else
78335a55a91Sjsing return -1;
78469a6ffbcSjsing duid[i / 2] <<= 4;
78569a6ffbcSjsing duid[i / 2] |= c & 0xf;
78635a55a91Sjsing }
78735a55a91Sjsing
78869a6ffbcSjsing memcpy(lp->d_uid, &duid, sizeof(lp->d_uid));
78935a55a91Sjsing return 0;
79035a55a91Sjsing }
79135a55a91Sjsing
792df930be7Sderaadt /*
7931007bfb9Sray * Read an ascii label in from FILE f,
794df930be7Sderaadt * in the same format as that put out by display(),
795df930be7Sderaadt * and fill in lp.
796df930be7Sderaadt */
797df930be7Sderaadt int
getasciilabel(FILE * f,struct disklabel * lp)7988809fabbSderaadt getasciilabel(FILE *f, struct disklabel *lp)
799df930be7Sderaadt {
800598e0fa8Sguenther const char * const *cpp;
801598e0fa8Sguenther const char *s;
802598e0fa8Sguenther char *cp;
80318ec52beSotto const char *errstr;
804df930be7Sderaadt struct partition *pp;
805598e0fa8Sguenther char *mp, *tp, line[BUFSIZ];
806038e2c8cSkrw char **omountpoints = NULL;
80718ec52beSotto int lineno = 0, errors = 0;
808ddfcbf38Sotto u_int32_t v, fsize;
8091e0ad43cSotto u_int64_t lv;
810038e2c8cSkrw unsigned int part;
811df930be7Sderaadt
8121e0ad43cSotto lp->d_version = 1;
813038e2c8cSkrw
814038e2c8cSkrw if (!(omountpoints = calloc(MAXPARTITIONS, sizeof(char *))))
815b7cc13deSkrw err(1, NULL);
816038e2c8cSkrw
817038e2c8cSkrw mpcopy(omountpoints, mountpoints);
818038e2c8cSkrw for (part = 0; part < MAXPARTITIONS; part++) {
819038e2c8cSkrw free(mountpoints[part]);
820038e2c8cSkrw mountpoints[part] = NULL;
821038e2c8cSkrw }
822038e2c8cSkrw
8230420c874Sray while (fgets(line, sizeof(line), f)) {
824df930be7Sderaadt lineno++;
825038e2c8cSkrw mp = NULL;
826038e2c8cSkrw if ((cp = strpbrk(line, "\r\n")))
827df930be7Sderaadt *cp = '\0';
828038e2c8cSkrw if ((cp = strpbrk(line, "#"))) {
829038e2c8cSkrw *cp = '\0';
830038e2c8cSkrw mp = skip(cp+1);
831038e2c8cSkrw if (mp && *mp != '/')
832038e2c8cSkrw mp = NULL;
833038e2c8cSkrw }
834df930be7Sderaadt cp = skip(line);
835df930be7Sderaadt if (cp == NULL)
836df930be7Sderaadt continue;
837df930be7Sderaadt tp = strchr(cp, ':');
838df930be7Sderaadt if (tp == NULL) {
839df930be7Sderaadt warnx("line %d: syntax error", lineno);
840df930be7Sderaadt errors++;
841df930be7Sderaadt continue;
842df930be7Sderaadt }
843df930be7Sderaadt *tp++ = '\0', tp = skip(tp);
844df930be7Sderaadt if (!strcmp(cp, "flags")) {
845df930be7Sderaadt for (v = 0; (cp = tp) && *cp != '\0';) {
846df930be7Sderaadt tp = word(cp);
84726606d2cSkrw if (!strcmp(cp, "badsect"))
848ea6c4d24Skrw ; /* Ignore obsolete flag. */
84969e812cbSkrw else if (!strcmp(cp, "vendor"))
85069e812cbSkrw v |= D_VENDOR;
851df930be7Sderaadt else {
852df930be7Sderaadt warnx("line %d: bad flag: %s",
853df930be7Sderaadt lineno, cp);
854df930be7Sderaadt errors++;
855df930be7Sderaadt }
856df930be7Sderaadt }
857df930be7Sderaadt lp->d_flags = v;
858df930be7Sderaadt continue;
859df930be7Sderaadt }
860df930be7Sderaadt if (sscanf(cp, "%d partitions", &v) == 1) {
86118ec52beSotto if (v == 0 || v > MAXPARTITIONS) {
862df930be7Sderaadt warnx("line %d: bad # of partitions", lineno);
863df930be7Sderaadt lp->d_npartitions = MAXPARTITIONS;
864df930be7Sderaadt errors++;
865df930be7Sderaadt } else
866df930be7Sderaadt lp->d_npartitions = v;
867df930be7Sderaadt continue;
868df930be7Sderaadt }
869df930be7Sderaadt if (tp == NULL)
870df930be7Sderaadt tp = "";
871df930be7Sderaadt if (!strcmp(cp, "disk")) {
872df930be7Sderaadt strncpy(lp->d_typename, tp, sizeof (lp->d_typename));
873df930be7Sderaadt continue;
874df930be7Sderaadt }
875df930be7Sderaadt if (!strcmp(cp, "label")) {
876df930be7Sderaadt strncpy(lp->d_packname, tp, sizeof (lp->d_packname));
877df930be7Sderaadt continue;
878df930be7Sderaadt }
87969a6ffbcSjsing if (!strcmp(cp, "duid")) {
88069a6ffbcSjsing if (duid_parse(lp, tp) != 0) {
881ac4d310fSjsing warnx("line %d: bad %s: %s", lineno, cp, tp);
882ac4d310fSjsing errors++;
88335a55a91Sjsing }
884ac4d310fSjsing continue;
885ac4d310fSjsing }
886ecc04265Skrw
887a2fe6e2dSkrw /* Ignore fields that are no longer used. */
888ecc04265Skrw if (!strcmp(cp, "rpm") ||
889ecc04265Skrw !strcmp(cp, "interleave") ||
890ecc04265Skrw !strcmp(cp, "trackskew") ||
891ecc04265Skrw !strcmp(cp, "cylinderskew") ||
892ecc04265Skrw !strcmp(cp, "headswitch") ||
893a2fe6e2dSkrw !strcmp(cp, "track-to-track seek") ||
894a2fe6e2dSkrw !strcmp(cp, "drivedata"))
895df930be7Sderaadt continue;
896ecc04265Skrw
897ecc04265Skrw /* Ignore fields that are forcibly set when label is read. */
898ecc04265Skrw if (!strcmp(cp, "total sectors") ||
899ecc04265Skrw !strcmp(cp, "boundstart") ||
900ba275c17Skrw !strcmp(cp, "boundend") ||
901ba275c17Skrw !strcmp(cp, "bytes/sector") ||
902ba275c17Skrw !strcmp(cp, "sectors/track") ||
903ba275c17Skrw !strcmp(cp, "sectors/cylinder") ||
904ba275c17Skrw !strcmp(cp, "tracks/cylinder") ||
9051cc333d2Skrw !strcmp(cp, "cylinders") ||
9061cc333d2Skrw !strcmp(cp, "type"))
907df930be7Sderaadt continue;
908ecc04265Skrw
909df930be7Sderaadt if ('a' <= *cp && *cp <= 'z' && cp[1] == '\0') {
910db93f2f1Sderaadt unsigned int part = *cp - 'a';
911df930be7Sderaadt
91294e8b936Smillert if (part >= lp->d_npartitions) {
91394e8b936Smillert if (part >= MAXPARTITIONS) {
914df930be7Sderaadt warnx("line %d: bad partition name: %s",
915df930be7Sderaadt lineno, cp);
916df930be7Sderaadt errors++;
917df930be7Sderaadt continue;
91894e8b936Smillert } else {
91994e8b936Smillert lp->d_npartitions = part + 1;
92094e8b936Smillert }
921df930be7Sderaadt }
922df930be7Sderaadt pp = &lp->d_partitions[part];
92318ec52beSotto #define NXTNUM(n, field, errstr) { \
924*498920cdSkrw if (tp == NULL || *tp == '\0') { \
925df930be7Sderaadt warnx("line %d: too few fields", lineno); \
926df930be7Sderaadt errors++; \
927df930be7Sderaadt break; \
928df930be7Sderaadt } else \
92918ec52beSotto cp = tp, tp = word(cp), (n) = GETNUM(field, cp, 0, errstr); \
930df930be7Sderaadt }
9311e0ad43cSotto NXTNUM(lv, lv, &errstr);
93218ec52beSotto if (errstr) {
933df930be7Sderaadt warnx("line %d: bad partition size: %s",
934df930be7Sderaadt lineno, cp);
935df930be7Sderaadt errors++;
9361e0ad43cSotto } else {
9371e0ad43cSotto DL_SETPSIZE(pp, lv);
9381e0ad43cSotto }
9391e0ad43cSotto NXTNUM(lv, lv, &errstr);
94018ec52beSotto if (errstr) {
941df930be7Sderaadt warnx("line %d: bad partition offset: %s",
942df930be7Sderaadt lineno, cp);
943df930be7Sderaadt errors++;
9441e0ad43cSotto } else {
9451e0ad43cSotto DL_SETPOFFSET(pp, lv);
9461e0ad43cSotto }
947bf01d747Sderaadt if (tp == NULL) {
948bf01d747Sderaadt pp->p_fstype = FS_UNUSED;
949bf01d747Sderaadt goto gottype;
950bf01d747Sderaadt }
951df930be7Sderaadt cp = tp, tp = word(cp);
952df930be7Sderaadt cpp = fstypenames;
953df930be7Sderaadt for (; cpp < &fstypenames[FSMAXTYPES]; cpp++)
954b1b8d330Sdownsj if ((s = *cpp) && !strcasecmp(s, cp)) {
955df930be7Sderaadt pp->p_fstype = cpp - fstypenames;
956df930be7Sderaadt goto gottype;
957df930be7Sderaadt }
958025f5691Sderaadt if (isdigit((unsigned char)*cp))
95918ec52beSotto v = GETNUM(pp->p_fstype, cp, 0, &errstr);
960df930be7Sderaadt else
961df930be7Sderaadt v = FSMAXTYPES;
96218ec52beSotto if (errstr || v >= FSMAXTYPES) {
963df930be7Sderaadt warnx("line %d: warning, unknown filesystem type: %s",
964df930be7Sderaadt lineno, cp);
965df930be7Sderaadt v = FS_UNUSED;
966df930be7Sderaadt }
967df930be7Sderaadt pp->p_fstype = v;
968df930be7Sderaadt gottype:
969df930be7Sderaadt switch (pp->p_fstype) {
970df930be7Sderaadt
971df930be7Sderaadt case FS_UNUSED: /* XXX */
972bf01d747Sderaadt if (tp == NULL) /* ok to skip fsize/bsize */
973bf01d747Sderaadt break;
974ddfcbf38Sotto NXTNUM(fsize, fsize, &errstr);
975ddfcbf38Sotto if (fsize == 0)
976df930be7Sderaadt break;
97718ec52beSotto NXTNUM(v, v, &errstr);
978ddfcbf38Sotto pp->p_fragblock =
979ddfcbf38Sotto DISKLABELV1_FFS_FRAGBLOCK(fsize, v / fsize);
980df930be7Sderaadt break;
981df930be7Sderaadt
982df930be7Sderaadt case FS_BSDFFS:
983ddfcbf38Sotto NXTNUM(fsize, fsize, &errstr);
984ddfcbf38Sotto if (fsize == 0)
985df930be7Sderaadt break;
98618ec52beSotto NXTNUM(v, v, &errstr);
987ddfcbf38Sotto pp->p_fragblock =
988ddfcbf38Sotto DISKLABELV1_FFS_FRAGBLOCK(fsize, v / fsize);
98918ec52beSotto NXTNUM(pp->p_cpg, pp->p_cpg, &errstr);
990df930be7Sderaadt break;
991df930be7Sderaadt
992df930be7Sderaadt default:
993df930be7Sderaadt break;
994df930be7Sderaadt }
995038e2c8cSkrw if (mp)
996038e2c8cSkrw mountpoints[part] = strdup(mp);
997df930be7Sderaadt continue;
998df930be7Sderaadt }
999df930be7Sderaadt warnx("line %d: unknown field: %s", lineno, cp);
1000df930be7Sderaadt errors++;
1001df930be7Sderaadt }
1002df930be7Sderaadt errors += checklabel(lp);
1003038e2c8cSkrw
1004038e2c8cSkrw if (errors > 0)
1005038e2c8cSkrw mpcopy(mountpoints, omountpoints);
1006e46ff49bSkrw mpfree(omountpoints, DISCARD);
1007038e2c8cSkrw
1008bb12209fSkrw return errors > 0;
1009df930be7Sderaadt }
1010df930be7Sderaadt
1011df930be7Sderaadt /*
1012df930be7Sderaadt * Check disklabel for errors and fill in
1013df930be7Sderaadt * derived fields according to supplied values.
1014df930be7Sderaadt */
1015df930be7Sderaadt int
checklabel(struct disklabel * lp)10168809fabbSderaadt checklabel(struct disklabel *lp)
1017df930be7Sderaadt {
1018df930be7Sderaadt struct partition *pp;
1019df930be7Sderaadt int i, errors = 0;
1020df930be7Sderaadt char part;
1021df930be7Sderaadt
1022df930be7Sderaadt if (lp->d_secsize == 0) {
10233feb1724Skrw warnx("sector size 0");
1024bb12209fSkrw return 1;
1025df930be7Sderaadt }
1026df930be7Sderaadt if (lp->d_nsectors == 0) {
10273feb1724Skrw warnx("sectors/track 0");
1028bb12209fSkrw return 1;
1029df930be7Sderaadt }
1030df930be7Sderaadt if (lp->d_ntracks == 0) {
10313feb1724Skrw warnx("tracks/cylinder 0");
1032bb12209fSkrw return 1;
1033df930be7Sderaadt }
1034df930be7Sderaadt if (lp->d_ncylinders == 0) {
10353feb1724Skrw warnx("cylinders/unit 0");
1036df930be7Sderaadt errors++;
1037df930be7Sderaadt }
1038df930be7Sderaadt if (lp->d_secpercyl == 0)
1039df930be7Sderaadt lp->d_secpercyl = lp->d_nsectors * lp->d_ntracks;
104034af67a3Sotto if (DL_GETDSIZE(lp) == 0)
104134af67a3Sotto DL_SETDSIZE(lp, (u_int64_t)lp->d_secpercyl * lp->d_ncylinders);
1042df930be7Sderaadt if (lp->d_npartitions > MAXPARTITIONS)
1043df930be7Sderaadt warnx("warning, number of partitions (%d) > MAXPARTITIONS (%d)",
1044df930be7Sderaadt lp->d_npartitions, MAXPARTITIONS);
1045df930be7Sderaadt for (i = 0; i < lp->d_npartitions; i++) {
1046df930be7Sderaadt part = 'a' + i;
1047df930be7Sderaadt pp = &lp->d_partitions[i];
10481e0ad43cSotto if (DL_GETPSIZE(pp) == 0 && DL_GETPOFFSET(pp) != 0)
1049605eea5fSkrw warnx("warning, partition %c: size 0, but offset %llu",
1050db60327dSkrw part, DL_GETPOFFSET(pp));
1051fc1a4cc6Sderaadt #ifdef SUN_CYLCHECK
1052fc1a4cc6Sderaadt if (lp->d_flags & D_VENDOR) {
10531e0ad43cSotto if (i != RAW_PART && DL_GETPSIZE(pp) % lp->d_secpercyl)
1054fc1a4cc6Sderaadt warnx("warning, partition %c: size %% "
1055fc1a4cc6Sderaadt "cylinder-size != 0", part);
10561e0ad43cSotto if (i != RAW_PART && DL_GETPOFFSET(pp) % lp->d_secpercyl)
1057fc1a4cc6Sderaadt warnx("warning, partition %c: offset %% "
1058fc1a4cc6Sderaadt "cylinder-size != 0", part);
1059fc1a4cc6Sderaadt }
1060df930be7Sderaadt #endif
1061fc1a4cc6Sderaadt #ifdef SUN_AAT0
1062fc1a4cc6Sderaadt if ((lp->d_flags & D_VENDOR) &&
1063fc1a4cc6Sderaadt i == 0 && DL_GETPSIZE(pp) != 0 && DL_GETPOFFSET(pp) != 0) {
106449bf537cSderaadt warnx("this architecture requires partition 'a' to "
106549bf537cSderaadt "start at sector 0");
106649bf537cSderaadt errors++;
106749bf537cSderaadt }
106849bf537cSderaadt #endif
10691e0ad43cSotto if (DL_GETPOFFSET(pp) > DL_GETDSIZE(lp)) {
1070df930be7Sderaadt warnx("partition %c: offset past end of unit", part);
1071df930be7Sderaadt errors++;
10728bec302fSkrw } else if (DL_GETPOFFSET(pp) + DL_GETPSIZE(pp) >
10738bec302fSkrw DL_GETDSIZE(lp)) {
10748bec302fSkrw warnx("partition %c: extends past end of unit",
1075df930be7Sderaadt part);
1076df930be7Sderaadt errors++;
1077df930be7Sderaadt }
1078ddfcbf38Sotto #if 0
10795384f9eeSmillert if (pp->p_frag == 0 && pp->p_fsize != 0) {
10805384f9eeSmillert warnx("partition %c: block size < fragment size", part);
10815384f9eeSmillert errors++;
10825384f9eeSmillert }
1083ddfcbf38Sotto #endif
1084df930be7Sderaadt }
1085df930be7Sderaadt for (; i < MAXPARTITIONS; i++) {
1086df930be7Sderaadt part = 'a' + i;
1087df930be7Sderaadt pp = &lp->d_partitions[i];
10881e0ad43cSotto if (DL_GETPSIZE(pp) || DL_GETPOFFSET(pp))
1089605eea5fSkrw warnx("warning, unused partition %c: size %llu "
1090605eea5fSkrw "offset %llu", part, DL_GETPSIZE(pp),
109154bd9d93Skrw DL_GETPOFFSET(pp));
1092df930be7Sderaadt }
1093bb12209fSkrw return errors > 0;
1094df930be7Sderaadt }
1095df930be7Sderaadt
10965362a395Smillert int
cmplabel(struct disklabel * lp1,struct disklabel * lp2)10978809fabbSderaadt cmplabel(struct disklabel *lp1, struct disklabel *lp2)
10985362a395Smillert {
10995362a395Smillert struct disklabel lab1 = *lp1;
11005362a395Smillert struct disklabel lab2 = *lp2;
11015362a395Smillert
11025362a395Smillert /* We don't compare these fields */
11035362a395Smillert lab1.d_magic = lab2.d_magic;
11045362a395Smillert lab1.d_magic2 = lab2.d_magic2;
11055362a395Smillert lab1.d_checksum = lab2.d_checksum;
1106fc88f2eeSfgsch lab1.d_bstart = lab2.d_bstart;
1107fc88f2eeSfgsch lab1.d_bstarth = lab2.d_bstarth;
1108fc88f2eeSfgsch lab1.d_bend = lab2.d_bend;
1109fc88f2eeSfgsch lab1.d_bendh = lab2.d_bendh;
11105362a395Smillert
1111bb12209fSkrw return memcmp(&lab1, &lab2, sizeof(struct disklabel));
11125362a395Smillert }
11135362a395Smillert
1114df930be7Sderaadt void
usage(void)11158809fabbSderaadt usage(void)
1116df930be7Sderaadt {
1117625b9b20Sderaadt fprintf(stderr,
1118b70cc458Sjmc "usage: disklabel [-Acdtv] [-h | -p unit] [-T file] disk\n");
1119625b9b20Sderaadt fprintf(stderr,
1120b70cc458Sjmc " disklabel -w [-Acdnv] [-T file] disk disktype [packid]\n");
1121625b9b20Sderaadt fprintf(stderr,
1122b70cc458Sjmc " disklabel -e [-Acdnv] [-T file] disk\n");
11236fe57b42Smillert fprintf(stderr,
1124b70cc458Sjmc " disklabel -E [-Acdnv] [-F|-f file] [-T file] disk\n");
112552317843Sjmc fprintf(stderr,
1126b70cc458Sjmc " disklabel -R [-nv] [-F|-f file] disk protofile\n");
1127b70cc458Sjmc
1128df930be7Sderaadt exit(1);
1129df930be7Sderaadt }
1130