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

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

Huge patch to introduce low level functions that will bw used everywhere (mr_free, mr_asprintf, ...)
Nearly linking now due to that.

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