source: MondoRescue/trunk/mondo/src/common/libmondo-mountlist.c@ 1161

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

Update trunk with the latest feedback from stable (obtained with meld) - First pass

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