source: MondoRescue/branches/3.2/mondo/src/mondorestore/mondo-rstr-mountlist.c

Last change on this file was 3611, checked in by Bruno Cornec, 7 years ago

Remove more static allocation

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