xref: /csrg-svn/sbin/disklabel/disklabel.c (revision 30419)
130418Skarels #ifndef lint
2*30419Skarels static char sccsid[] = "@(#)disklabel.c	5.2 (Berkeley) 01/19/87";
330418Skarels /* from static char sccsid[] = "@(#)disklabel.c	1.2 (Symmetric) 11/28/85"; */
430418Skarels #endif
530418Skarels 
630418Skarels #include <stdio.h>
730418Skarels #include <ctype.h>
830418Skarels #include <sys/param.h>
930418Skarels #include <sys/errno.h>
1030418Skarels #include <sys/file.h>
1130418Skarels #include <sys/ioctl.h>
1230418Skarels #define DKTYPENAMES
1330418Skarels #include <sys/disklabel.h>
1430418Skarels 
1530418Skarels /*
1630418Skarels  * Disklabel: read and write disklabels.
1730418Skarels  * The label is usually placed on one of the first sectors of the disk.
1830418Skarels  * Many machines (VAX 11/750) also place a bootstrap in the same area,
1930418Skarels  * in which case the label is embedded in the bootstrap.
2030418Skarels  * The bootstrap source must leave space at the proper offset
2130418Skarels  * for the label on such machines.
2230418Skarels  */
2330418Skarels 
2430418Skarels #define	BBSIZE	8192			/* size of boot area, with label */
2530418Skarels 
2630418Skarels #ifdef vax
2730418Skarels #define	BOOT				/* also have bootstrap in "boot area" */
2830418Skarels #define	BOOTDIR	"/usr/mdec"		/* source of boot binaries */
2930418Skarels #endif
3030418Skarels 
3130418Skarels char	*dkname;
3230418Skarels char	*dkbasename;
3330418Skarels char	*xxboot;
3430418Skarels char	*bootxx;
3530418Skarels char	*specname;
3630418Skarels char	*sprintf();
3730418Skarels char	*rindex();
3830418Skarels 
3930418Skarels extern	int errno;
4030418Skarels char	namebuf[BBSIZE], *np = namebuf;
4130418Skarels char	bootarea[BBSIZE];
4230418Skarels struct	disklabel lab;
4330418Skarels struct	disklabel *readlabel(), *getbootarea();
4430418Skarels 
4530418Skarels int	op;			/* one of: */
4630418Skarels #define	READ	1
4730418Skarels #define	WRITE	2
4830418Skarels #define	EDIT	3
4930418Skarels #define	RESTORE	4
5030418Skarels 
5130418Skarels main(argc, argv)
5230418Skarels 	int argc;
5330418Skarels 	char *argv[];
5430418Skarels {
5530418Skarels 	register struct disklabel *lp;
5630418Skarels 	int f, t;
5730418Skarels 	char *name = 0, *asciifile, *type;
5830418Skarels 
5930418Skarels 	while (argc > 1 && argv[1][0] == '-') {
6030418Skarels 		if (strcmp(argv[1], "-e") == 0) {
6130418Skarels 			if (argc != 3)
6230418Skarels 				goto usage;
6330418Skarels 			op = EDIT;
6430418Skarels 		} else if (strcmp(argv[1], "-w") == 0) {
6530418Skarels 			if (argc != 4)
6630418Skarels 				goto usage;
6730418Skarels 			op = RESTORE;
6830418Skarels 		} else
6930418Skarels 			goto usage;
7030418Skarels 		argv++;
7130418Skarels 		argc--;
7230418Skarels 	}
7330418Skarels 	if (argc < 2 || argc > 6) {
7430418Skarels usage:
7530418Skarels 		fprintf(stderr, "%s%s%s%s",
7630418Skarels #ifdef BOOT
7730418Skarels "usage: disklabel disk    				(to read label)\n",
7830418Skarels "or disklabel disk type [ packid ] [ xxboot bootxx ]    (to write label)\n",
7930418Skarels "or disklabel -e disk    				(to edit label)\n",
8030418Skarels "or disklabel -w disk protofile [ xxboot bootxx ]	(to restore label)\n"
8130418Skarels #else
8230418Skarels "usage: disklabel disk    			(to read label)\n",
8330418Skarels "or disklabel disk type [ packid ]		(to write label)\n",
8430418Skarels "or disklabel -e disk    			(to edit label)\n",
8530418Skarels "or disklabel -w disk protofile			(to restore label)\n"
8630418Skarels #endif
8730418Skarels 			);
8830418Skarels 		exit(1);
8930418Skarels 	}
9030418Skarels 	if (op == 0)
9130418Skarels 		if (argc == 2)
9230418Skarels 			op = READ;
9330418Skarels 		else
9430418Skarels 			op = WRITE;
9530418Skarels 	dkname = argv[1];
9630418Skarels 	if (dkname[0] != '/') {
9730418Skarels 		sprintf(np, "/dev/r%sc", dkname);
9830418Skarels 		specname = np;
9930418Skarels 		np += strlen(specname) + 1;
10030418Skarels 	} else
10130418Skarels 		specname = dkname;
10230418Skarels 	f = open(specname, op == READ ? O_RDONLY : O_RDWR);
10330418Skarels 	if (f < 0 && errno == ENOENT && dkname[0] != '/') {
10430418Skarels 		sprintf(specname, "/dev/r%s", dkname);
10530418Skarels 		np = namebuf + strlen(specname) + 1;
10630418Skarels 		f = open(specname, op == READ ? O_RDONLY : O_RDWR);
10730418Skarels 	}
10830418Skarels 	if (f < 0)
10930418Skarels 		Perror(specname);
11030418Skarels 
11130418Skarels 	if (op == WRITE) {
11230418Skarels 		type = argv[2];
11330418Skarels 		if (argc == 4 || argc == 6) {
11430418Skarels 			name = argv[3];
11530418Skarels 			argv++;
11630418Skarels 			argc--;
11730418Skarels 		}
11830418Skarels 	}
11930418Skarels 	if (op == RESTORE) {
12030418Skarels 		asciifile = argv[2];
12130418Skarels 		argv++;
12230418Skarels 		argc--;
12330418Skarels 	}
12430418Skarels #ifdef BOOT
12530418Skarels 	if (argc == 5) {
12630418Skarels 		xxboot = argv[3];
12730418Skarels 		bootxx = argv[4];
12830418Skarels 	}
12930418Skarels #endif
13030418Skarels 
13130418Skarels 
13230418Skarels 	switch (op) {
13330418Skarels 
13430418Skarels 	case READ:
13530418Skarels 		lp = readlabel(f, 0);
13630418Skarels 		display(stdout, lp);
13730418Skarels 		break;
13830418Skarels 
13930418Skarels 	case EDIT:
14030418Skarels 		lp = readlabel(f, bootarea);
14130418Skarels 		edit(f, lp);
14230418Skarels 		writelabel(f, bootarea, lp);
14330418Skarels 		break;
14430418Skarels 
14530418Skarels 	case WRITE:
14630418Skarels 		makelabel(type, name, &lab);
14730418Skarels 		lp = getbootarea(bootarea, &lab);
14830418Skarels 		*lp = lab;
14930418Skarels 		writelabel(f, bootarea, lp);
15030418Skarels 		break;
15130418Skarels 
15230418Skarels 	case RESTORE:
15330418Skarels 		lab.d_secsize = DEV_BSIZE;			/* XXX */
15430418Skarels 		lab.d_bbsize = BBSIZE;				/* XXX */
15530418Skarels 		lp = getbootarea(bootarea, &lab);
15630418Skarels 		t = open(asciifile, O_RDONLY);
15730418Skarels 		if (t < 0)
15830418Skarels 			Perror(asciifile);
15930418Skarels 		getasciilabel(t, lp);
16030418Skarels 		writelabel(f, bootarea, lp);
16130418Skarels 		break;
16230418Skarels 	}
16330418Skarels 	exit(0);
16430418Skarels }
16530418Skarels 
16630418Skarels makelabel(type, name, lp)
16730418Skarels 	char *type, *name;
16830418Skarels 	register struct disklabel *lp;
16930418Skarels {
17030418Skarels 	register struct disklabel *dp;
17130418Skarels 	register char *p;
17230418Skarels 
17330418Skarels 	dp = getdiskbyname(type);
17430418Skarels 	if (dp == NULL) {
17530418Skarels 		fprintf(stderr, "%s: unknown disk type\n", type);
17630418Skarels 		exit(1);
17730418Skarels 	}
17830418Skarels 	*lp = *dp;
17930418Skarels 	if (name)
18030418Skarels 		strncpy(lp->d_name, name, sizeof(lp->d_name));
18130418Skarels }
18230418Skarels 
18330418Skarels writelabel(f, boot, lp)
18430418Skarels 	int f;
18530418Skarels 	char *boot;
18630418Skarels 	register struct disklabel *lp;
18730418Skarels {
18830418Skarels 	register i;
189*30419Skarels 	daddr_t bbsize;
190*30419Skarels #if vax
19130418Skarels 	daddr_t alt;
192*30419Skarels 	int nsectors, secsize;
193*30419Skarels #endif
19430418Skarels 
19530418Skarels 	lp->d_magic = DISKMAGIC;
19630418Skarels 	lp->d_magic2 = DISKMAGIC;
197*30419Skarels 	bbsize = lp->d_bbsize;
198*30419Skarels #if vax
199*30419Skarels 	/* copy before swabbing */
200*30419Skarels 	if (lp->d_type == DTYPE_SMD && lp->d_flags & D_BADSECT)
201*30419Skarels 		alt = lp->d_ncylinders * lp->d_secpercyl - lp->d_nsectors;
202*30419Skarels 	else
203*30419Skarels 		alt = 0;
204*30419Skarels 	nsectors = lp->d_nsectors;
205*30419Skarels 	secsize = lp->d_secsize;
206*30419Skarels #endif
20730418Skarels 	swablabel(lp);
20830418Skarels 	lp->d_checksum = 0;
20930418Skarels 	lp->d_checksum = dkcksum(lp);
21030418Skarels 	lseek(f, (off_t)0, L_SET);
211*30419Skarels 	if (write(f, boot, bbsize) < bbsize)
21230418Skarels 		Perror("write");
213*30419Skarels #if vax
214*30419Skarels 	if (alt)
215*30419Skarels 	for (i = 1; i < 11 && i < nsectors; i += 2) {
216*30419Skarels 		lseek(f, (off_t)(alt + i) * secsize, L_SET);
217*30419Skarels 		if (write(f, boot, secsize) < secsize) {
21830418Skarels 			int oerrno = errno;
21930418Skarels 			fprintf(stderr, "alternate label %d ", i/2);
22030418Skarels 			errno = oerrno;
22130418Skarels 			perror("write");
22230418Skarels 		}
22330418Skarels 	}
224*30419Skarels #endif
225*30419Skarels #ifdef notyet
22630418Skarels 	if (ioctl(f, DIOCSDINFO, lp) < 0)
22730418Skarels 		Perror("ioctl DIOCSDINFO");
22830418Skarels #endif
22930418Skarels }
23030418Skarels 
23130418Skarels /*
23230418Skarels  * Read disklabel from disk.
23330418Skarels  * If boot is given, need bootstrap too.
23430418Skarels  * If boot not needed, could use ioctl to get label.
23530418Skarels  */
23630418Skarels struct disklabel *
23730418Skarels readlabel(f, boot)
23830418Skarels 	int f;
23930418Skarels 	char *boot;
24030418Skarels {
24130418Skarels 	register struct disklabel *lp;
24230418Skarels 	u_long magic = htonl(DISKMAGIC);
24330418Skarels 
24430418Skarels 	if (boot == NULL)
24530418Skarels 		boot = bootarea;
24630418Skarels 	if (read(f, boot, BBSIZE) < BBSIZE)
24730418Skarels 		Perror(specname);
24830418Skarels 	for (lp = (struct disklabel *)(boot + LABELOFFSET);
24930418Skarels 	    lp <= (struct disklabel *)(boot + BBSIZE -
25030418Skarels 	    sizeof(struct disklabel));
25130418Skarels 	    lp = (struct disklabel *)((char *)lp + 128))
25230418Skarels 		if (lp->d_magic == magic && lp->d_magic2 == magic)
25330418Skarels 			break;
25430418Skarels 	if (lp > (struct disklabel *)(boot + BBSIZE -
25530418Skarels 	    sizeof(struct disklabel)) ||
25630418Skarels 	    lp->d_magic != magic || lp->d_magic2 != magic ||
25730418Skarels 	    dkcksum(lp) != 0) {
25830418Skarels 		fprintf(stderr,
25930418Skarels 	"Bad pack magic number (label is damaged, or pack is unlabeled)\n");
26030418Skarels 		exit(1);
26130418Skarels 	}
26230418Skarels 	swablabel(lp);
26330418Skarels 	return (lp);
26430418Skarels }
26530418Skarels 
26630418Skarels struct disklabel *
26730418Skarels getbootarea(boot, dp)
26830418Skarels 	char *boot;
26930418Skarels 	register struct disklabel *dp;
27030418Skarels {
27130418Skarels 	struct disklabel *lp;
27230418Skarels 	register char *p;
27330418Skarels 	int b;
27430418Skarels 
27530418Skarels #ifdef BOOT
27630418Skarels 	if (xxboot == NULL) {
27730418Skarels 		dkbasename = np;
27830418Skarels 		if ((p = rindex(dkname, '/')) == NULL)
27930418Skarels 			p = dkname;
28030418Skarels 		else
28130418Skarels 			p++;
28230418Skarels 		while (*p && !isdigit(*p))
28330418Skarels 			*np++ = *p++;
28430418Skarels 		*np++ = '\0';
28530418Skarels 
28630418Skarels 		sprintf(np, "%s/%sboot", BOOTDIR, dkbasename);
28730418Skarels 		if (access(np, F_OK) < 0 && dkbasename[0] == 'r')
28830418Skarels 			dkbasename++;
28930418Skarels 		xxboot = np;
29030418Skarels 		sprintf(xxboot, "%s/%sboot", BOOTDIR, dkbasename);
29130418Skarels 		np += strlen(xxboot) + 1;
29230418Skarels 
29330418Skarels 		bootxx = np;
29430418Skarels 		sprintf(bootxx, "%s/boot%s", BOOTDIR, dkbasename);
29530418Skarels 		np += strlen(bootxx) + 1;
29630418Skarels 	}
29730418Skarels 
29830418Skarels 	b = open(xxboot, O_RDONLY);
29930418Skarels 	if (b < 0)
30030418Skarels 		Perror(xxboot);
30130418Skarels 	if (read(b, boot, dp->d_secsize) < 0)
30230418Skarels 		Perror(xxboot);
30330418Skarels 	close(b);
30430418Skarels 	b = open(bootxx, O_RDONLY);
30530418Skarels 	if (b < 0)
30630418Skarels 		Perror(bootxx);
30730418Skarels 	if (read(b, &boot[dp->d_secsize], dp->d_bbsize-dp->d_secsize) < 0)
30830418Skarels 		Perror(bootxx);
30930418Skarels 	close(b);
31030418Skarels #endif
31130418Skarels 
31230418Skarels 	lp = (struct disklabel *)(boot + (LABELSECTOR * dp->d_secsize) +
31330418Skarels 	    LABELOFFSET);
31430418Skarels 	for (p = (char *)lp; p < (char *)lp + sizeof(struct disklabel); p++)
31530418Skarels 		if (*p) {
31630418Skarels 			fprintf(stderr,
31730418Skarels 			    "Bootstrap doesn't leave room for disk label\n");
31830418Skarels 			exit(2);
31930418Skarels 		}
32030418Skarels 	return (lp);
32130418Skarels }
32230418Skarels 
32330418Skarels display(f, lp)
32430418Skarels 	FILE *f;
32530418Skarels 	register struct disklabel *lp;
32630418Skarels {
32730418Skarels 	register i, j;
32830418Skarels 	register struct partition *pp;
32930418Skarels 
33030418Skarels 	fprintf(f, "# %s:\n", specname);
33130418Skarels 	if ((unsigned) lp->d_type < DKMAXTYPES)
33230418Skarels 		fprintf(f, "type: %s\n", dktypenames[lp->d_type]);
33330418Skarels 	else
33430418Skarels 		fprintf(f, "type: %d\n", lp->d_type);
33530418Skarels 	fprintf(f, "disk: %.*s\n", sizeof(lp->d_typename), lp->d_typename);
33630418Skarels 	fprintf(f, "label: %.*s\n", sizeof(lp->d_name), lp->d_name);
33730418Skarels 	fprintf(f, "flags: ");
33830418Skarels 	if (lp->d_flags & D_REMOVABLE)
33930418Skarels 		fprintf(f, "removeable ");
34030418Skarels 	if (lp->d_flags & D_ECC)
34130418Skarels 		fprintf(f, "ecc ");
34230418Skarels 	if (lp->d_flags & D_BADSECT)
34330418Skarels 		fprintf(f, "badsect ");
34430418Skarels 	fprintf(f, "\n");
34530418Skarels 	fprintf(f, "bytes/sector: %d\n", lp->d_secsize);
34630418Skarels 	fprintf(f, "sectors/track: %d\n", lp->d_nsectors);
34730418Skarels 	fprintf(f, "tracks/cylinder: %d\n", lp->d_ntracks);
34830418Skarels 	fprintf(f, "cylinders: %d\n", lp->d_ncylinders);
34930418Skarels 	fprintf(f, "interleave: %d\n", lp->d_interleave);
35030418Skarels 	fprintf(f, "trackskew: %d\n", lp->d_trackskew);
35130418Skarels 	fprintf(f, "cylinderskew: %d\n", lp->d_cylskew);
35230418Skarels 	fprintf(f, "headswitch: %d\t\t# milliseconds\n", lp->d_headswitch);
35330418Skarels 	fprintf(f, "track-to-track seek: %d\t# milliseconds\n", lp->d_trkseek);
35430418Skarels 	fprintf(f, "drivedata: ");
35530418Skarels 	for (i = NDDATA - 1; i >= 0; i--)
35630418Skarels 		if (lp->d_drivedata[i])
35730418Skarels 			break;
35830418Skarels 	if (i < 0)
35930418Skarels 		i = 0;
36030418Skarels 	for (j = 0; j <= i; j++)
36130418Skarels 		fprintf(f, "%d ", lp->d_drivedata[j]);
36230418Skarels 	fprintf(f, "\n\n%d partitions:\n", lp->d_npartitions);
36330418Skarels 	fprintf(f, "#\t       size    offset     fstype\n");
36430418Skarels 	pp = lp->d_partitions;
36530418Skarels 	for (i = 0; i < lp->d_npartitions; i++, pp++) {
36630418Skarels 		fprintf(f, "\t%c: %8d %8d    ", 'a' + i,
36730418Skarels 		   pp->p_size, pp->p_offset);
36830418Skarels 		if (pp->p_size) {
36930418Skarels 			if ((unsigned) pp->p_fstype < FSMAXTYPES)
37030418Skarels 				fprintf(f, "%8.8s", fstypenames[pp->p_fstype]);
37130418Skarels 			else
37230418Skarels 				fprintf(f, "%8d", pp->p_fstype);
37330418Skarels 			fprintf(f, "\t# (Cyl. %4d",
37430418Skarels 			    pp->p_offset / lp->d_secpercyl);
37530418Skarels 			if (pp->p_offset % lp->d_secpercyl)
37630418Skarels 			    putc('*', f);
37730418Skarels 			else
37830418Skarels 			    putc(' ', f);
37930418Skarels 			fprintf(f, "- %d",
38030418Skarels 			    (pp->p_offset +
38130418Skarels 			    pp->p_size + lp->d_secpercyl - 1) /
38230418Skarels 			    lp->d_secpercyl - 1);
38330418Skarels 			if (pp->p_size % lp->d_secpercyl)
38430418Skarels 			    putc('*', f);
38530418Skarels 			putc(')', f);
38630418Skarels 		}
38730418Skarels 		fprintf(f, "\n");
38830418Skarels 	}
38930418Skarels }
39030418Skarels 
39130418Skarels edit(f)
39230418Skarels 	int f;
39330418Skarels {
39430418Skarels 	fprintf(stderr, "sorry, not yet\n");
39530418Skarels 	exit(1);
39630418Skarels }
39730418Skarels 
39830418Skarels 
39930418Skarels /*
40030418Skarels  * Read an ascii label in from fd f,
40130418Skarels  * in the same format as that put out by display(),
40230418Skarels  * and fill in lp.
40330418Skarels  */
40430418Skarels getasciilabel(f, lp)
40530418Skarels 	int f;
40630418Skarels 	register struct disklabel *lp;
40730418Skarels {
40830418Skarels 	fprintf(stderr, "sorry, not yet\n");
40930418Skarels 	exit(1);
41030418Skarels }
41130418Skarels 
41230418Skarels Perror(op)
41330418Skarels 	char *op;
41430418Skarels {
41530418Skarels 
41630418Skarels 	fprintf(stderr, "disklabel: "); perror(op);
41730418Skarels 	exit(4);
41830418Skarels }
419