1 /* @(#)makelabel.c	1.57 11/08/13 Copyright 1988-2011 J. Schilling */
2 #include <schily/mconfig.h>
3 #ifndef lint
4 static	UConst char sccsid[] =
5 	"@(#)makelabel.c	1.57 11/08/13 Copyright 1988-2011 J. Schilling";
6 #endif
7 /*
8  *	Routines to create / modify a label
9  *
10  *	Copyright (c) 1988-2011 J. Schilling
11  */
12 /*
13  * The contents of this file are subject to the terms of the
14  * Common Development and Distribution License, Version 1.0 only
15  * (the "License").  You may not use this file except in compliance
16  * with the License.
17  *
18  * See the file CDDL.Schily.txt in this distribution for details.
19  * A copy of the CDDL is also available via the Internet at
20  * http://www.opensource.org/licenses/cddl1.txt
21  *
22  * When distributing Covered Code, include this CDDL HEADER in each
23  * file and include the License file CDDL.Schily.txt from this distribution.
24  */
25 
26 #include <schily/stdio.h>
27 #include <schily/standard.h>
28 #include <schily/ioctl.h>
29 #include <schily/termios.h>	/* For TIOCSTI (simulate terminal input) */
30 #include <schily/fcntl.h>
31 #ifdef	HAVE_SYS_FILE_H
32 #include <sys/file.h>
33 #endif
34 #include "dsklabel.h"
35 #ifndef	HAVE_DKIO
36 #	undef	SVR4
37 #endif
38 #ifdef	SVR4
39 #include <sys/vtoc.h>
40 #endif
41 #include <schily/unistd.h>
42 #include <schily/stdlib.h>
43 #include <schily/string.h>
44 #include <schily/schily.h>
45 
46 #include <scg/scsireg.h>
47 #include <scg/scsitransp.h>
48 
49 #include "fmt.h"
50 
51 LOCAL	char	labelbuf[80];
52 extern	struct	dk_label *d_label;
53 
54 char	labelname[] = "Label";
55 char	labelproto[] = "Label.prototype";
56 char	*Lname = labelname;
57 char	*Lproto = labelproto;
58 
59 EXPORT	void	set_default_vtmap	__PR((struct dk_label *lp));
60 EXPORT	unsigned short do_cksum		__PR((struct dk_label *l));
61 EXPORT	BOOL	check_vtmap		__PR((struct dk_label *lp, BOOL set));
62 EXPORT	void	setlabel_from_val	__PR((SCSI *scgp, struct disk *dp, struct dk_label *lp));
63 EXPORT	void	makelabel		__PR((SCSI *scgp, struct disk *dp, struct dk_label *lp));
64 LOCAL	void	chpart			__PR((struct disk *dp, struct dk_label *lp, int idx));
65 #ifdef	SVR4
66 LOCAL	int	prvttab			__PR((FILE *f, struct dk_label *lp, int i, int n));
67 #endif
68 EXPORT	void	prpartab		__PR((FILE *f, char *disk_type, struct dk_label *lp));
69 EXPORT	void	printlabel		__PR((struct dk_label *lp));
70 LOCAL	void	printparthead		__PR((void));
71 EXPORT	void	printpart		__PR((struct dk_label *lp, int i));
72 LOCAL	void	_printpart		__PR((struct dk_label *lp, int i));
73 EXPORT	void	printparts		__PR((struct dk_label *lp));
74 EXPORT	int	readlabel		__PR((char *name, struct dk_label *lp));
75 EXPORT	void	writelabel		__PR((char *name, struct dk_label *lp));
76 LOCAL	void	writebackuplabel	__PR((int f, struct dk_label *lp));
77 EXPORT	int	setlabel		__PR((char *name, struct dk_label *lp));
78 LOCAL	int	setgeom			__PR((int f, struct dk_label *lp));
79 EXPORT	char	*getasciilabel		__PR((struct dk_label *lp));
80 EXPORT	void	setasciilabel		__PR((struct dk_label *lp, char *lname));
81 EXPORT	BOOL	setval_from_label	__PR((struct disk *dp, struct dk_label *lp));
82 EXPORT	void	label_null		__PR((struct dk_label *lp));
83 EXPORT	int	label_cmp		__PR((struct dk_label *lp1, struct dk_label *lp2));
84 EXPORT	BOOL	labelgeom_ok		__PR((struct dk_label *lp, BOOL print));
85 LOCAL	void	lerror			__PR((struct dk_label *lp, char *name));
86 LOCAL	void	tty_insert		__PR((char *s));
87 LOCAL	long	getprevpart		__PR((void));
88 LOCAL	long	getnextpart		__PR((void));
89 EXPORT	BOOL	cvt_cyls		__PR((char *linep, long *lp, long mini, long maxi, struct disk *dp));
90 EXPORT	BOOL	cvt_bcyls		__PR((char *linep, long *lp, long mini, long maxi, struct disk *dp));
91 
92 #ifdef	SVR4
93 struct strval	vtags[] = {
94 	{	V_UNASSIGNED,	"unassigned",	"" },
95 	{	V_BOOT,		"boot",		"" },
96 	{	V_ROOT,		"root",		"" },
97 	{	V_SWAP,		"swap",		"" },
98 	{	V_USR,		"usr",		"" },
99 	{	V_BACKUP,	"backup",	"" },
100 	{	V_STAND,	"stand",	"(used for opt)" },
101 	{	V_VAR,		"var",		"" },
102 	{	V_HOME,		"home",		"" },
103 	{ 0 }
104 };
105 
106 struct strval	vflags[] = {
107 	{ 0,			"wm",	"read-write, mountable" },
108 	{ V_UNMNT,		"wu",	"read-write, unmountable" },
109 	{ V_RONLY,		"rm",	"read-only, mountable" },
110 	{ V_RONLY|V_UNMNT,	"ru",	"read-only, unmountable" },
111 	{ 0 }
112 };
113 
114 struct dk_map2	default_vtmap[NDKMAP] = {
115 	{	V_ROOT,		0	},	/* a == 0 */
116 	{	V_SWAP,		V_UNMNT	},	/* b == 1 */
117 	{	V_BACKUP,	V_UNMNT	},	/* c == 2 */
118 	{	V_UNASSIGNED,	0	},	/* d == 3 */
119 	{	V_UNASSIGNED,	0	},	/* e == 4 */
120 	{	V_UNASSIGNED,	0	},	/* f == 5 */
121 	{	V_USR,		0	},	/* g == 6 */
122 	{	V_UNASSIGNED,	0	},	/* h == 7 */
123 };
124 
125 EXPORT void
set_default_vtmap(lp)126 set_default_vtmap(lp)
127 	register struct dk_label *lp;
128 {
129 	register int i;
130 
131 	lp->dkl_vtoc.v_version = V_VERSION;
132 	lp->dkl_vtoc.v_nparts = NDKMAP;
133 	lp->dkl_vtoc.v_sanity = VTOC_SANE;
134 
135 	for (i = 0; i < NDKMAP; i++) {
136 		lp->dkl_vtoc.v_part[i].p_tag = default_vtmap[i].p_tag;
137 		lp->dkl_vtoc.v_part[i].p_flag = default_vtmap[i].p_flag;
138 
139 	}
140 }
141 #else
142 /*
143  * dummies for SunOS 4.x
144  * to allow the interpratation of a unique database for
145  * SunOS 4.x and Solaris 2.x
146  */
147 struct strval	vtags[] = {
148 	{	0,	"unassigned",	"" },
149 	{	0,	"boot",		"" },
150 	{	0,	"root",		"" },
151 	{	0,	"swap",		"" },
152 	{	0,	"usr",		"" },
153 	{	0,	"backup",	"" },
154 	{	0,	"stand",	"" },
155 	{	0,	"var",		"" },
156 	{	0,	"home",		"" },
157 	{ 0 }
158 };
159 
160 struct strval	vflags[] = {
161 	{ 0,	"wm",	"" },
162 	{ 0,	"wu",	"" },
163 	{ 0,	"rm",	"" },
164 	{ 0,	"ru",	"" },
165 	{ 0 }
166 };
167 
168 /* ARGSUSED */
169 EXPORT void
set_default_vtmap(lp)170 set_default_vtmap(lp)
171 	register struct dk_label *lp;
172 {
173 }
174 #endif
175 
176 EXPORT unsigned short
do_cksum(l)177 do_cksum(l)
178 	register struct dk_label *l;
179 {
180 	register short	*sp;
181 	register short	sum = 0;
182 	register short	count = (sizeof (struct dk_label)/sizeof (short)) - 1;
183 
184 	sp = (short *)l;
185 	while (count--)  {
186 		sum ^= *sp++;
187 	}
188 	return (sum);
189 }
190 
191 EXPORT BOOL
check_vtmap(lp,set)192 check_vtmap(lp, set)
193 	register struct dk_label *lp;
194 		BOOL		set;
195 {
196 	int	ret = TRUE;
197 
198 #ifdef	SVR4
199 	if (lp->dkl_vtoc.v_version != V_VERSION) {
200 		unsigned short sum = do_cksum(lp);
201 
202 		ret = FALSE;
203 		if (set) {
204 			printf("Assigning default vtoc map to label.\n");
205 			set_default_vtmap(lp);
206 			if (sum == lp->dkl_cksum)
207 				lp->dkl_cksum =	do_cksum(lp);
208 		} else {
209 			printf("WARNING: no vtoc map in label.\n");
210 		}
211 	}
212 #endif
213 	return (ret);
214 }
215 
216 EXPORT void
setlabel_from_val(scgp,dp,lp)217 setlabel_from_val(scgp, dp, lp)
218 	SCSI			*scgp;
219 	struct disk		*dp;
220 	register struct dk_label *lp;
221 {
222 	if (lp->dkl_magic != DKL_MAGIC)
223 		fillbytes((caddr_t)lp, sizeof (*lp), '\0');
224 
225 	getasciilabel(lp);
226 
227 	lp->dkl_rpm = dp->rpm;
228 
229 	/*
230 	 * XXX
231 	 * Alternates pro Zylinder sind von SUN noch nicht vollst�ndig
232 	 * implementiert. Es ist noch nicht klar, wie
233 	 */
234 /*	lp->dkl_apc = dp->nhead * dp->aspz / dp->tpz;*/
235 	lp->dkl_apc = 0;
236 	if (dp->gap1 < 0)		/* Hack fuer label.c */
237 		dp->gap1 = 0;
238 	if (dp->gap2 < 0)		/* Hack fuer label.c */
239 		dp->gap2 = 0;
240 	lp->dkl_gap1 = dp->gap1;
241 	lp->dkl_gap2 = dp->gap2;
242 	if (dp->interleave < 0)	/* Hack fuer label.c */
243 		dp->interleave = 1;
244 	lp->dkl_intrlv = dp->interleave;
245 	if (lp->dkl_intrlv == 0)	/* Hack fuer Sony */
246 		lp->dkl_intrlv = 1;
247 	if (dp->lncyl <= 0)	/* XXX kann spaeter weg */
248 		raisecond("setlabel_from_val: lncyl", 0L);
249 	if (dp->lpcyl <= 0 || dp->lpcyl > 0xFFFE)
250 		get_lgeom_defaults(scgp, dp);
251 	lp->dkl_ncyl = dp->lncyl;
252 	lp->dkl_acyl = dp->lacyl;
253 	lp->dkl_pcyl = dp->lpcyl;
254 	lp->dkl_nhead = dp->lhead;
255 	lp->dkl_nsect = dp->lspt;
256 	lp->dkl_bhead = 0;	/* Kopf auf dem das Label steht */
257 	lp->dkl_ppart = 0;	/* Nummer der physikalischen Partition */
258 
259 	setasciilabel(lp, labelbuf);
260 
261 	if (dp->labelread < 0) {
262 		printf("Setting part '%c' to calculated values.\n", PARTOFF+2);
263 		lp->dkl_map[2].dkl_nblk =
264 			lp->dkl_ncyl * lp->dkl_nhead * lp->dkl_nsect;
265 		lp->dkl_map[2].dkl_cylno = 0;
266 	}
267 
268 	lp->dkl_magic = DKL_MAGIC;
269 	lp->dkl_cksum =	do_cksum(lp);
270 }
271 
272 EXPORT void
makelabel(scgp,dp,lp)273 makelabel(scgp, dp, lp)
274 	SCSI			*scgp;
275 	struct disk		*dp;
276 	register struct dk_label *lp;
277 {
278 	char	lbuf[80];
279 
280 	setlabel_from_val(scgp, dp, lp);
281 
282 	if (yes("Label: <%s> change ? ", labelbuf)) {
283 		printf("Enter disk label: "); flush();
284 		tty_insert(labelbuf);
285 		(void) getline(lbuf, sizeof (lbuf));
286 		strcpy(labelbuf, lbuf);
287 	}
288 	setasciilabel(lp, labelbuf);
289 
290 #ifdef	SVR4
291 	strncpy(lbuf, lp->dkl_vtoc.v_volume, LEN_DKL_VVOL);
292 	lbuf[LEN_DKL_VVOL] = '\0';
293 	if (yes("Volume Name: <%s> change ? ", lbuf)) {
294 		printf("Enter volume name: "); flush();
295 		tty_insert(lbuf);
296 		(void) getline(lbuf, LEN_DKL_VVOL+1);
297 		strncpy(lp->dkl_vtoc.v_volume, lbuf, LEN_DKL_VVOL);
298 	}
299 #endif
300 
301 	if (yes("Change partition table? ")) {
302 		register int	i;
303 
304 		for (i = 0; i < 8; i++) {
305 			printpart(lp, i);
306 			if (yes("Change ? "))
307 				chpart(dp, lp, i);
308 		}
309 	}
310 
311 	lp->dkl_magic = DKL_MAGIC;
312 	lp->dkl_cksum =	do_cksum(lp);
313 }
314 
315 LOCAL struct dk_label	*cur_lp;	/* for cvt_cyls() */
316 LOCAL long		cur_part;	/* for cvt_cyls() */
317 
318 LOCAL void
chpart(dp,lp,idx)319 chpart(dp, lp, idx)
320 	struct disk		*dp;
321 	register struct dk_label *lp;
322 	register int		idx;
323 {
324 	long	l;
325 	long	maxsect = lp->dkl_ncyl * lp->dkl_nhead * lp->dkl_nsect;
326 
327 	do {
328 top:
329 		printf("Partition %c\n", idx+PARTOFF);
330 
331 #ifdef	SVR4
332 		lp->dkl_vtoc.v_version = V_VERSION;
333 		lp->dkl_vtoc.v_nparts = NDKMAP;
334 		lp->dkl_vtoc.v_sanity = VTOC_SANE;
335 
336 		l = lp->dkl_vtoc.v_part[idx].p_tag;
337 		getstrval("Enter partition id Tag", &l, vtags, 0);
338 		lp->dkl_vtoc.v_part[idx].p_tag = l;
339 		l = lp->dkl_vtoc.v_part[idx].p_flag;
340 		getstrval("Enter partition permission Flags", &l, vflags, 0);
341 		lp->dkl_vtoc.v_part[idx].p_flag = l;
342 #endif
343 
344 		cur_lp = lp;
345 		cur_part = idx;
346 		l = lp->dkl_map[idx].dkl_cylno;
347 		getdiskcyls("Enter starting cylinder",
348 				&l, 0L, (long)lp->dkl_ncyl);
349 		lp->dkl_map[idx].dkl_cylno = l;
350 
351 		l = lp->dkl_map[idx].dkl_nblk;
352 		getdiskblocks("Enter number of blocks",
353 				&l, 0L,
354 		    (long)(maxsect -
355 		    (lp->dkl_map[idx].dkl_cylno*lp->dkl_nhead*lp->dkl_nsect)),
356 				dp);
357 		lp->dkl_map[idx].dkl_nblk = l;
358 
359 
360 		if (lp->dkl_map[idx].dkl_nblk %
361 					(long)(lp->dkl_nhead*lp->dkl_nsect))
362 			printf("Not on a cylidner boundary!!!\n");
363 
364 		if (lp->dkl_map[idx].dkl_cylno*
365 				(long)(lp->dkl_nhead*lp->dkl_nsect) +
366 						lp->dkl_map[idx].dkl_nblk >
367 						maxsect) {
368 			printf("Partition exceeds end of disk.\n");
369 			goto top;
370 		}
371 		printpart(lp, idx);
372 	} while (!yes("Ok ? "));
373 }
374 
375 #ifdef	SVR4
376 LOCAL int
prvttab(f,lp,i,n)377 prvttab(f, lp, i, n)
378 	register FILE	*f;
379 	register struct dk_label *lp;
380 	int	i;
381 	int	n;
382 {
383 	struct strval	*sp;
384 
385 	if (lp->dkl_vtoc.v_part[i].p_tag != default_vtmap[i].p_tag) {
386 		if ((sp = strval(lp->dkl_vtoc.v_part[i].p_tag, vtags)) != 0) {
387 			fprintf(f, "%s, ", sp->s_name);
388 			if (n % 4)
389 				n++;
390 		}
391 	}
392 	if (lp->dkl_vtoc.v_part[i].p_flag != default_vtmap[i].p_flag) {
393 		if ((sp = strval(lp->dkl_vtoc.v_part[i].p_flag, vflags)) != 0) {
394 			fprintf(f, "%s, ", sp-> s_name);
395 			if (n % 4)
396 				n++;
397 		}
398 	}
399 	return (n);
400 }
401 #endif
402 
403 EXPORT void
prpartab(f,disk_type,lp)404 prpartab(f, disk_type, lp)
405 	register FILE	*f;
406 	char		*disk_type;
407 	register struct dk_label *lp;
408 {
409 	register int	i;
410 	register int	n = 0;
411 
412 	getasciilabel(lp);
413 	fprintf(f, "partition = \"%s\"\n", labelbuf);
414 	fprintf(f, "\tdisk = \"%s\"\n\t", disk_type);
415 #ifdef	nono
416 /*	fprintf(f, "lrpm = %d : ", lp->dkl_rpm);*/
417 	fprintf(f, "pcyl:       %d\n", lp->dkl_pcyl);
418 	fprintf(f, "apc:        %d\n", lp->dkl_apc);
419 	fprintf(f, "gap1:       %d\n", lp->dkl_gap1);
420 	fprintf(f, "gap2:       %d\n", lp->dkl_gap2);
421 	fprintf(f, "interleave: %d\n", lp->dkl_intrlv);
422 #endif
423 	if (f == stdout) {
424 		/*
425 		 * We don't want this to appear in the database.
426 		 */
427 		fprintf(f, "lpcyl = %d : ", lp->dkl_pcyl);
428 	}
429 
430 	fprintf(f, "lncyl = %d : ", lp->dkl_ncyl);
431 	fprintf(f, "lacyl = %d : ", lp->dkl_acyl);
432 	fprintf(f, "lhead = %d : ", lp->dkl_nhead);
433 	fprintf(f, "lspt = %d : ", lp->dkl_nsect);
434 #ifdef	nono
435 	fprintf(f, "bhead:      %d\n", lp->dkl_bhead);
436 	fprintf(f, "ppart:      %d\n", lp->dkl_ppart);
437 #endif
438 
439 	for (i = 0; i < NDKMAP; i++) {
440 		if (lp->dkl_map[i].dkl_nblk) {
441 
442 			if (n++ % 4 == 0)
443 				fprintf(f, "\n\t");
444 			else
445 				fprintf(f, " : ");
446 			fprintf(f, "%c = ", i + PARTOFF);
447 #ifdef	SVR4
448 			n = prvttab(f, lp, i, n);
449 #endif
450 			fprintf(f, "%ld, %ld",
451 					(long)lp->dkl_map[i].dkl_cylno,
452 					(long)lp->dkl_map[i].dkl_nblk);
453 		}
454 	}
455 	fprintf(f, "\n");
456 }
457 
458 EXPORT void
printlabel(lp)459 printlabel(lp)
460 	register struct dk_label *lp;
461 {
462 	printf("label:      <%s>\n", lp->dkl_asciilabel);
463 #ifdef	SVR4
464 	printf("volname:    '%.8s'\n", lp->dkl_vtoc.v_volume);
465 #endif
466 	printf("rpm:        %d\n", lp->dkl_rpm);
467 	printf("pcyl:       %d\n", lp->dkl_pcyl);
468 	printf("apc:        %d\n", lp->dkl_apc);
469 	if ((short)lp->dkl_gap1 > 0 || (short)lp->dkl_gap2 > 0) {
470 		printf("gap1:       %d\n", lp->dkl_gap1);
471 		printf("gap2:       %d\n", lp->dkl_gap2);
472 	}
473 	printf("interleave: %d\n", lp->dkl_intrlv);
474 	printf("ncyl:       %d\n", lp->dkl_ncyl);
475 	printf("acyl:       %d\n", lp->dkl_acyl);
476 	printf("nhead:      %d\n", lp->dkl_nhead);
477 	printf("nsect:      %d\n", lp->dkl_nsect);
478 	if (lp->dkl_bhead || lp->dkl_ppart) {
479 		printf("bhead:      %d\n", lp->dkl_bhead);
480 		printf("ppart:      %d\n", lp->dkl_ppart);
481 	}
482 
483 	if (lp->dkl_nhead == 0 || lp->dkl_nsect == 0)
484 		printf("ILLEGAL GEOMETRY\n");
485 	else
486 		printparts(lp);
487 
488 	if (lp->dkl_magic != DKL_MAGIC)
489 		printf("WRONG MAGIC: 0x%X\n", lp->dkl_magic);
490 
491 	printf("Checksum: 0x%X", lp->dkl_cksum);
492 	if (lp->dkl_cksum != do_cksum(lp))
493 		printf(" (should be 0x%X)", do_cksum(lp));
494 	printf("\n");
495 }
496 
497 LOCAL void
printparthead()498 printparthead()
499 {
500 /*
501  *              0       root 00     0 -   34        0    49595     24.22MB (35)
502  */
503 #ifdef	SVR4
504 	printf("Part     Tag Flag  Cylinders Startsec # of Sec      Size    Blocks\n");
505 #else
506 	printf("Part Cylinders Startsec # of Sec      Size    Blocks\n");
507 #endif
508 }
509 
510 EXPORT void
printpart(lp,i)511 printpart(lp, i)
512 	struct dk_label *lp;
513 	int	i;
514 {
515 	printparthead();
516 	_printpart(lp, i);
517 }
518 
519 LOCAL void
_printpart(lp,i)520 _printpart(lp, i)
521 	register struct dk_label *lp;
522 	register int	i;
523 {
524 	register long	a;
525 #ifdef	SVR4
526 	struct strval	*sp;
527 	char		*tag = "ILLEGAL";
528 	char		*flag = "XX";
529 #endif
530 
531 	a = (lp->dkl_map[i].dkl_nblk-1)/(long)(lp->dkl_nhead*lp->dkl_nsect);
532 	a += lp->dkl_map[i].dkl_cylno;
533 	if (lp->dkl_map[i].dkl_nblk == 0)
534 		a = 0;
535 
536 #ifdef	SVR4
537 	sp = strval(lp->dkl_vtoc.v_part[i].p_tag, vtags);
538 	if (sp)
539 		tag = sp->s_name;
540 	sp = strval(lp->dkl_vtoc.v_part[i].p_flag, vflags);
541 	if (sp)
542 		flag = sp->s_name;
543 
544 	/*
545 	 * Ugly, but Linux incude files violate POSIX and #define printf
546 	 * so we cannot include the #ifdef into the printf() arg list.
547 	 */
548 #	define	__PARTARGS1	(i + PARTOFF), tag, flag
549 #	define	__PARTFMT	"%c %10s %2s %5ld -%5ld %8ld %8ld %6ld.%02ldMB ("
550 #else
551 #	define	__PARTARGS1	(i + PARTOFF)
552 #	define	__PARTFMT	"%c %5ld -%5ld %8ld %8ld %6ld.%02ldMB ("
553 #endif
554 	printf(__PARTFMT,
555 			__PARTARGS1,
556 			(long)lp->dkl_map[i].dkl_cylno, a,
557 			(long)lp->dkl_map[i].dkl_cylno*lp->dkl_nsect*lp->dkl_nhead,
558 			(long)lp->dkl_map[i].dkl_nblk,
559 			(long)lp->dkl_map[i].dkl_nblk/(2*1024),
560 			(long)(lp->dkl_map[i].dkl_nblk%(2*1024))*100/(2*1024));
561 	a = lp->dkl_map[i].dkl_nblk/(long)(lp->dkl_nhead*lp->dkl_nsect);
562 	printf("%ld", a);
563 	a = lp->dkl_map[i].dkl_nblk%(long)(lp->dkl_nhead*lp->dkl_nsect);
564 	printf("/%ld/%ld",
565 			a / (long)lp->dkl_nsect,
566 			a % (long)lp->dkl_nsect);
567 	printf(")\n");
568 }
569 
570 EXPORT void
printparts(lp)571 printparts(lp)
572 	register struct dk_label *lp;
573 {
574 	register int	i;
575 
576 	printparthead();
577 	for (i = 0; i < NDKMAP; i++) {
578 		if (lp->dkl_map[i].dkl_nblk)
579 			_printpart(lp, i);
580 	}
581 }
582 
583 EXPORT int
readlabel(name,lp)584 readlabel(name, lp)
585 	char	*name;
586 	register struct dk_label *lp;
587 {
588 	int	f;
589 
590 	if ((f = open(name, O_RDONLY|O_NDELAY)) < 0) {
591 		errmsg("Cannot open prototype '%s'\n", name);
592 		return (0);
593 	}
594 	if (read(f, (char *)lp, sizeof (*lp)) != sizeof (*lp)) {
595 		errmsg("Cannot read prototype '%s'\n", name);
596 		close(f);
597 		return (0);
598 	}
599 	close(f);
600 	return (1);
601 }
602 
603 /*
604  * This function is only used by the stand-alone 'label' program.
605  */
606 EXPORT void
writelabel(name,lp)607 writelabel(name, lp)
608 	char	*name;
609 	register struct dk_label *lp;
610 {
611 	register int	f;
612 	struct dk_allmap	map;
613 
614 	if ((f = open(name, O_CREAT|O_WRONLY|O_NDELAY, (mode_t)0666)) < 0)
615 		comerr("Cannot create '%s'\n", name);
616 	if (write(f, (char *)lp, sizeof (*lp)) < 0)
617 		errmsg("Cannot write '%s'\n", name);
618 
619 #ifdef	HAVE_IOCTL
620 	if (ioctl(f, DKIOCGAPART, &map) >= 0) {
621 		/*
622 		 * It seemes to be a disk!
623 		 */
624 		writebackuplabel(f, lp);
625 		if (ioctl(f, DKIOCSAPART,
626 				(struct dk_allmap *)&lp->dkl_map[0]) < 0)
627 			comerr("Cannot set partitions.\n");
628 		(void) setgeom(f, lp);
629 	}
630 #endif
631 	close(f);
632 	exit(0);
633 }
634 
635 LOCAL void
writebackuplabel(f,lp)636 writebackuplabel(f, lp)
637 	int	f;
638 	register struct dk_label *lp;
639 {
640 	struct dk_allmap	map;
641 		long	backup_label_blk;
642 		int	i;
643 
644 	backup_label_blk = lp->dkl_ncyl + lp->dkl_acyl - 1;
645 	backup_label_blk *= lp->dkl_nhead * lp->dkl_nsect;
646 	backup_label_blk += (lp->dkl_nhead-1) * lp->dkl_nsect;
647 
648 #ifdef	HAVE_IOCTL
649 	ioctl(f, DKIOCGAPART, &map);
650 	/*
651 	 * If he's not using partition '2' (the whole disk)
652 	 * he will fail later on.
653 	 */
654 	map.dka_map[2].dkl_cylno = 0;
655 	map.dka_map[2].dkl_nblk = backup_label_blk + 10;
656 
657 	if (ioctl(f, DKIOCSAPART, &map) >= 0) {
658 		for (i = 1; i < 10; i += 2) {
659 			if (lseek(f, (off_t)(512*(backup_label_blk + i)),
660 								SEEK_SET) < 0) {
661 				errmsg("Seek error for backup label\n");
662 				continue;
663 			}
664 			if (write(f, (char *)lp, sizeof (*lp)) < 0)
665 				errmsg("Cannot write backup label\n");
666 		}
667 	}
668 #endif
669 }
670 
671 EXPORT int
setlabel(name,lp)672 setlabel(name, lp)
673 	char	*name;
674 	register struct dk_label *lp;
675 {
676 	register int	f;
677 	int		err;
678 	struct dk_allmap	map;
679 
680 	if ((f = open(name, O_RDONLY|O_NDELAY)) < 0) {
681 		err = geterrno();
682 		errmsgno(err, "Cannot open '%s'\n", name);
683 		return (err);
684 	}
685 
686 #ifdef	HAVE_IOCTL
687 	if (ioctl(f, DKIOCGAPART, &map) < 0) {
688 		err = geterrno();
689 		errmsgno(err, "Cannot get partitions from '%s'.\n", name);
690 		close(f);
691 		return (err);
692 	}
693 
694 	if (ioctl(f, DKIOCSAPART, (struct dk_allmap *)&lp->dkl_map[0]) < 0) {
695 		err = geterrno();
696 		errmsgno(err, "Cannot set partitions on '%s'.\n", name);
697 		close(f);
698 		return (err);
699 	}
700 #endif
701 	err = setgeom(f, lp);
702 	close(f);
703 	return (err);
704 }
705 
706 LOCAL int
setgeom(f,lp)707 setgeom(f, lp)
708 	int	f;
709 	register struct dk_label *lp;
710 {
711 	struct dk_geom geom;
712 	register struct dk_geom *gp;
713 
714 	gp = &geom;
715 
716 	gp->dkg_ncyl = lp->dkl_ncyl;
717 	gp->dkg_acyl = lp->dkl_acyl;
718 /*	gp->dkg_bcyl = lp->dkl_bcyl;*/
719 	gp->dkg_bcyl = 0;
720 	gp->dkg_nhead = lp->dkl_nhead;
721 	gp->dkg_bhead = lp->dkl_bhead;
722 	gp->dkg_nsect = lp->dkl_nsect;
723 	gp->dkg_intrlv = lp->dkl_intrlv;
724 	gp->dkg_gap1 = lp->dkl_gap1;
725 	gp->dkg_gap2 = lp->dkl_gap2;
726 	gp->dkg_apc = lp->dkl_apc;
727 	gp->dkg_rpm = lp->dkl_rpm;
728 	gp->dkg_pcyl = lp->dkl_pcyl;
729 
730 #ifdef	HAVE_IOCTL
731 	if (ioctl(f, DKIOCSGEOM, gp) < 0) {
732 		int	err = geterrno();
733 
734 		errmsgno(err, "Cannot set geometry\n");
735 		return (err);
736 	}
737 #endif
738 	return (0);
739 }
740 
741 EXPORT char *
getasciilabel(lp)742 getasciilabel(lp)
743 	register struct dk_label *lp;
744 {
745 	register char	*idx;
746 
747 	labelbuf[0] = '\0';
748 	if (lp->dkl_magic != DKL_MAGIC || lp->dkl_cksum != do_cksum(lp))
749 		return ((char *)0);
750 	if ((idx = strstr(lp->dkl_asciilabel, " cyl")) != NULL) {
751 		strncpy(labelbuf, lp->dkl_asciilabel, idx-lp->dkl_asciilabel);
752 		labelbuf[idx - lp->dkl_asciilabel] = '\0';
753 		return (labelbuf);
754 	}
755 	strcpy(labelbuf, lp->dkl_asciilabel);
756 	return (labelbuf);
757 }
758 
759 EXPORT void
setasciilabel(lp,lname)760 setasciilabel(lp, lname)
761 	register struct dk_label *lp;
762 	char	*lname;
763 {
764 	char	lbuf[150];
765 
766 	sprintf(lbuf, "%.80s cyl %d alt %d hd %d sec %d",
767 			lname,
768 			lp->dkl_ncyl, lp->dkl_acyl,
769 			lp->dkl_nhead, lp->dkl_nsect);
770 	sprintf(lp->dkl_asciilabel, "%.128s", lbuf);
771 }
772 
773 EXPORT BOOL
setval_from_label(dp,lp)774 setval_from_label(dp, lp)
775 	struct disk		*dp;
776 	register struct dk_label *lp;
777 {
778 	if (lp->dkl_magic != DKL_MAGIC || lp->dkl_cksum != do_cksum(lp))
779 		return (FALSE);
780 
781 	getasciilabel(lp);
782 
783 	/*
784 	 * Die nicht direkt der evt. gef�lschten Labelgeometrie zugeordneten
785 	 * Werte d�rfen nicht die schon vorhandenen echten Werte �berschreiben.
786 	 */
787 	if (dp->rpm <= 0 && lp->dkl_rpm != ((unsigned short)-1) &&
788 							lp->dkl_rpm > 0)
789 		dp->rpm = lp->dkl_rpm;
790 
791 	if (dp->pcyl <= 0 && lp->dkl_pcyl != ((unsigned short)-1)) {
792 		if (lp->dkl_pcyl > 0) {
793 			dp->pcyl = lp->dkl_pcyl;
794 		} else {
795 			dp->pcyl = lp->dkl_ncyl + lp->dkl_acyl;
796 			if (dp->atrk >= 0 && dp->nhead > 0)
797 				dp->pcyl += dp->atrk/dp->nhead;
798 			if (dp->int_cyl >= 0)
799 				dp->pcyl += dp->int_cyl;
800 		}
801 		if (dp->lpcyl < 0)
802 			dp->lpcyl = dp->pcyl;
803 	}
804 
805 	if (dp->gap1 < 0 && lp->dkl_gap1 != ((unsigned short)-1))
806 		dp->gap1 = lp->dkl_gap1;
807 	if (dp->gap2 < 0 && lp->dkl_gap1 != ((unsigned short)-1))
808 		dp->gap2 = lp->dkl_gap2;
809 
810 	if (dp->interleave < 0 && lp->dkl_intrlv != ((unsigned short)-1))
811 		dp->interleave = lp->dkl_intrlv;
812 
813 	/*
814 	 * Hier folgen die evt. gef�lschten Werte f�r die Labegeometrie.
815 	 */
816 	dp->lncyl = lp->dkl_ncyl;
817 	dp->lacyl = lp->dkl_acyl;
818 	dp->lhead = lp->dkl_nhead;
819 	dp->lspt = lp->dkl_nsect;
820 	/*
821 	 *XXX
822 	 * Alternates pro Zylinder sind von SUN noch nicht vollst�ndig
823 	 * implementiert. Es ist noch nicht klar, wie
824 	 */
825 /*	dp->aspz = lp->dkl_apc * dp->tpz / lp->dkl_nhead;*/
826 	if (dp->spt < 0)
827 		dp->spt = dp->lspt /*+ lp->dkl_apc / lp->dkl_nhead*/;
828 
829 	if (dp->int_cyl < 0 && dp->nhead > 0) {
830 		dp->int_cyl = dp->pcyl - dp->lncyl
831 					- dp->lacyl
832 					- dp->atrk/dp->nhead;
833 	}
834 	return (TRUE);
835 }
836 
837 EXPORT void
label_null(lp)838 label_null(lp)
839 	register struct dk_label *lp;
840 {
841 	fillbytes((caddr_t)lp, sizeof (*lp), '\0');
842 
843 	lp->dkl_rpm	= -1;	/* rotations per minute */
844 	lp->dkl_pcyl	= -1;	/* # physical cylinders */
845 	lp->dkl_apc	= -1;	/* alternates per cylinder */
846 	lp->dkl_gap1	= -1;	/* used to be gap1 */
847 	lp->dkl_gap2	= -1;	/* used to be gap2 */
848 	lp->dkl_intrlv	= -1;	/* interleave factor */
849 	lp->dkl_ncyl	= -1;	/* # of data cylinders */
850 	lp->dkl_acyl	= -1;	/* # of alternate cylinders */
851 	lp->dkl_nhead	= -1;	/* # of heads in this partition */
852 	lp->dkl_nsect	= -1;	/* # of 512 byte sectors per track */
853 	lp->dkl_bhead	= -1;	/* used to be label head offset */
854 	lp->dkl_ppart	= -1;	/* used to by physical partition */
855 }
856 
857 #define	loff(a)		((size_t)&((struct dk_label *)0)->a)
858 
859 EXPORT int
label_cmp(lp1,lp2)860 label_cmp(lp1, lp2)
861 	register struct dk_label *lp1;
862 	register struct dk_label *lp2;
863 {
864 	int	ret = 0;
865 
866 	/*
867 	 * If Partition differs return (0)
868 	 */
869 	if (cmpbytes(lp1->dkl_map, lp2->dkl_map, sizeof (lp1->dkl_map)) <
870 						sizeof (lp1->dkl_map))
871 		return (0);
872 
873 #ifdef	SVR4
874 	if (cmpbytes(&lp1->dkl_vtoc, &lp2->dkl_vtoc, sizeof (lp1->dkl_vtoc)) >=
875 						sizeof (lp1->dkl_vtoc))
876 		ret++;
877 #endif
878 
879 	if (cmpbytes(lp1->dkl_pad, lp2->dkl_pad,
880 				loff(dkl_map[0]) - loff(dkl_pad[0])) >=
881 				loff(dkl_map[0]) - loff(dkl_pad[0]))
882 		ret++;
883 
884 	if (streql(lp1->dkl_asciilabel, lp2->dkl_asciilabel))
885 		ret++;
886 
887 	return (ret);
888 }
889 
890 EXPORT BOOL
labelgeom_ok(lp,print)891 labelgeom_ok(lp, print)
892 	register struct dk_label *lp;
893 	BOOL	print;
894 {
895 	if (lp->dkl_ncyl == (unsigned short) -1) {
896 		if (print) lerror(lp, "lncyl");
897 		return (FALSE);
898 	}
899 	if (lp->dkl_acyl == (unsigned short) -1) {
900 		if (print) lerror(lp, "lacyl");
901 		return (FALSE);
902 	}
903 	if (lp->dkl_nhead == (unsigned short) -1) {
904 		if (print) lerror(lp, "lnhead");
905 		return (FALSE);
906 	}
907 	if (lp->dkl_nsect == (unsigned short) -1) {
908 		if (print) lerror(lp, "lspt");
909 		return (FALSE);
910 	}
911 	return (TRUE);
912 }
913 
914 LOCAL void
lerror(lp,name)915 lerror(lp, name)
916 	register struct dk_label *lp;
917 	char	*name;
918 {
919 	error("Missing '%s' in label \"%s\".\n", name, getasciilabel(lp));
920 }
921 
922 LOCAL void
tty_insert(s)923 tty_insert(s)
924 	char	*s;
925 {
926 #ifdef	TIOCSTI
927 	while (*s)
928 		ioctl(fdown(stdin), TIOCSTI, s++);
929 #endif
930 }
931 
932 
933 LOCAL long
getprevpart()934 getprevpart()
935 {
936 	long part = cur_part - 1;
937 
938 	/*
939 	 * Look for previous partition that is in use
940 	 * and ends before end of the disk.
941 	 */
942 	while (part > 0 &&
943 			(cur_lp->dkl_map[part].dkl_nblk == 0 ||
944 			(cur_lp->dkl_map[part].dkl_cylno +
945 			(cur_lp->dkl_map[part].dkl_nblk-1) /
946 			(long)(cur_lp->dkl_nhead * cur_lp->dkl_nsect))
947 					>= (long)(cur_lp->dkl_ncyl - 1))) {
948 		part--;
949 	}
950 	return (part);
951 }
952 
953 LOCAL long
getnextpart()954 getnextpart()
955 {
956 	long part = cur_part + 1;
957 
958 	/*
959 	 * Look for next partition that is in use
960 	 * and starts after the beginning of the current partition.
961 	 */
962 	while (part < NDKMAP &&
963 			(cur_lp->dkl_map[part].dkl_nblk == 0 ||
964 			cur_lp->dkl_map[part].dkl_cylno <=
965 			cur_lp->dkl_map[cur_part].dkl_cylno)) {
966 		part++;
967 	}
968 	return (part);
969 }
970 
971 /*---------------------------------------------------------------------------
972 |
973 | Hier wird der Anfang einer Partition festgelegt
974 |
975 +---------------------------------------------------------------------------*/
976 
977 EXPORT BOOL
cvt_cyls(linep,lp,mini,maxi,dp)978 cvt_cyls(linep, lp, mini, maxi, dp)
979 	char		*linep;
980 	long		*lp;
981 	long		mini;
982 	long		maxi;
983 	struct disk	*dp;
984 {
985 	long	l;
986 	long	part	= 0L;
987 	BOOL	doshift	= FALSE;
988 
989 	if (linep[0] == '?') {
990 		printf("To enter cylinders as simple number:\n");
991 		(void) cvt_std(linep, lp, mini, maxi, dp);
992 
993 		printf("To start this partition past the end of a partition:\n");
994 		printf("\tEnter '>' to start past the end of the previous valid partition (%ld).\n",
995 					getprevpart());
996 		printf("\tEnter '>g' to start past the end of partition 'g'.\n");
997 		printf("\tEnter '>5' to start past the end of partition '5'.\n");
998 
999 		printf("To shift this partition to end at the beginning of a partition:\n");
1000 		printf("\tEnter '>>' to shift to the beginning of the next valid partition (%ld).\n",
1001 					getnextpart());
1002 		printf("\tEnter '>>g' to shift to the beginning of partition 'g'.\n");
1003 		printf("\tEnter '>>5' to shift to the beginning of partition '5'.\n");
1004 		printf("\tEnter '>>%d' to shift to the the end of the disk.\n", NDKMAP);
1005 		return (FALSE);
1006 	}
1007 	/*
1008 	 * If line does not begin with '>'
1009 	 * convert as int.
1010 	 */
1011 	if (*linep != '>')
1012 		return (cvt_std(linep, lp, mini, maxi, (void *)0));
1013 
1014 	if (linep[1] == '>') {
1015 		doshift = TRUE;
1016 		linep++;
1017 	}
1018 
1019 	if (*++linep) {
1020 
1021 		/*
1022 		 * It's a > part 'x' end notation.
1023 		 */
1024 		if (strchr("abcdefgh", linep[0]) && linep[1] == '\0')
1025 			part = linep[0] - 'a';
1026 		else
1027 			if (!cvt_std(linep, &part, 0L, NDKMAP, (void *)0))
1028 				return (FALSE);
1029 	} else {
1030 		if (doshift) {
1031 			part = getnextpart();
1032 		} else {
1033 			part = getprevpart();
1034 			if (part < 0) {
1035 				*lp = mini;
1036 				return (TRUE);
1037 			}
1038 		}
1039 	}
1040 	if ((doshift && (part <= 0 || part > NDKMAP)) ||
1041 	    (!doshift && (part < 0 || part >= NDKMAP))) {
1042 		printf("partition '%ld' is out of range.\n", part);
1043 		return (FALSE);
1044 	}
1045 	if (doshift)
1046 		printf("shifting to partition %ld\n", part);
1047 	else
1048 		printf("appending to partition %ld\n", part);
1049 
1050 	if (doshift) {
1051 		if (part == NDKMAP) {
1052 			l =  cur_lp->dkl_ncyl;
1053 		} else {
1054 			l =  cur_lp->dkl_map[part].dkl_cylno;
1055 		}
1056 		/*
1057 		 * Round up to start at prev cylinder
1058 		 */
1059 		l -= (cur_lp->dkl_map[cur_part].dkl_nblk-1) /
1060 			(long)(cur_lp->dkl_nhead * cur_lp->dkl_nsect);
1061 		l -= 1;
1062 	} else {
1063 		/*
1064 		 * Round up to start at next cylinder
1065 		 */
1066 		l =  cur_lp->dkl_map[part].dkl_cylno;
1067 		l += (cur_lp->dkl_map[part].dkl_nblk-1) /
1068 			(long)(cur_lp->dkl_nhead * cur_lp->dkl_nsect);
1069 		l += 1;
1070 	}
1071 
1072 	if (l < mini || l > maxi) {
1073 		printf("'%ld' is out of range.\n", l);
1074 		return (FALSE);
1075 	}
1076 	*lp = l;
1077 	return (TRUE);
1078 }
1079 
1080 /*---------------------------------------------------------------------------
1081 |
1082 | Hier wird das Ende einer Partition festgelegt
1083 |
1084 +---------------------------------------------------------------------------*/
1085 
1086 EXPORT BOOL
cvt_bcyls(linep,lp,mini,maxi,dp)1087 cvt_bcyls(linep, lp, mini, maxi, dp)
1088 	char		*linep;
1089 	long		*lp;
1090 	long		mini;
1091 	long		maxi;
1092 	struct disk	*dp;
1093 {
1094 	long	l;
1095 	long	part	= 0L;
1096 
1097 	if (linep[0] == '?') {
1098 		printf("To fill up this partition to the beginning of a partition:\n");
1099 		printf("\tEnter '>' to fill up to the beginning of the next valid partition (%ld).\n",
1100 					getnextpart());
1101 		printf("\tEnter '>g' to fill up to the beginning of partition 'g'.\n");
1102 		printf("\tEnter '>5' to fill up to the beginning of partition '5'.\n");
1103 		return (FALSE);
1104 	}
1105 	/*
1106 	 * If line does not begin with '>'
1107 	 * convert as int.
1108 	 */
1109 	if (*linep != '>')
1110 		return (cvt_std(linep, lp, mini, maxi, (void *)0));
1111 
1112 	if (*++linep) {
1113 
1114 		/*
1115 		 * It's a > part 'x' end notation.
1116 		 */
1117 		if (strchr("abcdefgh", linep[0]) && linep[1] == '\0')
1118 			part = linep[0] - 'a';
1119 		else
1120 			if (!cvt_std(linep, &part, 0L, NDKMAP, (void *)0))
1121 				return (FALSE);
1122 	} else {
1123 		part = getnextpart();
1124 		if (part >= NDKMAP) {
1125 			*lp = maxi;
1126 			return (TRUE);
1127 		}
1128 	}
1129 	if (part < 0 || part >= NDKMAP) {
1130 		printf("partition '%ld' is out of range.\n", part);
1131 		return (FALSE);
1132 	}
1133 	printf("filling up to partition %ld\n", part);
1134 
1135 	l =  cur_lp->dkl_map[part].dkl_cylno -
1136 			cur_lp->dkl_map[cur_part].dkl_cylno;
1137 
1138 	l *= (long)(cur_lp->dkl_nhead * cur_lp->dkl_nsect);
1139 
1140 	if (l < mini || l > maxi) {
1141 		printf("'%ld' is out of range.\n", l);
1142 		return (FALSE);
1143 	}
1144 	*lp = l;
1145 	return (TRUE);
1146 }
1147