file reorg, pathnames.h, paths.h
[unix-history] / usr / src / sbin / disklabel / disklabel.c
CommitLineData
12c6e49c 1/*
bc246bd5
KB
2 * Copyright (c) 1987 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Symmetric Computer Systems.
7 *
8 * Redistribution and use in source and binary forms are permitted
9 * provided that the above copyright notice and this paragraph are
10 * duplicated in all such forms and that any documentation,
11 * advertising materials, and other materials related to such
12 * distribution and use acknowledge that the software was developed
13 * by the University of California, Berkeley. The name of the
14 * University may not be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
18 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
12c6e49c
KB
19 */
20
ee5681fe 21#ifndef lint
bc246bd5
KB
22char copyright[] =
23"@(#) Copyright (c) 1987 The Regents of the University of California.\n\
24 All rights reserved.\n";
25#endif /* not lint */
26
27#ifndef lint
7abf8d65 28static char sccsid[] = "@(#)disklabel.c 5.16 (Berkeley) %G%";
ee5681fe 29/* from static char sccsid[] = "@(#)disklabel.c 1.2 (Symmetric) 11/28/85"; */
bc246bd5 30#endif /* not lint */
ee5681fe 31
ee5681fe 32#include <sys/param.h>
12c6e49c 33#include <sys/signal.h>
ee5681fe
MK
34#include <sys/errno.h>
35#include <sys/file.h>
36#include <sys/ioctl.h>
12c6e49c
KB
37#include <sys/fs.h>
38#include <strings.h>
ee5681fe
MK
39#define DKTYPENAMES
40#include <sys/disklabel.h>
d85a3360
KB
41#include <stdio.h>
42#include <ctype.h>
43#include "pathnames.h"
ee5681fe
MK
44
45/*
46 * Disklabel: read and write disklabels.
47 * The label is usually placed on one of the first sectors of the disk.
48 * Many machines (VAX 11/750) also place a bootstrap in the same area,
49 * in which case the label is embedded in the bootstrap.
50 * The bootstrap source must leave space at the proper offset
51 * for the label on such machines.
52 */
53
452bf484
MK
54#ifdef vax
55#define RAWPARTITION 'c'
56#else
57#define RAWPARTITION 'a'
58#endif
59
60#ifndef BBSIZE
ee5681fe 61#define BBSIZE 8192 /* size of boot area, with label */
452bf484 62#endif
ee5681fe
MK
63
64#ifdef vax
65#define BOOT /* also have bootstrap in "boot area" */
d85a3360 66#define BOOTDIR _PATH_BOOTDIR /* source of boot binaries */
452bf484
MK
67#else
68#ifdef lint
69#define BOOT
70#endif
ee5681fe
MK
71#endif
72
d85a3360 73#define DEFEDITOR _PATH_EDITOR
12c6e49c
KB
74#define streq(a,b) (strcmp(a,b) == 0)
75
12c6e49c 76#ifdef BOOT
ee5681fe
MK
77char *xxboot;
78char *bootxx;
12c6e49c 79#endif
53e3e5d6
MK
80
81char *dkname;
ee5681fe 82char *specname;
7abf8d65 83char tmpfil[] = _PATH_TMP;
ee5681fe
MK
84
85extern int errno;
86char namebuf[BBSIZE], *np = namebuf;
ee5681fe 87struct disklabel lab;
53e3e5d6
MK
88struct disklabel *readlabel(), *makebootarea();
89char bootarea[BBSIZE];
40aed5b4
MK
90char boot0[MAXPATHLEN];
91char boot1[MAXPATHLEN];
ee5681fe 92
40aed5b4 93enum { UNSPEC, EDIT, NOWRITE, READ, RESTORE, WRITE, WRITEABLE } op = UNSPEC;
ee5681fe 94
452bf484
MK
95int rflag;
96
40aed5b4
MK
97#ifdef DEBUG
98int debug;
99#endif
100
ee5681fe
MK
101main(argc, argv)
102 int argc;
103 char *argv[];
104{
40aed5b4 105 extern int optind;
ee5681fe 106 register struct disklabel *lp;
40aed5b4 107 FILE *t;
3956638c 108 int ch, f, error = 0;
12c6e49c
KB
109 char *name = 0, *type;
110
40aed5b4
MK
111 while ((ch = getopt(argc, argv, "NRWerw")) != EOF)
112 switch (ch) {
113 case 'N':
114 if (op != UNSPEC)
115 usage();
116 op = NOWRITE;
117 break;
12c6e49c 118 case 'R':
40aed5b4
MK
119 if (op != UNSPEC)
120 usage();
12c6e49c
KB
121 op = RESTORE;
122 break;
40aed5b4
MK
123 case 'W':
124 if (op != UNSPEC)
125 usage();
126 op = WRITEABLE;
127 break;
12c6e49c 128 case 'e':
40aed5b4
MK
129 if (op != UNSPEC)
130 usage();
12c6e49c
KB
131 op = EDIT;
132 break;
133 case 'r':
134 ++rflag;
135 break;
136 case 'w':
40aed5b4
MK
137 if (op != UNSPEC)
138 usage();
12c6e49c
KB
139 op = WRITE;
140 break;
40aed5b4
MK
141#ifdef DEBUG
142 case 'd':
143 debug++;
144 break;
145#endif
12c6e49c
KB
146 case '?':
147 default:
148 usage();
149 }
150 argc -= optind;
151 argv += optind;
40aed5b4
MK
152 if (op == UNSPEC)
153 op = READ;
12c6e49c
KB
154 if (argc < 1)
155 usage();
156
157 dkname = argv[0];
ee5681fe 158 if (dkname[0] != '/') {
7abf8d65 159 (void)sprintf(np, "%s/r%s%c", _PATH_DEV, dkname, RAWPARTITION);
ee5681fe
MK
160 specname = np;
161 np += strlen(specname) + 1;
162 } else
163 specname = dkname;
164 f = open(specname, op == READ ? O_RDONLY : O_RDWR);
165 if (f < 0 && errno == ENOENT && dkname[0] != '/') {
7abf8d65 166 (void)sprintf(specname, "%s/r%s", _PATH_DEV, dkname);
ee5681fe
MK
167 np = namebuf + strlen(specname) + 1;
168 f = open(specname, op == READ ? O_RDONLY : O_RDWR);
169 }
170 if (f < 0)
171 Perror(specname);
172
12c6e49c 173 switch(op) {
ee5681fe 174 case EDIT:
12c6e49c
KB
175 if (argc != 1)
176 usage();
40aed5b4 177 lp = readlabel(f);
3956638c 178 error = edit(lp, f);
ee5681fe 179 break;
40aed5b4
MK
180 case NOWRITE: {
181 int flag = 0;
182 if (ioctl(f, DIOCWLABEL, (char *)&flag) < 0)
183 Perror("ioctl DIOCWLABEL");
184 break;
185 }
12c6e49c
KB
186 case READ:
187 if (argc != 1)
188 usage();
40aed5b4 189 lp = readlabel(f);
12c6e49c 190 display(stdout, lp);
3956638c 191 error = checklabel(lp);
ee5681fe 192 break;
ee5681fe 193 case RESTORE:
12c6e49c 194#ifdef BOOT
40aed5b4
MK
195 if (rflag) {
196 if (argc == 4) { /* [ priboot secboot ] */
197 xxboot = argv[2];
198 bootxx = argv[3];
199 lab.d_secsize = DEV_BSIZE; /* XXX */
200 lab.d_bbsize = BBSIZE; /* XXX */
201 }
202 else if (argc == 3) /* [ disktype ] */
203 makelabel(argv[2], (char *)NULL, &lab);
204 else {
205 fprintf(stderr,
206"Must specify either disktype or bootfiles with -r flag of RESTORE option\n");
207 exit(1);
208 }
209 }
210 else
53e3e5d6 211#endif
12c6e49c
KB
212 if (argc != 2)
213 usage();
53e3e5d6 214 lp = makebootarea(bootarea, &lab);
12c6e49c
KB
215 if (!(t = fopen(argv[1],"r")))
216 Perror(argv[1]);
217 if (getasciilabel(t, lp))
3956638c 218 error = writelabel(f, bootarea, lp);
12c6e49c
KB
219 break;
220 case WRITE:
221 type = argv[1];
222#ifdef BOOT
223 if (argc > 5 || argc < 2)
224 usage();
225 if (argc > 3) {
226 bootxx = argv[--argc];
227 xxboot = argv[--argc];
228 }
229#else
12c6e49c 230 if (argc > 3 || argc < 2)
12c6e49c
KB
231 usage();
232#endif
233 if (argc > 2)
234 name = argv[--argc];
235 makelabel(type, name, &lab);
53e3e5d6 236 lp = makebootarea(bootarea, &lab);
12c6e49c
KB
237 *lp = lab;
238 if (checklabel(lp) == 0)
3956638c 239 error = writelabel(f, bootarea, lp);
ee5681fe 240 break;
40aed5b4
MK
241 case WRITEABLE: {
242 int flag = 1;
243 if (ioctl(f, DIOCWLABEL, (char *)&flag) < 0)
244 Perror("ioctl DIOCWLABEL");
245 break;
246 }
ee5681fe 247 }
3956638c 248 exit(error);
ee5681fe
MK
249}
250
40aed5b4
MK
251/*
252 * Construct a prototype disklabel from /etc/disktab. As a side
253 * effect, set the names of the primary and secondary boot files
254 * if specified.
255 */
ee5681fe
MK
256makelabel(type, name, lp)
257 char *type, *name;
258 register struct disklabel *lp;
259{
260 register struct disklabel *dp;
40aed5b4 261 char *strcpy();
ee5681fe
MK
262
263 dp = getdiskbyname(type);
264 if (dp == NULL) {
265 fprintf(stderr, "%s: unknown disk type\n", type);
266 exit(1);
267 }
268 *lp = *dp;
40aed5b4
MK
269#ifdef BOOT
270 /*
271 * Check if disktab specifies the bootstraps (b0 or b1).
272 */
273 if (!xxboot && lp->d_boot0) {
274 if (*lp->d_boot0 != '/')
275 (void)sprintf(boot0, "%s/%s", BOOTDIR, lp->d_boot0);
276 else
277 (void)strcpy(boot0, lp->d_boot0);
278 xxboot = boot0;
279 }
280 if (!bootxx && lp->d_boot1) {
281 if (*lp->d_boot1 != '/')
282 (void)sprintf(boot1, "%s/%s", BOOTDIR, lp->d_boot1);
283 else
284 (void)strcpy(boot1, lp->d_boot1);
285 bootxx = boot1;
286 }
287 /*
288 * If bootstraps not specified anywhere, makebootarea()
289 * will choose ones based on the name of the disk special
290 * file. E.g. /dev/ra0 -> raboot, bootra
291 */
292#endif /*BOOT*/
293 /* d_packname is union d_boot[01], so zero */
294 bzero(lp->d_packname, sizeof(lp->d_packname));
ee5681fe 295 if (name)
40aed5b4 296 (void)strncpy(lp->d_packname, name, sizeof(lp->d_packname));
ee5681fe
MK
297}
298
299writelabel(f, boot, lp)
300 int f;
301 char *boot;
302 register struct disklabel *lp;
303{
12c6e49c 304 register int i;
40aed5b4
MK
305 int flag;
306 off_t lseek();
ee5681fe
MK
307
308 lp->d_magic = DISKMAGIC;
309 lp->d_magic2 = DISKMAGIC;
ee5681fe
MK
310 lp->d_checksum = 0;
311 lp->d_checksum = dkcksum(lp);
452bf484 312 if (rflag) {
40aed5b4
MK
313 /*
314 * First set the kernel disk label,
315 * then write a label to the raw disk.
316 * If the SDINFO ioctl fails because it is unimplemented,
317 * keep going; otherwise, the kernel consistency checks
318 * may prevent us from changing the current (in-core)
319 * label.
320 */
321 if (ioctl(f, DIOCSDINFO, lp) < 0 &&
3956638c
MK
322 errno != ENODEV && errno != ENOTTY) {
323 l_perror("ioctl DIOCSDINFO");
324 return (1);
325 }
53e3e5d6 326 (void)lseek(f, (off_t)0, L_SET);
40aed5b4
MK
327 /*
328 * write enable label sector before write (if necessary),
329 * disable after writing.
330 */
331 flag = 1;
332 if (ioctl(f, DIOCWLABEL, &flag) < 0)
333 perror("ioctl DIOCWLABEL");
3956638c
MK
334 if (write(f, boot, lp->d_bbsize) != lp->d_bbsize) {
335 perror("write");
336 return (1);
337 }
40aed5b4
MK
338 flag = 0;
339 (void) ioctl(f, DIOCWLABEL, &flag);
3956638c
MK
340 } else if (ioctl(f, DIOCWDINFO, lp) < 0) {
341 l_perror("ioctl DIOCWDINFO");
342 return (1);
343 }
40aed5b4 344#ifdef vax
452bf484
MK
345 if (lp->d_type == DTYPE_SMD && lp->d_flags & D_BADSECT) {
346 daddr_t alt;
347
348 alt = lp->d_ncylinders * lp->d_secpercyl - lp->d_nsectors;
349 for (i = 1; i < 11 && i < lp->d_nsectors; i += 2) {
12c6e49c 350 (void)lseek(f, (off_t)((alt + i) * lp->d_secsize), L_SET);
452bf484
MK
351 if (write(f, boot, lp->d_secsize) < lp->d_secsize) {
352 int oerrno = errno;
353 fprintf(stderr, "alternate label %d ", i/2);
354 errno = oerrno;
355 perror("write");
356 }
ee5681fe
MK
357 }
358 }
1268bb93 359#endif
3956638c
MK
360 return (0);
361}
362
363l_perror(s)
364 char *s;
365{
366 int saverrno = errno;
367
368 fprintf(stderr, "disklabel: %s: ", s);
369
370 switch (saverrno) {
371
372 case ESRCH:
373 fprintf(stderr, "No disk label on disk;\n");
374 fprintf(stderr,
375 "use \"disklabel -r\" to install initial label\n");
376 break;
377
378 case EINVAL:
379 fprintf(stderr, "Label magic number or checksum is wrong!\n");
380 fprintf(stderr, "(disklabel or kernel is out of date?)\n");
381 break;
382
383 case EBUSY:
384 fprintf(stderr, "Open partition would move or shrink\n");
385 break;
386
387 case EXDEV:
388 fprintf(stderr,
389 "Labeled partition or 'a' partition must start at beginning of disk\n");
390 break;
391
392 default:
393 errno = saverrno;
394 perror((char *)NULL);
395 break;
396 }
ee5681fe
MK
397}
398
399/*
53e3e5d6 400 * Fetch disklabel for disk.
53e3e5d6 401 * Use ioctl to get label unless -r flag is given.
ee5681fe
MK
402 */
403struct disklabel *
40aed5b4
MK
404readlabel(f)
405 int f;
ee5681fe
MK
406{
407 register struct disklabel *lp;
ee5681fe 408
40aed5b4 409 if (rflag) {
53e3e5d6 410 if (read(f, bootarea, BBSIZE) < BBSIZE)
88b9be0b 411 Perror(specname);
53e3e5d6
MK
412 for (lp = (struct disklabel *)bootarea;
413 lp <= (struct disklabel *)(bootarea + BBSIZE - sizeof(*lp));
452bf484
MK
414 lp = (struct disklabel *)((char *)lp + 16))
415 if (lp->d_magic == DISKMAGIC &&
416 lp->d_magic2 == DISKMAGIC)
417 break;
53e3e5d6 418 if (lp > (struct disklabel *)(bootarea+BBSIZE-sizeof(*lp)) ||
452bf484
MK
419 lp->d_magic != DISKMAGIC || lp->d_magic2 != DISKMAGIC ||
420 dkcksum(lp) != 0) {
421 fprintf(stderr,
ee5681fe 422 "Bad pack magic number (label is damaged, or pack is unlabeled)\n");
40aed5b4
MK
423 /* lp = (struct disklabel *)(bootarea + LABELOFFSET); */
424 exit (1);
452bf484 425 }
40aed5b4
MK
426 } else {
427 lp = &lab;
428 if (ioctl(f, DIOCGDINFO, lp) < 0)
429 Perror("ioctl DIOCGDINFO");
ee5681fe 430 }
ee5681fe
MK
431 return (lp);
432}
433
434struct disklabel *
53e3e5d6 435makebootarea(boot, dp)
ee5681fe
MK
436 char *boot;
437 register struct disklabel *dp;
438{
439 struct disklabel *lp;
440 register char *p;
441 int b;
ee5681fe 442#ifdef BOOT
12c6e49c 443 char *dkbasename;
40aed5b4 444#endif /*BOOT*/
12c6e49c 445
40aed5b4
MK
446 lp = (struct disklabel *)(boot + (LABELSECTOR * dp->d_secsize) +
447 LABELOFFSET);
448#ifdef BOOT
449 if (!rflag)
450 return (lp);
451
452 if (xxboot == NULL || bootxx == NULL) {
ee5681fe
MK
453 dkbasename = np;
454 if ((p = rindex(dkname, '/')) == NULL)
455 p = dkname;
456 else
457 p++;
458 while (*p && !isdigit(*p))
459 *np++ = *p++;
460 *np++ = '\0';
461
40aed5b4
MK
462 if (xxboot == NULL) {
463 (void)sprintf(np, "%s/%sboot", BOOTDIR, dkbasename);
464 if (access(np, F_OK) < 0 && dkbasename[0] == 'r')
465 dkbasename++;
466 xxboot = np;
467 (void)sprintf(xxboot, "%s/%sboot", BOOTDIR, dkbasename);
468 np += strlen(xxboot) + 1;
469 }
470 if (bootxx == NULL) {
471 (void)sprintf(np, "%s/boot%s", BOOTDIR, dkbasename);
472 if (access(np, F_OK) < 0 && dkbasename[0] == 'r')
473 dkbasename++;
474 bootxx = np;
475 (void)sprintf(bootxx, "%s/boot%s", BOOTDIR, dkbasename);
476 np += strlen(bootxx) + 1;
477 }
ee5681fe 478 }
40aed5b4
MK
479#ifdef DEBUG
480 if (debug)
481 fprintf(stderr, "bootstraps: xxboot = %s, bootxx = %s\n",
482 xxboot, bootxx);
483#endif
ee5681fe
MK
484
485 b = open(xxboot, O_RDONLY);
486 if (b < 0)
487 Perror(xxboot);
12c6e49c 488 if (read(b, boot, (int)dp->d_secsize) < 0)
ee5681fe
MK
489 Perror(xxboot);
490 close(b);
491 b = open(bootxx, O_RDONLY);
492 if (b < 0)
493 Perror(bootxx);
12c6e49c 494 if (read(b, &boot[dp->d_secsize], (int)(dp->d_bbsize-dp->d_secsize)) < 0)
ee5681fe 495 Perror(bootxx);
12c6e49c 496 (void)close(b);
40aed5b4 497#endif /*BOOT*/
ee5681fe 498
ee5681fe
MK
499 for (p = (char *)lp; p < (char *)lp + sizeof(struct disklabel); p++)
500 if (*p) {
501 fprintf(stderr,
502 "Bootstrap doesn't leave room for disk label\n");
503 exit(2);
504 }
505 return (lp);
506}
507
508display(f, lp)
509 FILE *f;
510 register struct disklabel *lp;
511{
12c6e49c 512 register int i, j;
ee5681fe
MK
513 register struct partition *pp;
514
515 fprintf(f, "# %s:\n", specname);
516 if ((unsigned) lp->d_type < DKMAXTYPES)
517 fprintf(f, "type: %s\n", dktypenames[lp->d_type]);
518 else
519 fprintf(f, "type: %d\n", lp->d_type);
520 fprintf(f, "disk: %.*s\n", sizeof(lp->d_typename), lp->d_typename);
40aed5b4 521 fprintf(f, "label: %.*s\n", sizeof(lp->d_packname), lp->d_packname);
88b9be0b 522 fprintf(f, "flags:");
ee5681fe 523 if (lp->d_flags & D_REMOVABLE)
88b9be0b 524 fprintf(f, " removeable");
ee5681fe 525 if (lp->d_flags & D_ECC)
88b9be0b 526 fprintf(f, " ecc");
ee5681fe 527 if (lp->d_flags & D_BADSECT)
88b9be0b 528 fprintf(f, " badsect");
ee5681fe
MK
529 fprintf(f, "\n");
530 fprintf(f, "bytes/sector: %d\n", lp->d_secsize);
531 fprintf(f, "sectors/track: %d\n", lp->d_nsectors);
532 fprintf(f, "tracks/cylinder: %d\n", lp->d_ntracks);
c6e761b2 533 fprintf(f, "sectors/cylinder: %d\n", lp->d_secpercyl);
ee5681fe 534 fprintf(f, "cylinders: %d\n", lp->d_ncylinders);
12c6e49c 535 fprintf(f, "rpm: %d\n", lp->d_rpm);
ee5681fe
MK
536 fprintf(f, "interleave: %d\n", lp->d_interleave);
537 fprintf(f, "trackskew: %d\n", lp->d_trackskew);
538 fprintf(f, "cylinderskew: %d\n", lp->d_cylskew);
539 fprintf(f, "headswitch: %d\t\t# milliseconds\n", lp->d_headswitch);
540 fprintf(f, "track-to-track seek: %d\t# milliseconds\n", lp->d_trkseek);
541 fprintf(f, "drivedata: ");
542 for (i = NDDATA - 1; i >= 0; i--)
543 if (lp->d_drivedata[i])
544 break;
545 if (i < 0)
546 i = 0;
547 for (j = 0; j <= i; j++)
548 fprintf(f, "%d ", lp->d_drivedata[j]);
549 fprintf(f, "\n\n%d partitions:\n", lp->d_npartitions);
9e0e871b
MK
550 fprintf(f,
551 "# size offset fstype [fsize bsize cpg]\n");
ee5681fe
MK
552 pp = lp->d_partitions;
553 for (i = 0; i < lp->d_npartitions; i++, pp++) {
ee5681fe 554 if (pp->p_size) {
9e0e871b
MK
555 fprintf(f, " %c: %8d %8d ", 'a' + i,
556 pp->p_size, pp->p_offset);
ee5681fe
MK
557 if ((unsigned) pp->p_fstype < FSMAXTYPES)
558 fprintf(f, "%8.8s", fstypenames[pp->p_fstype]);
559 else
560 fprintf(f, "%8d", pp->p_fstype);
9e0e871b
MK
561 switch (pp->p_fstype) {
562
563 case FS_UNUSED: /* XXX */
564 fprintf(f, " %5d %5d %5.5s ",
565 pp->p_fsize, pp->p_fsize * pp->p_frag, "");
566 break;
567
568 case FS_BSDFFS:
569 fprintf(f, " %5d %5d %5d ",
570 pp->p_fsize, pp->p_fsize * pp->p_frag,
571 pp->p_cpg);
572 break;
573
574 default:
575 fprintf(f, "%20.20s", "");
576 break;
577 }
ee5681fe
MK
578 fprintf(f, "\t# (Cyl. %4d",
579 pp->p_offset / lp->d_secpercyl);
580 if (pp->p_offset % lp->d_secpercyl)
581 putc('*', f);
582 else
583 putc(' ', f);
584 fprintf(f, "- %d",
585 (pp->p_offset +
586 pp->p_size + lp->d_secpercyl - 1) /
587 lp->d_secpercyl - 1);
588 if (pp->p_size % lp->d_secpercyl)
589 putc('*', f);
9e0e871b 590 fprintf(f, ")\n");
ee5681fe 591 }
ee5681fe 592 }
816cd0ca 593 fflush(f);
ee5681fe
MK
594}
595
3956638c 596edit(lp, f)
12c6e49c 597 struct disklabel *lp;
3956638c 598 int f;
ee5681fe 599{
12c6e49c
KB
600 register int c;
601 struct disklabel label;
602 FILE *fd;
603 char *mktemp();
604
605 (void) mktemp(tmpfil);
606 fd = fopen(tmpfil, "w");
607 if (fd == NULL) {
608 fprintf(stderr, "%s: Can't create\n", tmpfil);
3956638c 609 return (1);
12c6e49c
KB
610 }
611 (void)fchmod(fd, 0600);
612 display(fd, lp);
613 fclose(fd);
614 for (;;) {
615 if (!editit())
616 break;
617 fd = fopen(tmpfil, "r");
618 if (fd == NULL) {
40aed5b4
MK
619 fprintf(stderr, "%s: Can't reopen for reading\n",
620 tmpfil);
12c6e49c
KB
621 break;
622 }
9e0e871b 623 bzero((char *)&label, sizeof(label));
12c6e49c
KB
624 if (getasciilabel(fd, &label)) {
625 *lp = label;
3956638c
MK
626 if (writelabel(f, bootarea, lp) == 0) {
627 (void) unlink(tmpfil);
628 return (0);
629 }
12c6e49c
KB
630 }
631 printf("re-edit the label? [y]: "); fflush(stdout);
632 c = getchar();
633 if (c != EOF && c != (int)'\n')
634 while (getchar() != (int)'\n')
635 ;
636 if (c == (int)'n')
637 break;
638 }
639 (void) unlink(tmpfil);
3956638c 640 return (1);
ee5681fe
MK
641}
642
12c6e49c
KB
643editit()
644{
645 register int pid, xpid;
646 int stat, omask;
647 extern char *getenv();
648
649 omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGHUP));
650 while ((pid = fork()) < 0) {
651 extern int errno;
652
653 if (errno == EPROCLIM) {
654 fprintf(stderr, "You have too many processes\n");
655 return(0);
656 }
657 if (errno != EAGAIN) {
658 perror("fork");
659 return(0);
660 }
661 sleep(1);
662 }
663 if (pid == 0) {
664 register char *ed;
665
666 sigsetmask(omask);
667 setgid(getgid());
668 setuid(getuid());
669 if ((ed = getenv("EDITOR")) == (char *)0)
670 ed = DEFEDITOR;
671 execlp(ed, ed, tmpfil, 0);
672 perror(ed);
673 exit(1);
674 }
675 while ((xpid = wait(&stat)) >= 0)
676 if (xpid == pid)
677 break;
678 sigsetmask(omask);
679 return(!stat);
680}
681
682char *
683skip(cp)
684 register char *cp;
685{
686
687 while (*cp != '\0' && isspace(*cp))
688 cp++;
689 if (*cp == '\0' || *cp == '#')
690 return ((char *)NULL);
691 return (cp);
692}
693
694char *
695word(cp)
696 register char *cp;
697{
698 register char c;
699
88b9be0b
MK
700 while (*cp != '\0' && !isspace(*cp) && *cp != '#')
701 cp++;
12c6e49c
KB
702 if ((c = *cp) != '\0') {
703 *cp++ = '\0';
704 if (c != '#')
705 return (skip(cp));
706 }
707 return ((char *)NULL);
708}
ee5681fe
MK
709
710/*
711 * Read an ascii label in from fd f,
712 * in the same format as that put out by display(),
713 * and fill in lp.
714 */
715getasciilabel(f, lp)
12c6e49c 716 FILE *f;
ee5681fe
MK
717 register struct disklabel *lp;
718{
12c6e49c 719 register char **cpp, *cp;
9e0e871b 720 register struct partition *pp;
12c6e49c
KB
721 char *tp, *s, line[BUFSIZ];
722 int v, lineno = 0, errors = 0;
723
724 lp->d_bbsize = BBSIZE; /* XXX */
725 lp->d_sbsize = SBSIZE; /* XXX */
726 while (fgets(line, sizeof(line) - 1, f)) {
727 lineno++;
728 if (cp = index(line,'\n'))
729 *cp = '\0';
730 cp = skip(line);
731 if (cp == NULL)
732 continue;
733 tp = index(cp, ':');
734 if (tp == NULL) {
735 fprintf(stderr, "line %d: syntax error\n", lineno);
736 errors++;
737 continue;
738 }
739 *tp++ = '\0', tp = skip(tp);
740 if (streq(cp, "type")) {
741 if (tp == NULL)
742 tp = "unknown";
743 cpp = dktypenames;
744 for (; cpp < &dktypenames[DKMAXTYPES]; cpp++)
745 if ((s = *cpp) && streq(s, tp)) {
746 lp->d_type = cpp - dktypenames;
747 goto next;
748 }
749 v = atoi(tp);
750 if ((unsigned)v >= DKMAXTYPES)
751 fprintf(stderr, "line %d:%s %d\n", lineno,
752 "Warning, unknown disk type", v);
753 lp->d_type = v;
754 continue;
755 }
756 if (streq(cp, "flags")) {
40aed5b4
MK
757 for (v = 0; (cp = tp) && *cp != '\0';) {
758 tp = word(cp);
12c6e49c
KB
759 if (streq(cp, "removeable"))
760 v |= D_REMOVABLE;
761 else if (streq(cp, "ecc"))
762 v |= D_ECC;
763 else if (streq(cp, "badsect"))
764 v |= D_BADSECT;
765 else {
766 fprintf(stderr,
767 "line %d: %s: bad flag\n",
768 lineno, cp);
769 errors++;
770 }
771 }
772 lp->d_flags = v;
773 continue;
774 }
775 if (streq(cp, "drivedata")) {
776 register int i;
777
c6e761b2 778 for (i = 0; (cp = tp) && *cp != '\0' && i < NDDATA;) {
12c6e49c 779 lp->d_drivedata[i++] = atoi(cp);
c6e761b2 780 tp = word(cp);
12c6e49c
KB
781 }
782 continue;
783 }
784 if (sscanf(cp, "%d partitions", &v) == 1) {
9e0e871b 785 if (v == 0 || (unsigned)v > MAXPARTITIONS) {
12c6e49c
KB
786 fprintf(stderr,
787 "line %d: bad # of partitions\n", lineno);
9e0e871b
MK
788 lp->d_npartitions = MAXPARTITIONS;
789 errors++;
790 } else
12c6e49c
KB
791 lp->d_npartitions = v;
792 continue;
793 }
794 if (tp == NULL)
795 tp = "";
796 if (streq(cp, "disk")) {
797 strncpy(lp->d_typename, tp, sizeof (lp->d_typename));
798 continue;
799 }
800 if (streq(cp, "label")) {
40aed5b4 801 strncpy(lp->d_packname, tp, sizeof (lp->d_packname));
12c6e49c
KB
802 continue;
803 }
804 if (streq(cp, "bytes/sector")) {
805 v = atoi(tp);
806 if (v <= 0 || (v % 512) != 0) {
807 fprintf(stderr,
808 "line %d: %s: bad sector size\n",
809 lineno, tp);
810 errors++;
811 } else
812 lp->d_secsize = v;
813 continue;
814 }
815 if (streq(cp, "sectors/track")) {
816 v = atoi(tp);
817 if (v <= 0) {
818 fprintf(stderr, "line %d: %s: bad %s\n",
819 lineno, tp, cp);
820 errors++;
821 } else
822 lp->d_nsectors = v;
823 continue;
824 }
c6e761b2
MK
825 if (streq(cp, "sectors/cylinder")) {
826 v = atoi(tp);
827 if (v <= 0) {
828 fprintf(stderr, "line %d: %s: bad %s\n",
829 lineno, tp, cp);
830 errors++;
831 } else
832 lp->d_secpercyl = v;
833 continue;
834 }
12c6e49c
KB
835 if (streq(cp, "tracks/cylinder")) {
836 v = atoi(tp);
837 if (v <= 0) {
838 fprintf(stderr, "line %d: %s: bad %s\n",
839 lineno, tp, cp);
840 errors++;
841 } else
842 lp->d_ntracks = v;
843 continue;
844 }
845 if (streq(cp, "cylinders")) {
846 v = atoi(tp);
847 if (v <= 0) {
848 fprintf(stderr, "line %d: %s: bad %s\n",
849 lineno, tp, cp);
850 errors++;
851 } else
852 lp->d_ncylinders = v;
853 continue;
854 }
855 if (streq(cp, "rpm")) {
856 v = atoi(tp);
857 if (v <= 0) {
858 fprintf(stderr, "line %d: %s: bad %s\n",
859 lineno, tp, cp);
860 errors++;
861 } else
862 lp->d_rpm = v;
863 continue;
864 }
865 if (streq(cp, "interleave")) {
866 v = atoi(tp);
867 if (v <= 0) {
868 fprintf(stderr, "line %d: %s: bad %s\n",
869 lineno, tp, cp);
870 errors++;
871 } else
872 lp->d_interleave = v;
873 continue;
874 }
875 if (streq(cp, "trackskew")) {
876 v = atoi(tp);
877 if (v < 0) {
878 fprintf(stderr, "line %d: %s: bad %s\n",
879 lineno, tp, cp);
880 errors++;
881 } else
882 lp->d_trackskew = v;
883 continue;
884 }
885 if (streq(cp, "cylinderskew")) {
886 v = atoi(tp);
887 if (v < 0) {
888 fprintf(stderr, "line %d: %s: bad %s\n",
889 lineno, tp, cp);
890 errors++;
891 } else
892 lp->d_cylskew = v;
893 continue;
894 }
895 if (streq(cp, "headswitch")) {
896 v = atoi(tp);
897 if (v < 0) {
898 fprintf(stderr, "line %d: %s: bad %s\n",
899 lineno, tp, cp);
900 errors++;
901 } else
902 lp->d_headswitch = v;
903 continue;
904 }
905 if (streq(cp, "track-to-track seek")) {
906 v = atoi(tp);
907 if (v < 0) {
908 fprintf(stderr, "line %d: %s: bad %s\n",
909 lineno, tp, cp);
910 errors++;
911 } else
912 lp->d_trkseek = v;
913 continue;
914 }
915 if ('a' <= *cp && *cp <= 'z' && cp[1] == '\0') {
9e0e871b 916 unsigned part = *cp - 'a';
12c6e49c 917
9e0e871b 918 if (part > lp->d_npartitions) {
12c6e49c
KB
919 fprintf(stderr,
920 "line %d: bad partition name\n", lineno);
921 errors++;
922 continue;
923 }
9e0e871b
MK
924 pp = &lp->d_partitions[part];
925#define NXTNUM(n) { \
926 cp = tp, tp = word(cp); \
927 if (tp == NULL) \
928 tp = cp; \
929 (n) = atoi(cp); \
930 }
931
932 NXTNUM(v);
12c6e49c
KB
933 if (v < 0) {
934 fprintf(stderr,
935 "line %d: %s: bad partition size\n",
936 lineno, cp);
937 errors++;
938 } else
9e0e871b
MK
939 pp->p_size = v;
940 NXTNUM(v);
12c6e49c
KB
941 if (v < 0) {
942 fprintf(stderr,
943 "line %d: %s: bad partition offset\n",
944 lineno, cp);
945 errors++;
946 } else
9e0e871b 947 pp->p_offset = v;
12c6e49c
KB
948 cp = tp, tp = word(cp);
949 cpp = fstypenames;
950 for (; cpp < &fstypenames[FSMAXTYPES]; cpp++)
951 if ((s = *cpp) && streq(s, cp)) {
9e0e871b
MK
952 pp->p_fstype = cpp - fstypenames;
953 goto gottype;
12c6e49c 954 }
40aed5b4
MK
955 if (isdigit(*cp))
956 v = atoi(cp);
957 else
958 v = FSMAXTYPES;
959 if ((unsigned)v >= FSMAXTYPES) {
12c6e49c
KB
960 fprintf(stderr, "line %d: %s %s\n", lineno,
961 "Warning, unknown filesystem type", cp);
40aed5b4
MK
962 v = FS_UNUSED;
963 }
9e0e871b
MK
964 pp->p_fstype = v;
965 gottype:
966
967 switch (pp->p_fstype) {
968
969 case FS_UNUSED: /* XXX */
970 NXTNUM(pp->p_fsize);
971 if (pp->p_fsize == 0)
972 break;
973 NXTNUM(v);
974 pp->p_frag = v / pp->p_fsize;
975 break;
976
977 case FS_BSDFFS:
978 NXTNUM(pp->p_fsize);
979 if (pp->p_fsize == 0)
980 break;
981 NXTNUM(v);
982 pp->p_frag = v / pp->p_fsize;
983 NXTNUM(pp->p_cpg);
984 break;
985
986 default:
987 break;
988 }
12c6e49c
KB
989 continue;
990 }
991 fprintf(stderr, "line %d: %s: Unknown disklabel field\n",
992 lineno, cp);
993 errors++;
994 next:
995 ;
996 }
997 errors += checklabel(lp);
998 return (errors == 0);
999}
1000
1001/*
1002 * Check disklabel for errors and fill in
1003 * derived fields according to supplied values.
1004 */
1005checklabel(lp)
1006 register struct disklabel *lp;
1007{
1008 register struct partition *pp;
1009 int i, errors = 0;
1010 char part;
1011
1012 if (lp->d_secsize == 0) {
1013 fprintf(stderr, "sector size %d\n", lp->d_secsize);
1014 return (1);
1015 }
1016 if (lp->d_nsectors == 0) {
1017 fprintf(stderr, "sectors/track %d\n", lp->d_nsectors);
1018 return (1);
1019 }
1020 if (lp->d_ntracks == 0) {
1021 fprintf(stderr, "tracks/cylinder %d\n", lp->d_ntracks);
1022 return (1);
1023 }
1024 if (lp->d_ncylinders == 0) {
1025 fprintf(stderr, "cylinders/unit %d\n", lp->d_ncylinders);
1026 errors++;
1027 }
1028 if (lp->d_rpm == 0)
1029 Warning("revolutions/minute %d\n", lp->d_rpm);
1030 if (lp->d_secpercyl == 0)
1031 lp->d_secpercyl = lp->d_nsectors * lp->d_ntracks;
1032 if (lp->d_secperunit == 0)
1033 lp->d_secperunit = lp->d_secpercyl * lp->d_ncylinders;
1034 if (lp->d_bbsize == 0) {
1035 fprintf(stderr, "boot block size %d\n", lp->d_bbsize);
1036 errors++;
1037 } else if (lp->d_bbsize % lp->d_secsize)
1038 Warning("boot block size %% sector-size != 0\n");
1039 if (lp->d_sbsize == 0) {
1040 fprintf(stderr, "super block size %d\n", lp->d_sbsize);
1041 errors++;
1042 } else if (lp->d_sbsize % lp->d_secsize)
1043 Warning("super block size %% sector-size != 0\n");
1044 if (lp->d_npartitions > MAXPARTITIONS)
1045 Warning("number of partitions (%d) > MAXPARTITIONS (%d)\n",
1046 lp->d_npartitions, MAXPARTITIONS);
1047 for (i = 0; i < lp->d_npartitions; i++) {
1048 part = 'a' + i;
1049 pp = &lp->d_partitions[i];
1050 if (pp->p_size == 0 && pp->p_offset != 0)
1051 Warning("partition %c: size 0, but offset %d\n",
1052 part, pp->p_offset);
1053#ifdef notdef
1054 if (pp->p_size % lp->d_secpercyl)
1055 Warning("partition %c: size %% cylinder-size != 0\n",
1056 part);
1057 if (pp->p_offset % lp->d_secpercyl)
1058 Warning("partition %c: offset %% cylinder-size != 0\n",
1059 part);
1060#endif
1061 if (pp->p_offset > lp->d_secperunit) {
1062 fprintf(stderr,
1063 "partition %c: offset past end of unit\n", part);
1064 errors++;
1065 }
1066 if (pp->p_offset + pp->p_size > lp->d_secperunit) {
1067 fprintf(stderr,
1068 "partition %c: partition extends past end of unit\n",
1069 part);
1070 errors++;
1071 }
1072 }
1073 for (; i < MAXPARTITIONS; i++) {
1074 part = 'a' + i;
1075 pp = &lp->d_partitions[i];
1076 if (pp->p_size || pp->p_offset)
1077 Warning("unused partition %c: size %d offset %d\n",
40aed5b4 1078 'a' + i, pp->p_size, pp->p_offset);
12c6e49c
KB
1079 }
1080 return (errors);
ee5681fe
MK
1081}
1082
12c6e49c
KB
1083/*VARARGS1*/
1084Warning(fmt, a1, a2, a3, a4, a5)
1085 char *fmt;
ee5681fe
MK
1086{
1087
12c6e49c
KB
1088 fprintf(stderr, "Warning, ");
1089 fprintf(stderr, fmt, a1, a2, a3, a4, a5);
1090 fprintf(stderr, "\n");
1091}
1092
1093Perror(str)
1094 char *str;
1095{
1096 fputs("disklabel: ", stderr); perror(str);
ee5681fe
MK
1097 exit(4);
1098}
12c6e49c
KB
1099
1100usage()
1101{
1102#ifdef BOOT
40aed5b4 1103 fprintf(stderr, "%-62s%s\n%-62s%s\n%-62s%s\n%-62s%s\n%-62s%s\n",
12c6e49c
KB
1104"usage: disklabel [-r] disk", "(to read label)",
1105"or disklabel -w [-r] disk type [ packid ] [ xxboot bootxx ]", "(to write label)",
1106"or disklabel -e [-r] disk", "(to edit label)",
40aed5b4
MK
1107"or disklabel -R [-r] disk protofile [ type | xxboot bootxx ]", "(to restore label)",
1108"or disklabel [-NW] disk", "(to write disable/enable label)");
12c6e49c 1109#else
40aed5b4 1110 fprintf(stderr, "%-43s%s\n%-43s%s\n%-43s%s\n%-43s%s\n%-43s%s\n",
12c6e49c
KB
1111"usage: disklabel [-r] disk", "(to read label)",
1112"or disklabel -w [-r] disk type [ packid ]", "(to write label)",
1113"or disklabel -e [-r] disk", "(to edit label)",
40aed5b4
MK
1114"or disklabel -R [-r] disk protofile", "(to restore label)",
1115"or disklabel [-NW] disk", "(to write disable/enable label)");
12c6e49c
KB
1116#endif
1117 exit(1);
1118}