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