source: MondoRescue/branches/2.2.2/mondo/src/common/libmondo-mountlist.c@ 1229

Last change on this file since 1229 was 541, checked in by bcornec, 18 years ago

Stable is reverted to r436 (2.0.7) to put it in line with 2.0.8 and start from there over

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