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

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

Remove more static allocation

  • Property svn:keywords set to Id
File size: 30.3 KB
RevLine 
[2052]1/* subroutines for handling mountlist
[128]2 $Id: mondo-rstr-mountlist.c 3611 2016-11-10 20:09:54Z bruno $
[1]3*/
4
5
6/**
7 * @file
8 * Functions which manipulate the mountlist.
9 */
10
11#include "my-stuff.h"
[2209]12#include "mr_mem.h"
[1]13#include "mondostructures.h"
14#include "libmondo-mountlist.h"
[541]15#include "lib-common-externs.h"
[1]16#include "libmondo-raid-EXT.h"
17#include "libmondo-devices-EXT.h"
18#include "libmondo-tools-EXT.h"
19#include "libmondo-string-EXT.h"
[1236]20#include "newt-specific-EXT.h"
[1]21
22/*@unused@*/
[128]23//static char cvsid[] = "$Id: mondo-rstr-mountlist.c 3611 2016-11-10 20:09:54Z bruno $";
[1]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).
[2207]37 * @return The flaws string found (NULL for success) allocated to be freed
[1]38 * @see evaluate_mountlist
39 */
[2207]40char *evaluate_drive_within_mountlist(struct mountlist_itself *mountlist, char *drive)
[1]41#ifdef __FreeBSD__
42{
43// FreeBSD-specific version of evaluate_drive_within_mountlist()
[128]44 /*@ int ************************************************************* */
45 int prev_part_no = 0;
[1]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
[128]55 /*@ buffers ******************************************************** */
[2516]56 char tmp = NULL;
[3611]57 char tmp1 = NULL;
[1]58 char device[MAX_STR_LEN];
59
[2209]60 char *flaws_str = NULL;
61
[128]62 /*@ long *********************************************************** */
63 long physical_drive_size = 0;
[1]64 long amount_allocated = 0;
65
[128]66 /*@ pointers ******************************************************* */
[3237]67 char *part_table_fmt = NULL;
[1]68
[128]69 /*@ initialize ***************************************************** */
70 prev_part_no = 0;
[3185]71 mr_asprintf(flaws_str, "%s", "");
[1]72
73
[128]74 physical_drive_size = get_phys_size_of_drive(drive);
[1]75
[128]76 if (physical_drive_size < 0) {
[3185]77 mr_asprintf(tmp, " %s does not exist.", drive);
[2209]78 mr_strcat(flaws_str, "%s", tmp);
[128]79 } else {
[3185]80 mr_asprintf(tmp, "%s is %ld MB", drive, physical_drive_size);
[128]81 }
82 log_it(tmp);
[2516]83 mr_free(tmp);
[1]84
85
[128]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') {
[3185]101 mr_asprintf(tmp, " Can only have up to 'h' in disklabel.");
[128]102 log_it(tmp);
[2207]103 mr_strcat(flaws_str, tmp);
[2516]104 mr_free(tmp);
[128]105 res++;
106 }
107 /* does partition /dev/adXsYZ exist more than once in the mountlist? */
[3060]108 for (i = 0, device_copies = 0;
[128]109 i < mountlist->entries; i++) {
110 if (!strcmp(device, mountlist->el[i].device)) {
111 device_copies++;
112 }
113 }
114 if (device_copies > 1) {
[3611]115 tmp1 = number_to_text(device_copies);
116 mr_asprintf(tmp, " %s %s's.", tmp1, device);
117 mr_free(tmp1);
[128]118 if (!strstr(flaws_str, tmp)) {
119 log_it(tmp);
[2207]120 mr_strcat(flaws_str, tmp);
[128]121 res++;
122 }
[2516]123 mr_free(tmp);
[128]124 }
125 /* silly partition size? */
126 if (mountlist->el[pos].size < 8192
127 && strcmp(mountlist->el[pos].mountpoint, "lvm")) {
[3185]128 mr_asprintf(tmp, " %s is tiny!", device);
[128]129 log_it(tmp);
[2207]130 mr_strcat(flaws_str, tmp);
[2516]131 mr_free(tmp);
[128]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] != '/') {
[3185]141 mr_asprintf(tmp, " %s has a weird mountpoint.", device);
[128]142 log_it(tmp);
[2207]143 mr_strcat(flaws_str, tmp);
[2516]144 mr_free(tmp);
[128]145 res++;
146 }
147 /* is format sensible? */
148 if (!is_this_a_valid_disk_format(mountlist->el[pos].format)) {
[3185]149 mr_asprintf(tmp, " %s has unsupported format %s.", device, mountlist->el[pos].format);
[128]150 log_it(tmp);
[2207]151 mr_strcat(flaws_str, tmp);
[2516]152 mr_free(tmp);
[128]153 res++;
154 }
[2125]155 amount_allocated += mountlist->el[pos].size / 1024L;
[128]156 prev_sp_no = cur_sp_no;
157 }
158 }
[1]159
[128]160 npos = pos = 0;
161 for (curr_part_no = 1; curr_part_no < 99; curr_part_no++) {
[1303]162 build_partition_name(device, drive, curr_part_no);
[128]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) {
[2207]171 mr_strcat(flaws_str, " %s has both DD and PC-style partitions.", drive);
[2209]172 return(flaws_str); // fatal error
[128]173 }
174
[1303]175 build_partition_name(device, drive, curr_part_no);
[128]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) {
[3185]180 mr_asprintf(tmp, " Gap prior to %s.", device);
[128]181 log_it(tmp);
[2209]182 mr_strcat(flaws_str, "%s", tmp);
[2516]183 mr_free(tmp);
[128]184 res++;
185 } else if (curr_part_no > 5
186 || (curr_part_no <= 4 && prev_part_no > 0)) {
[3185]187 mr_asprintf(tmp, " Gap between %ss%d and %d.", drive, prev_part_no, curr_part_no);
[128]188 log_it(tmp);
[2209]189 mr_strcat(flaws_str, "%s", tmp);
[2516]190 mr_free(tmp);
[128]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)? */
[3237]197 if ((curr_part_no >= 5 && prev_part_no == 4) && (strcmp(part_table_fmt, "MBR") == 0)) {
[3185]198 mr_asprintf(tmp, " Partition %ss4 is occupied.", drive);
[128]199 log_it(tmp);
[2209]200 mr_strcat(flaws_str, "%s", tmp);
[2516]201 mr_free(tmp);
[128]202 res++;
203 }
[3237]204 mr_free(part_table_fmt);
205
[128]206 /* does partition /dev/adXsY exist more than once in the mountlist? */
[3060]207 for (i = 0, device_copies = 0;
[128]208 i < mountlist->entries; i++) {
209 if (!strcmp(device, mountlist->el[i].device)) {
210 device_copies++;
211 }
212 }
213 if (device_copies > 1) {
[3611]214 tmp1 = number_to_text(device_copies);
215 mr_asprintf(tmp, " %s %s's.", tmp1, device);
216 mr_free(tmp1);
[2209]217 if (!strstr(flaws_str, "%s", tmp)) {
[128]218 log_it(tmp);
[2209]219 mr_strcat(flaws_str, "%s", tmp);
[128]220 res++;
221 }
[2516]222 mr_free(tmp);
[128]223 }
224 /* silly partition size? */
225 if (mountlist->el[pos].size < 8192
226 && strcmp(mountlist->el[pos].mountpoint, "lvm")) {
[3185]227 mr_asprintf(tmp, " %s is tiny!", device);
[128]228 log_it(tmp);
[2209]229 mr_strcat(flaws_str, "%s", tmp);
[2516]230 mr_free(tmp);
[128]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] != '/') {
[3185]240 mr_asprintf(tmp, " %s has a weird mountpoint.", device);
[128]241 log_it(tmp);
[2209]242 mr_strcat(flaws_str, "%s", tmp);
[2516]243 mr_free(tmp);
[128]244 res++;
245 }
246 /* is format sensible? */
247 if (!is_this_a_valid_disk_format(mountlist->el[pos].format)) {
[3185]248 mr_asprintf(tmp, " %s has unsupported format %s.", device, mountlist->el[pos].format);
[128]249 log_it(tmp);
[2209]250 mr_strcat(flaws_str, "%s", tmp);
[2516]251 mr_free(tmp);
[128]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') {
[3185]264 mr_asprintf(tmp, " Can only have up to 'h' in disklabel.");
[128]265 log_it(tmp);
[2209]266 mr_strcat(flaws_str, "%s", tmp);
[2516]267 mr_free(tmp);
[128]268 res++;
269 }
270 /* does partition /dev/adXsYZ exist more than once in the mountlist? */
[3060]271 for (i = 0, device_copies = 0;
[128]272 i < mountlist->entries; i++) {
273 if (!strcmp(device, mountlist->el[i].device)) {
274 device_copies++;
275 }
276 }
277 if (device_copies > 1) {
[3611]278 tmp1 = number_to_text(device_copies);
279 mr_asprintf(tmp, " %s %s's.", tmp1, device);
280 mr_free(tmp1);
[128]281 if (!strstr(flaws_str, tmp)) {
282 log_it(tmp);
[2209]283 mr_strcat(flaws_str, "%s", tmp);
[128]284 res++;
285 }
[2516]286 mr_free(tmp);
[128]287 }
288 /* silly partition size? */
289 if (mountlist->el[pos].size < 8192
290 && strcmp(mountlist->el[pos].mountpoint, "lvm")) {
[3185]291 mr_asprintf(tmp, " %s is tiny!", device);
[128]292 log_it(tmp);
[2209]293 mr_strcat(flaws_str, "%s", tmp);
[2516]294 mr_free(tmp);
[128]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] != '/') {
[3185]304 mr_asprintf(tmp, " %s has a weird mountpoint.", device);
[128]305 log_it(tmp);
[2209]306 mr_strcat(flaws_str, "%s", tmp);
[2516]307 mr_free(tmp);
[128]308 res++;
309 }
310 /* is format sensible? */
[3308]311 if (!is_this_a_valid_disk_format(mountlist->el[pos].format)) {
[3185]312 mr_asprintf(tmp, " %s has unsupported format %s.", device, mountlist->el[pos].format);
[128]313 log_it(tmp);
[2209]314 mr_strcat(flaws_str, "%s", tmp);
[2516]315 mr_free(tmp);
[128]316 res++;
317 }
[2125]318 amount_allocated += mountlist->el[pos].size / 1024L;
[128]319 prev_sp_no = cur_sp_no;
320 }
321 }
322
323 /* OK, continue with main loop */
[2125]324 amount_allocated += mountlist->el[pos].size / 1024L;
[2665]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?
[3191]329 mr_asprintf(tmp, " %ld MB over-allocated on %s.",amount_allocated - physical_drive_size, drive);
[2665]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 }
[128]345 prev_part_no = curr_part_no;
346 }
347
348 /* Over-allocated the disk? Unallocated space on disk? */
[3191]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);
[1236]352 log_it(tmp);
[2209]353 mr_strcat(flaws_str, "%s", tmp);
[2516]354 mr_free(tmp);
[3191]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);
[128]361 }
362 if (res) {
[2209]363 return (NULL);
[128]364 } else {
[2209]365 return (flaws_str);
[128]366 }
[1]367}
368
369#else
370// Linux-specific version of evaluate_drive_within_mountlist()
371{
372
[128]373 /*@ int ************************************************************* */
374 int prev_part_no = 0;
[1]375 int curr_part_no = 0;
376 int pos = 0;
377 int res = 0;
378 int device_copies = 0;
379 int i = 0;
380
[128]381 /*@ buffers ******************************************************** */
[2516]382 char *tmp = NULL;
[3611]383 char *tmp1 = NULL;
[2516]384 char *device = NULL;
[2209]385 char *flaws_str = NULL;
[1]386
[128]387 /*@ long *********************************************************** */
[1295]388 long physical_drive_size = 0L;
389 long amount_allocated = 0L;
[1]390
[128]391 /*@ pointers ******************************************************* */
[2204]392 char *part_table_fmt = NULL;
[1]393
[128]394 /*@ initialize ***************************************************** */
395 assert_string_is_neither_NULL_nor_zerolength(drive);
396 assert(mountlist != NULL);
[3185]397 mr_asprintf(flaws_str, "%s", "");
[1]398
[128]399 malloc_string(device);
400 prev_part_no = 0;
[1]401
[128]402 physical_drive_size = get_phys_size_of_drive(drive);
[1]403
[128]404 if (physical_drive_size < 0) {
[2733]405 if (strstr(drive,"/dev/dm-") == NULL) {
[3185]406 mr_asprintf(tmp, " %s does not exist.", drive);
[2731]407 log_it(tmp);
408 mr_strcat(flaws_str, "%s", tmp);
409 res++;
410 mr_free(tmp);
411 goto endoffunc;
412 } else {
[3191]413 log_it(" %s (dm) will be setup later on", drive);
[2731]414 }
[128]415 } else {
[3191]416 log_it("%s is %ld MB", drive, physical_drive_size);
[128]417 }
[1]418
[3263]419 /* GPT allows more than 4 primary partitions - detect partition type now */
420 part_table_fmt = which_partition_format(drive);
421
[128]422 for (curr_part_no = 1; curr_part_no < 99; curr_part_no++) {
[1298]423 build_partition_name(device, drive, curr_part_no);
[128]424 pos = find_device_in_mountlist(mountlist, device);
425 if (pos < 0) {
426 continue;
427 }
[2380]428 log_msg(2, "Processing partition %s on %s #%d in mountlist", device, drive, pos);
[128]429 /* gap in the partition list? */
430 if (curr_part_no - prev_part_no > 1) {
431 if (prev_part_no == 0) {
[3185]432 mr_asprintf(tmp, " Gap prior to %s.", device);
[128]433 log_it(tmp);
[2209]434 mr_strcat(flaws_str, "%s", tmp);
[2516]435 mr_free(tmp);
[128]436 res++;
[3263]437 } else if (curr_part_no > 5 || (curr_part_no <= 4 && prev_part_no > 0)) {
[3191]438 mr_asprintf(tmp, " Gap on %s between %d and %d.", drive, prev_part_no, curr_part_no);
[128]439 log_it(tmp);
[2209]440 mr_strcat(flaws_str, "%s", tmp);
[2516]441 mr_free(tmp);
[128]442 res++;
443 }
444 }
445 /* no spare primary partitions to help accommodate the logical(s)? */
[3191]446 if ((curr_part_no >= 5 && prev_part_no == 4) && (strcmp(part_table_fmt, "MBR") == 0)) {
[3185]447 mr_asprintf(tmp, " Partition 4 of %s is occupied.", drive);
[128]448 log_it(tmp);
[2209]449 mr_strcat(flaws_str, "%s", tmp);
[2516]450 mr_free(tmp);
[128]451 res++;
452 }
[3191]453
[128]454 /* does partition /dev/hdNX exist more than once in the mountlist? */
[3060]455 for (i = 0, device_copies = 0;
[128]456 i < mountlist->entries; i++) {
457 if (!strcmp(device, mountlist->el[i].device)) {
458 device_copies++;
459 }
460 }
461 if (device_copies > 1) {
[3611]462 tmp1 = number_to_text(device_copies);
463 mr_asprintf(tmp, " %s %s's.", tmp1, device);
464 mr_free(tmp1);
[128]465 if (!strstr(flaws_str, tmp)) {
466 log_it(tmp);
[2209]467 mr_strcat(flaws_str, "%s", tmp);
[128]468 res++;
469 }
[2516]470 mr_free(tmp);
[128]471 }
472 /* silly partition size? */
473 if (mountlist->el[pos].size < 8192
474 && strcmp(mountlist->el[pos].mountpoint, "lvm")) {
[3185]475 mr_asprintf(tmp, " %s is tiny!", device);
[128]476 log_it(tmp);
[2209]477 mr_strcat(flaws_str, "%s", tmp);
[2516]478 mr_free(tmp);
[128]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] != '/') {
[3185]487 mr_asprintf(tmp, " %s has a weird mountpoint.", device);
[128]488 log_it(tmp);
[2209]489 mr_strcat(flaws_str, "%s", tmp);
[2516]490 mr_free(tmp);
[128]491 res++;
492 }
493 /* is format sensible? */
494 if (!is_this_a_valid_disk_format(mountlist->el[pos].format)) {
[3185]495 mr_asprintf(tmp, " %s has unsupported format %s.", device, mountlist->el[pos].format);
[128]496 log_it(tmp);
[2209]497 mr_strcat(flaws_str, "%s", tmp);
[2516]498 mr_free(tmp);
[128]499 res++;
500 }
501 /* OK, continue with main loop */
[2125]502 amount_allocated += mountlist->el[pos].size / 1024L;
[128]503 prev_part_no = curr_part_no;
[1]504 }
[3263]505 mr_free(part_table_fmt);
[128]506
507 /* Over-allocated the disk? Unallocated space on disk? */
508 if (amount_allocated > physical_drive_size + 1) {
[3191]509 mr_asprintf(tmp, " %ld MB over-allocated on %s.", amount_allocated - physical_drive_size, drive);
[128]510 log_it(tmp);
[2209]511 mr_strcat(flaws_str, "%s", tmp);
[2516]512 mr_free(tmp);
[128]513 res++;
514 } else if (amount_allocated < physical_drive_size - 1) { /* NOT AN ERROR, JUST A WARNING :-) */
[3191]515 mr_asprintf(tmp, " %ld MB unallocated on %s.", physical_drive_size - amount_allocated, drive);
[1236]516 log_it(tmp);
[2209]517 mr_strcat(flaws_str, "%s", tmp);
[2516]518 mr_free(tmp);
[1]519 }
520
[128]521 endoffunc:
522 paranoid_free(device);
[1]523
[2371]524 if (res == 0) {
525 mr_free(flaws_str);
[2380]526 log_msg(2, "Fine, no error in evaluate_drive_within_mountlist");
[2209]527 return (NULL);
[128]528 } else {
[2380]529 log_msg(2, "Error in evaluate_drive_within_mountlist: %s", flaws_str);
[2209]530 return (flaws_str);
[128]531 }
[1]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.
[2394]540 * @return The flaws string (NULL for success).
[1]541 * @see evaluate_drive_within_mountlist
542 */
[2394]543char *evaluate_mountlist(struct mountlist_itself *mountlist) {
[1]544
[128]545 /*@ buffer *********************************************************** */
546 struct list_of_disks *drivelist;
[2202]547 char *tmp = NULL;
[3611]548 char *tmp1 = NULL;
[2202]549 char *flaws_str = NULL;
[1]550
[2384]551 int currline = 0;
552 int copies = 0;
553 int last_copy = 0;
554
555 /*@ buffetr ********************************************************* */
556 char *curr_mountpoint = NULL;
557
[128]558 /*@ int ************************************************************** */
[1]559 int i = 0;
560
[128]561 /*@ initialize ******************************************************* */
[1]562
[128]563 drivelist = malloc(sizeof(struct list_of_disks));
564 assert(mountlist != NULL);
[1]565
[128]566 make_list_of_drives_in_mountlist(mountlist, drivelist);
[1]567
[128]568 log_it("Evaluating mountlist...");
[1]569
[128]570 for (i = 0; i < drivelist->entries; i++) {
[3236]571 if (strstr(drivelist->el[i].device, DONT_KNOW_HOW_TO_EVALUATE_THIS_DEVICE_TYPE)) {
[3191]572 log_it(" Not evaluating %s (I don't know how yet)", drivelist->el[i].device);
[128]573 } else {
[2235]574 log_msg(8, "Evaluating drive #%d (%s) within mountlist", i, drivelist->el[i].device);
[2304]575 tmp = evaluate_drive_within_mountlist(mountlist, drivelist->el[i].device);
[128]576 }
[2207]577 log_msg(8,"Entry: %d (%s)", i, drivelist->el[i].device);
[3430]578 /* TODO: tmp can be NULL */
[2219]579 if (tmp != NULL) {
[2394]580 log_msg(8,"Adding: %s to flaws_str", tmp);
[3279]581 if (flaws_str != NULL) {
582 mr_strcat(flaws_str, "%s", tmp);
583 } else {
584 mr_asprintf(flaws_str, "%s", tmp);
585 }
[3191]586 mr_free(tmp);
[2219]587 }
[1]588 }
[2384]589
590 /* Look for duplicate mountpoints in mountlist. */
591 for (currline = 0; currline < mountlist->entries; currline++) {
[3185]592 mr_asprintf(curr_mountpoint, "%s", mountlist->el[currline].mountpoint);
[2384]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 }
[3263]601 if (copies > 1 && last_copy == currline && strcmp(curr_mountpoint, "raid")) {
[3611]602 tmp1 = number_to_text(copies);
603 mr_asprintf(tmp, " %s %s's.", tmp1, curr_mountpoint);
604 mr_free(tmp1);
[2394]605 log_msg(8,"Adding: %s to flaws_str", tmp);
[3279]606 if (flaws_str != NULL) {
607 mr_strcat(flaws_str, "%s", tmp);
608 } else {
609 mr_asprintf(flaws_str, "%s", tmp);
610 }
[3191]611 mr_free(tmp);
[2384]612 }
[3191]613 mr_free(curr_mountpoint);
[2384]614 }
[2350]615 return(flaws_str);
[1]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
[128]627find_device_in_mountlist(struct mountlist_itself *mountlist, char *device)
[1]628{
629
[128]630 /*@ int ************************************************************** */
631 int i = 0;
[1]632
[128]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 }
[1]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
[128]654make_list_of_drives_in_mountlist(struct mountlist_itself *mountlist,
655 struct list_of_disks *drivelist)
[1]656{
657
[128]658 /*@ int ************************************************************* */
659 int lino;
660 int noof_drives;
661 int j;
[1]662
[128]663 /*@ buffers ********************************************************* */
[2204]664 char *drive = NULL;
[2230]665 char *truncdrive = NULL;
[1]666
[128]667 long long size;
[1]668
[128]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++) {
[1]673
[3185]674 mr_asprintf(drive, "%s", mountlist->el[lino].device);
[128]675 if (!strncmp(drive, RAID_DEVICE_STUB, strlen(RAID_DEVICE_STUB))) {
[2205]676 log_msg(8, "Not putting %s in list of drives: it's a virtual drive", drive);
[3191]677 mr_free(drive);
[128]678 continue;
679 }
[1]680
[128]681 size = mountlist->el[lino].size;
682 if (size == 0) {
[2205]683 log_msg(8, "Not putting %s in list of drives: it has zero size (maybe an LVM volume)", drive);
[3191]684 mr_free(drive);
[128]685 continue;
686 }
687
[2205]688 log_msg(8, "Putting %s with size %lli in list of drives", drive, size);
[1]689
[2237]690 /* memory allocation */
[2230]691 truncdrive = truncate_to_drive_name(drive);
[3191]692 mr_free(drive);
[2237]693
[2230]694 log_msg(8, "drive truncated to %s", truncdrive);
[2206]695
[128]696 for (j = 0;
697 j < noof_drives
[2230]698 && strcmp(drivelist->el[j].device, truncdrive) != 0; j++) {
[128]699 continue;
[2205]700 }
[128]701 if (j == noof_drives) {
[2237]702 strncpy(drivelist->el[noof_drives].device, truncdrive, 63);
[2235]703 drivelist->el[noof_drives].device[63] = '\0';
[2236]704 log_msg(8,"Adding drive %s to list", drivelist->el[noof_drives].device);
[2235]705 noof_drives++;
[128]706 }
[2230]707 paranoid_free(truncdrive);
[2237]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 }
[1]713 }
[128]714 drivelist->entries = noof_drives;
[2235]715 log_msg(8, "Made list of %d drives",noof_drives);
[1]716
[128]717 return (noof_drives);
[1]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 */
[128]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)
[1]734{
735
[128]736 /*@ int ************************************************************* */
737 int items = 0;
[1]738 int i = 0;
739 int used_by = 0;
740
[128]741 assert(output_list != NULL);
742 assert(mountlist != NULL);
743 assert(raidlist != NULL);
744 log_it("MLOURP -- starting");
745 items = 0;
[1]746
747
[128]748 for (i = 0; i < mountlist->entries; i++) {
749 if (strstr(mountlist->el[i].mountpoint, "raid")) {
[3191]750 used_by = which_raid_device_is_using_this_partition(raidlist, mountlist->el[i].device);
[128]751 if (used_by < 0) {
752 memcpy((void *) &output_list->el[items++],
753 (void *) &mountlist->el[i],
754 sizeof(struct mountlist_line));
[3191]755 log_it("%s is available; user may choose to add it to raid device", output_list->el[items - 1].device);
[128]756 }
757 }
[1]758 }
[128]759 output_list->entries = items;
760 log_it("MLUORP -- ending");
[1]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
[128]771size_of_specific_device_in_mountlist(struct mountlist_itself *mountlist,
772 char *device)
[1]773{
[128]774 /*@ int ************************************************************** */
775 int i = 0;
[1]776
777
[128]778 assert(mountlist != NULL);
779 assert_string_is_neither_NULL_nor_zerolength(device);
[1]780
[128]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 }
[1]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 */
[128]802int load_mountlist(struct mountlist_itself *mountlist, char *fname)
[1]803{
[2204]804 FILE *fin = NULL;
[128]805 /* malloc ** */
[2204]806 char *incoming = NULL;
807 char *siz = NULL;
808 char *tmp = NULL;
809 char *p = NULL;
[1]810
[2204]811 int items = 0;
812 int j = 0;
813 int res = 0;
[1]814
[128]815 assert(mountlist != NULL);
816 assert_string_is_neither_NULL_nor_zerolength(fname);
[2204]817
[128]818 if (!(fin = fopen(fname, "r"))) {
819 log_it("Unable to open mountlist - '%s'", fname);
[541]820 log_to_screen("Cannot open mountlist");
[128]821 return (1);
822 }
[2204]823 malloc_string(siz);
[128]824 log_it("Loading mountlist...");
[3191]825 mr_getline(incoming, fin);
826 while (!feof(fin)) {
[1]827#if linux
[3191]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);
[2204]829 if (res < 5) {
830 /* no label found */
[2206]831 log_msg(4, "no label found for %s",mountlist->el[items].device);
832 strcpy(mountlist->el[items].label,"");
[2204]833 }
[1]834#elif __FreeBSD__
[3191]835 res = sscanf(incoming, "%s %s %s %s", mountlist->el[items].device, mountlist->el[items].mountpoint, mountlist->el[items].format, siz);
[2206]836 strcpy(mountlist->el[items].label,"");
[1]837#endif
838
[128]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") ||
[2918]843 !strcmp(mountlist->el[items].device, "/run") ||
844 !strcmp(mountlist->el[items].device, "run") ||
[128]845 !strcmp(mountlist->el[items].device, "/devpts") ||
846 !strcmp(mountlist->el[items].device, "devpts")
847 ) {
[3191]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);
[128]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");
[3191]862 log_it("Duplicate entry in mountlist - renaming to %s", mountlist->el[items].device);
[128]863 }
[3185]864 mr_asprintf(tmp, "%s", mountlist->el[items].device);
[128]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 }
[3191]873 log_it("It was %s; it is now %s", mountlist->el[items].device, tmp);
[128]874 strcpy(mountlist->el[items].device, tmp);
875 }
[2204]876 paranoid_free(tmp);
[1]877
[3191]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);
[128]879 items++;
[2206]880 if (items >= MAX_MOUNTLIST_ENTRIES) {
881 log_to_screen("Too many lines in mountlist.. ABORTING");
882 finish(1);
883 }
[128]884 }
[3191]885 mr_free(incoming);
886 mr_getline(incoming, fin);
[1]887 }
[3191]888 mr_free(incoming);
[128]889 paranoid_fclose(fin);
890 mountlist->entries = items;
[1]891
[128]892 log_it("Mountlist loaded successfully.");
[2204]893 log_it("%d entries in mountlist", items);
894
[128]895 paranoid_free(siz);
896 return (0);
[1]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 */
[128]908int save_mountlist_to_disk(struct mountlist_itself *mountlist, char *fname)
[1]909{
[128]910 FILE *fout;
911 int i;
[1]912
[128]913 assert(mountlist != NULL);
914 assert_string_is_neither_NULL_nor_zerolength(fname);
[1]915
[128]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,
[1909]923 "%-15s %-15s %-15s %-15lld %-15s\n",
[128]924 mountlist->el[i].device, mountlist->el[i].mountpoint,
925 mountlist->el[i].format, mountlist->el[i].size,
[1899]926 mountlist->el[i].label);
[128]927 }
928 paranoid_fclose(fout);
[2944]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);
[128]935 return (0);
[1]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 */
[128]944void sort_mountlist_by_device(struct mountlist_itself *mountlist)
[1]945{
[128]946 int diff;
947 int lino = -999;
[1]948
[128]949 assert(mountlist != NULL);
[1]950
[128]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 }
[1]961 }
962}
963
[2204]964
[1]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 */
[128]971void
972sort_mountlist_by_mountpoint(struct mountlist_itself *mountlist,
973 bool reverse)
[1]974{
[128]975 int diff;
976 int lino = -999;
[1]977
[128]978 assert(mountlist != NULL);
[1]979
[128]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 }
[1]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 */
[128]1000void
[1]1001swap_mountlist_entries(struct mountlist_itself *mountlist, int a, int b)
1002{
[128]1003 /*@ mallocs *** */
[2204]1004 char *device = NULL;
1005 char *mountpoint = NULL;
1006 char *format = NULL;
[1]1007
[128]1008 long long size;
[1]1009
[128]1010 assert(mountlist != NULL);
1011 assert(a >= 0);
1012 assert(b >= 0);
[1]1013
[3185]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);
[1]1017
[128]1018 size = mountlist->el[a].size;
[1]1019
[128]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);
[1]1023
[128]1024 mountlist->el[a].size = mountlist->el[b].size;
[1]1025
[128]1026 strcpy(mountlist->el[b].device, device);
1027 strcpy(mountlist->el[b].mountpoint, mountpoint);
1028 strcpy(mountlist->el[b].format, format);
[1]1029
[128]1030 mountlist->el[b].size = size;
[3191]1031 mr_free(device);
1032 mr_free(mountpoint);
1033 mr_free(format);
[1]1034}
1035
1036/* @} - end of mountlistGroup */
Note: See TracBrowser for help on using the repository browser.