source: branches/2.04_berlios/mondo/mondo/common/libmondo-mountlist.c @ 2708

Last change on this file since 2708 was 2708, checked in by bruno, 8 years ago

r4184@localhost: bruno | 2011-01-27 15:52:51 +0100

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