source: trunk/mondo/mondo/common/libmondo-mountlist.c @ 507

Last change on this file since 507 was 507, checked in by bcornec, 13 years ago

merge -r489:506 $SVN_M/branches/stable

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