source: 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, 13 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
Line 
1/* libmondo-mountlist.c                            subroutines for handling mountlist
2   $Id: libmondo-mountlist.c 1645 2007-09-24 01:04:43Z bruno $
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 "newt-specific-EXT.h"
61
62/*@unused@*/
63//static char cvsid[] = "$Id: libmondo-mountlist.c 1645 2007-09-24 01:04:43Z bruno $";
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/* Reference to global bkpinfo */
72extern struct s_bkpinfo *bkpinfo;
73
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 */
90int evaluate_drive_within_mountlist(struct mountlist_itself *mountlist,
91                                    char *drive, char *flaws_str)
92#ifdef __FreeBSD__
93{
94// FreeBSD-specific version of evaluate_drive_within_mountlist()
95    /*@ int ************************************************************* */
96    int prev_part_no = 0;
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
107    /*@ buffers ******************************************************** */
108    char tmp[MAX_STR_LEN];
109    char device[MAX_STR_LEN];
110    char mountpoint[MAX_STR_LEN];
111
112    /*@ long *********************************************************** */
113    long physical_drive_size = 0;
114    long amount_allocated = 0;
115
116    /*@ pointers ******************************************************* */
117    char *part_table_fmt;
118
119    /*@ initialize ***************************************************** */
120    flaws_str[0] = '\0';
121    prev_part_no = 0;
122    tmp[0] = '\0';
123
124
125    physical_drive_size = get_phys_size_of_drive(drive);
126
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);
134
135
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)) {
195                sprintf(tmp, " %s has unsupported format %s.", device, mountlist->el[pos].format);
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    }
204
205    npos = pos = 0;
206    for (curr_part_no = 1; curr_part_no < 99; curr_part_no++) {
207        build_partition_name(device, drive, curr_part_no);
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
221        build_partition_name(device, drive, curr_part_no);
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)) {
288                sprintf(tmp, " %s has unsupported format %s.", device, mountlist->el[pos].format);
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)) {
348                    sprintf(tmp, " %s has unsupported format %s.", device, mountlist->el[pos].format);
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);
374        log_it(tmp);
375        strcat(flaws_str, tmp);
376    }
377    if (res) {
378        return (FALSE);
379    } else {
380        return (TRUE);
381    }
382}
383
384#else
385// Linux-specific version of evaluate_drive_within_mountlist()
386{
387
388    /*@ int ************************************************************* */
389    int prev_part_no = 0;
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
397    /*@ buffers ******************************************************** */
398    char *tmp;
399    char *device;
400
401    /*@ long *********************************************************** */
402    long physical_drive_size = 0L;
403    long amount_allocated = 0L;
404
405    /*@ pointers ******************************************************* */
406    char *part_table_fmt;
407
408    /*@ initialize ***************************************************** */
409    assert_string_is_neither_NULL_nor_zerolength(drive);
410    assert(mountlist != NULL);
411    assert(flaws_str != NULL);
412
413    malloc_string(tmp);
414    malloc_string(device);
415    flaws_str[0] = '\0';
416    prev_part_no = 0;
417    tmp[0] = '\0';
418
419
420    physical_drive_size = get_phys_size_of_drive(drive);
421
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    }
432
433    for (curr_part_no = 1; curr_part_no < 99; curr_part_no++) {
434        build_partition_name(device, drive, curr_part_no);
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)) {
448                sprintf(tmp, " Gap on %s between %d and %d.", drive,
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)) {
460            sprintf(tmp, " Partition 4 of %s is occupied.", drive);
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)) {
502            sprintf(tmp, " %s has unsupported format %s.", device, mountlist->el[pos].format);
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;
510    }
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);
522        log_it(tmp);
523        strcat(flaws_str, tmp);
524    }
525
526  endoffunc:
527    paranoid_free(tmp);
528    paranoid_free(device);
529
530    if (res) {
531        return (FALSE);
532    } else {
533        return (TRUE);
534    }
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
551evaluate_mountlist(struct mountlist_itself *mountlist, char *flaws_str_A,
552                   char *flaws_str_B, char *flaws_str_C)
553{
554
555    /*@ buffer *********************************************************** */
556    struct list_of_disks *drivelist;
557    char *tmp;
558    char *flaws_str;
559
560    /*@ int ************************************************************** */
561    int i = 0;
562    int res = 0;
563
564    /*@ initialize ******************************************************* */
565
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';
574
575    make_list_of_drives_in_mountlist(mountlist, drivelist);
576
577    log_it("Evaluating mountlist...");
578
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);
594    }
595    res += look_for_duplicate_mountpoints(mountlist, flaws_str);
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 */
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));
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
612find_device_in_mountlist(struct mountlist_itself *mountlist, char *device)
613{
614
615    /*@ int ************************************************************** */
616    int i = 0;
617    char *tmp;
618    char *flaws_str;
619
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    }
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
650look_for_duplicate_mountpoints(struct mountlist_itself *mountlist,
651                               char *flaws_str)
652{
653
654    /*@ int ************************************************************* */
655    int res = 0;
656    int currline = 0;
657    int i = 0;
658    int copies = 0;
659    int last_copy = 0;
660
661    /*@ buffetr ********************************************************* */
662    char *curr_mountpoint;
663    char *tmp;
664
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        }
688    }
689    paranoid_free(curr_mountpoint);
690    paranoid_free(tmp);
691    return (res);
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
702look_for_weird_formats(struct mountlist_itself *mountlist, char *flaws_str)
703{
704
705    /*@ int ************************************************************* */
706    int i = 0;
707    int res = 0;
708
709    /*@ buffers ********************************************************* */
710    char *tmp;
711    char *format_sz;
712
713    malloc_string(tmp);
714    malloc_string(format_sz);
715
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        }
739    }
740    paranoid_free(tmp);
741    paranoid_free(format_sz);
742    return (res);
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
754make_list_of_drives_in_mountlist(struct mountlist_itself *mountlist,
755                                 struct list_of_disks *drivelist)
756{
757
758    /*@ int ************************************************************* */
759    int lino;
760    int noof_drives;
761    int j;
762
763    /*@ buffers ********************************************************* */
764    char *drive;
765    char *tmp;
766
767    long long size;
768
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++) {
775
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        }
784
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
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
805        sprintf(tmp,
806                "Putting %s with size %lli in list of drives",
807                drive, size);
808        log_msg(8, tmp);
809
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        }
818    }
819    drivelist->entries = noof_drives;
820    log_msg(8, "Made list of drives");
821    paranoid_free(drive);
822    paranoid_free(tmp);
823
824    return (noof_drives);
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 */
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)
845{
846
847    /*@ int ************************************************************* */
848    int items = 0;
849    int i = 0;
850    int used_by = 0;
851
852    /*@ buffers ********************************************************* */
853    char *tmp;
854
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;
861
862
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        }
879    }
880    output_list->entries = items;
881    log_it("MLUORP -- ending");
882    paranoid_free(tmp);
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
896size_of_specific_device_in_mountlist(struct mountlist_itself *mountlist,
897                                     char *device)
898{
899    /*@ int ************************************************************** */
900    int i = 0;
901
902
903    assert(mountlist != NULL);
904    assert_string_is_neither_NULL_nor_zerolength(device);
905
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    }
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 */
929int load_mountlist(struct mountlist_itself *mountlist, char *fname)
930{
931    FILE *fin;
932    /* malloc ** */
933    char *incoming;
934    char *siz;
935    char *tmp;
936    char *p;
937
938    int items;
939    int j;
940
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);
948        log_to_screen("Cannot open mountlist");
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)) {
958#if linux
959        sscanf(incoming,
960               "%s %s %s %s %s %s",
961               mountlist->el[items].device,
962               mountlist->el[items].mountpoint,
963               mountlist->el[items].format,
964               siz, mountlist->el[items].label, mountlist->el[items].uuid);
965#elif __FreeBSD__
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, "");
972        strcpy(mountlist->el[items].uuid, "");
973#endif
974
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) {
992                log_to_screen("Too many lines in mountlist.. ABORTING");
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            }
1019
1020            sprintf(tmp,
1021                    "%s %s %s %lld %s %s",
1022                    mountlist->el[items].device,
1023                    mountlist->el[items].mountpoint,
1024                    mountlist->el[items].format,
1025                    mountlist->el[items].size,
1026                    mountlist->el[items].label,
1027                    mountlist->el[items].uuid);
1028
1029            log_it(tmp);
1030            items++;
1031        }
1032        (void) fgets(incoming, MAX_STR_LEN - 1, fin);
1033    }
1034    paranoid_fclose(fin);
1035    mountlist->entries = items;
1036
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);
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 */
1055int save_mountlist_to_disk(struct mountlist_itself *mountlist, char *fname)
1056{
1057    FILE *fout;
1058    int i;
1059
1060    assert(mountlist != NULL);
1061    assert_string_is_neither_NULL_nor_zerolength(fname);
1062
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,
1070                "%-15s %-15s %-15s %-15lld %-15s %-15s\n",
1071                mountlist->el[i].device, mountlist->el[i].mountpoint,
1072                mountlist->el[i].format, mountlist->el[i].size,
1073                mountlist->el[i].label, mountlist->el[i].uuid);
1074    }
1075    paranoid_fclose(fout);
1076    return (0);
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 */
1086void sort_mountlist_by_device(struct mountlist_itself *mountlist)
1087{
1088    int diff;
1089    int lino = -999;
1090
1091    assert(mountlist != NULL);
1092
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        }
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 */
1112void
1113sort_mountlist_by_mountpoint(struct mountlist_itself *mountlist,
1114                             bool reverse)
1115{
1116    int diff;
1117    int lino = -999;
1118
1119    assert(mountlist != NULL);
1120
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        }
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 */
1141void
1142swap_mountlist_entries(struct mountlist_itself *mountlist, int a, int b)
1143{
1144    /*@ mallocs *** */
1145    char device[64];
1146    char mountpoint[256];
1147    char format[64];
1148
1149    long long size;
1150
1151    assert(mountlist != NULL);
1152    assert(a >= 0);
1153    assert(b >= 0);
1154
1155    strcpy(device, mountlist->el[a].device);
1156    strcpy(mountpoint, mountlist->el[a].mountpoint);
1157    strcpy(format, mountlist->el[a].format);
1158
1159    size = mountlist->el[a].size;
1160
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);
1164
1165    mountlist->el[a].size = mountlist->el[b].size;
1166
1167    strcpy(mountlist->el[b].device, device);
1168    strcpy(mountlist->el[b].mountpoint, mountpoint);
1169    strcpy(mountlist->el[b].format, format);
1170
1171    mountlist->el[b].size = size;
1172}
1173
1174/* @} - end of mountlistGroup */
Note: See TracBrowser for help on using the repository browser.