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

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

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

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