xref: /csrg-svn/sbin/disklabel/disklabel.c (revision 30677)
130418Skarels #ifndef lint
2*30677Skarels static char sccsid[] = "@(#)disklabel.c	5.3 (Berkeley) 03/27/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>
11*30677Skarels #include <sys/fs.h>
1230418Skarels #include <sys/ioctl.h>
1330418Skarels #define DKTYPENAMES
1430418Skarels #include <sys/disklabel.h>
1530418Skarels 
1630418Skarels /*
1730418Skarels  * Disklabel: read and write disklabels.
1830418Skarels  * The label is usually placed on one of the first sectors of the disk.
1930418Skarels  * Many machines (VAX 11/750) also place a bootstrap in the same area,
2030418Skarels  * in which case the label is embedded in the bootstrap.
2130418Skarels  * The bootstrap source must leave space at the proper offset
2230418Skarels  * for the label on such machines.
2330418Skarels  */
2430418Skarels 
25*30677Skarels #ifdef vax
26*30677Skarels #define RAWPARTITION	'c'
27*30677Skarels #else
28*30677Skarels #define RAWPARTITION	'a'
29*30677Skarels #endif
30*30677Skarels 
31*30677Skarels #ifndef BBSIZE
3230418Skarels #define	BBSIZE	8192			/* size of boot area, with label */
33*30677Skarels #endif
3430418Skarels 
3530418Skarels #ifdef vax
3630418Skarels #define	BOOT				/* also have bootstrap in "boot area" */
3730418Skarels #define	BOOTDIR	"/usr/mdec"		/* source of boot binaries */
38*30677Skarels #else
39*30677Skarels #ifdef lint
40*30677Skarels #define	BOOT
4130418Skarels #endif
42*30677Skarels #endif
4330418Skarels 
4430418Skarels char	*dkname;
4530418Skarels char	*dkbasename;
4630418Skarels char	*xxboot;
4730418Skarels char	*bootxx;
4830418Skarels char	*specname;
4930418Skarels char	*sprintf();
5030418Skarels char	*rindex();
5130418Skarels 
5230418Skarels extern	int errno;
5330418Skarels char	namebuf[BBSIZE], *np = namebuf;
5430418Skarels char	bootarea[BBSIZE];
5530418Skarels struct	disklabel lab;
5630418Skarels struct	disklabel *readlabel(), *getbootarea();
5730418Skarels 
5830418Skarels int	op;			/* one of: */
5930418Skarels #define	READ	1
6030418Skarels #define	WRITE	2
6130418Skarels #define	EDIT	3
6230418Skarels #define	RESTORE	4
6330418Skarels 
64*30677Skarels int	rflag;
65*30677Skarels 
6630418Skarels main(argc, argv)
6730418Skarels 	int argc;
6830418Skarels 	char *argv[];
6930418Skarels {
7030418Skarels 	register struct disklabel *lp;
7130418Skarels 	int f, t;
7230418Skarels 	char *name = 0, *asciifile, *type;
7330418Skarels 
7430418Skarels 	while (argc > 1 && argv[1][0] == '-') {
7530418Skarels 		if (strcmp(argv[1], "-e") == 0) {
7630418Skarels 			if (argc != 3)
7730418Skarels 				goto usage;
7830418Skarels 			op = EDIT;
7930418Skarels 		} else if (strcmp(argv[1], "-w") == 0) {
8030418Skarels 			if (argc != 4)
8130418Skarels 				goto usage;
8230418Skarels 			op = RESTORE;
83*30677Skarels 		} else if (strcmp(argv[1], "-r") == 0)
84*30677Skarels 			rflag++;
85*30677Skarels 		else
8630418Skarels 			goto usage;
8730418Skarels 		argv++;
8830418Skarels 		argc--;
8930418Skarels 	}
9030418Skarels 	if (argc < 2 || argc > 6) {
9130418Skarels usage:
9230418Skarels 		fprintf(stderr, "%s%s%s%s",
9330418Skarels #ifdef BOOT
9430418Skarels "usage: disklabel disk    				(to read label)\n",
9530418Skarels "or disklabel disk type [ packid ] [ xxboot bootxx ]    (to write label)\n",
9630418Skarels "or disklabel -e disk    				(to edit label)\n",
9730418Skarels "or disklabel -w disk protofile [ xxboot bootxx ]	(to restore label)\n"
9830418Skarels #else
9930418Skarels "usage: disklabel disk    			(to read label)\n",
10030418Skarels "or disklabel disk type [ packid ]		(to write label)\n",
10130418Skarels "or disklabel -e disk    			(to edit label)\n",
10230418Skarels "or disklabel -w disk protofile			(to restore label)\n"
10330418Skarels #endif
10430418Skarels 			);
10530418Skarels 		exit(1);
10630418Skarels 	}
10730418Skarels 	if (op == 0)
10830418Skarels 		if (argc == 2)
10930418Skarels 			op = READ;
11030418Skarels 		else
11130418Skarels 			op = WRITE;
11230418Skarels 	dkname = argv[1];
11330418Skarels 	if (dkname[0] != '/') {
114*30677Skarels 		sprintf(np, "/dev/r%s%c", dkname, RAWPARTITION);
11530418Skarels 		specname = np;
11630418Skarels 		np += strlen(specname) + 1;
11730418Skarels 	} else
11830418Skarels 		specname = dkname;
11930418Skarels 	f = open(specname, op == READ ? O_RDONLY : O_RDWR);
12030418Skarels 	if (f < 0 && errno == ENOENT && dkname[0] != '/') {
12130418Skarels 		sprintf(specname, "/dev/r%s", dkname);
12230418Skarels 		np = namebuf + strlen(specname) + 1;
12330418Skarels 		f = open(specname, op == READ ? O_RDONLY : O_RDWR);
12430418Skarels 	}
12530418Skarels 	if (f < 0)
12630418Skarels 		Perror(specname);
12730418Skarels 
12830418Skarels 	if (op == WRITE) {
12930418Skarels 		type = argv[2];
13030418Skarels 		if (argc == 4 || argc == 6) {
13130418Skarels 			name = argv[3];
13230418Skarels 			argv++;
13330418Skarels 			argc--;
13430418Skarels 		}
13530418Skarels 	}
13630418Skarels 	if (op == RESTORE) {
13730418Skarels 		asciifile = argv[2];
13830418Skarels 		argv++;
13930418Skarels 		argc--;
14030418Skarels 	}
14130418Skarels #ifdef BOOT
14230418Skarels 	if (argc == 5) {
14330418Skarels 		xxboot = argv[3];
14430418Skarels 		bootxx = argv[4];
14530418Skarels 	}
14630418Skarels #endif
14730418Skarels 
14830418Skarels 
14930418Skarels 	switch (op) {
15030418Skarels 
15130418Skarels 	case READ:
15230418Skarels 		lp = readlabel(f, 0);
15330418Skarels 		display(stdout, lp);
15430418Skarels 		break;
15530418Skarels 
15630418Skarels 	case EDIT:
15730418Skarels 		lp = readlabel(f, bootarea);
15830418Skarels 		edit(f, lp);
15930418Skarels 		writelabel(f, bootarea, lp);
16030418Skarels 		break;
16130418Skarels 
16230418Skarels 	case WRITE:
16330418Skarels 		makelabel(type, name, &lab);
16430418Skarels 		lp = getbootarea(bootarea, &lab);
16530418Skarels 		*lp = lab;
16630418Skarels 		writelabel(f, bootarea, lp);
16730418Skarels 		break;
16830418Skarels 
16930418Skarels 	case RESTORE:
17030418Skarels 		lab.d_secsize = DEV_BSIZE;			/* XXX */
17130418Skarels 		lab.d_bbsize = BBSIZE;				/* XXX */
17230418Skarels 		lp = getbootarea(bootarea, &lab);
17330418Skarels 		t = open(asciifile, O_RDONLY);
17430418Skarels 		if (t < 0)
17530418Skarels 			Perror(asciifile);
17630418Skarels 		getasciilabel(t, lp);
17730418Skarels 		writelabel(f, bootarea, lp);
17830418Skarels 		break;
17930418Skarels 	}
18030418Skarels 	exit(0);
18130418Skarels }
18230418Skarels 
18330418Skarels makelabel(type, name, lp)
18430418Skarels 	char *type, *name;
18530418Skarels 	register struct disklabel *lp;
18630418Skarels {
18730418Skarels 	register struct disklabel *dp;
18830418Skarels 	register char *p;
18930418Skarels 
19030418Skarels 	dp = getdiskbyname(type);
19130418Skarels 	if (dp == NULL) {
19230418Skarels 		fprintf(stderr, "%s: unknown disk type\n", type);
19330418Skarels 		exit(1);
19430418Skarels 	}
19530418Skarels 	*lp = *dp;
19630418Skarels 	if (name)
19730418Skarels 		strncpy(lp->d_name, name, sizeof(lp->d_name));
19830418Skarels }
19930418Skarels 
20030418Skarels writelabel(f, boot, lp)
20130418Skarels 	int f;
20230418Skarels 	char *boot;
20330418Skarels 	register struct disklabel *lp;
20430418Skarels {
20530418Skarels 	register i;
20630418Skarels 
20730418Skarels 	lp->d_magic = DISKMAGIC;
20830418Skarels 	lp->d_magic2 = DISKMAGIC;
20930418Skarels 	lp->d_checksum = 0;
21030418Skarels 	lp->d_checksum = dkcksum(lp);
21130418Skarels 	lseek(f, (off_t)0, L_SET);
212*30677Skarels 	if (rflag) {
213*30677Skarels 		if (write(f, boot, lp->d_bbsize) < lp->d_bbsize)
214*30677Skarels 			Perror("write");
215*30677Skarels 		if (ioctl(f, DIOCSDINFO, lp) < 0)
216*30677Skarels 			Perror("ioctl DIOCSDINFO");
217*30677Skarels 	} else if (ioctl(f, DIOCWDINFO, lp) < 0)
218*30677Skarels 		Perror("ioctl DIOCWDINFO");
21930419Skarels #if vax
220*30677Skarels 	if (lp->d_type == DTYPE_SMD && lp->d_flags & D_BADSECT) {
221*30677Skarels 		daddr_t alt;
222*30677Skarels 
223*30677Skarels 		alt = lp->d_ncylinders * lp->d_secpercyl - lp->d_nsectors;
224*30677Skarels 		for (i = 1; i < 11 && i < lp->d_nsectors; i += 2) {
225*30677Skarels 			lseek(f, (off_t)(alt + i) * lp->d_secsize, L_SET);
226*30677Skarels 			if (write(f, boot, lp->d_secsize) < lp->d_secsize) {
227*30677Skarels 				int oerrno = errno;
228*30677Skarels 				fprintf(stderr, "alternate label %d ", i/2);
229*30677Skarels 				errno = oerrno;
230*30677Skarels 				perror("write");
231*30677Skarels 			}
23230418Skarels 		}
23330418Skarels 	}
23430419Skarels #endif
23530418Skarels }
23630418Skarels 
23730418Skarels /*
23830418Skarels  * Read disklabel from disk.
23930418Skarels  * If boot is given, need bootstrap too.
240*30677Skarels  * If boot not needed, use ioctl to get label
241*30677Skarels  * unless -r flag is given.
24230418Skarels  */
24330418Skarels struct disklabel *
24430418Skarels readlabel(f, boot)
24530418Skarels 	int f;
24630418Skarels 	char *boot;
24730418Skarels {
24830418Skarels 	register struct disklabel *lp;
249*30677Skarels 	register char *buf;
25030418Skarels 
251*30677Skarels 	if (boot)
252*30677Skarels 		buf = boot;
253*30677Skarels 	else
254*30677Skarels 		buf = bootarea;
255*30677Skarels 	lp = (struct disklabel *)(buf + LABELOFFSET);
256*30677Skarels 	if (rflag == 0 && boot == 0) {
257*30677Skarels 		if (ioctl(f, DIOCGDINFO, lp) < 0)
258*30677Skarels 			Perror("ioctl DIOCGDINFO");
259*30677Skarels 	} else {
260*30677Skarels 		if (read(f, buf, BBSIZE) < BBSIZE)
261*30677Skarels 			Perror(specname);
262*30677Skarels 		for (lp = (struct disklabel *)buf;
263*30677Skarels 		    lp <= (struct disklabel *)(buf + BBSIZE - sizeof(*lp));
264*30677Skarels 		    lp = (struct disklabel *)((char *)lp + 16))
265*30677Skarels 			if (lp->d_magic == DISKMAGIC &&
266*30677Skarels 			    lp->d_magic2 == DISKMAGIC)
267*30677Skarels 				break;
268*30677Skarels 		if (lp > (struct disklabel *)(buf + BBSIZE - sizeof(*lp)) ||
269*30677Skarels 		    lp->d_magic != DISKMAGIC || lp->d_magic2 != DISKMAGIC ||
270*30677Skarels 		    dkcksum(lp) != 0) {
271*30677Skarels 			fprintf(stderr,
27230418Skarels 	"Bad pack magic number (label is damaged, or pack is unlabeled)\n");
273*30677Skarels 			exit(1);
274*30677Skarels 		}
27530418Skarels 	}
27630418Skarels 	return (lp);
27730418Skarels }
27830418Skarels 
27930418Skarels struct disklabel *
28030418Skarels getbootarea(boot, dp)
28130418Skarels 	char *boot;
28230418Skarels 	register struct disklabel *dp;
28330418Skarels {
28430418Skarels 	struct disklabel *lp;
28530418Skarels 	register char *p;
28630418Skarels 	int b;
28730418Skarels 
28830418Skarels #ifdef BOOT
28930418Skarels 	if (xxboot == NULL) {
29030418Skarels 		dkbasename = np;
29130418Skarels 		if ((p = rindex(dkname, '/')) == NULL)
29230418Skarels 			p = dkname;
29330418Skarels 		else
29430418Skarels 			p++;
29530418Skarels 		while (*p && !isdigit(*p))
29630418Skarels 			*np++ = *p++;
29730418Skarels 		*np++ = '\0';
29830418Skarels 
29930418Skarels 		sprintf(np, "%s/%sboot", BOOTDIR, dkbasename);
30030418Skarels 		if (access(np, F_OK) < 0 && dkbasename[0] == 'r')
30130418Skarels 			dkbasename++;
30230418Skarels 		xxboot = np;
30330418Skarels 		sprintf(xxboot, "%s/%sboot", BOOTDIR, dkbasename);
30430418Skarels 		np += strlen(xxboot) + 1;
30530418Skarels 
30630418Skarels 		bootxx = np;
30730418Skarels 		sprintf(bootxx, "%s/boot%s", BOOTDIR, dkbasename);
30830418Skarels 		np += strlen(bootxx) + 1;
30930418Skarels 	}
31030418Skarels 
31130418Skarels 	b = open(xxboot, O_RDONLY);
31230418Skarels 	if (b < 0)
31330418Skarels 		Perror(xxboot);
31430418Skarels 	if (read(b, boot, dp->d_secsize) < 0)
31530418Skarels 		Perror(xxboot);
31630418Skarels 	close(b);
31730418Skarels 	b = open(bootxx, O_RDONLY);
31830418Skarels 	if (b < 0)
31930418Skarels 		Perror(bootxx);
32030418Skarels 	if (read(b, &boot[dp->d_secsize], dp->d_bbsize-dp->d_secsize) < 0)
32130418Skarels 		Perror(bootxx);
32230418Skarels 	close(b);
32330418Skarels #endif
32430418Skarels 
32530418Skarels 	lp = (struct disklabel *)(boot + (LABELSECTOR * dp->d_secsize) +
32630418Skarels 	    LABELOFFSET);
32730418Skarels 	for (p = (char *)lp; p < (char *)lp + sizeof(struct disklabel); p++)
32830418Skarels 		if (*p) {
32930418Skarels 			fprintf(stderr,
33030418Skarels 			    "Bootstrap doesn't leave room for disk label\n");
33130418Skarels 			exit(2);
33230418Skarels 		}
33330418Skarels 	return (lp);
33430418Skarels }
33530418Skarels 
33630418Skarels display(f, lp)
33730418Skarels 	FILE *f;
33830418Skarels 	register struct disklabel *lp;
33930418Skarels {
34030418Skarels 	register i, j;
34130418Skarels 	register struct partition *pp;
34230418Skarels 
34330418Skarels 	fprintf(f, "# %s:\n", specname);
34430418Skarels 	if ((unsigned) lp->d_type < DKMAXTYPES)
34530418Skarels 		fprintf(f, "type: %s\n", dktypenames[lp->d_type]);
34630418Skarels 	else
34730418Skarels 		fprintf(f, "type: %d\n", lp->d_type);
34830418Skarels 	fprintf(f, "disk: %.*s\n", sizeof(lp->d_typename), lp->d_typename);
34930418Skarels 	fprintf(f, "label: %.*s\n", sizeof(lp->d_name), lp->d_name);
35030418Skarels 	fprintf(f, "flags: ");
35130418Skarels 	if (lp->d_flags & D_REMOVABLE)
35230418Skarels 		fprintf(f, "removeable ");
35330418Skarels 	if (lp->d_flags & D_ECC)
35430418Skarels 		fprintf(f, "ecc ");
35530418Skarels 	if (lp->d_flags & D_BADSECT)
35630418Skarels 		fprintf(f, "badsect ");
35730418Skarels 	fprintf(f, "\n");
35830418Skarels 	fprintf(f, "bytes/sector: %d\n", lp->d_secsize);
35930418Skarels 	fprintf(f, "sectors/track: %d\n", lp->d_nsectors);
36030418Skarels 	fprintf(f, "tracks/cylinder: %d\n", lp->d_ntracks);
36130418Skarels 	fprintf(f, "cylinders: %d\n", lp->d_ncylinders);
36230418Skarels 	fprintf(f, "interleave: %d\n", lp->d_interleave);
36330418Skarels 	fprintf(f, "trackskew: %d\n", lp->d_trackskew);
36430418Skarels 	fprintf(f, "cylinderskew: %d\n", lp->d_cylskew);
36530418Skarels 	fprintf(f, "headswitch: %d\t\t# milliseconds\n", lp->d_headswitch);
36630418Skarels 	fprintf(f, "track-to-track seek: %d\t# milliseconds\n", lp->d_trkseek);
36730418Skarels 	fprintf(f, "drivedata: ");
36830418Skarels 	for (i = NDDATA - 1; i >= 0; i--)
36930418Skarels 		if (lp->d_drivedata[i])
37030418Skarels 			break;
37130418Skarels 	if (i < 0)
37230418Skarels 		i = 0;
37330418Skarels 	for (j = 0; j <= i; j++)
37430418Skarels 		fprintf(f, "%d ", lp->d_drivedata[j]);
37530418Skarels 	fprintf(f, "\n\n%d partitions:\n", lp->d_npartitions);
37630418Skarels 	fprintf(f, "#\t       size    offset     fstype\n");
37730418Skarels 	pp = lp->d_partitions;
37830418Skarels 	for (i = 0; i < lp->d_npartitions; i++, pp++) {
37930418Skarels 		fprintf(f, "\t%c: %8d %8d    ", 'a' + i,
38030418Skarels 		   pp->p_size, pp->p_offset);
38130418Skarels 		if (pp->p_size) {
38230418Skarels 			if ((unsigned) pp->p_fstype < FSMAXTYPES)
38330418Skarels 				fprintf(f, "%8.8s", fstypenames[pp->p_fstype]);
38430418Skarels 			else
38530418Skarels 				fprintf(f, "%8d", pp->p_fstype);
38630418Skarels 			fprintf(f, "\t# (Cyl. %4d",
38730418Skarels 			    pp->p_offset / lp->d_secpercyl);
38830418Skarels 			if (pp->p_offset % lp->d_secpercyl)
38930418Skarels 			    putc('*', f);
39030418Skarels 			else
39130418Skarels 			    putc(' ', f);
39230418Skarels 			fprintf(f, "- %d",
39330418Skarels 			    (pp->p_offset +
39430418Skarels 			    pp->p_size + lp->d_secpercyl - 1) /
39530418Skarels 			    lp->d_secpercyl - 1);
39630418Skarels 			if (pp->p_size % lp->d_secpercyl)
39730418Skarels 			    putc('*', f);
39830418Skarels 			putc(')', f);
39930418Skarels 		}
40030418Skarels 		fprintf(f, "\n");
40130418Skarels 	}
40230418Skarels }
40330418Skarels 
40430418Skarels edit(f)
40530418Skarels 	int f;
40630418Skarels {
40730418Skarels 	fprintf(stderr, "sorry, not yet\n");
40830418Skarels 	exit(1);
40930418Skarels }
41030418Skarels 
41130418Skarels 
41230418Skarels /*
41330418Skarels  * Read an ascii label in from fd f,
41430418Skarels  * in the same format as that put out by display(),
41530418Skarels  * and fill in lp.
41630418Skarels  */
41730418Skarels getasciilabel(f, lp)
41830418Skarels 	int f;
41930418Skarels 	register struct disklabel *lp;
42030418Skarels {
42130418Skarels 	fprintf(stderr, "sorry, not yet\n");
42230418Skarels 	exit(1);
42330418Skarels }
42430418Skarels 
42530418Skarels Perror(op)
42630418Skarels 	char *op;
42730418Skarels {
42830418Skarels 
42930418Skarels 	fprintf(stderr, "disklabel: "); perror(op);
43030418Skarels 	exit(4);
43130418Skarels }
432