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

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

Remove g_bkpinfo_DONTUSETHIS

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