1 /* @(#)check_part.c	1.35 11/08/13 Copyright 1993-2011 J. Schilling */
2 #include <schily/mconfig.h>
3 #ifndef lint
4 static	UConst char sccsid[] =
5 	"@(#)check_part.c	1.35 11/08/13 Copyright 1993-2011 J. Schilling";
6 #endif
7 /*
8  *	Check Partition validity
9  *
10  *	Copyright (c) 1993-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/param.h>	/* Include various defs needed with some OS */
28 #include <schily/standard.h>
29 #include <schily/schily.h>
30 #include <schily/ioctl.h>
31 #include <schily/fcntl.h>
32 #ifdef	HAVE_SYS_FILE_H
33 #include <sys/file.h>
34 #endif
35 #include "dsklabel.h"
36 #include <schily/float.h>
37 
38 #include "fmt.h"
39 
40 #include <scg/scsireg.h>
41 
42 typedef struct chk_label {
43 	int	part_chk;
44 } CHK_LABEL;
45 
46 #define	ADJACENT_START		0x0001	/* Ansto�ender Start */
47 #define	ADJACENT_END		0x0002	/* Ansto�endes Ende */
48 #define	SAME_START		0x0004	/* Start gemeinsam mit anderer part */
49 #define	SAME_END		0x0008	/* Ende gemeinsam mit anderer part */
50 #define	UNALIGNED_START		0x0010	/* Einsamer Start */
51 #define	UNALIGNED_END		0x0020	/* Einsames Ende */
52 #define	SPACE_BEFORE_START	0x0040	/* Ungenutzter Raum vor part */
53 #define	SPACE_AFTER_END		0x0080	/* Ungenutzter Raum nach part */
54 #define	PART_C_CONV_ERR		0x0100	/* Part 'c'/2 nicht nach convention */
55 #define	PART_RANGE_ERR		0x1000	/* Start < 0 */
56 #define	PART_TO_BIG		0x2000	/* Ende nach lncyl */
57 
58 #define	WARNING			0x0FF0	/* Maske f�r nicht fatale Fehler */
59 #define	DANGER			0xF000	/* Maske f�r fatale Fehler */
60 
61 /*
62  * A C H T U N G  !!!
63  *
64  * Mit diesen Makros geht es nur bis 1 TByte groszen Platten gut.
65  */
66 #define	SPCYL			((long)(lp->dkl_nhead * lp->dkl_nsect))
67 #define	START(x)		(lp->dkl_map[x].dkl_cylno * SPCYL)
68 #define	END(x)			(lp->dkl_map[x].dkl_cylno * SPCYL + \
69 						lp->dkl_map[x].dkl_nblk)
70 
71 extern	struct	dk_label *d_label;
72 
73 LOCAL	void	check_start	__PR((struct dk_label *, int));
74 LOCAL	void	check_end	__PR((struct dk_label *, int));
75 LOCAL	void	check_bounds	__PR((struct dk_label *, int));
76 LOCAL	void	init_result	__PR((void));
77 LOCAL	void	set_bounds	__PR((struct dk_label *, long *, long *));
78 LOCAL	void	analyse_parts	__PR((struct dk_label *));
79 EXPORT	void	checklabel	__PR((struct disk *, struct dk_label *, int));
80 LOCAL	void	check_partc	__PR((struct disk *, struct dk_label *, int));
81 LOCAL	char	get_startc	__PR((int));
82 LOCAL	char	get_endc	__PR((int));
83 LOCAL	void	graph		__PR((struct dk_label *, long, long));
84 LOCAL	void	print_lwarn	__PR((void));
85 
86 CHK_LABEL	result[8];
87 
88 LOCAL void
check_start(lp,n)89 check_start(lp, n)
90 	register struct dk_label *lp;
91 	int	n;
92 {
93 	int	i;
94 
95 	/*
96 	 * Partition beginnt nicht gemeinsam mit einer anderen Partition
97 	 * Partition beginnt nicht direkt hinter einer anderen Partition
98 	 * Partition beginnt nicht am Anfang der Platte
99 	 */
100 	if (!(result[n].part_chk & ADJACENT_START) && (START(n) > 0)) {
101 		result[n].part_chk |= UNALIGNED_START;
102 
103 		for (i = 0; i < 8; i++) {
104 			if (lp->dkl_map[i].dkl_nblk <= 0) /*XXX <= ??? sd.c */
105 				continue;
106 
107 			if (i == n || (result[i].part_chk & DANGER))
108 				continue;
109 
110 			if (START(n) > START(i)) {
111 				result[n].part_chk &= ~SPACE_BEFORE_START;
112 				break;
113 			}
114 			result[n].part_chk |= SPACE_BEFORE_START;
115 		}
116 	}
117 }
118 
119 LOCAL void
check_end(lp,n)120 check_end(lp, n)
121 	register struct dk_label *lp;
122 	int	n;
123 {
124 	int	i;
125 
126 	/*
127 	 * Partition endet nicht gemeinsam mit einer anderen Partition
128 	 * Partition endet nicht direkt vor einer anderen Partition
129 	 * Partition endet nicht auf dem g�ltigen Ende
130 	 */
131 	if (!(result[n].part_chk & ADJACENT_END) &&
132 				(END(n) < (long)(lp->dkl_ncyl*SPCYL))) {
133 		result[n].part_chk |= UNALIGNED_END;
134 
135 		for (i = 0; i < 8; i++) {
136 			if (lp->dkl_map[i].dkl_nblk <= 0) /*XXX <= ??? sd.c */
137 				continue;
138 
139 			if (i == n || (result[i].part_chk & DANGER))
140 				continue;
141 
142 			if (END(n) < END(i)) {
143 				result[n].part_chk &= ~SPACE_AFTER_END;
144 				break;
145 			}
146 			result[n].part_chk |= SPACE_AFTER_END;
147 		}
148 	}
149 }
150 
151 LOCAL void
check_bounds(lp,n)152 check_bounds(lp, n)
153 	register struct dk_label	*lp;
154 			int		n;
155 {
156 	int	i;
157 	long	spcyl = SPCYL;
158 
159 	/*
160 	 * Avoid divide by zero!
161 	 */
162 	if (spcyl == 0)
163 		spcyl = 1;
164 
165 	if (START(n) < 0)
166 		result[n].part_chk |= PART_RANGE_ERR;
167 	if ((long)lp->dkl_ncyl < (END(n) / spcyl))
168 		result[n].part_chk |= PART_TO_BIG;
169 
170 	for (i = 0; i < 8; i++) {
171 		if (lp->dkl_map[i].dkl_nblk <= 0) /*XXX <= ??? sd.c */
172 			continue;
173 
174 		if (i == n)
175 			continue;
176 
177 		if (START(n) == END(i))
178 			result[n].part_chk |= ADJACENT_START;
179 		if (END(n) == START(i))
180 			result[n].part_chk |= ADJACENT_END;
181 		if (START(n) == START(i))
182 			result[n].part_chk |= SAME_START;
183 		if (END(n) == END(i))
184 			result[n].part_chk |= SAME_END;
185 	}
186 }
187 
188 LOCAL void
init_result()189 init_result()
190 {
191 	int	i;
192 
193 	for (i = 0; i < 8; i++)
194 		result[i].part_chk = 0;
195 }
196 
197 LOCAL void
set_bounds(lp,low,high)198 set_bounds(lp, low, high)
199 	register struct dk_label *lp;
200 	long	*low,
201 		*high;
202 {
203 	int	i;
204 
205 	for (i = 0; i < 8; i++) {
206 		if (lp->dkl_map[i].dkl_nblk <= 0)	/*XXX <= ??? sd.c */
207 			continue;
208 
209 		if (*low > START(i) && START(i) >= 0)
210 			*low = START(i);
211 		if (*high < END(i) && END(i) <= ((long)lp->dkl_ncyl*SPCYL))
212 			*high = END(i);
213 	}
214 }
215 
216 LOCAL void
analyse_parts(lp)217 analyse_parts(lp)
218 	register struct dk_label *lp;
219 {
220 	int	i;
221 
222 	for (i = 0; i < 8; i++) {
223 		check_bounds(lp, i);
224 		check_start(lp, i);
225 		check_end(lp, i);
226 	}
227 }
228 
229 LOCAL void
check_partc(dp,lp,set)230 check_partc(dp, lp, set)
231 	struct disk	*dp;
232 	register struct dk_label *lp;
233 	int	set;
234 {
235 	if (dp->labelread >= 0 &&
236 			lp->dkl_map[2].dkl_cylno == 0 &&
237 			(lp->dkl_ncyl * SPCYL == lp->dkl_map[2].dkl_nblk))
238 		return;
239 	/*
240 	 * Label wurde nicht gelesen, part 'c'/2 beginnt nicht auf 0,
241 	 * oder part 'c'/2 ist nicht dkl_ncyl gro�.
242 	 */
243 
244 	if (dp->labelread >= 0) {
245 		/*
246 		 * Part 'c'/2 convention error.
247 		 */
248 		struct dk_label l;
249 
250 		l = *lp;
251 		l.dkl_map[2].dkl_cylno = 0;
252 		l.dkl_map[2].dkl_nblk = lp->dkl_ncyl * SPCYL;
253 
254 		printf("WARNING! \ncalculated part '%c':\n", PARTOFF+2);
255 		printpart(&l, 2);
256 		printf("current part '%c':\n", PARTOFF+2);
257 		printpart(lp, 2);
258 		result[2].part_chk |= PART_C_CONV_ERR;
259 	}
260 	if (!set)
261 		return;
262 
263 	if (dp->labelread < 0 || yes("set to calculated value? ")) {
264 		lp->dkl_map[2].dkl_cylno = 0;
265 		lp->dkl_map[2].dkl_nblk = lp->dkl_ncyl * SPCYL;
266 		lp->dkl_magic = DKL_MAGIC;
267 		lp->dkl_cksum =	do_cksum(lp);
268 		result[2].part_chk &= ~PART_C_CONV_ERR;
269 	}
270 }
271 
272 EXPORT void
checklabel(dp,lp,set)273 checklabel(dp, lp, set)
274 	struct disk	*dp;
275 	register struct dk_label *lp;
276 	int	set;
277 {
278 	long		low;
279 	long		high;
280 
281 	low  = lp->dkl_ncyl*SPCYL;
282 	high = 0;
283 
284 	init_result();
285 	check_partc(dp, lp, set);
286 	set_bounds(lp, &low, &high);
287 	analyse_parts(lp);
288 	graph(lp, low, high);
289 	print_lwarn();
290 }
291 
292 LOCAL char
get_startc(n)293 get_startc(n)
294 	int	n;
295 {
296 	if (result[n].part_chk & PART_RANGE_ERR)
297 		return ('X');
298 	if (result[n].part_chk & ADJACENT_START)
299 		return ('/');
300 	if (result[n].part_chk & SAME_START)
301 		return ('+');
302 	if (result[n].part_chk & UNALIGNED_START)
303 		return ('<');
304 	return ('*');
305 }
306 
307 LOCAL char
get_endc(n)308 get_endc(n)
309 	int	n;
310 {
311 	if (result[n].part_chk & PART_TO_BIG)
312 		return ('X');
313 	if (result[n].part_chk & ADJACENT_END)
314 		return ('/');
315 	if (result[n].part_chk & SAME_END)
316 		return ('+');
317 	if (result[n].part_chk & UNALIGNED_END)
318 		return ('>');
319 	return ('*');
320 }
321 
322 LOCAL void
graph(lp,low,high)323 graph(lp, low, high)
324 	register struct dk_label *lp;
325 	long	low;
326 	long	high;
327 {
328 #define	LINELEN	75.0
329 	int		i;
330 	int		j;
331 	long		s;
332 	long		e;
333 	char		startc;
334 	char		endc;
335 	float		blkpc;
336 	char		line[(int)LINELEN+2+1];
337 
338 	printf("\n");
339 	blkpc = (high - low) / LINELEN;
340 	if (blkpc < 0.1) {
341 		blkpc = FLT_MAX;
342 	}
343 
344 	for (i = 0; i < 8; i++) {
345 		startc = endc = 'I';
346 		line[0] = '\0';
347 		printf("%c ", PARTOFF + i);
348 
349 		if (lp->dkl_map[i].dkl_nblk <= 0) {	/*XXX <= ??? sd.c */
350 			printf("partition not defined\n");
351 				if (START(i) != 0)
352 					printf("partition has no size but start != 0\n");
353 			result[i].part_chk &= PART_C_CONV_ERR;
354 			continue;
355 		}
356 
357 		if (START(i) != 0)
358 			startc = get_startc(i);
359 		if (END(i) != (lp->dkl_ncyl * SPCYL))
360 			endc = get_endc(i);
361 
362 		e = (END(i) > high) ? high-low : END(i) - low;
363 		if (e < 0)
364 			e = 0;
365 		/* Die Rundung ist Absicht! */
366 		j = e / blkpc + 1.0;
367 		line[j+1] = '\0';
368 		line[j] = endc;
369 
370 		while (--j >= 0)
371 			line[j] = '-';
372 
373 		s = (START(i) < low) ? 0 : START(i) - low;
374 		if (s > high)
375 			s = high-low;
376 		/* Die Rundung ist Absicht! */
377 		for (j = s / blkpc + 1.0; --j >= 0; )
378 			line[j] = ' ';
379 
380 		/* Die Rundung ist Absicht! */
381 		j = s / blkpc + 0.999999999;
382 		line[j] = startc;
383 		printf("%s\n", line);
384 	}
385 }
386 
387 LOCAL void
print_lwarn()388 print_lwarn()
389 {
390 	int		i;
391 	int		printed = 0;
392 
393 	for (i = 0; i < 8; i++) {
394 		if (result[i].part_chk & DANGER) {
395 			printf("DANGER:\n");
396 			break;
397 		}
398 	}
399 
400 	for (i = 0; i < 8; i++) {
401 		if ((result[i].part_chk & DANGER) == 0)
402 			continue;
403 
404 		printed = 0;
405 		printf("part '%c'", PARTOFF + i);
406 		if (result[i].part_chk & PART_RANGE_ERR) {
407 			if (printed)
408 				printf(" and");
409 			printf(" starts before 0");
410 			printed++;
411 		}
412 		if (result[i].part_chk & PART_TO_BIG) {
413 			if (printed)
414 				printf(" and");
415 			printf(" ends behind lncyl");
416 			printed++;
417 		}
418 		printf("!\n");
419 	}
420 
421 	for (i = 0; i < 8; i++) {
422 		if (result[i].part_chk & WARNING) {
423 			printf("WARNING:\n");
424 			break;
425 		}
426 	}
427 
428 	for (i = 0; i < 8; i++) {
429 		if ((result[i].part_chk & WARNING) == 0)
430 			continue;
431 
432 		printed = 0;
433 		printf("part '%c' has", PARTOFF + i);
434 		if (result[i].part_chk & UNALIGNED_START) {
435 			if (printed)
436 				printf(" and");
437 			printf(" unaligned start");
438 			printed++;
439 		}
440 		if (result[i].part_chk & UNALIGNED_END) {
441 			if (printed)
442 				printf(" and");
443 			printf(" unaligned end");
444 			printed++;
445 		}
446 		if (result[i].part_chk & SPACE_BEFORE_START) {
447 			if (printed)
448 				printf(" and");
449 			printf(" space before start");
450 			printed++;
451 		}
452 		if (result[i].part_chk & SPACE_AFTER_END) {
453 			if (printed)
454 				printf(" and");
455 			printf(" space after end");
456 			printed++;
457 		}
458 		if (result[i].part_chk & PART_C_CONV_ERR) {
459 			if (printed)
460 				printf(" and");
461 			printf(" not full size");
462 			printed++;
463 		}
464 		printf(".\n");
465 	}
466 	printf("\n");
467 }
468