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

Last change on this file since 30 was 30, checked in by bcornec, 19 years ago

Id property added on files to allow for better conf. management

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