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