source: branches/stable/mondo/mondo/common/libmondo-mountlist.c @ 541

Last change on this file since 541 was 541, checked in by bcornec, 14 years ago

Stable is reverted to r436 (2.0.7) to put it in line with 2.0.8 and start from there over

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