xref: /csrg-svn/sbin/disklabel/disklabel.c (revision 30418)
1*30418Skarels #ifndef lint
2*30418Skarels static char sccsid[] = "@(#)disklabel.c	5.1 (Berkeley) 01/19/87";
3*30418Skarels /* from static char sccsid[] = "@(#)disklabel.c	1.2 (Symmetric) 11/28/85"; */
4*30418Skarels #endif
5*30418Skarels 
6*30418Skarels #include <stdio.h>
7*30418Skarels #include <ctype.h>
8*30418Skarels #include <sys/param.h>
9*30418Skarels #include <sys/errno.h>
10*30418Skarels #include <sys/file.h>
11*30418Skarels #include <sys/ioctl.h>
12*30418Skarels #define DKTYPENAMES
13*30418Skarels #include <sys/disklabel.h>
14*30418Skarels 
15*30418Skarels /*
16*30418Skarels  * Disklabel: read and write disklabels.
17*30418Skarels  * The label is usually placed on one of the first sectors of the disk.
18*30418Skarels  * Many machines (VAX 11/750) also place a bootstrap in the same area,
19*30418Skarels  * in which case the label is embedded in the bootstrap.
20*30418Skarels  * The bootstrap source must leave space at the proper offset
21*30418Skarels  * for the label on such machines.
22*30418Skarels  */
23*30418Skarels 
24*30418Skarels #define	BBSIZE	8192			/* size of boot area, with label */
25*30418Skarels 
26*30418Skarels #ifdef vax
27*30418Skarels #define	BOOT				/* also have bootstrap in "boot area" */
28*30418Skarels #define	BOOTDIR	"/usr/mdec"		/* source of boot binaries */
29*30418Skarels #endif
30*30418Skarels 
31*30418Skarels char	*dkname;
32*30418Skarels char	*dkbasename;
33*30418Skarels char	*xxboot;
34*30418Skarels char	*bootxx;
35*30418Skarels char	*specname;
36*30418Skarels char	*sprintf();
37*30418Skarels char	*rindex();
38*30418Skarels 
39*30418Skarels extern	int errno;
40*30418Skarels char	namebuf[BBSIZE], *np = namebuf;
41*30418Skarels char	bootarea[BBSIZE];
42*30418Skarels struct	disklabel lab;
43*30418Skarels struct	disklabel *readlabel(), *getbootarea();
44*30418Skarels 
45*30418Skarels int	op;			/* one of: */
46*30418Skarels #define	READ	1
47*30418Skarels #define	WRITE	2
48*30418Skarels #define	EDIT	3
49*30418Skarels #define	RESTORE	4
50*30418Skarels 
51*30418Skarels main(argc, argv)
52*30418Skarels 	int argc;
53*30418Skarels 	char *argv[];
54*30418Skarels {
55*30418Skarels 	register struct disklabel *lp;
56*30418Skarels 	int f, t;
57*30418Skarels 	char *name = 0, *asciifile, *type;
58*30418Skarels 
59*30418Skarels 	while (argc > 1 && argv[1][0] == '-') {
60*30418Skarels 		if (strcmp(argv[1], "-e") == 0) {
61*30418Skarels 			if (argc != 3)
62*30418Skarels 				goto usage;
63*30418Skarels 			op = EDIT;
64*30418Skarels 		} else if (strcmp(argv[1], "-w") == 0) {
65*30418Skarels 			if (argc != 4)
66*30418Skarels 				goto usage;
67*30418Skarels 			op = RESTORE;
68*30418Skarels 		} else
69*30418Skarels 			goto usage;
70*30418Skarels 		argv++;
71*30418Skarels 		argc--;
72*30418Skarels 	}
73*30418Skarels 	if (argc < 2 || argc > 6) {
74*30418Skarels usage:
75*30418Skarels 		fprintf(stderr, "%s%s%s%s",
76*30418Skarels #ifdef BOOT
77*30418Skarels "usage: disklabel disk    				(to read label)\n",
78*30418Skarels "or disklabel disk type [ packid ] [ xxboot bootxx ]    (to write label)\n",
79*30418Skarels "or disklabel -e disk    				(to edit label)\n",
80*30418Skarels "or disklabel -w disk protofile [ xxboot bootxx ]	(to restore label)\n"
81*30418Skarels #else
82*30418Skarels "usage: disklabel disk    			(to read label)\n",
83*30418Skarels "or disklabel disk type [ packid ]		(to write label)\n",
84*30418Skarels "or disklabel -e disk    			(to edit label)\n",
85*30418Skarels "or disklabel -w disk protofile			(to restore label)\n"
86*30418Skarels #endif
87*30418Skarels 			);
88*30418Skarels 		exit(1);
89*30418Skarels 	}
90*30418Skarels 	if (op == 0)
91*30418Skarels 		if (argc == 2)
92*30418Skarels 			op = READ;
93*30418Skarels 		else
94*30418Skarels 			op = WRITE;
95*30418Skarels 	dkname = argv[1];
96*30418Skarels 	if (dkname[0] != '/') {
97*30418Skarels 		sprintf(np, "/dev/r%sc", dkname);
98*30418Skarels 		specname = np;
99*30418Skarels 		np += strlen(specname) + 1;
100*30418Skarels 	} else
101*30418Skarels 		specname = dkname;
102*30418Skarels 	f = open(specname, op == READ ? O_RDONLY : O_RDWR);
103*30418Skarels 	if (f < 0 && errno == ENOENT && dkname[0] != '/') {
104*30418Skarels 		sprintf(specname, "/dev/r%s", dkname);
105*30418Skarels 		np = namebuf + strlen(specname) + 1;
106*30418Skarels 		f = open(specname, op == READ ? O_RDONLY : O_RDWR);
107*30418Skarels 	}
108*30418Skarels 	if (f < 0)
109*30418Skarels 		Perror(specname);
110*30418Skarels 
111*30418Skarels 	if (op == WRITE) {
112*30418Skarels 		type = argv[2];
113*30418Skarels 		if (argc == 4 || argc == 6) {
114*30418Skarels 			name = argv[3];
115*30418Skarels 			argv++;
116*30418Skarels 			argc--;
117*30418Skarels 		}
118*30418Skarels 	}
119*30418Skarels 	if (op == RESTORE) {
120*30418Skarels 		asciifile = argv[2];
121*30418Skarels 		argv++;
122*30418Skarels 		argc--;
123*30418Skarels 	}
124*30418Skarels #ifdef BOOT
125*30418Skarels 	if (argc == 5) {
126*30418Skarels 		xxboot = argv[3];
127*30418Skarels 		bootxx = argv[4];
128*30418Skarels 	}
129*30418Skarels #endif
130*30418Skarels 
131*30418Skarels 
132*30418Skarels 	switch (op) {
133*30418Skarels 
134*30418Skarels 	case READ:
135*30418Skarels 		lp = readlabel(f, 0);
136*30418Skarels 		display(stdout, lp);
137*30418Skarels 		break;
138*30418Skarels 
139*30418Skarels 	case EDIT:
140*30418Skarels 		lp = readlabel(f, bootarea);
141*30418Skarels 		edit(f, lp);
142*30418Skarels 		writelabel(f, bootarea, lp);
143*30418Skarels 		break;
144*30418Skarels 
145*30418Skarels 	case WRITE:
146*30418Skarels 		makelabel(type, name, &lab);
147*30418Skarels 		lp = getbootarea(bootarea, &lab);
148*30418Skarels 		*lp = lab;
149*30418Skarels 		writelabel(f, bootarea, lp);
150*30418Skarels 		break;
151*30418Skarels 
152*30418Skarels 	case RESTORE:
153*30418Skarels 		lab.d_secsize = DEV_BSIZE;			/* XXX */
154*30418Skarels 		lab.d_bbsize = BBSIZE;				/* XXX */
155*30418Skarels 		lp = getbootarea(bootarea, &lab);
156*30418Skarels 		t = open(asciifile, O_RDONLY);
157*30418Skarels 		if (t < 0)
158*30418Skarels 			Perror(asciifile);
159*30418Skarels 		getasciilabel(t, lp);
160*30418Skarels 		writelabel(f, bootarea, lp);
161*30418Skarels 		break;
162*30418Skarels 	}
163*30418Skarels 	exit(0);
164*30418Skarels }
165*30418Skarels 
166*30418Skarels makelabel(type, name, lp)
167*30418Skarels 	char *type, *name;
168*30418Skarels 	register struct disklabel *lp;
169*30418Skarels {
170*30418Skarels 	register struct disklabel *dp;
171*30418Skarels 	register char *p;
172*30418Skarels 
173*30418Skarels 	dp = getdiskbyname(type);
174*30418Skarels 	if (dp == NULL) {
175*30418Skarels 		fprintf(stderr, "%s: unknown disk type\n", type);
176*30418Skarels 		exit(1);
177*30418Skarels 	}
178*30418Skarels 	*lp = *dp;
179*30418Skarels 	if (name)
180*30418Skarels 		strncpy(lp->d_name, name, sizeof(lp->d_name));
181*30418Skarels }
182*30418Skarels 
183*30418Skarels writelabel(f, boot, lp)
184*30418Skarels 	int f;
185*30418Skarels 	char *boot;
186*30418Skarels 	register struct disklabel *lp;
187*30418Skarels {
188*30418Skarels 	register i;
189*30418Skarels 	daddr_t alt;
190*30418Skarels 
191*30418Skarels 	lp->d_magic = DISKMAGIC;
192*30418Skarels 	lp->d_magic2 = DISKMAGIC;
193*30418Skarels #if ENDIAN != BIG
194*30418Skarels 	swablabel(lp);
195*30418Skarels #endif
196*30418Skarels 	lp->d_checksum = 0;
197*30418Skarels 	lp->d_checksum = dkcksum(lp);
198*30418Skarels 	lseek(f, (off_t)0, L_SET);
199*30418Skarels 	if (write(f, boot, lp->d_bbsize) < lp->d_bbsize)
200*30418Skarels 		Perror("write");
201*30418Skarels #ifdef notyet
202*30418Skarels 	alt = lp->d_ncylinders * lp->d_secpercyl - lp->d_nsectors;
203*30418Skarels 	for (i = 1; i < 11 && i < lp->d_nsectors; i += 2) {
204*30418Skarels 		lseek(f, (off_t)(alt + i) * lp->d_secsize, L_SET);
205*30418Skarels 		if (write(f, boot, lp->d_secsize) < lp->d_secsize) {
206*30418Skarels 			int oerrno = errno;
207*30418Skarels 			fprintf(stderr, "alternate label %d ", i/2);
208*30418Skarels 			errno = oerrno;
209*30418Skarels 			perror("write");
210*30418Skarels 		}
211*30418Skarels 	}
212*30418Skarels 	if (ioctl(f, DIOCSDINFO, lp) < 0)
213*30418Skarels 		Perror("ioctl DIOCSDINFO");
214*30418Skarels #endif
215*30418Skarels }
216*30418Skarels 
217*30418Skarels /*
218*30418Skarels  * Read disklabel from disk.
219*30418Skarels  * If boot is given, need bootstrap too.
220*30418Skarels  * If boot not needed, could use ioctl to get label.
221*30418Skarels  */
222*30418Skarels struct disklabel *
223*30418Skarels readlabel(f, boot)
224*30418Skarels 	int f;
225*30418Skarels 	char *boot;
226*30418Skarels {
227*30418Skarels 	register struct disklabel *lp;
228*30418Skarels 	u_long magic = htonl(DISKMAGIC);
229*30418Skarels 
230*30418Skarels 	if (boot == NULL)
231*30418Skarels 		boot = bootarea;
232*30418Skarels 	if (read(f, boot, BBSIZE) < BBSIZE)
233*30418Skarels 		Perror(specname);
234*30418Skarels 	for (lp = (struct disklabel *)(boot + LABELOFFSET);
235*30418Skarels 	    lp <= (struct disklabel *)(boot + BBSIZE -
236*30418Skarels 	    sizeof(struct disklabel));
237*30418Skarels 	    lp = (struct disklabel *)((char *)lp + 128))
238*30418Skarels 		if (lp->d_magic == magic && lp->d_magic2 == magic)
239*30418Skarels 			break;
240*30418Skarels 	if (lp > (struct disklabel *)(boot + BBSIZE -
241*30418Skarels 	    sizeof(struct disklabel)) ||
242*30418Skarels 	    lp->d_magic != magic || lp->d_magic2 != magic ||
243*30418Skarels 	    dkcksum(lp) != 0) {
244*30418Skarels 		fprintf(stderr,
245*30418Skarels 	"Bad pack magic number (label is damaged, or pack is unlabeled)\n");
246*30418Skarels 		exit(1);
247*30418Skarels 	}
248*30418Skarels #if ENDIAN != BIG
249*30418Skarels 	swablabel(lp);
250*30418Skarels #endif
251*30418Skarels 	return (lp);
252*30418Skarels }
253*30418Skarels 
254*30418Skarels struct disklabel *
255*30418Skarels getbootarea(boot, dp)
256*30418Skarels 	char *boot;
257*30418Skarels 	register struct disklabel *dp;
258*30418Skarels {
259*30418Skarels 	struct disklabel *lp;
260*30418Skarels 	register char *p;
261*30418Skarels 	int b;
262*30418Skarels 
263*30418Skarels #ifdef BOOT
264*30418Skarels 	if (xxboot == NULL) {
265*30418Skarels 		dkbasename = np;
266*30418Skarels 		if ((p = rindex(dkname, '/')) == NULL)
267*30418Skarels 			p = dkname;
268*30418Skarels 		else
269*30418Skarels 			p++;
270*30418Skarels 		while (*p && !isdigit(*p))
271*30418Skarels 			*np++ = *p++;
272*30418Skarels 		*np++ = '\0';
273*30418Skarels 
274*30418Skarels 		sprintf(np, "%s/%sboot", BOOTDIR, dkbasename);
275*30418Skarels 		if (access(np, F_OK) < 0 && dkbasename[0] == 'r')
276*30418Skarels 			dkbasename++;
277*30418Skarels 		xxboot = np;
278*30418Skarels 		sprintf(xxboot, "%s/%sboot", BOOTDIR, dkbasename);
279*30418Skarels 		np += strlen(xxboot) + 1;
280*30418Skarels 
281*30418Skarels 		bootxx = np;
282*30418Skarels 		sprintf(bootxx, "%s/boot%s", BOOTDIR, dkbasename);
283*30418Skarels 		np += strlen(bootxx) + 1;
284*30418Skarels 	}
285*30418Skarels 
286*30418Skarels 	b = open(xxboot, O_RDONLY);
287*30418Skarels 	if (b < 0)
288*30418Skarels 		Perror(xxboot);
289*30418Skarels 	if (read(b, boot, dp->d_secsize) < 0)
290*30418Skarels 		Perror(xxboot);
291*30418Skarels 	close(b);
292*30418Skarels 	b = open(bootxx, O_RDONLY);
293*30418Skarels 	if (b < 0)
294*30418Skarels 		Perror(bootxx);
295*30418Skarels 	if (read(b, &boot[dp->d_secsize], dp->d_bbsize-dp->d_secsize) < 0)
296*30418Skarels 		Perror(bootxx);
297*30418Skarels 	close(b);
298*30418Skarels #endif
299*30418Skarels 
300*30418Skarels 	lp = (struct disklabel *)(boot + (LABELSECTOR * dp->d_secsize) +
301*30418Skarels 	    LABELOFFSET);
302*30418Skarels 	for (p = (char *)lp; p < (char *)lp + sizeof(struct disklabel); p++)
303*30418Skarels 		if (*p) {
304*30418Skarels 			fprintf(stderr,
305*30418Skarels 			    "Bootstrap doesn't leave room for disk label\n");
306*30418Skarels 			exit(2);
307*30418Skarels 		}
308*30418Skarels 	return (lp);
309*30418Skarels }
310*30418Skarels 
311*30418Skarels display(f, lp)
312*30418Skarels 	FILE *f;
313*30418Skarels 	register struct disklabel *lp;
314*30418Skarels {
315*30418Skarels 	register i, j;
316*30418Skarels 	register struct partition *pp;
317*30418Skarels 
318*30418Skarels 	fprintf(f, "# %s:\n", specname);
319*30418Skarels 	if ((unsigned) lp->d_type < DKMAXTYPES)
320*30418Skarels 		fprintf(f, "type: %s\n", dktypenames[lp->d_type]);
321*30418Skarels 	else
322*30418Skarels 		fprintf(f, "type: %d\n", lp->d_type);
323*30418Skarels 	fprintf(f, "disk: %.*s\n", sizeof(lp->d_typename), lp->d_typename);
324*30418Skarels 	fprintf(f, "label: %.*s\n", sizeof(lp->d_name), lp->d_name);
325*30418Skarels 	fprintf(f, "flags: ");
326*30418Skarels 	if (lp->d_flags & D_REMOVABLE)
327*30418Skarels 		fprintf(f, "removeable ");
328*30418Skarels 	if (lp->d_flags & D_ECC)
329*30418Skarels 		fprintf(f, "ecc ");
330*30418Skarels 	if (lp->d_flags & D_BADSECT)
331*30418Skarels 		fprintf(f, "badsect ");
332*30418Skarels 	fprintf(f, "\n");
333*30418Skarels 	fprintf(f, "bytes/sector: %d\n", lp->d_secsize);
334*30418Skarels 	fprintf(f, "sectors/track: %d\n", lp->d_nsectors);
335*30418Skarels 	fprintf(f, "tracks/cylinder: %d\n", lp->d_ntracks);
336*30418Skarels 	fprintf(f, "cylinders: %d\n", lp->d_ncylinders);
337*30418Skarels 	fprintf(f, "interleave: %d\n", lp->d_interleave);
338*30418Skarels 	fprintf(f, "trackskew: %d\n", lp->d_trackskew);
339*30418Skarels 	fprintf(f, "cylinderskew: %d\n", lp->d_cylskew);
340*30418Skarels 	fprintf(f, "headswitch: %d\t\t# milliseconds\n", lp->d_headswitch);
341*30418Skarels 	fprintf(f, "track-to-track seek: %d\t# milliseconds\n", lp->d_trkseek);
342*30418Skarels 	fprintf(f, "drivedata: ");
343*30418Skarels 	for (i = NDDATA - 1; i >= 0; i--)
344*30418Skarels 		if (lp->d_drivedata[i])
345*30418Skarels 			break;
346*30418Skarels 	if (i < 0)
347*30418Skarels 		i = 0;
348*30418Skarels 	for (j = 0; j <= i; j++)
349*30418Skarels 		fprintf(f, "%d ", lp->d_drivedata[j]);
350*30418Skarels 	fprintf(f, "\n\n%d partitions:\n", lp->d_npartitions);
351*30418Skarels 	fprintf(f, "#\t       size    offset     fstype\n");
352*30418Skarels 	pp = lp->d_partitions;
353*30418Skarels 	for (i = 0; i < lp->d_npartitions; i++, pp++) {
354*30418Skarels 		fprintf(f, "\t%c: %8d %8d    ", 'a' + i,
355*30418Skarels 		   pp->p_size, pp->p_offset);
356*30418Skarels 		if (pp->p_size) {
357*30418Skarels 			if ((unsigned) pp->p_fstype < FSMAXTYPES)
358*30418Skarels 				fprintf(f, "%8.8s", fstypenames[pp->p_fstype]);
359*30418Skarels 			else
360*30418Skarels 				fprintf(f, "%8d", pp->p_fstype);
361*30418Skarels 			fprintf(f, "\t# (Cyl. %4d",
362*30418Skarels 			    pp->p_offset / lp->d_secpercyl);
363*30418Skarels 			if (pp->p_offset % lp->d_secpercyl)
364*30418Skarels 			    putc('*', f);
365*30418Skarels 			else
366*30418Skarels 			    putc(' ', f);
367*30418Skarels 			fprintf(f, "- %d",
368*30418Skarels 			    (pp->p_offset +
369*30418Skarels 			    pp->p_size + lp->d_secpercyl - 1) /
370*30418Skarels 			    lp->d_secpercyl - 1);
371*30418Skarels 			if (pp->p_size % lp->d_secpercyl)
372*30418Skarels 			    putc('*', f);
373*30418Skarels 			putc(')', f);
374*30418Skarels 		}
375*30418Skarels 		fprintf(f, "\n");
376*30418Skarels 	}
377*30418Skarels }
378*30418Skarels 
379*30418Skarels edit(f)
380*30418Skarels 	int f;
381*30418Skarels {
382*30418Skarels 	fprintf(stderr, "sorry, not yet\n");
383*30418Skarels 	exit(1);
384*30418Skarels }
385*30418Skarels 
386*30418Skarels 
387*30418Skarels /*
388*30418Skarels  * Read an ascii label in from fd f,
389*30418Skarels  * in the same format as that put out by display(),
390*30418Skarels  * and fill in lp.
391*30418Skarels  */
392*30418Skarels getasciilabel(f, lp)
393*30418Skarels 	int f;
394*30418Skarels 	register struct disklabel *lp;
395*30418Skarels {
396*30418Skarels 	fprintf(stderr, "sorry, not yet\n");
397*30418Skarels 	exit(1);
398*30418Skarels }
399*30418Skarels 
400*30418Skarels Perror(op)
401*30418Skarels 	char *op;
402*30418Skarels {
403*30418Skarels 
404*30418Skarels 	fprintf(stderr, "disklabel: "); perror(op);
405*30418Skarels 	exit(4);
406*30418Skarels }
407