source: MondoRescue/branches/3.1/mondo/src/common/libmondo-mountlist.c@ 3190

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