source: MondoRescue/branches/2.2.5/mondo/src/common/libmondo-mountlist.c@ 1645

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

Render bkpinfo global (potential issue on thread, but should not be a problem as that structure is indeed static during archive)
Should solve the tmpdir issue from previous rev.
May still not compile

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