source: MondoRescue/trunk/mondo/src/common/libmondo-mountlist.c@ 1161

Last change on this file since 1161 was 1161, checked in by Bruno Cornec, 17 years ago

Update trunk with the latest feedback from stable (obtained with meld) - First pass

  • Property svn:keywords set to Id
File size: 34.5 KB
Line 
1/* subroutines for handling mountlist
2 $Id: libmondo-mountlist.c 1161 2007-02-14 12:13:49Z bruno $
3*/
4
5/**
6 * @file
7 * Functions which manipulate the mountlist.
8 */
9
10#include "my-stuff.h"
11#include "mondostructures.h"
12#include "libmondo-mountlist.h"
13#include "libmondo-raid-EXT.h"
14#include "libmondo-devices-EXT.h"
15#include "libmondo-tools-EXT.h"
16#include "libmondo-string-EXT.h"
17#include "newt-specific-EXT.h"
18#include "mr_mem.h"
19#include "mr_msg.h"
20
21/*@unused@*/
22//static char cvsid[] = "$Id: libmondo-mountlist.c 1161 2007-02-14 12:13:49Z bruno $";
23
24/**
25 * A global copy of @c bkpinfo, to aid in debugging. As the name implies, <em>don't use this</em>.
26 * @ingroup globalGroup
27 */
28struct s_bkpinfo *g_bkpinfo_DONTUSETHIS = NULL;
29
30/**
31 * @addtogroup mountlistGroup
32 * @{
33 */
34/**
35 * Evaluate a drive within the mountlist for flaws. For example, too many
36 * primary partitions, the first logical isn't 5, duplicate partitions,
37 * ovar-allocated or under-allocated, unsupported format, silly size, or
38 * silly mountpoint. Under FreeBSD, this checks the disklabel too, for the above-mentioned
39 * errors as well as too many BSD partitions (more than 'h').
40 * @param mountlist The mountlist to check.
41 * @param drive The drive to check (e.g. @c /dev/hda).
42 * @param flaws_str Where to put the found flaws (human-readable).
43 * @return The number of flaws found (0 for success).
44 * @see evaluate_mountlist
45 */
46int evaluate_drive_within_mountlist(struct mountlist_itself *mountlist,
47 char *drive, char *flaws_str)
48#ifdef __FreeBSD__
49{
50// FreeBSD-specific version of evaluate_drive_within_mountlist()
51 /*@ int ************************************************************* */
52 int prev_part_no = 0;
53 int curr_part_no = 0;
54 int pos = 0, npos = 0;
55 int res = 0;
56 int mountpoint_copies = 0;
57 int device_copies = 0;
58 int i = 0;
59 int cur_sp_no = 0;
60 int prev_sp_no = 0;
61 int foundsome = FALSE;
62
63 /*@ buffers ******************************************************** */
64 char *tmp = NULL;
65 char *tmp1 = NULL;
66 char *device = NULL;
67 char *ndevice = NULL;
68 // BERLIOS : useless ? char *mountpoint;
69
70 /*@ long *********************************************************** */
71 long physical_drive_size = 0;
72 long amount_allocated = 0;
73
74 /*@ pointers ******************************************************* */
75 char *part_table_fmt = NULL;
76
77 /*@ initialize ***************************************************** */
78 prev_part_no = 0;
79 // BERLIOS: tmp[0] = '\0';
80
81
82 physical_drive_size = get_phys_size_of_drive(drive);
83
84 if (physical_drive_size < 0) {
85 mr_asprintf(&tmp, " %s does not exist.", drive);
86 flaws_str = tmp;
87 } else {
88 mr_asprintf(&tmp, "%s is %ld MB", drive, physical_drive_size);
89 flaws_str = NULL;
90 }
91 log_it(tmp);
92 mr_free(tmp);
93
94
95 /* check DD */
96 for (cur_sp_no = 'a'; cur_sp_no < 'z'; ++cur_sp_no) {
97 mr_asprintf(&device, "%s%c", drive, cur_sp_no);
98 if (find_device_in_mountlist(mountlist, device) >= 0)
99 foundsome = TRUE;
100 mr_free(device);
101 }
102 if (foundsome) {
103 for (cur_sp_no = 'a'; cur_sp_no < 'z'; ++cur_sp_no) {
104 mr_asprintf(&device, "%s%c", drive, cur_sp_no);
105 pos = find_device_in_mountlist(mountlist, device);
106 if (pos < 0) {
107 continue;
108 }
109 // BERLIOS : useless ? mr_asprintf(&mountpoint, mountlist->el[pos].mountpoint);
110 /* is it too big? */
111 if (curr_part_no > 'h') {
112 mr_asprintf(&tmp, " Can only have up to 'h' in disklabel.");
113 log_it(tmp);
114 if (flaws_str) {
115 mr_asprintf(&tmp1, "%s%s",flaws_str, tmp);
116 } else {
117 mr_asprintf(&tmp1, "%s", tmp);
118 }
119 mr_free(flaws_str);
120 flaws_str = tmp1;
121 mr_free(tmp);
122 res++;
123 }
124 /* does partition /dev/adXsYZ exist more than once in the mountlist? */
125 for (i = 0, mountpoint_copies = 0, device_copies = 0;
126 i < mountlist->entries; i++) {
127 if (!strcmp(device, mountlist->el[i].device)) {
128 device_copies++;
129 }
130 }
131 if (device_copies > 1) {
132 mr_asprintf(&tmp, " %s %s's.", number_to_text(device_copies),
133 device);
134 if (!strstr(flaws_str, tmp)) {
135 log_it(tmp);
136 if (flaws_str) {
137 mr_asprintf(&tmp1, "%s%s",flaws_str, tmp);
138 } else {
139 mr_asprintf(&tmp1, "%s", tmp);
140 }
141 mr_free(flaws_str);
142 flaws_str = tmp1;
143 res++;
144 }
145 mr_free(tmp);
146 }
147 /* silly partition size? */
148 if (mountlist->el[pos].size < 8192
149 && strcmp(mountlist->el[pos].mountpoint, "lvm")) {
150 mr_asprintf(&tmp, " %s is tiny!", device);
151 log_it(tmp);
152 if (flaws_str) {
153 mr_asprintf(&tmp1, "%s%s",flaws_str, tmp);
154 } else {
155 mr_asprintf(&tmp1, "%s", tmp);
156 }
157 mr_free(flaws_str);
158 flaws_str = tmp1;
159 mr_free(tmp);
160 res++;
161 }
162 /* mountpoint should begin with / unless it is swap, lvm or raid */
163 if (strcmp(mountlist->el[pos].mountpoint, "swap")
164 && strcmp(mountlist->el[pos].mountpoint, "lvm")
165 && strcmp(mountlist->el[pos].mountpoint, "raid")
166 && strcmp(mountlist->el[pos].mountpoint, "image")
167 && strcmp(mountlist->el[pos].mountpoint, "none")
168 && mountlist->el[pos].mountpoint[0] != '/') {
169 mr_asprintf(&tmp, " %s has a weird mountpoint.", device);
170 log_it(tmp);
171 if (flaws_str) {
172 mr_asprintf(&tmp1, "%s%s",flaws_str, tmp);
173 } else {
174 mr_asprintf(&tmp1, "%s", tmp);
175 }
176 mr_free(flaws_str);
177 flaws_str = tmp1;
178 mr_free(tmp);
179 res++;
180 }
181 /* is format sensible? */
182 if (!is_this_a_valid_disk_format(mountlist->el[pos].format)) {
183 mr_asprintf(&tmp, " %s has unsupported format %s.", device, mountlist->el[pos].format);
184 log_it(tmp);
185 if (flaws_str) {
186 mr_asprintf(&tmp1, "%s%s",flaws_str, tmp);
187 } else {
188 mr_asprintf(&tmp1, "%s", tmp);
189 }
190 mr_free(flaws_str);
191 flaws_str = tmp1;
192 mr_free(tmp);
193 res++;
194 }
195 amount_allocated += mountlist->el[pos].size / 1024;
196 prev_sp_no = cur_sp_no;
197
198 mr_free(device);
199 }
200 }
201
202 npos = pos = 0;
203 for (curr_part_no = 1; curr_part_no < 99; curr_part_no++) {
204 mr_asprintf(&device, "%ss%d", drive, curr_part_no);
205 pos = find_device_in_mountlist(mountlist, device);
206 npos = 0;
207 for (cur_sp_no = 'a'; cur_sp_no <= 'h'; cur_sp_no++) {
208 mr_asprintf(&ndevice, "%ss%d%c", device, curr_part_no, cur_sp_no);
209 if (find_device_in_mountlist(mountlist, ndevice) >= 0)
210 npos++;
211 mr_free(ndevice);
212 }
213 mr_free(device);
214
215 if (((pos >= 0) || npos) && foundsome) {
216 mr_asprintf(&tmp, " %s has both DD and PC-style partitions.", drive);
217 if (flaws_str) {
218 mr_asprintf(&tmp1, "%s%s",flaws_str, tmp);
219 } else {
220 mr_asprintf(&tmp1, "%s", tmp);
221 }
222 mr_free(flaws_str);
223 flaws_str = tmp1;
224 mr_free(tmp);
225 return ++res; // fatal error
226 }
227 // BERLIOS : useless ? mr_asprintf(&mountpoint, mountlist->el[pos].mountpoint);
228 if (pos > 0 && !npos) {
229 mr_asprintf(&device, "%ss%d", drive, curr_part_no);
230 /* gap in the partition list? */
231 if (curr_part_no - prev_part_no > 1) {
232 if (prev_part_no == 0) {
233 mr_asprintf(&tmp, " Gap prior to %s.", device);
234 log_it(tmp);
235 if (flaws_str) {
236 mr_asprintf(&tmp1, "%s%s",flaws_str, tmp);
237 } else {
238 mr_asprintf(&tmp1, "%s", tmp);
239 }
240 mr_free(flaws_str);
241 flaws_str = tmp1;
242 mr_free(tmp);
243 res++;
244 } else if (curr_part_no > 5
245 || (curr_part_no <= 4 && prev_part_no > 0)) {
246 mr_asprintf(&tmp, " Gap between %ss%d and %d.", drive,
247 prev_part_no, curr_part_no);
248 log_it(tmp);
249 if (flaws_str) {
250 mr_asprintf(&tmp1, "%s%s",flaws_str, tmp);
251 } else {
252 mr_asprintf(&tmp1, "%s", tmp);
253 }
254 mr_free(flaws_str);
255 flaws_str = tmp1;
256 mr_free(tmp);
257 res++;
258 }
259 }
260 /* GPT allows more than 4 primary partitions */
261 part_table_fmt = which_partition_format(drive);
262 /* no spare primary partitions to help accommodate the logical(s)? */
263 if ((curr_part_no >= 5 && prev_part_no == 4)
264 && (strcmp(part_table_fmt, "MBR") == 0)) {
265 mr_asprintf(&tmp, " Partition %ss4 is occupied.", drive);
266 log_it(tmp);
267 if (flaws_str) {
268 mr_asprintf(&tmp1, "%s%s",flaws_str, tmp);
269 } else {
270 mr_asprintf(&tmp1, "%s", tmp);
271 }
272 mr_free(flaws_str);
273 flaws_str = tmp1;
274 mr_free(tmp);
275 res++;
276 }
277 /* does partition /dev/adXsY exist more than once in the mountlist? */
278 for (i = 0, mountpoint_copies = 0, device_copies = 0;
279 i < mountlist->entries; i++) {
280 if (!strcmp(device, mountlist->el[i].device)) {
281 device_copies++;
282 }
283 }
284 if (device_copies > 1) {
285 mr_asprintf(&tmp, " %s %s's.", number_to_text(device_copies),
286 device);
287 if (!strstr(flaws_str, tmp)) {
288 log_it(tmp);
289 if (flaws_str) {
290 mr_asprintf(&tmp1, "%s%s",flaws_str, tmp);
291 } else {
292 mr_asprintf(&tmp1, "%s", tmp);
293 }
294 mr_free(flaws_str);
295 flaws_str = tmp1;
296 res++;
297 }
298 mr_free(tmp);
299 }
300 /* silly partition size? */
301 if (mountlist->el[pos].size < 8192
302 && strcmp(mountlist->el[pos].mountpoint, "lvm")) {
303 mr_asprintf(&tmp, " %s is tiny!", device);
304 log_it(tmp);
305 if (flaws_str) {
306 mr_asprintf(&tmp1, "%s%s",flaws_str, tmp);
307 } else {
308 mr_asprintf(&tmp1, "%s", tmp);
309 }
310 mr_free(flaws_str);
311 flaws_str = tmp1;
312 mr_free(tmp);
313 res++;
314 }
315 /* mountpoint should begin with / unless it is swap, lvm or raid */
316 if (strcmp(mountlist->el[pos].mountpoint, "swap")
317 && strcmp(mountlist->el[pos].mountpoint, "lvm")
318 && strcmp(mountlist->el[pos].mountpoint, "raid")
319 && strcmp(mountlist->el[pos].mountpoint, "image")
320 && strcmp(mountlist->el[pos].mountpoint, "none")
321 && mountlist->el[pos].mountpoint[0] != '/') {
322 mr_asprintf(&tmp, " %s has a weird mountpoint.", device);
323 log_it(tmp);
324 if (flaws_str) {
325 mr_asprintf(&tmp1, "%s%s",flaws_str, tmp);
326 } else {
327 mr_asprintf(&tmp1, "%s", tmp);
328 }
329 mr_free(flaws_str);
330 flaws_str = tmp1;
331 mr_free(tmp);
332 res++;
333 }
334 /* is format sensible? */
335 if (!is_this_a_valid_disk_format(mountlist->el[pos].format)) {
336 mr_asprintf(&tmp, " %s has unsupported format %s.", device, mountlist->el[pos].format);
337 log_it(tmp);
338 if (flaws_str) {
339 mr_asprintf(&tmp1, "%s%s",flaws_str, tmp);
340 } else {
341 mr_asprintf(&tmp1, "%s", tmp);
342 }
343 mr_free(flaws_str);
344 flaws_str = tmp1;
345 mr_free(tmp);
346 res++;
347 }
348 mr_free(device);
349 } else {
350 /* Check subpartitions */
351 for (cur_sp_no = 'a'; cur_sp_no < 'z'; ++cur_sp_no) {
352 mr_asprintf(&device, "%ss%d%c", drive, curr_part_no,
353 cur_sp_no);
354 pos = find_device_in_mountlist(mountlist, device);
355 if (pos < 0) {
356 continue;
357 }
358 // BERLIOS : useless ? mr_asprintf(&mountpoint, mountlist->el[pos].mountpoint);
359 /* is it too big? */
360 if (curr_part_no > 'h') {
361 mr_asprintf(&tmp,
362 " Can only have up to 'h' in disklabel.");
363 log_it(tmp);
364 if (flaws_str) {
365 mr_asprintf(&tmp1, "%s%s",flaws_str, tmp);
366 } else {
367 mr_asprintf(&tmp1, "%s", tmp);
368 }
369 mr_free(flaws_str);
370 flaws_str = tmp1;
371 mr_free(tmp);
372 res++;
373 }
374 /* does partition /dev/adXsYZ exist more than once in the mountlist? */
375 for (i = 0, mountpoint_copies = 0, device_copies = 0;
376 i < mountlist->entries; i++) {
377 if (!strcmp(device, mountlist->el[i].device)) {
378 device_copies++;
379 }
380 }
381 if (device_copies > 1) {
382 mr_asprintf(&tmp, " %s %s's.",
383 number_to_text(device_copies), device);
384 if (!strstr(flaws_str, tmp)) {
385 log_it(tmp);
386 if (flaws_str) {
387 mr_asprintf(&tmp1, "%s%s",flaws_str, tmp);
388 } else {
389 mr_asprintf(&tmp1, "%s", tmp);
390 }
391 mr_free(flaws_str);
392 flaws_str = tmp1;
393 res++;
394 }
395 mr_free(tmp);
396 }
397 /* silly partition size? */
398 if (mountlist->el[pos].size < 8192
399 && strcmp(mountlist->el[pos].mountpoint, "lvm")) {
400 mr_asprintf(&tmp, " %s is tiny!", device);
401 log_it(tmp);
402 if (flaws_str) {
403 mr_asprintf(&tmp1, "%s%s",flaws_str, tmp);
404 } else {
405 mr_asprintf(&tmp1, "%s", tmp);
406 }
407 mr_free(flaws_str);
408 flaws_str = tmp1;
409 mr_free(tmp);
410 res++;
411 }
412 /* mountpoint should begin with / unless it is swap, lvm or raid */
413 if (strcmp(mountlist->el[pos].mountpoint, "swap")
414 && strcmp(mountlist->el[pos].mountpoint, "lvm")
415 && strcmp(mountlist->el[pos].mountpoint, "raid")
416 && strcmp(mountlist->el[pos].mountpoint, "image")
417 && strcmp(mountlist->el[pos].mountpoint, "none")
418 && mountlist->el[pos].mountpoint[0] != '/') {
419 mr_asprintf(&tmp, " %s has a weird mountpoint.", device);
420 log_it(tmp);
421 if (flaws_str) {
422 mr_asprintf(&tmp1, "%s%s",flaws_str, tmp);
423 } else {
424 mr_asprintf(&tmp1, "%s", tmp);
425 }
426 mr_free(flaws_str);
427 flaws_str = tmp1;
428 mr_free(tmp);
429 res++;
430 }
431 /* is format sensible? */
432 if (!is_this_a_valid_disk_format
433 (mountlist->el[pos].format)) {
434 mr_asprintf(&tmp, " %s has unsupported format %s.", device, mountlist->el[pos].format);
435 log_it(tmp);
436 if (flaws_str) {
437 mr_asprintf(&tmp1, "%s%s",flaws_str, tmp);
438 } else {
439 mr_asprintf(&tmp1, "%s", tmp);
440 }
441 mr_free(flaws_str);
442 flaws_str = tmp1;
443 mr_free(tmp);
444 res++;
445 }
446 amount_allocated += mountlist->el[pos].size / 1024;
447 prev_sp_no = cur_sp_no;
448 mr_free(device);
449 }
450 }
451
452 /* OK, continue with main loop */
453 amount_allocated += mountlist->el[pos].size / 1024;
454 prev_part_no = curr_part_no;
455 }
456
457 /* Over-allocated the disk? Unallocated space on disk? */
458 if (amount_allocated > physical_drive_size) // Used to be +1, but what if you're 1 MB too high?
459 {
460 mr_asprintf(&tmp, " %ld MB over-allocated on %s.",
461 amount_allocated - physical_drive_size, drive);
462 log_it(tmp);
463 if (flaws_str) {
464 mr_asprintf(&tmp1, "%s%s",flaws_str, tmp);
465 } else {
466 mr_asprintf(&tmp1, "%s", tmp);
467 }
468 mr_free(flaws_str);
469 flaws_str = tmp1;
470 mr_free(tmp);
471 res++;
472 } else if (amount_allocated < physical_drive_size - 1) { /* NOT AN ERROR, JUST A WARNING :-) */
473 mr_asprintf(&tmp, " %ld MB unallocated on %s.",
474 physical_drive_size - amount_allocated, drive);
475 log_it(tmp);
476 if (flaws_str) {
477 mr_asprintf(&tmp1, "%s%s",flaws_str, tmp);
478 } else {
479 mr_asprintf(&tmp1, "%s", tmp);
480 }
481 mr_free(flaws_str);
482 flaws_str = tmp1;
483 mr_free(tmp);
484 }
485 if (res) {
486 return (FALSE);
487 } else {
488 return (TRUE);
489 }
490}
491
492#else
493// Linux-specific version of evaluate_drive_within_mountlist()
494{
495
496 /*@ int ************************************************************* */
497 int prev_part_no = 0;
498 int curr_part_no = 0;
499 int pos = 0;
500 int res = 0;
501 int mountpoint_copies = 0;
502 int device_copies = 0;
503 int i = 0;
504
505 /*@ buffers ******************************************************** */
506 char *tmp = NULL;
507 char *tmp1 = NULL;
508 char *device = NULL;
509
510 /*@ long *********************************************************** */
511 long physical_drive_size = 0L;
512 long amount_allocated = 0L;
513
514 /*@ pointers ******************************************************* */
515 char *part_table_fmt = NULL;
516
517 /*@ initialize ***************************************************** */
518 assert_string_is_neither_NULL_nor_zerolength(drive);
519 assert(mountlist != NULL);
520 flaws_str = NULL;
521
522 prev_part_no = 0;
523 // BERLIOS : useless ? tmp[0] = '\0';
524
525
526 physical_drive_size = get_phys_size_of_drive(drive);
527
528 if (physical_drive_size < 0) {
529 mr_asprintf(&tmp, " %s does not exist.", drive);
530 if (flaws_str) {
531 mr_asprintf(&tmp1, "%s%s",flaws_str, tmp);
532 } else {
533 mr_asprintf(&tmp1, "%s", tmp);
534 }
535 mr_free(flaws_str);
536 flaws_str = tmp1;
537 res++;
538 mr_msg(1, tmp);
539 mr_free(tmp);
540 return (FALSE);
541 } else {
542 mr_asprintf(&tmp, "%s is %ld MB", drive, physical_drive_size);
543 log_it(tmp);
544 mr_free(tmp);
545 }
546
547 for (curr_part_no = 1; curr_part_no < 99; curr_part_no++) {
548 mr_asprintf(&device, "%s%d", drive, curr_part_no);
549 pos = find_device_in_mountlist(mountlist, device);
550 if (pos < 0) {
551 continue;
552 }
553 if (physical_drive_size < 0) {
554 mr_asprintf(&tmp, " %s refers to non-existent hardware.", device);
555 if (flaws_str) {
556 mr_asprintf(&tmp1, "%s%s",flaws_str, tmp);
557 } else {
558 mr_asprintf(&tmp1, "%s", tmp);
559 }
560 mr_free(flaws_str);
561 flaws_str = tmp1;
562 res++;
563 mr_free(tmp);
564 continue;
565 }
566 // BERLIOS : useless ? str-cpy(mountpoint, mountlist->el[pos].mountpoint);
567 /* gap in the partition list? */
568 if (curr_part_no - prev_part_no > 1) {
569 if (prev_part_no == 0) {
570 mr_asprintf(&tmp, " Gap prior to %s.", device);
571 log_it(tmp);
572 if (flaws_str) {
573 mr_asprintf(&tmp1, "%s%s",flaws_str, tmp);
574 } else {
575 mr_asprintf(&tmp1, "%s", tmp);
576 }
577 mr_free(flaws_str);
578 flaws_str = tmp1;
579 mr_free(tmp);
580 res++;
581 } else if (curr_part_no > 5
582 || (curr_part_no <= 4 && prev_part_no > 0)) {
583 mr_asprintf(&tmp, " Gap between %s%d and %d.", drive,
584 prev_part_no, curr_part_no);
585 log_it(tmp);
586 if (flaws_str) {
587 mr_asprintf(&tmp1, "%s%s",flaws_str, tmp);
588 } else {
589 mr_asprintf(&tmp1, "%s", tmp);
590 }
591 mr_free(flaws_str);
592 flaws_str = tmp1;
593 mr_free(tmp);
594 res++;
595 }
596 }
597 /* GPT allows more than 4 primary partitions */
598 part_table_fmt = which_partition_format(drive);
599 /* no spare primary partitions to help accommodate the logical(s)? */
600 if ((curr_part_no >= 5 && prev_part_no == 4)
601 && (strcmp(part_table_fmt, "MBR") == 0)) {
602 mr_asprintf(&tmp, " Partition %s4 is occupied.", drive);
603 log_it(tmp);
604 if (flaws_str) {
605 mr_asprintf(&tmp1, "%s%s",flaws_str, tmp);
606 } else {
607 mr_asprintf(&tmp1, "%s", tmp);
608 }
609 mr_free(flaws_str);
610 flaws_str = tmp1;
611 mr_free(tmp);
612 res++;
613 }
614 mr_free(part_table_fmt);
615
616 /* does partition /dev/hdNX exist more than once in the mountlist? */
617 for (i = 0, mountpoint_copies = 0, device_copies = 0;
618 i < mountlist->entries; i++) {
619 if (!strcmp(device, mountlist->el[i].device)) {
620 device_copies++;
621 }
622 }
623 if (device_copies > 1) {
624 mr_asprintf(&tmp, " %s %s's.", number_to_text(device_copies),
625 device);
626 if (!strstr(flaws_str, tmp)) {
627 log_it(tmp);
628 if (flaws_str) {
629 mr_asprintf(&tmp1, "%s%s",flaws_str, tmp);
630 } else {
631 mr_asprintf(&tmp1, "%s", tmp);
632 }
633 mr_free(flaws_str);
634 flaws_str = tmp1;
635 res++;
636 }
637 mr_free(tmp);
638 }
639 /* silly partition size? */
640 if (mountlist->el[pos].size < 8192
641 && strcmp(mountlist->el[pos].mountpoint, "lvm")) {
642 mr_asprintf(&tmp, " %s is tiny!", device);
643 log_it(tmp);
644 if (flaws_str) {
645 mr_asprintf(&tmp1, "%s%s",flaws_str, tmp);
646 } else {
647 mr_asprintf(&tmp1, "%s", tmp);
648 }
649 mr_free(flaws_str);
650 flaws_str = tmp1;
651 mr_free(tmp);
652 res++;
653 }
654 /* mountpoint should begin with / unless it is swap, lvm or raid */
655 if (strcmp(mountlist->el[pos].mountpoint, "swap")
656 && strcmp(mountlist->el[pos].mountpoint, "lvm")
657 && strcmp(mountlist->el[pos].mountpoint, "raid")
658 && strcmp(mountlist->el[pos].mountpoint, "image")
659 && mountlist->el[pos].mountpoint[0] != '/') {
660 mr_asprintf(&tmp, " %s has a weird mountpoint.", device);
661 log_it(tmp);
662 if (flaws_str) {
663 mr_asprintf(&tmp1, "%s%s",flaws_str, tmp);
664 } else {
665 mr_asprintf(&tmp1, "%s", tmp);
666 }
667 mr_free(flaws_str);
668 flaws_str = tmp1;
669 mr_free(tmp);
670 res++;
671 }
672 /* is format sensible? */
673 if (!is_this_a_valid_disk_format(mountlist->el[pos].format)) {
674 mr_asprintf(&tmp, " %s has unsupported format %s.", device, mountlist->el[pos].format);
675 log_it(tmp);
676 if (flaws_str) {
677 mr_asprintf(&tmp1, "%s%s",flaws_str, tmp);
678 } else {
679 mr_asprintf(&tmp1, "%s", tmp);
680 }
681 mr_free(flaws_str);
682 flaws_str = tmp1;
683 mr_free(tmp);
684 res++;
685 }
686 /* OK, continue with main loop */
687 amount_allocated += mountlist->el[pos].size / 1024;
688 prev_part_no = curr_part_no;
689 mr_free(device);
690 }
691
692 /* Over-allocated the disk? Unallocated space on disk? */
693 if (amount_allocated > physical_drive_size + 1) {
694 mr_asprintf(&tmp, " %ld MB over-allocated on %s.",
695 amount_allocated - physical_drive_size, drive);
696 log_it(tmp);
697 if (flaws_str) {
698 mr_asprintf(&tmp1, "%s%s",flaws_str, tmp);
699 } else {
700 mr_asprintf(&tmp1, "%s", tmp);
701 }
702 mr_free(flaws_str);
703 flaws_str = tmp1;
704 mr_free(tmp);
705 res++;
706 } else if (amount_allocated < physical_drive_size - 1) { /* NOT AN ERROR, JUST A WARNING :-) */
707 mr_asprintf(&tmp, " %ld MB unallocated on %s.",
708 physical_drive_size - amount_allocated, drive);
709 log_it(tmp);
710 if (flaws_str) {
711 mr_asprintf(&tmp1, "%s%s",flaws_str, tmp);
712 } else {
713 mr_asprintf(&tmp1, "%s", tmp);
714 }
715 mr_free(flaws_str);
716 flaws_str = tmp1;
717 mr_free(tmp);
718 }
719
720 if (res) {
721 return (FALSE);
722 } else {
723 return (TRUE);
724 }
725}
726#endif
727
728
729/**
730 * Evaluate a whole mountlist for flaws. Calls evaluate_drive_within_mountlist()
731 * for each drive, and then spreads the flaws across three lines.
732 * @param mountlist The mountlist to evaluate.
733 * @param flaws_str_A Where to put the first line listing errors found.
734 * @param flaws_str_B Where to put the second line listing errors found.
735 * @param flaws_str_C Where to put the third line listing errors found.
736 * @return The number of flaws found (0 for success).
737 * @see evaluate_drive_within_mountlist
738 */
739int
740evaluate_mountlist(struct mountlist_itself *mountlist, char *flaws_str_A,
741 char *flaws_str_B, char *flaws_str_C)
742{
743
744 /*@ buffer *********************************************************** */
745 struct list_of_disks *drivelist;
746 char *tmp;
747 char *tmp1;
748 char *flaws_str;
749
750 /*@ int ************************************************************** */
751 int i = 0;
752 int res = 0;
753
754 /*@ initialize ******************************************************* */
755
756 drivelist = mr_malloc(sizeof(struct list_of_disks));
757 assert(mountlist != NULL);
758
759 mr_asprintf(&flaws_str, " ");
760
761 make_list_of_drives_in_mountlist(mountlist, drivelist);
762
763 log_it("Evaluating mountlist...");
764
765 for (i = 0; i < drivelist->entries; i++) {
766 if (strstr
767 (drivelist->el[i].device,
768 DONT_KNOW_HOW_TO_EVALUATE_THIS_DEVICE_TYPE)) {
769 mr_asprintf(&tmp, " Not evaluating %s (I don't know how yet)",
770 drivelist->el[i].device);
771 log_it(tmp);
772 } else {
773 // This function allocates tmp
774 if (!evaluate_drive_within_mountlist
775 (mountlist, drivelist->el[i].device, tmp)) {
776 res++;
777 }
778 }
779 mr_asprintf(&tmp1, "%s%s", flaws_str, tmp);
780 mr_free(tmp);
781 mr_free(flaws_str);
782 flaws_str = tmp1;
783 }
784 res += look_for_duplicate_mountpoints(mountlist, flaws_str);
785 return (spread_flaws_across_three_lines
786 (flaws_str, flaws_str_A, flaws_str_B, flaws_str_C, res));
787}
788
789
790/**
791 * Find the index number of @p device in the mountlist.
792 * The device given must match @p mountlist->el[N].device exactly, case-sensitive.
793 * @param mountlist The mountlist to search in.
794 * @param device The device to search for.
795 * @return The zero-based index of the device, or -1 if it could not be found.
796 */
797int
798find_device_in_mountlist(struct mountlist_itself *mountlist, char *device)
799{
800
801 /*@ int ************************************************************** */
802 int i = 0;
803
804 assert(mountlist != NULL);
805 assert_string_is_neither_NULL_nor_zerolength(device);
806 for (i = 0;
807 i < mountlist->entries
808 && strcmp(mountlist->el[i].device, device) != 0; i++);
809
810 if (i == mountlist->entries) {
811 return (-1);
812 } else {
813 return (i);
814 }
815}
816
817
818/**
819 * Look for duplicate mountpoints in @p mountlist.
820 * @param mountlist The mountlist to check.
821 * @param flaws_str The flaws string to append the results to.
822 * @return The number of mountpoints that have duplicates, or 0 for success.
823 */
824int
825look_for_duplicate_mountpoints(struct mountlist_itself *mountlist,
826 char *flaws_str)
827{
828
829 /*@ int ************************************************************* */
830 int res = 0;
831 int currline = 0;
832 int i = 0;
833 int copies = 0;
834 int last_copy = 0;
835
836 /*@ buffetr ********************************************************* */
837 char *curr_mountpoint = NULL;
838 char *tmp = NULL;
839 char *tmp1 = NULL;
840
841 assert(mountlist != NULL);
842 assert(flaws_str != NULL);
843
844 for (currline = 0; currline < mountlist->entries; currline++) {
845 mr_asprintf(&curr_mountpoint, mountlist->el[currline].mountpoint);
846 for (i = 0, copies = 0, last_copy = -1; i < mountlist->entries;
847 i++) {
848 if (!strcmp(mountlist->el[i].mountpoint, curr_mountpoint)
849 && strcmp(mountlist->el[i].mountpoint, "lvm")
850 && strcmp(mountlist->el[i].mountpoint, "swap")) {
851 last_copy = i;
852 copies++;
853 }
854 }
855 if (copies > 1 && last_copy == currline
856 && strcmp(curr_mountpoint, "raid")) {
857 mr_asprintf(&tmp, " %s %s's.", number_to_text(copies),
858 curr_mountpoint);
859 log_it(tmp);
860 mr_asprintf(&tmp1, "%s%s",flaws_str, tmp);
861 mr_free(flaws_str);
862 flaws_str = tmp1;
863 mr_free(tmp);
864 res++;
865 }
866 mr_free(curr_mountpoint);
867 }
868 return (res);
869}
870
871
872/**
873 * Make a list of the drives mentioned in the mountlist.
874 * @param mountlist The mountlist to examine.
875 * @param drivelist Where to put the list of drives found.
876 * @return The number of physical (non-RAID non-LVM) drives found, or \<= 0 for error.
877 */
878int
879make_list_of_drives_in_mountlist(struct mountlist_itself *mountlist,
880 struct list_of_disks *drivelist)
881{
882
883 /*@ int ************************************************************* */
884 int lino;
885 int noof_drives;
886 int j;
887
888 /*@ buffers ********************************************************* */
889 char *drive;
890 char *tmp;
891
892 long long size;
893
894 assert(mountlist != NULL);
895 assert(drivelist != NULL);
896 log_it("Making list of drives");
897 for (lino = 0, noof_drives = 0; lino < mountlist->entries; lino++) {
898
899 mr_asprintf(&drive, mountlist->el[lino].device);
900 if (!strncmp(drive, RAID_DEVICE_STUB, strlen(RAID_DEVICE_STUB))) {
901 mr_asprintf(&tmp,
902 "Not putting %s in list of drives: it's a virtual drive",
903 drive);
904 mr_msg(8, tmp);
905 mr_free(tmp);
906 continue;
907 }
908
909 size = mountlist->el[lino].size;
910 if (size == 0) {
911 mr_asprintf(&tmp,
912 "Not putting %s in list of drives: it has zero size (maybe an LVM volume)",
913 drive);
914 mr_msg(8, tmp);
915 mr_free(tmp);
916 continue;
917 }
918
919/*
920 for (i = strlen (drive); isdigit (drive[i - 1]); i--);
921 drive[i] = '\0';
922 if (get_phys_size_of_drive (drive) <= 0 && drive[i - 1] == 'p')
923 {
924 i--;
925 drive[i] = '\0';
926 }
927 for (j = 0; j < noof_drives && strcmp (drivelist[j], drive) != 0; j++);
928*/
929
930 mr_asprintf(&tmp,
931 "Putting %s with size %lli in list of drives",
932 drive, size);
933 mr_msg(8, tmp);
934 mr_free(tmp);
935
936 (void) truncate_to_drive_name(drive);
937 for (j = 0;
938 j < noof_drives
939 && strcmp(drivelist->el[j].device, drive) != 0; j++)
940 continue;
941 if (j == noof_drives) {
942 strcpy(drivelist->el[noof_drives++].device, drive);
943 }
944 mr_free(drive);
945
946 }
947 drivelist->entries = noof_drives;
948 mr_msg(8, "Made list of drives");
949
950 return (noof_drives);
951}
952
953
954/**
955 * Make a list of RAID partitions not currently associated with any RAID device.
956 * The user may add any of these partitions to the RAID device.
957 * @param output_list Where to put the list of unallocated RAID partitions.
958 * @param mountlist The mountlist to examine.
959 * @param raidlist The raidlist to examine.
960 */
961void make_list_of_unallocated_raid_partitions(struct mountlist_itself
962 *output_list, struct mountlist_itself
963 *mountlist, struct raidlist_itself
964 *raidlist)
965{
966
967 /*@ int ************************************************************* */
968 int items = 0;
969 int i = 0;
970 int used_by = 0;
971
972 /*@ buffers ********************************************************* */
973 char *tmp;
974
975 assert(output_list != NULL);
976 assert(mountlist != NULL);
977 assert(raidlist != NULL);
978 log_it("MLOURP -- starting");
979 items = 0;
980
981
982 for (i = 0; i < mountlist->entries; i++) {
983 if (strstr(mountlist->el[i].mountpoint, "raid")) {
984 used_by =
985 which_raid_device_is_using_this_partition(raidlist,
986 mountlist->el[i].
987 device);
988 if (used_by < 0) {
989 memcpy((void *) &output_list->el[items++],
990 (void *) &mountlist->el[i],
991 sizeof(struct mountlist_line));
992 mr_asprintf(&tmp,
993 "%s is available; user may choose to add it to raid device",
994 output_list->el[items - 1].device);
995 log_it(tmp);
996 mr_free(tmp);
997 }
998 }
999 }
1000 output_list->entries = items;
1001 log_it("MLUORP -- ending");
1002}
1003
1004
1005/**
1006 * Get the size of a mountlist entry by the @c device field.
1007 * @param mountlist The mountlist to search in.
1008 * @param device The device to search for
1009 * @return The size of the device (in KB), or -1 if it could not be found.
1010 */
1011long long
1012size_of_specific_device_in_mountlist(struct mountlist_itself *mountlist,
1013 char *device)
1014{
1015 /*@ int ************************************************************** */
1016 int i = 0;
1017
1018
1019 assert(mountlist != NULL);
1020 assert_string_is_neither_NULL_nor_zerolength(device);
1021
1022 for (i = 0;
1023 i < mountlist->entries && strcmp(mountlist->el[i].device, device);
1024 i++);
1025 if (i == mountlist->entries) {
1026 return (-1);
1027 } else {
1028 return (mountlist->el[i].size);
1029 }
1030}
1031
1032
1033/**
1034 * Load a file on disk into @p mountlist.
1035 * The file on disk should consist of multiple lines, each containing 4 or 5
1036 * columns: the device, the mountpoint, the filesystem type, the size in kilobytes, and optionally the filesystem label.
1037 * Comments begin with a '#' without any leading whitespace. Any duplicate
1038 * entries are renamed.
1039 * @param mountlist The mountlist to load into.
1040 * @param fname The name of the file to load the mountlist from.
1041 * @return 0 for success, 1 for failure.
1042 */
1043int load_mountlist(struct mountlist_itself *mountlist, char *fname)
1044{
1045 FILE *fin;
1046 /* malloc ** */
1047 char *incoming = NULL;
1048 char *siz;
1049 char *tmp;
1050 char *p;
1051
1052 int items;
1053 int j;
1054 size_t n = 0;
1055
1056 assert(mountlist != NULL);
1057 assert_string_is_neither_NULL_nor_zerolength(fname);
1058 malloc_string(siz);
1059 if (!(fin = fopen(fname, "r"))) {
1060 log_it("Unable to open mountlist - '%s'", fname);
1061 log_to_screen(_("Cannot open mountlist"));
1062 mr_free(siz);
1063 return (1);
1064 }
1065 items = 0;
1066 mr_getline(&incoming, &n, fin);
1067 log_it("Loading mountlist...");
1068 while (!feof(fin)) {
1069#if linux
1070 sscanf(incoming,
1071 "%s %s %s %s %s",
1072 mountlist->el[items].device,
1073 mountlist->el[items].mountpoint,
1074 mountlist->el[items].format,
1075 siz, mountlist->el[items].label);
1076#elif __FreeBSD__
1077 sscanf(incoming,
1078 "%s %s %s %s",
1079 mountlist->el[items].device,
1080 mountlist->el[items].mountpoint,
1081 mountlist->el[items].format, siz);
1082 strcpy(mountlist->el[items].label, "");
1083#endif
1084
1085 if (!strcmp(mountlist->el[items].device, "/proc") ||
1086 !strcmp(mountlist->el[items].device, "proc") ||
1087 !strcmp(mountlist->el[items].device, "/sys") ||
1088 !strcmp(mountlist->el[items].device, "sys") ||
1089 !strcmp(mountlist->el[items].device, "/devpts") ||
1090 !strcmp(mountlist->el[items].device, "devpts")
1091 ) {
1092 mr_msg(1,
1093 "Ignoring %s in mountlist - not loading that line :) ",
1094 mountlist->el[items].device);
1095 mr_getline(&incoming, &n, fin);
1096 continue;
1097 }
1098 mountlist->el[items].size = atoll(siz);
1099 if (mountlist->el[items].device[0] != '\0'
1100 && mountlist->el[items].device[0] != '#') {
1101 if (items >= ARBITRARY_MAXIMUM) {
1102 log_to_screen(_("Too many lines in mountlist.. ABORTING"));
1103 finish(1);
1104 }
1105 for (j = 0;
1106 j < items
1107 && strcmp(mountlist->el[j].device,
1108 mountlist->el[items].device); j++);
1109 if (j < items) {
1110 strcat(mountlist->el[items].device, "_dup");
1111 mr_asprintf(&tmp,
1112 "Duplicate entry in mountlist - renaming to %s",
1113 mountlist->el[items].device);
1114 log_it(tmp);
1115 mr_free(tmp);
1116 }
1117 mr_asprintf(&tmp, mountlist->el[items].device);
1118 if (strstr(tmp, "/dev/md/")) {
1119 log_it("format_device() --- Contracting %s", tmp);
1120 p = strrchr(tmp, '/');
1121 if (p) {
1122 *p = *(p + 1);
1123 *(p + 1) = *(p + 2);
1124 *(p + 2) = *(p + 3);
1125 }
1126 log_it("It was %s; it is now %s",
1127 mountlist->el[items].device, tmp);
1128 strcpy(mountlist->el[items].device, tmp);
1129 }
1130 mr_free(tmp);
1131
1132 mr_asprintf(&tmp,
1133 "%s %s %s %lld %s",
1134 mountlist->el[items].device,
1135 mountlist->el[items].mountpoint,
1136 mountlist->el[items].format,
1137 mountlist->el[items].size,
1138 mountlist->el[items].label);
1139
1140 log_it(tmp);
1141 mr_free(tmp);
1142 items++;
1143 }
1144 mr_getline(&incoming, &n, fin);
1145 }
1146 paranoid_fclose(fin);
1147 mr_free(incoming);
1148 mountlist->entries = items;
1149
1150 log_it("Mountlist loaded successfully.");
1151 mr_asprintf(&tmp, "%d entries in mountlist", items);
1152 log_it(tmp);
1153 mr_free(tmp);
1154
1155 mr_free(siz);
1156 return (0);
1157}
1158
1159
1160
1161/**
1162 * Save @p mountlist to a file on disk.
1163 * @param mountlist The mountlist to save.
1164 * @param fname The file to save it to.
1165 * @return 0 for success, 1 for failure.
1166 * @see load_mountlist
1167 */
1168int save_mountlist_to_disk(struct mountlist_itself *mountlist, char *fname)
1169{
1170 FILE *fout;
1171 int i;
1172
1173 assert(mountlist != NULL);
1174 assert_string_is_neither_NULL_nor_zerolength(fname);
1175
1176 log_it("save_mountlist_to_disk() --- saving to %s", fname);
1177 if (!(fout = fopen(fname, "w"))) {
1178 log_OS_error("WMTD - Cannot openout mountlist");
1179 return (1);
1180 }
1181 for (i = 0; i < mountlist->entries; i++) {
1182 fprintf(fout,
1183 "%-15s %-15s %-15s %-15lld %-15s\n",
1184 mountlist->el[i].device, mountlist->el[i].mountpoint,
1185 mountlist->el[i].format, mountlist->el[i].size,
1186 mountlist->el[i].label);
1187 }
1188 paranoid_fclose(fout);
1189 return (0);
1190}
1191
1192
1193/**
1194 * Sort the mountlist alphabetically by device.
1195 * The sorting is done in-place.
1196 * @param mountlist The mountlist to sort.
1197 */
1198void sort_mountlist_by_device(struct mountlist_itself *mountlist)
1199{
1200 int diff;
1201 int lino = -999;
1202
1203 assert(mountlist != NULL);
1204
1205 while (lino < mountlist->entries) {
1206 for (lino = 1; lino < mountlist->entries; lino++) {
1207 diff =
1208 strcmp_inc_numbers(mountlist->el[lino - 1].device,
1209 mountlist->el[lino].device);
1210 if (diff > 0) {
1211 swap_mountlist_entries(mountlist, lino - 1, lino);
1212 break;
1213 }
1214 }
1215 }
1216}
1217
1218
1219/**
1220 * Sort the mountlist alphabetically by mountpoint.
1221 * The sorting is done in-place.
1222 * @param mountlist The mountlist to sort.
1223 * @param reverse If TRUE, then do a reverse sort.
1224 */
1225void
1226sort_mountlist_by_mountpoint(struct mountlist_itself *mountlist,
1227 bool reverse)
1228{
1229 int diff;
1230 int lino = -999;
1231
1232 assert(mountlist != NULL);
1233
1234 while (lino < mountlist->entries) {
1235 for (lino = 1; lino < mountlist->entries; lino++) {
1236 diff =
1237 strcmp(mountlist->el[lino - 1].mountpoint,
1238 mountlist->el[lino].mountpoint);
1239 if ((diff > 0 && !reverse) || ((diff < 0 && reverse))) {
1240 swap_mountlist_entries(mountlist, lino - 1, lino);
1241 break;
1242 }
1243 }
1244 }
1245}
1246
1247
1248/**
1249 * Swap two entries in the mountlist in-place.
1250 * @param mountlist The mountlist to swap the entries in.
1251 * @param a The index number of the first entry.
1252 * @param b The index number of the second entry.
1253 */
1254void
1255swap_mountlist_entries(struct mountlist_itself *mountlist, int a, int b)
1256{
1257 /*@ mallocs *** */
1258 char *device;
1259 char *mountpoint;
1260 char *format;
1261
1262 long long size;
1263
1264 assert(mountlist != NULL);
1265 assert(a >= 0);
1266 assert(b >= 0);
1267
1268 mr_asprintf(&device, mountlist->el[a].device);
1269 mr_asprintf(&mountpoint, mountlist->el[a].mountpoint);
1270 mr_asprintf(&format, mountlist->el[a].format);
1271
1272 size = mountlist->el[a].size;
1273
1274 strcpy(mountlist->el[a].device, mountlist->el[b].device);
1275 strcpy(mountlist->el[a].mountpoint, mountlist->el[b].mountpoint);
1276 strcpy(mountlist->el[a].format, mountlist->el[b].format);
1277
1278 mountlist->el[a].size = mountlist->el[b].size;
1279
1280 strcpy(mountlist->el[b].device, device);
1281 strcpy(mountlist->el[b].mountpoint, mountpoint);
1282 strcpy(mountlist->el[b].format, format);
1283
1284 mountlist->el[b].size = size;
1285}
1286
1287/* @} - end of mountlistGroup */
Note: See TracBrowser for help on using the repository browser.