source: MondoRescue/branches/3.2/mondo/src/mondorestore/mondo-rstr-newt.c@ 3611

Last change on this file since 3611 was 3611, checked in by Bruno Cornec, 7 years ago

Remove more static allocation

  • Property svn:keywords set to Id
File size: 83.9 KB
Line 
1/***************************************************************************
2 * $Id: mondo-rstr-newt.c 3611 2016-11-10 20:09:54Z bruno $
3 * Functions for handling GUI interfaces in the restore.
4 */
5
6#ifdef __FreeBSD__
7#define OSSWAP(linux,fbsd) fbsd
8#else
9#define OSSWAP(linux,fbsd) linux
10#endif
11
12#include "mondo-rstr-newt.h"
13#include "mr_mem.h"
14#include "mr_str.h"
15
16//static char cvsid[] = "$Id: mondo-rstr-newt.c 3611 2016-11-10 20:09:54Z bruno $";
17
18extern bool popup_with_buttons(char *p, char *button1, char *button2);
19extern char err_log_lines[NOOF_ERR_LINES][MAX_STR_LEN];
20
21/**
22 * @defgroup restoreGuiDisklist Disklist GUI
23 * Functions for manipulating the disklist GUI.
24 * @ingroup restoreGuiGroup
25 */
26/**
27 * @defgroup restoreGuiMountlist Mountlist GUI
28 * Functions for manipulating the mountlist/raidlist GUI.
29 * @ingroup restoreGuiGroup
30 */
31/**
32 * @defgroup restoreGuiVarslist RAID Variables GUI
33 * Functions for manipulating the RAID variables GUI.
34 * @ingroup restoreGuiGroup
35 */
36
37/**
38 * @addtogroup restoreGuiGroup
39 * @{
40 */
41/**
42 * Add an entry in @p disklist from the list in @p unallocated_raid_partitions.
43 * @param disklist The disklist to add an entry to.
44 * @param raid_device Unused; make sure it's non-NULL non-"".
45 * @param unallocated_raid_partitions The list of unallocated RAID partitions
46 * that the user may choose from.
47 * @bug raid_device is unused.
48 * @ingroup restoreGuiDisklist
49 */
50void
51add_disklist_entry(struct list_of_disks *disklist, char *raid_device,
52 struct mountlist_itself *unallocated_raid_partitions)
53{
54 /** buffers ***********************************************************/
55 char *tmp = NULL;
56
57 /** newt **************************************************************/
58 newtComponent myForm;
59 newtComponent bOK;
60 newtComponent bCancel;
61 newtComponent b_res;
62 newtComponent partitionsListbox;
63 newtComponent headerMsg;
64
65 /** prototypes *********************************************************/
66 void *keylist[ARBITRARY_MAXIMUM];
67 void *curr_choice;
68
69 /** int ****************************************************************/
70 int i = 0;
71 int index = 0;
72 int currline = 0;
73 int items = 0;
74
75 assert(disklist != NULL);
76 assert_string_is_neither_NULL_nor_zerolength(raid_device);
77 assert(unallocated_raid_partitions != NULL);
78
79 newtPushHelpLine
80 (" Add one of the following unallocated RAID partitions to this RAID device.");
81 mr_asprintf(tmp, "%-26s %s", "Device", "Size");
82 headerMsg = newtLabel(1, 1, tmp);
83 partitionsListbox =
84 newtListbox(1, 2, 6, NEWT_FLAG_SCROLL | NEWT_FLAG_RETURNEXIT);
85 redraw_unallocpartnslist(unallocated_raid_partitions, keylist,
86 partitionsListbox);
87 i = 7;
88 bOK = newtCompactButton(i, 9, " OK ");
89 bCancel = newtCompactButton(i += 9, 9, "Cancel");
90 newtOpenWindow(22, 6, 36, 10, "Unallocated RAID partitions");
91 myForm = newtForm(NULL, NULL, 0);
92 newtFormAddComponents(myForm, headerMsg, partitionsListbox, bOK,
93 bCancel, NULL);
94 b_res = newtRunForm(myForm);
95 if (b_res != bCancel) {
96 curr_choice = newtListboxGetCurrent(partitionsListbox);
97 for (currline = 0;
98 currline < unallocated_raid_partitions->entries
99 && keylist[currline] != curr_choice; currline++);
100 if (currline == unallocated_raid_partitions->entries
101 && unallocated_raid_partitions->entries > 0) {
102 log_it("I don't know what this button does");
103 } else {
104 index = find_next_free_index_in_disklist(disklist);
105
106 items = disklist->entries;
107 strcpy(disklist->el[items].device, unallocated_raid_partitions->el[currline].device);
108 disklist->el[items].index = index;
109 disklist->entries = ++items;
110
111 }
112 }
113 newtFormDestroy(myForm);
114 mr_free(tmp);
115 newtPopWindow();
116 newtPopHelpLine();
117}
118
119
120
121
122/**
123 * Add an entry to @p mountlist.
124 * @param mountlist The mountlist to add an entry to.
125 * @param raidlist The raidlist that accompanies @p mountlist.
126 * @param listbox The listbox component in the mountlist editor.
127 * @param currline The line selected in @p listbox.
128 * @param keylist The list of keys for @p listbox.
129 * @ingroup restoreGuiMountlist
130 */
131void
132add_mountlist_entry(struct mountlist_itself *mountlist,
133 struct raidlist_itself *raidlist,
134 newtComponent listbox, int currline, void *keylist[])
135{
136
137 /** int **************************************************************/
138 int i = 0;
139
140 /** newt *************************************************************/
141 newtComponent myForm;
142 newtComponent bOK;
143 newtComponent bCancel;
144 newtComponent b_res;
145 newtComponent mountpointComp;
146 newtComponent label0;
147 newtComponent label1;
148 newtComponent label2;
149 newtComponent label3;
150 newtComponent sizeComp;
151 newtComponent deviceComp;
152 newtComponent formatComp;
153
154 /** buffers **********************************************************/
155 char *drive_to_add = NULL;
156 char *mountpoint_str = NULL;
157 char *size_str = NULL;
158 char *device_str = NULL;
159 char *format_str = NULL;
160
161 /** pointers *********************************************************/
162 char *mountpoint_here;
163 char *size_here;
164 char *device_here;
165 char *format_here;
166
167 assert(mountlist != NULL);
168 assert(raidlist != NULL);
169 assert(listbox != NULL);
170 assert(keylist != NULL);
171
172 mr_asprintf(device_str, "/dev/");
173 mr_asprintf(mountpoint_str, "/");
174 mr_asprintf(size_str, "");
175#ifdef __FreeBSD__
176 mr_asprintf(format_str, "ufs");
177#else
178 mr_asprintf(format_str, "ext3");
179#endif
180 newtOpenWindow(20, 5, 48, 10, "Add entry");
181 label0 = newtLabel(2, 1, "Device: ");
182 label1 = newtLabel(2, 2, "Mountpoint:");
183 label2 = newtLabel(2, 3, "Size (MB): ");
184 label3 = newtLabel(2, 4, "Format: ");
185 deviceComp = newtEntry(14, 1, device_str, 30, (void *) &device_here, 0);
186 mountpointComp = newtEntry(14, 2, mountpoint_str, 30, (void *) &mountpoint_here, 0);
187 formatComp = newtEntry(14, 4, format_str, 15, (void *) &format_here, 0);
188 sizeComp = newtEntry(14, 3, size_str, 10, (void *) &size_here, 0);
189 bOK = newtButton(5, 6, " OK ");
190 bCancel = newtButton(17, 6, "Cancel");
191 newtPushHelpLine
192 ("To add an entry to the mountlist, please fill in these fields and then hit 'OK'");
193 myForm = newtForm(NULL, NULL, 0);
194 newtFormAddComponents(myForm, deviceComp, mountpointComp, sizeComp,
195 formatComp, label0, label1, label2, label3, bOK,
196 bCancel, NULL);
197 for (b_res = NULL; b_res != bOK && b_res != bCancel;) {
198 b_res = newtRunForm(myForm);
199 mr_free(device_str);
200 mr_asprintf(device_str, "%s", device_here);
201
202 mr_free(mountpoint_str);
203 mr_asprintf(mountpoint_str, "%s", mountpoint_here);
204 mr_strip_spaces(mountpoint_str);
205
206 mr_free(format_str);
207 mr_asprintf(format_str, "%s", format_here);
208 mr_strip_spaces(format_str);
209
210 mr_free(size_str);
211 mr_asprintf(size_str, "%s", size_here);
212 mr_strip_spaces(size_str);
213
214 mr_strip_spaces(device_str);
215 if (b_res == bOK) {
216 if (device_str[strlen(device_str) - 1] == '/') {
217 popup_and_OK("You left the device nearly blank!");
218 b_res = NULL;
219 }
220 if (size_of_specific_device_in_mountlist(mountlist, device_str) >= 0) {
221 popup_and_OK("Can't add this - you've got one already!");
222 b_res = NULL;
223 }
224 }
225 }
226 newtFormDestroy(myForm);
227 newtPopHelpLine();
228 newtPopWindow();
229 if (b_res == bCancel) {
230 return;
231 }
232 mr_asprintf(drive_to_add, "%s", device_str);
233 for (i = strlen(drive_to_add); isdigit(drive_to_add[i - 1]); i--);
234 mr_free(drive_to_add);
235
236 currline = mountlist->entries;
237 strcpy(mountlist->el[currline].device, device_str);
238 strcpy(mountlist->el[currline].mountpoint, mountpoint_str);
239 mr_free(mountpoint_str);
240
241 strcpy(mountlist->el[currline].format, format_str);
242 mr_free(format_str);
243
244 mountlist->el[currline].size = atol(size_str) * 1024L;
245 mr_free(size_str);
246
247 mountlist->entries++;
248 if (strstr(mountlist->el[currline].device, RAID_DEVICE_STUB)) {
249 initiate_new_raidlist_entry(raidlist, mountlist, currline, device_str);
250 }
251 mr_free(device_str);
252
253 redraw_mountlist(mountlist, keylist, listbox);
254}
255
256
257#ifndef __FreeBSD__
258/**
259 * Add an entry to the additional RAID variables section of @p raidrec.
260 * @param raidrec The RAID device record containing the RAID variables list to add to.
261 * @ingroup restoreGuiVarslist
262 */
263void add_varslist_entry(struct raid_device_record *raidrec)
264{
265
266 /** buffers ***********************************************************/
267 char sz_out[MAX_STR_LEN];
268
269 /** int ****************************************************************/
270 int items = 0;
271 int i = 0;
272
273 assert(raidrec != NULL);
274
275 sz_out[0] = '\0';
276 if (popup_and_get_string
277 ("Add variable", "Enter the name of the variable to add", sz_out,
278 MAX_STR_LEN)) {
279 strip_spaces(sz_out);
280 items = raidrec->additional_vars.entries;
281 for (i = 0;
282 i < items
283 && strcmp(raidrec->additional_vars.el[i].label, sz_out); i++);
284 if (i < items) {
285 popup_and_OK
286 ("No need to add that variable. It is already listed here.");
287 } else {
288 strcpy(raidrec->additional_vars.el[items].label, sz_out);
289 edit_varslist_entry(raidrec, items);
290 raidrec->additional_vars.entries = ++items;
291 }
292 }
293}
294#endif
295
296/**
297 * Calculate the size of @p raid_device.
298 * @param mountlist The mountlist containing information about the user's partitions.
299 * @param raidlist The raidlist that goes with @p mountlist.
300 * @param raid_device The device to calculate the size of.
301 * @return The size of the RAID device in Kilobytes.
302 * @ingroup restoreUtilityGroup
303 */
304long
305calculate_raid_device_size(struct mountlist_itself *mountlist,
306 struct raidlist_itself *raidlist,
307 char *raid_device)
308{
309#ifdef __FreeBSD__
310 /** FreeBSD-specific version of calculate_raid_device_size() **/
311
312 /** structures ********************************************************/
313 struct vinum_volume *raidrec;
314
315 /** int ***************************************************************/
316 int i = 0, j = 0;
317 int noof_partitions = 0;
318
319 /** long **************************************************************/
320 long total_size = 0;
321 long plex_size = 0;
322 long smallest_partition = 999999999;
323 long smallest_plex = 999999999;
324 long sp = 0;
325
326 /** buffers ***********************************************************/
327 char tmp = NULL;
328 char *devname = NULL;
329
330 for (i = 0;
331 i < raidlist->entries
332 && strcmp(raidlist->el[i].volname, basename(raid_device)); i++);
333 if (i == raidlist->entries) {
334 log_it("Cannot calc size of raid device %s - cannot find it in raidlist", raid_device);
335 return (0); // Isn't this more sensible than 999999999? If the raid dev !exists,
336 // then it has no size, right?
337 }
338 raidrec = &raidlist->el[i];
339 total_size = 0;
340 if (raidrec->plexes == 0)
341 return 0;
342 for (j = 0; j < raidrec->plexes; j++) {
343 plex_size = 0;
344 int k = 0, l = 0;
345 for (k = 0; k < raidrec->plex[j].subdisks; ++k) {
346 mr_asprintf(devname, "%s", raidrec->plex[j].sd[k].which_device);
347 for (l = 0; l < raidlist->disks.entries; ++l) {
348 if (!strcmp(devname, raidlist->disks.el[l].name)) {
349 switch (raidrec->plex[j].raidlevel) {
350 case -1:
351 plex_size +=
352 size_of_specific_device_in_mountlist(mountlist,
353 raidlist->
354 disks.
355 el[l].
356 device);
357 break;
358 case 0:
359 case 5:
360 if (size_of_specific_device_in_mountlist(mountlist,
361 raidlist->
362 disks.
363 el[l].
364 device) <
365 smallest_partition) {
366 smallest_partition =
367 size_of_specific_device_in_mountlist
368 (mountlist, raidlist->disks.el[l].device);
369 }
370 break;
371 }
372 }
373 }
374 mr_free(devname);
375 }
376
377 if (!is_this_raid_personality_registered
378 (raidrec->plex[j].raidlevel)) {
379 log_it
380 ("%s has a really weird RAID level - couldn't calc size :(",
381 raid_device);
382 return (999999999);
383 }
384 if (raidrec->plex[j].raidlevel != -1) {
385 plex_size = smallest_partition * (raidrec->plex[j].subdisks -
386 (raidrec->plex[j].
387 raidlevel == 5 ? 1 : 0));
388 }
389 if (plex_size < smallest_plex)
390 smallest_plex = plex_size;
391
392 smallest_partition = 999999999;
393 }
394
395 log_it("I have calculated %s's real size to be %ld", raid_device, (long) smallest_plex);
396 return (smallest_plex);
397#else
398 /** Linux-specific version of calculate_raid_device_size() **/
399
400 /** structures ********************************************************/
401 struct raid_device_record *raidrec;
402
403 /** int ***************************************************************/
404 int i = 0;
405 int noof_partitions = 0;
406
407 /** long **************************************************************/
408 long total_size = 0;
409 long smallest_partition = 999999999;
410 long sp = 0;
411
412 assert(mountlist != NULL);
413 assert(raidlist != NULL);
414 assert_string_is_neither_NULL_nor_zerolength(raid_device);
415
416 for (i = 0;
417 i < raidlist->entries
418 && strcmp(raidlist->el[i].raid_device, raid_device); i++);
419 if (i == raidlist->entries) {
420 log_it("Cannot calc size of raid device %s - cannot find it in raidlist", raid_device);
421 return (999999999);
422 }
423 raidrec = &raidlist->el[i];
424 noof_partitions = raidrec->data_disks.entries;
425 if (raidrec->raid_level == -1 || raidrec->raid_level == 0) {
426 for (total_size = 0, i = 0; i < noof_partitions; i++) {
427 total_size +=
428 size_of_specific_device_in_mountlist(mountlist,
429 raidrec->data_disks.
430 el[i].device);
431 }
432 } else {
433 for (i = 0; i < noof_partitions; i++) {
434 sp = size_of_specific_device_in_mountlist(mountlist,
435 raidrec->data_disks.
436 el[i].device);
437 if (smallest_partition > sp) {
438 smallest_partition = sp;
439 }
440 }
441 total_size = smallest_partition * (noof_partitions - 1);
442 }
443 log_it("I have calculated %s's real size to be %ld", raid_device, (long) total_size);
444 return (total_size);
445#endif
446}
447
448
449
450/**
451 * Choose the RAID level for the RAID device record in @p raidrec.
452 * @param raidrec The RAID device record to set the RAID level of.
453 * @ingroup restoreGuiMountlist
454 */
455void
456choose_raid_level(struct OSSWAP (raid_device_record, vinum_plex) * raidrec)
457{
458
459#ifdef __FreeBSD__
460
461 /** int ***************************************************************/
462 int res = 0;
463 int out = 0;
464
465 /** buffers ***********************************************************/
466 char tmp[MAX_STR_LEN];
467 char *prompt = NULL;
468 char sz[MAX_STR_LEN];
469
470 mr_asprintf(prompt, "Please enter the RAID level you want. (concat, striped, raid5)");
471 if (raidrec->raidlevel == -1) {
472 strcpy(tmp, "concat");
473 } else if (raidrec->raidlevel == 0) {
474 strcpy(tmp, "striped");
475 } else {
476 sprintf(tmp, "raid%i", raidrec->raidlevel);
477 }
478 for (out = 999; out == 999;) {
479 res = popup_and_get_string("Specify RAID level", prompt, tmp, 10);
480 if (!res) {
481 mr_free(prompt);
482 return;
483 }
484 strip_spaces(tmp);
485 if (tmp[0] == '[' && tmp[strlen(tmp) - 1] == ']') {
486 strcpy(sz, tmp);
487 strncpy(tmp, sz + 1, strlen(sz) - 2);
488 tmp[strlen(sz) - 2] = '\0';
489 }
490 if (!strcmp(tmp, "concat")) {
491 out = -1;
492 } else if (!strcmp(tmp, "striped")) {
493 out = 0;
494 } else if (!strcmp(tmp, "raid5")) {
495 out = 5;
496 }
497 log_it(tmp);
498 if (is_this_raid_personality_registered(out)) {
499 log_it("Groovy. You've picked a RAID personality which is registered.");
500 } else {
501 if (ask_me_yes_or_no("You have chosen a RAID personality which is not registered with the kernel. Make another selection?"))
502 {
503 out = 999;
504 }
505 }
506 }
507 mr_free(prompt);
508
509 raidrec->raidlevel = out;
510#else
511 /** buffers ***********************************************************/
512 char tmp[MAX_STR_LEN];
513 char *personalities = NULL;
514 char *prompt = NULL;
515 char sz[MAX_STR_LEN];
516 int out = 0;
517 int res = 0;
518
519
520 assert(raidrec != NULL);
521 paranoid_system("grep Pers /proc/mdstat > /tmp/raid-personalities.txt 2> /dev/null");
522 mr_asprintf(personalities, "%s", last_line_of_file("/tmp/raid-personalities.txt"));
523 mr_asprintf(prompt, "Please enter the RAID level you want. %s", personalities);
524 mr_free(personalities);
525
526 if (raidrec->raid_level == -1) {
527 strcpy(tmp, "linear");
528 } else {
529 sprintf(tmp, "%d", raidrec->raid_level);
530 }
531 for (out = 999;
532 out != -1 && out != 0 && out != 1 && out != 4 && out != 5
533 && out != 10;) {
534 res = popup_and_get_string("Specify RAID level", prompt, tmp, 10);
535 if (!res) {
536 return;
537 }
538 strip_spaces(tmp);
539 if (tmp[0] == '[' && tmp[strlen(tmp) - 1] == ']') {
540 strcpy(sz, tmp);
541 strncpy(tmp, sz + 1, strlen(sz) - 2);
542 tmp[strlen(sz) - 2] = '\0';
543 }
544 if (!strcmp(tmp, "linear")) {
545 out = -1;
546 } else if (!strncmp(tmp, "raid", 4)) {
547 out = atoi(tmp + 4);
548 } else {
549 out = atoi(tmp);
550 }
551 log_it(tmp);
552 if (is_this_raid_personality_registered(out)) {
553 log_it("Groovy. You've picked a RAID personality which is registered.");
554 } else {
555 if (ask_me_yes_or_no("You have chosen a RAID personality which is not registered with the kernel. Make another selection?")) {
556 out = 999;
557 }
558 }
559 }
560 mr_free(prompt);
561
562 raidrec->raid_level = out;
563#endif
564}
565
566
567
568/**
569 * Delete the partitions in @p disklist from @p mountlist because they
570 * were part of a deleted RAID device.
571 * @param mountlist The mountlist containing information about the user's partitions.
572 * @param raidlist The raidlist that goes with @p mounntlist.
573 * @param disklist The list of disks to remove from @p mountlist.
574 * @ingroup restoreGuiDisklist
575 */
576void
577del_partns_listed_in_disklist(struct mountlist_itself *mountlist,
578 struct raidlist_itself *raidlist,
579 struct list_of_disks *disklist)
580{
581
582 /** int ***************************************************************/
583 int i = 0;
584 int pos = 0;
585
586 assert(mountlist != NULL);
587 assert(raidlist != NULL);
588 assert(disklist != NULL);
589
590 for (i = 0; i < disklist->entries; i++) {
591 for (pos = 0;
592 pos < mountlist->entries
593 && strcmp(mountlist->el[pos].device, disklist->el[i].device);
594 pos++);
595 if (pos < mountlist->entries) {
596 log_it("Deleting partition %s cos it was part of a now-defunct RAID", mountlist->el[pos].device);
597
598 memcpy((void *) &mountlist->el[pos],
599 (void *) &mountlist->el[mountlist->entries - 1],
600 sizeof(struct mountlist_line));
601 mountlist->entries--;
602 }
603 }
604}
605
606
607
608/**
609 * Delete entry number @p currline from @p disklist.
610 * @param disklist The disklist to remove the entry from.
611 * @param raid_device The RAID device containing the partition we're removing.
612 * Used only in the popup "are you sure?" box.
613 * @param currline The line number (starting from 0) of the item to delete.
614 * @ingroup restoreGuiDisklist
615 */
616void
617delete_disklist_entry(struct list_of_disks *disklist, char *raid_device,
618 int currline)
619{
620
621 /** int ***************************************************************/
622 int pos = 0;
623 int res = 0;
624
625 /** buffers ***********************************************************/
626 char *tmp = NULL;
627
628 assert(disklist != NULL);
629 assert_string_is_neither_NULL_nor_zerolength(raid_device);
630
631 mr_asprintf(tmp, "Delete %s from RAID device %s - are you sure?", disklist->el[currline].device, raid_device);
632 res = ask_me_yes_or_no(tmp);
633 mr_free(tmp);
634
635 if (!res) {
636 return;
637 }
638 for (pos = currline; pos < disklist->entries - 1; pos++) {
639 strcpy(disklist->el[pos].device, disklist->el[pos + 1].device);
640 }
641 disklist->entries--;
642}
643
644
645
646/**
647 * Delete entry number @p currline from @p mountlist.
648 * @param mountlist The mountlist to delete the entry from.
649 * @param raidlist The raidlist that goes with @p mountlist.
650 * @param listbox The Newt listbox component in the mountlist editor.
651 * @param currline The line number (starting from 0) of the item to delete.
652 * @param keylist The list of keys for @p listbox.
653 * @ingroup restoreGuiMountlist
654 */
655void
656delete_mountlist_entry(struct mountlist_itself *mountlist,
657 struct raidlist_itself *raidlist,
658 newtComponent listbox, int currline,
659 void *keylist[])
660{
661
662 /** int ***************************************************************/
663 int pos = 0;
664 int res = 0;
665
666 /** buffers ***********************************************************/
667 char *tmp = NULL;
668 char *device = NULL;
669
670
671 assert(mountlist != NULL);
672 assert(raidlist != NULL);
673 assert(listbox != NULL);
674 assert(keylist != NULL);
675
676 pos = which_raid_device_is_using_this_partition(raidlist, mountlist->el[currline].device);
677 if (pos >= 0) {
678 mr_asprintf(tmp, "Cannot delete %s: it is in use by RAID device %s", mountlist->el[currline].device, raidlist->el[pos].OSSWAP(raid_device, volname));
679 popup_and_OK(tmp);
680 mr_free(tmp);
681 return;
682 }
683 mr_asprintf(tmp, "Delete %s - are you sure?", mountlist->el[currline].device);
684 res = ask_me_yes_or_no(tmp);
685 mr_free(tmp);
686
687 if (!res) {
688 return;
689 }
690 if (strstr(mountlist->el[currline].device, RAID_DEVICE_STUB)) {
691 mr_asprintf(device, "%s", mountlist->el[currline].device);
692 delete_raidlist_entry(mountlist, raidlist, device);
693 for (currline = 0;
694 currline < mountlist->entries
695 && strcmp(mountlist->el[currline].device, device);
696 currline++);
697 mr_free(device);
698
699 if (currline == mountlist->entries) {
700 log_it("Dev is gone. I can't delete it. Ho-hum");
701 return;
702 }
703 }
704 memcpy((void *) &mountlist->el[currline],
705 (void *) &mountlist->el[mountlist->entries - 1],
706 sizeof(struct mountlist_line));
707 mountlist->entries--;
708 redraw_mountlist(mountlist, keylist, listbox);
709}
710
711
712/**
713 * Delete @p device from @p raidlist.
714 * @param mountlist The mountlist containing information about the user's partitions.
715 * @param raidlist The raidlist containing the RAID device to delete.
716 * @param device The device (e.g. /dev/md0) to delete.
717 * @ingroup restoreGuiMountlist
718 */
719void
720delete_raidlist_entry(struct mountlist_itself *mountlist,
721 struct raidlist_itself *raidlist, char *device)
722{
723
724 /** int ***************************************************************/
725 int i = 0;
726 int items = 0;
727
728 /** bool **************************************************************/
729 bool delete_partitions_too;
730
731 /** buffers ***********************************************************/
732 char *tmp = NULL;
733
734 assert(mountlist != NULL);
735 assert(raidlist != NULL);
736 assert_string_is_neither_NULL_nor_zerolength(device);
737
738 i = find_raid_device_in_raidlist(raidlist, device);
739 if (i < 0) {
740 return;
741 }
742 mr_asprintf(tmp, "Do you want me to delete %s's partitions, too?", device);
743 delete_partitions_too = ask_me_yes_or_no(tmp);
744 if (delete_partitions_too) {
745#ifdef __FreeBSD__
746 // static so it's zeroed
747 static struct list_of_disks d;
748 int x, y, z;
749
750 for (x = 0; x < raidlist->el[i].plexes; ++x) {
751 for (y = 0; y < raidlist->el[i].plex[x].subdisks; ++y) {
752 for (z = 0; z < raidlist->disks.entries; ++z) {
753 if (!strcmp(raidlist->el[i].plex[x].sd[y].which_device,
754 raidlist->disks.el[z].name)) {
755 strcpy(d.el[d.entries].name, raidlist->disks.el[z].name);
756 strcpy(d.el[d.entries++].device, raidlist->disks.el[z].device);
757 }
758 }
759 }
760 }
761
762 del_partns_listed_in_disklist(mountlist, raidlist, &d);
763#else
764 del_partns_listed_in_disklist(mountlist, raidlist,
765 &raidlist->el[i].data_disks);
766 del_partns_listed_in_disklist(mountlist, raidlist,
767 &raidlist->el[i].spare_disks);
768 del_partns_listed_in_disklist(mountlist, raidlist,
769 &raidlist->el[i].parity_disks);
770 del_partns_listed_in_disklist(mountlist, raidlist,
771 &raidlist->el[i].failed_disks);
772#endif
773 }
774 items = raidlist->entries;
775 if (items == 1) {
776 items = 0;
777 } else {
778 log_it(tmp);
779 memcpy((void *) &raidlist->el[i],
780 (void *) &raidlist->el[items - 1],
781 sizeof(struct OSSWAP (raid_device_record, vinum_volume)));
782 items--;
783 }
784 mr_free(tmp);
785 raidlist->entries = items;
786}
787
788
789#ifndef __FreeBSD__
790/**
791 * Delete entry number @p lino in the additional RAID variables section of @p raidrec.
792 * @param raidrec The RAID device record containing the RAID variable to delete.
793 * @param lino The line number (starting from 0) of the variable to delete.
794 * @ingroup restoreGuiVarslist
795 */
796void delete_varslist_entry(struct raid_device_record *raidrec, int lino)
797{
798
799 /** buffers ************************************************************/
800 char *tmp = NULL;
801 int res = 0;
802
803 /** structures *********************************************************/
804 struct additional_raid_variables *av;
805
806 assert(raidrec != NULL);
807
808 av = &raidrec->additional_vars;
809 mr_asprintf(tmp, "Delete %s - are you sure?", av->el[lino].label);
810 res = ask_me_yes_or_no(tmp);
811 mr_free(tmp);
812
813 if (res) {
814 if (!strcmp(av->el[lino].label, "persistent-superblock")
815 || !strcmp(av->el[lino].label, "chunk-size")) {
816 mr_asprintf(tmp, "%s must not be deleted. It would be bad.", av->el[lino].label);
817 popup_and_OK(tmp);
818 mr_free(tmp);
819 } else {
820 memcpy((void *) &av->el[lino], (void *) &av->el[av->entries--],
821 sizeof(struct raid_var_line));
822 }
823 }
824}
825#endif
826
827
828/**
829 * Redraw the filelist display.
830 * @param filelist The filelist structure to edit.
831 * @param keylist The list of keys for @p listbox.
832 * @param listbox The Newt listbox component containing some of the filelist entries.
833 * @return The number of lines currently being displayed.
834 * @ingroup restoreGuiGroup
835 */
836int
837redraw_filelist(struct s_node *filelist, void *keylist[ARBITRARY_MAXIMUM],
838 newtComponent listbox)
839{
840
841 /** int ***************************************************************/
842 static int lines_in_flist_window = 0;
843 static int depth = 0;
844
845 /** long **************************************************************/
846 long i = 0;
847
848 /** structures *******************************************************/
849 struct s_node *node;
850
851 /** buffers **********************************************************/
852 static char current_filename[MAX_STR_LEN];
853 char tmp[MAX_STR_LEN + 2];
854 char *tmp1 = NULL;
855
856 /** bool *************************************************************/
857 /* void*dummyptr; */
858 bool dummybool;
859 static bool warned_already;
860
861 assert(filelist != NULL);
862 assert(keylist != NULL);
863 assert(listbox != NULL);
864
865
866 if (depth == 0) {
867 lines_in_flist_window = 0;
868 warned_already = FALSE;
869 for (i = 0; i < ARBITRARY_MAXIMUM; i++) {
870 g_strings_of_flist_window[i][0] = '\0';
871 g_is_path_selected[i] = FALSE;
872 }
873 }
874 for (node = filelist; node != NULL; node = node->right) {
875 current_filename[depth] = node->ch;
876 if (node->down) {
877 depth++;
878 i = redraw_filelist(node->down, keylist, listbox);
879 depth--;
880 }
881 if (node->ch == '\0' && node->expanded) {
882 if (lines_in_flist_window == ARBITRARY_MAXIMUM) {
883 if (!warned_already) {
884 warned_already = TRUE;
885 mr_asprintf(tmp1, "Too many lines. Displaying first %d entries only. Close a directory to see more.", ARBITRARY_MAXIMUM);
886 popup_and_OK(tmp1);
887 mr_free(tmp1);
888 }
889 } else {
890 strcpy(g_strings_of_flist_window[lines_in_flist_window], current_filename);
891 g_is_path_selected[lines_in_flist_window] = node->selected;
892 lines_in_flist_window++;
893 }
894 }
895 }
896 if (depth == 0) {
897 if (lines_in_flist_window > ARBITRARY_MAXIMUM) {
898 lines_in_flist_window = ARBITRARY_MAXIMUM;
899 }
900/* do an elementary sort */
901 for (i = 1; i < lines_in_flist_window; i++) {
902 if (strcmp
903 (g_strings_of_flist_window[i],
904 g_strings_of_flist_window[i - 1]) < 0) {
905 mr_asprintf(tmp1, "%s", g_strings_of_flist_window[i]);
906 strcpy(g_strings_of_flist_window[i], g_strings_of_flist_window[i - 1]);
907 strcpy(g_strings_of_flist_window[i - 1], tmp1);
908 mr_free(tmp1);
909
910 dummybool = g_is_path_selected[i];
911 g_is_path_selected[i] = g_is_path_selected[i - 1];
912 g_is_path_selected[i - 1] = dummybool;
913 i = 0;
914 }
915 }
916/* write list to screen */
917 newtListboxClear(listbox);
918 for (i = 0; i < lines_in_flist_window; i++) {
919 sprintf(tmp, "%c%c %-80s", (g_is_path_selected[i] ? '*' : ' '),
920 (g_is_path_expanded[i] ? '+' : '-'),
921 strip_path(g_strings_of_flist_window[i]));
922 tmp[70] = '\0';
923 keylist[i] = (void *) i;
924 newtListboxAppendEntry(listbox, tmp, keylist[i]);
925 }
926 return (lines_in_flist_window);
927 } else {
928 return (0);
929 }
930}
931
932
933/**
934 * Strip a path to the bare minimum (^ pointing to the directory above, plus filename).
935 * @param tmp The path to strip.
936 * @return The stripped path.
937 * @author Conor Daly
938 * @ingroup restoreUtilityGroup
939 */
940char *strip_path(char *tmp)
941{
942
943 int i = 0, j = 0, slashcount = 0;
944 int slashloc = 0, lastslashloc = 0;
945
946 while (tmp[i] != '\0') { /* Count the slashes in tmp
947 1 slash per dir */
948 if (tmp[i] == '/') {
949 slashcount++;
950 lastslashloc = slashloc;
951 slashloc = i;
952 if (tmp[i + 1] == '\0') { /* if this slash is last char, back off */
953 slashcount--;
954 slashloc = lastslashloc;
955 }
956 }
957 i++;
958 }
959 if (slashcount > 0)
960 slashcount--; /* Keep one slash 'cos Hugh does... */
961
962 for (i = 0; i < slashcount; i++) { /* Replace each dir with a space char */
963 tmpnopath[i] = ' ';
964 }
965
966 i = slashloc;
967 j = slashcount;
968 while (tmp[i] != '\0') { /* Now add what's left of tmp */
969 if ((tmpprevpath[j] == ' ' || tmpprevpath[j] == '^')
970 && tmp[i] == '/' && tmpnopath[j - 1] != '^' && j != 0) { /* Add a pointer upwards if this is not in the same dir as line above */
971 tmpnopath[j - 1] = '^';
972 } else {
973 tmpnopath[j++] = tmp[i++];
974 }
975 }
976 tmpnopath[j] = '\0';
977
978 strcpy(tmpprevpath, tmpnopath); /* Make a copy for next iteration */
979
980 return (tmpnopath);
981}
982
983
984/**
985 * Allow the user to edit the filelist and choose which files to restore.
986 * @param filelist The node structure containing the filelist.
987 * @return 0 if the user pressed OK, 1 if they pressed Cancel.
988 */
989int edit_filelist(struct s_node *filelist)
990{
991
992 /** newt **************************************************************/
993 newtComponent myForm;
994 newtComponent bLess = NULL;
995 newtComponent bMore = NULL;
996 newtComponent bToggle = NULL;
997 newtComponent bOK = NULL;
998 newtComponent bCancel = NULL;
999 newtComponent b_res = NULL;
1000 newtComponent filelistListbox = NULL;
1001 newtComponent bRegex = NULL;
1002
1003 /** int ***************************************************************/
1004 int finished = FALSE;
1005 int lines_in_flist_window = 0;
1006 int indexno = 0;
1007 int j = 0;
1008
1009 /** ???? **************************************************************/
1010 void *curr_choice;
1011 void *keylist[ARBITRARY_MAXIMUM];
1012
1013 /** bool **************************************************************/
1014 bool dummybool;
1015
1016/* struct s_node *node; */
1017
1018 assert(filelist != NULL);
1019
1020 log_to_screen("Editing filelist");
1021 newtPushHelpLine
1022 (" Please edit the filelist to your satisfaction, then click OK or Cancel.");
1023 j = 4;
1024 bLess = newtCompactButton(j, 17, " Less ");
1025 bMore = newtCompactButton(j += 12, 17, " More ");
1026 bToggle = newtCompactButton(j += 12, 17, "Toggle");
1027 bRegex = newtCompactButton(j += 12, 17, "RegEx");
1028 bCancel = newtCompactButton(j += 12, 17, "Cancel");
1029 bOK = newtCompactButton(j += 12, 17, " OK ");
1030 filelistListbox =
1031 newtListbox(2, 1, 15, NEWT_FLAG_SCROLL | NEWT_FLAG_RETURNEXIT);
1032 toggle_all_root_dirs_on(filelist);
1033 lines_in_flist_window =
1034 redraw_filelist(filelist, keylist, filelistListbox);
1035 newtOpenWindow(1, 3, 77, 18, "Editing filelist");
1036 myForm = newtForm(NULL, NULL, 0);
1037 newtFormAddComponents(myForm, filelistListbox, bLess, bMore, bToggle,
1038 bRegex, bCancel, bOK, NULL);
1039 while (!finished) {
1040 b_res = newtRunForm(myForm);
1041 if (b_res == bOK) {
1042 finished =
1043 ask_me_yes_or_no
1044 ("Are you happy with your file selection?");
1045 } else if (b_res == bCancel) {
1046 finished = TRUE;
1047 } else if (b_res == bRegex) {
1048 popup_and_OK("I haven't implemented this yet...");
1049 } else {
1050 curr_choice = newtListboxGetCurrent(filelistListbox);
1051 for (indexno = 0;
1052 indexno < lines_in_flist_window
1053 && keylist[indexno] != curr_choice; indexno++);
1054 if (indexno == lines_in_flist_window) {
1055 log_it
1056 ("I don't know what this button does; assuming I am to toggle 1st entry");
1057 indexno = 0;
1058 }
1059 log_it("You selected '%s'", g_strings_of_flist_window[indexno]);
1060
1061 if (b_res == bMore) {
1062 g_is_path_expanded[indexno] = TRUE;
1063 toggle_path_expandability(filelist,
1064 g_strings_of_flist_window
1065 [indexno], TRUE);
1066 lines_in_flist_window =
1067 redraw_filelist(filelist, keylist, filelistListbox);
1068 newtListboxSetCurrentByKey(filelistListbox, curr_choice);
1069 } else if (b_res == bLess) {
1070 g_is_path_expanded[indexno] = FALSE;
1071 toggle_path_expandability(filelist,
1072 g_strings_of_flist_window
1073 [indexno], FALSE);
1074 lines_in_flist_window =
1075 redraw_filelist(filelist, keylist, filelistListbox);
1076 newtListboxSetCurrentByKey(filelistListbox, curr_choice);
1077 } else {
1078 if (!strcmp(g_strings_of_flist_window[indexno], "/")) {
1079 dummybool = !g_is_path_selected[indexno];
1080 for (j = 1; j < lines_in_flist_window; j++) {
1081 toggle_path_selection(filelist,
1082 g_strings_of_flist_window[j],
1083 dummybool);
1084 }
1085 } else {
1086 toggle_path_selection(filelist,
1087 g_strings_of_flist_window
1088 [indexno],
1089 !g_is_path_selected[indexno]);
1090 lines_in_flist_window =
1091 redraw_filelist(filelist, keylist,
1092 filelistListbox);
1093 }
1094 newtListboxSetCurrentByKey(filelistListbox, curr_choice);
1095 }
1096 for (indexno = 0;
1097 indexno < lines_in_flist_window
1098 && keylist[indexno] != curr_choice; indexno++);
1099 if (indexno == lines_in_flist_window) {
1100 log_it
1101 ("Layout of table has changed. Y pointer is reverting to zero.");
1102 indexno = 0;
1103 }
1104 }
1105 }
1106 newtFormDestroy(myForm);
1107 newtPopWindow();
1108 newtPopHelpLine();
1109 if (b_res == bOK) {
1110 return (0);
1111 } else {
1112/* popup_and_OK("You pushed 'cancel'. I shall now abort."); */
1113 return (1);
1114 }
1115}
1116
1117
1118/**
1119 * Edit an entry in @p mountlist.
1120 * @param mountlist The mountlist containing information about the user's partitions.
1121 * @param raidlist The raidlist to accompany @p mountlist.
1122 * @param listbox The Newt listbox component in the mountlist editor.
1123 * @param currline The selected line (starting from 0) in @p listbox.
1124 * @param keylist The list of keys for @p listbox.
1125 * @ingroup restoreGuiMountlist
1126 */
1127void
1128edit_mountlist_entry(struct mountlist_itself *mountlist,
1129 struct raidlist_itself *raidlist,
1130 newtComponent listbox, int currline, void *keylist[])
1131{
1132
1133 /** structures ********************************************************/
1134 static struct raidlist_itself bkp_raidlist;
1135
1136 /** newt **************************************************************/
1137 newtComponent myForm;
1138 newtComponent bOK;
1139 newtComponent bCancel;
1140 newtComponent b_res;
1141 newtComponent mountpointComp;
1142 newtComponent label0;
1143 newtComponent label1;
1144 newtComponent label2;
1145 newtComponent label3;
1146 newtComponent sizeComp;
1147 newtComponent deviceComp;
1148 newtComponent formatComp;
1149 newtComponent b_raid = NULL;
1150
1151 /** buffers ***********************************************************/
1152 char *device_str = NULL;
1153 char *mountpoint_str = NULL;
1154 char *size_str = NULL;
1155 char *format_str = NULL;
1156 char *tmp = NULL;
1157 char *device_used_to_be = NULL;
1158 char *mountpt_used_to_be = NULL;
1159
1160 /** pointers **********************************************************/
1161 char *device_here;
1162 char *mountpoint_here;
1163 char *size_here;
1164 char *format_here;
1165
1166 /** int ***************************************************************/
1167 int j = 0;
1168
1169 assert(mountlist != NULL);
1170 assert(raidlist != NULL);
1171 assert(listbox != NULL);
1172 assert(keylist != NULL);
1173
1174 memcpy((void *) &bkp_raidlist, (void *) raidlist,
1175 sizeof(struct raidlist_itself));
1176 mr_asprintf(device_str, "%s", mountlist->el[currline].device);
1177 mr_asprintf(device_used_to_be, "%s", mountlist->el[currline].device);
1178 mr_asprintf(mountpoint_str, "%s", mountlist->el[currline].mountpoint);
1179 mr_asprintf(mountpt_used_to_be, "%s", mountlist->el[currline].mountpoint);
1180 mr_asprintf(format_str, "%s", mountlist->el[currline].format);
1181 mr_asprintf(size_str, "%lld", mountlist->el[currline].size / 1024L);
1182 newtOpenWindow(20, 5, 48, 10, "Edit entry");
1183 label0 = newtLabel(2, 1, "Device:");
1184 label1 = newtLabel(2, 2, "Mountpoint:");
1185 label2 = newtLabel(2, 3, "Size (MB): ");
1186 label3 = newtLabel(2, 4, "Format: ");
1187 deviceComp = newtEntry(14, 1, device_str, 30, (void *) &device_here, 0);
1188 mountpointComp = newtEntry(14, 2, mountpoint_str, 30, (void *) &mountpoint_here, 0);
1189 formatComp = newtEntry(14, 4, format_str, 15, (void *) &format_here, 0);
1190 if (strstr(mountlist->el[currline].device, RAID_DEVICE_STUB)
1191 || !strcmp(mountlist->el[currline].mountpoint, "image")) {
1192 sizeComp = newtLabel(14, 3, size_str);
1193 } else {
1194 sizeComp = newtEntry(14, 3, size_str, 10, (void *) &size_here, 0);
1195 }
1196 bOK = newtButton(2, 6, " OK ");
1197 bCancel = newtButton(14, 6, "Cancel");
1198 if (strstr(mountlist->el[currline].device, RAID_DEVICE_STUB)) {
1199 b_raid = newtButton(26, 6, "RAID..");
1200 }
1201 newtPushHelpLine
1202 (" Edit this partition's mountpoint, size and format; then click 'OK'.");
1203 myForm = newtForm(NULL, NULL, 0);
1204 newtFormAddComponents(myForm, deviceComp, mountpointComp, sizeComp,
1205 formatComp, label0, label1, label2, label3, bOK,
1206 bCancel, b_raid, NULL);
1207 for (b_res = NULL; b_res != bOK && b_res != bCancel;) {
1208 b_res = newtRunForm(myForm);
1209 mr_free(device_str);
1210 mr_asprintf(device_str, "%s", device_here);
1211 mr_strip_spaces(device_str);
1212
1213 mr_free(mountpoint_str);
1214 mr_asprintf(mountpoint_str, "%s", mountpoint_here);
1215 mr_strip_spaces(mountpoint_str);
1216
1217 mr_free(format_str);
1218 mr_asprintf(format_str, "%s", format_here);
1219 mr_strip_spaces(format_str);
1220
1221 if (b_res == bOK && strstr(device_str, RAID_DEVICE_STUB)
1222 && strstr(device_used_to_be, RAID_DEVICE_STUB)
1223 && strcmp(device_str, device_used_to_be)) {
1224 popup_and_OK("You can't change /dev/mdX to /dev/mdY.");
1225 b_res = NULL;
1226 continue;
1227 } else if (b_res == bOK && !strcmp(mountpoint_str, "image")
1228 && strcmp(mountpt_used_to_be, "image")) {
1229 popup_and_OK("You can't change a regular device to an image.");
1230 b_res = NULL;
1231 continue;
1232 }
1233 if (!strstr(mountlist->el[currline].device, RAID_DEVICE_STUB)
1234 && strcmp(mountlist->el[currline].mountpoint, "image")) {
1235 mr_free(size_str);
1236 mr_asprintf(size_str, "%s", size_here);
1237 mr_strip_spaces(size_str);
1238 } else {
1239 mr_asprintf(size_str, "%ld", calculate_raid_device_size(mountlist, raidlist, mountlist->el[currline].device) / 1024);
1240 newtLabelSetText(sizeComp, size_str);
1241 }
1242 /* do not let user click RAID button if user has changed device_str */
1243 if (b_res == b_raid) {
1244 if (strcmp(device_str, mountlist->el[currline].device)) {
1245 /*
1246 can't change mountlist's entry from /dex/mdX to /dev/mdY: it would ugly
1247 when you try to map the changes over to the raidtab list, trust me
1248 */
1249 popup_and_OK
1250 ("You cannot edit the RAID settings until you have OK'd your change to the device node.");
1251 } else {
1252 j = find_raid_device_in_raidlist(raidlist,
1253 mountlist->el[currline].
1254 device);
1255 if (j < 0) {
1256 mr_asprintf(tmp, "/etc/raidtab does not have an entry for %s; please delete it and add it again", mountlist->el[currline].device);
1257 popup_and_OK(tmp);
1258 mr_free(tmp);
1259 } else {
1260 log_it("edit_raidlist_entry - calling");
1261 edit_raidlist_entry(mountlist, raidlist,
1262 &raidlist->el[j], currline);
1263 }
1264 }
1265 }
1266 }
1267 newtFormDestroy(myForm);
1268 newtPopHelpLine();
1269 newtPopWindow();
1270 mr_free(mountpt_used_to_be);
1271
1272 if (b_res == bCancel) {
1273 memcpy((void *) raidlist, (void *) &bkp_raidlist,
1274 sizeof(struct raidlist_itself));
1275 mr_free(device_str);
1276 mr_free(device_used_to_be);
1277 mr_free(format_str);
1278 mr_free(size_str);
1279 return;
1280 }
1281 strcpy(mountlist->el[currline].device, device_str);
1282 strcpy(mountlist->el[currline].mountpoint, mountpoint_str);
1283 mr_free(mountpoint_str);
1284
1285 strcpy(mountlist->el[currline].format, format_str);
1286 mr_free(format_str);
1287
1288 if (strcmp(mountlist->el[currline].mountpoint, "image")) {
1289 if (strstr(mountlist->el[currline].device, RAID_DEVICE_STUB)) {
1290 mountlist->el[currline].size =
1291 calculate_raid_device_size(mountlist, raidlist,
1292 mountlist->el[currline].device);
1293 } else {
1294 mountlist->el[currline].size = atol(size_str) * 1024L;
1295 }
1296 }
1297 mr_free(size_str);
1298
1299 tmp = mountlist_entry_to_string(mountlist, currline);
1300 newtListboxSetEntry(listbox, (long) keylist[currline], tmp);
1301 mr_free(tmp);
1302
1303 /* if new /dev/md RAID device then do funky stuff */
1304 if (strstr(mountlist->el[currline].device, RAID_DEVICE_STUB)
1305 && !strstr(device_used_to_be, RAID_DEVICE_STUB)) {
1306 initiate_new_raidlist_entry(raidlist, mountlist, currline, device_str);
1307 }
1308 /* if moving from RAID to non-RAID then do funky stuff */
1309 else if (strstr(device_used_to_be, RAID_DEVICE_STUB)
1310 && !strstr(device_str, RAID_DEVICE_STUB)) {
1311 delete_raidlist_entry(mountlist, raidlist, device_str);
1312 }
1313 /* if moving a non-RAID to another non-RAID then re-jig any RAID disks, if necessary */
1314 else if (!strstr(device_used_to_be, RAID_DEVICE_STUB)
1315 && !strstr(device_str, RAID_DEVICE_STUB)) {
1316 rejig_partition_name_in_raidlist_if_necessary(raidlist,
1317 device_used_to_be,
1318 device_str);
1319 }
1320/* else, moving a RAID to another RAID; bad idea, or so I thought */
1321#ifndef __FreeBSD__ /* It works fine under FBSD. */
1322 else if (strcmp(device_used_to_be, device_str)) {
1323 popup_and_OK("You are renaming a RAID device as another RAID device. I don't like it but I'll allow it.");
1324 }
1325#endif
1326 mr_free(device_str);
1327 mr_free(device_used_to_be);
1328
1329 redraw_mountlist(mountlist, keylist, listbox);
1330}
1331
1332
1333#if __FreeBSD__
1334/**
1335 * Add a subdisk to @p raidrec.
1336 * @param raidlist The raidlist containing information about RAID partitions.
1337 * @param raidrec The RAID device record to add the subdisk to.
1338 * @param temp The device name of the RAID disk to add it to.
1339 * @author Joshua Oreman
1340 * @ingroup restoreGuiMountlist
1341 */
1342void
1343add_raid_subdisk(struct raidlist_itself *raidlist,
1344 struct vinum_plex *raidrec, char *temp)
1345{
1346 int i;
1347 bool found = FALSE;
1348
1349 for (i = 0; i < raidlist->disks.entries; ++i) {
1350 if (!strcmp(raidlist->disks.el[i].device, temp)) {
1351 strcpy(raidrec->sd[raidrec->subdisks].which_device, raidlist->disks.el[i].name);
1352 found = TRUE;
1353 }
1354 }
1355 if (!found) {
1356 sprintf(raidlist->disks.el[raidlist->disks.entries].name, "drive%i", raidlist->disks.entries);
1357 sprintf(raidrec->sd[raidrec->subdisks].which_device, "drive%i", raidlist->disks.entries);
1358 strcpy(raidlist->disks.el[raidlist->disks.entries++].device, temp);
1359 }
1360 raidrec->subdisks++;
1361}
1362
1363
1364/**
1365 * Determine the /dev entry for @p vinum_name.
1366 * @param raidlist The raidlist containing information about RAID devices.
1367 * @param vinum_name The name of the Vinum drive to map to a /dev entry.
1368 * @return The /dev entry, or NULL if none was found.
1369 * @note The returned string points to static storage that will be overwritten with each call.
1370 * @author Joshua Oreman
1371 * @ingroup restoreUtilityGroup
1372 */
1373char *find_dev_entry_for_raid_device_name(struct raidlist_itself *raidlist,
1374 char *vinum_name)
1375{
1376 int i;
1377 for (i = 0; i < raidlist->disks.entries; ++i) {
1378 if (!strcmp(raidlist->disks.el[i].name, vinum_name)) {
1379 return raidlist->disks.el[i].device;
1380 }
1381 }
1382 return NULL;
1383}
1384
1385void
1386edit_raidlist_plex(struct mountlist_itself *mountlist,
1387 struct raidlist_itself *raidlist,
1388 struct vinum_plex *raidrec, int currline,
1389 int currline2);
1390
1391#endif
1392
1393
1394/**
1395 * Edit the entry for @p raidrec in @p raidlist.
1396 * @param mountlist The mountlist to get some information from.
1397 * @param raidlist The raidlist containing information about RAID devices.
1398 * @param raidrec The RAID device record for this partition.
1399 * @param currline The line number (starting from 0) in the mountlist of the RAID device.
1400 * @ingroup restoreGuiMountlist
1401 */
1402void
1403edit_raidlist_entry(struct mountlist_itself *mountlist,
1404 struct raidlist_itself *raidlist,
1405 struct OSSWAP (raid_device_record,
1406 vinum_volume) * raidrec, int currline)
1407{
1408
1409#ifdef __FreeBSD__
1410 /** structures ********************************************************/
1411 struct vinum_volume bkp_raidrec;
1412
1413
1414 /** buffers ***********************************************************/
1415 char title_of_editraidForm_window[MAX_STR_LEN];
1416
1417 /** newt **************************************************************/
1418 newtComponent editraidForm;
1419 newtComponent bOK;
1420 newtComponent bCancel;
1421 newtComponent bEdit;
1422 newtComponent bAdd;
1423 newtComponent bDelete;
1424 newtComponent b_res;
1425 newtComponent plexesListbox;
1426 newtComponent plexesHeader;
1427
1428 void *keylist[10];
1429 void *curr_choice;
1430 char *raidlevel = NULL;
1431 char *chunksize = NULL;
1432 char *msg = NULL;
1433
1434 int currline2 = 0;
1435 int res = 0;
1436
1437 log_it("Started edit_raidlist_entry");
1438 memcpy((void *) &bkp_raidrec, (void *) raidrec,
1439 sizeof(struct vinum_volume));
1440 sprintf(title_of_editraidForm_window, "Plexes on %s",
1441 raidrec->volname);
1442 newtPushHelpLine(" Please select a plex to edit");
1443 newtOpenWindow(13, 5, 54, 15, title_of_editraidForm_window);
1444 for (;;) {
1445 int i;
1446 char headerstr[MAX_STR_LEN];
1447 snprintf(headerstr, MAX_STR_LEN, "%-14s %-8s %11s %8s",
1448 "Plex", "Level", "Stripe Size", "Subdisks");
1449
1450 bOK = newtCompactButton(2, 13, " OK ");
1451 bCancel = newtCompactButton(12, 13, "Cancel");
1452 bAdd = newtCompactButton(22, 13, " Add ");
1453 bEdit = newtCompactButton(32, 13, " Edit ");
1454 bDelete = newtCompactButton(42, 13, "Delete");
1455
1456 plexesListbox =
1457 newtListbox(2, 3, 9, NEWT_FLAG_SCROLL | NEWT_FLAG_RETURNEXIT);
1458 plexesHeader = newtLabel(2, 2, headerstr);
1459 editraidForm = newtForm(NULL, NULL, 0);
1460
1461 newtListboxClear(plexesListbox);
1462 for (i = 0; i < 10; ++i) {
1463 keylist[i] = (void *) i;
1464 if (i < raidrec->plexes) {
1465 char pname[64], entry[MAX_STR_LEN];
1466 switch (raidrec->plex[i].raidlevel) {
1467 case -1:
1468 mr_asprintf(raidlevel, "concat");
1469 break;
1470 case 0:
1471 mr_asprintf(raidlevel, "striped");
1472 break;
1473 case 5:
1474 mr_asprintf(raidlevel, "raid5");
1475 break;
1476 default:
1477 mr_asprintf(raidlevel, "raid%i", raidrec->plex[i].raidlevel);
1478 break;
1479 }
1480
1481 if (raidrec->plex[i].raidlevel == -1) {
1482 mr_asprintf(chunksize, "N/A");
1483 } else {
1484 mr_asprintf(chunksize, "%dk", raidrec->plex[i].stripesize);
1485 }
1486 snprintf(pname, 64, "%s.p%i", raidrec->volname, i);
1487 snprintf(entry, MAX_STR_LEN, "%-14s %-8s %11s %8d",
1488 pname, raidlevel, chunksize,
1489 raidrec->plex[i].subdisks);
1490 mr_free(raidlevel);
1491 mr_free(chunksize);
1492
1493 newtListboxAppendEntry(plexesListbox, entry, keylist[i]);
1494 }
1495 }
1496
1497 newtFormAddComponents(editraidForm, bOK, bCancel, bAdd, bEdit,
1498 bDelete, plexesListbox, plexesHeader, NULL);
1499
1500 b_res = newtRunForm(editraidForm);
1501 if (b_res == bOK || b_res == bCancel) {
1502 break;
1503 }
1504
1505 curr_choice = newtListboxGetCurrent(plexesListbox);
1506 for (currline2 = 0; currline2 < raidrec->plexes; ++currline2) {
1507 if (currline2 > 9)
1508 break;
1509 if (keylist[currline2] == curr_choice)
1510 break;
1511 }
1512
1513 if (b_res == bDelete) {
1514 mr_asprintf(msg, "Are you sure you want to delete %s.p%i?", raidrec->volname, currline2);
1515 res = ask_me_yes_or_no(msg);
1516 mr_free(msg);
1517
1518 if (res) {
1519 log_it("Deleting RAID plex");
1520 memcpy((void *) &raidrec->plex[currline2],
1521 (void *) &raidrec->plex[raidrec->plexes - 1],
1522 sizeof(struct vinum_plex));
1523 raidrec->plexes--;
1524 }
1525 continue;
1526 }
1527 if (b_res == bAdd) {
1528 raidrec->plex[raidrec->plexes].raidlevel = 0;
1529 raidrec->plex[raidrec->plexes].stripesize = 279;
1530 raidrec->plex[raidrec->plexes].subdisks = 0;
1531 currline2 = raidrec->plexes++;
1532 }
1533 edit_raidlist_plex(mountlist, raidlist, &raidrec->plex[currline2],
1534 currline, currline2);
1535 newtFormDestroy(editraidForm);
1536 }
1537 if (b_res == bCancel) {
1538 memcpy((void *) raidrec, (void *) &bkp_raidrec,
1539 sizeof(struct vinum_volume));
1540 }
1541 newtPopHelpLine();
1542 newtPopWindow();
1543 mountlist->el[currline].size =
1544 calculate_raid_device_size(mountlist, raidlist, raidrec->volname);
1545#else
1546 /** structures ********************************************************/
1547 struct raid_device_record *bkp_raidrec;
1548
1549
1550 /** buffers ***********************************************************/
1551 char *title_of_editraidForm_window;
1552 char *sz_raid_level = NULL;
1553 char *sz_data_disks = NULL;
1554 char *sz_spare_disks = NULL;
1555 char *sz_parity_disks = NULL;
1556 char *sz_failed_disks = NULL;
1557
1558 /** newt **************************************************************/
1559 newtComponent editraidForm;
1560 newtComponent bOK;
1561 newtComponent bCancel;
1562 newtComponent bAdditional;
1563 newtComponent bChangeRaid;
1564 newtComponent bSelectData;
1565 newtComponent bSelectSpare;
1566 newtComponent bSelectParity;
1567 newtComponent bSelectFailed;
1568 newtComponent b_res;
1569
1570 assert(mountlist != NULL);
1571 assert(raidlist != NULL);
1572 assert(raidrec != NULL);
1573
1574 bkp_raidrec = mr_malloc(sizeof(struct raid_device_record));
1575 log_it("Started edit_raidlist_entry");
1576
1577 memcpy((void *) bkp_raidrec, (void *) raidrec, sizeof(struct raid_device_record));
1578 mr_asprintf(title_of_editraidForm_window, "%s", raidrec->raid_device);
1579 log_msg(2, "Opening newt window");
1580 newtOpenWindow(20, 5, 40, 14, title_of_editraidForm_window);
1581 for (;;) {
1582 log_msg(2, "Main loop");
1583 mr_free(title_of_editraidForm_window);
1584 mr_asprintf(title_of_editraidForm_window, "Edit %s", raidrec->raid_device);
1585 sz_raid_level = turn_raid_level_number_to_string(raidrec->raid_level);
1586 sz_data_disks = number_of_disks_as_string(raidrec->data_disks.entries, "data");
1587 sz_spare_disks = number_of_disks_as_string(raidrec->spare_disks.entries, "spare");
1588 sz_parity_disks = number_of_disks_as_string(raidrec->parity_disks.entries, "parity");
1589 sz_failed_disks = number_of_disks_as_string(raidrec->failed_disks.entries, "failed");
1590 bSelectData = newtButton(1, 1, sz_data_disks);
1591 bSelectSpare = newtButton(20, 1, sz_spare_disks);
1592 bSelectParity = newtButton(1, 5, sz_parity_disks);
1593 bSelectFailed = newtButton(20, 5, sz_failed_disks);
1594 bChangeRaid = newtButton(1, 9, sz_raid_level);
1595 bOK = newtButton(16 + (raidrec->raid_level == -1), 9, " OK ");
1596 bCancel = newtButton(28, 9, "Cancel");
1597 bAdditional =
1598 newtCompactButton(1, 13,
1599 "Additional settings and information");
1600 newtPushHelpLine
1601 (" Edit the RAID device's settings to your heart's content, then hit OK/Cancel.");
1602 editraidForm = newtForm(NULL, NULL, 0);
1603 newtFormAddComponents(editraidForm, bSelectData, bSelectParity,
1604 bChangeRaid, bSelectSpare, bSelectFailed,
1605 bOK, bCancel, bAdditional);
1606 b_res = newtRunForm(editraidForm);
1607 if (b_res == bChangeRaid) {
1608 choose_raid_level(raidrec);
1609 } else if (b_res == bSelectData) {
1610 select_raid_disks(mountlist, raidlist, raidrec, "data", &raidrec->data_disks);
1611 } else if (b_res == bSelectSpare) {
1612 select_raid_disks(mountlist, raidlist, raidrec, "spare", &raidrec->spare_disks);
1613 } else if (b_res == bSelectParity) {
1614 select_raid_disks(mountlist, raidlist, raidrec, "parity", &raidrec->parity_disks);
1615 } else if (b_res == bSelectFailed) {
1616 select_raid_disks(mountlist, raidlist, raidrec, "failed", &raidrec->failed_disks);
1617 } else if (b_res == bAdditional) {
1618 edit_raidrec_additional_vars(raidrec);
1619 }
1620 newtFormDestroy(editraidForm);
1621 if (b_res == bOK || b_res == bCancel) {
1622 break;
1623 }
1624 mr_free(sz_data_disks);
1625 mr_free(sz_spare_disks);
1626 mr_free(sz_parity_disks);
1627 mr_free(sz_failed_disks);
1628 }
1629 if (b_res == bCancel) {
1630 memcpy((void *) raidrec, (void *) bkp_raidrec, sizeof(struct raid_device_record));
1631 }
1632 newtPopHelpLine();
1633 newtPopWindow();
1634 mountlist->el[currline].size = calculate_raid_device_size(mountlist, raidlist, raidrec->raid_device);
1635 mr_free(title_of_editraidForm_window);
1636 mr_free(sz_raid_level);
1637 paranoid_free(bkp_raidrec);
1638#endif
1639}
1640
1641#ifdef __FreeBSD__
1642
1643/**
1644 * Edit the plex @p raidrec in @p raidlist.
1645 * @param mountlist The mountlist to get some of the information from.
1646 * @param raidlist The raidlist containing information about RAID devices.
1647 * @param raidrec The plex to edit.
1648 * @param currline The line number (starting from 0) of the RAID device in @p mountlist.
1649 * @param currline2 The line number (starting from 0) of the plex within the RAID device.
1650 * @author Joshua Oreman
1651 * @ingroup restoreGuiMountlist
1652 */
1653void
1654edit_raidlist_plex(struct mountlist_itself *mountlist,
1655 struct raidlist_itself *raidlist,
1656 struct vinum_plex *raidrec, int currline, int currline2)
1657{
1658
1659 /** structures ********************************************************/
1660 struct vinum_plex bkp_raidrec;
1661
1662
1663 /** buffers ***********************************************************/
1664 char *title_of_editraidForm_window = NULL;
1665
1666 /** newt **************************************************************/
1667 newtComponent editraidForm;
1668 newtComponent bOK;
1669 newtComponent bCancel;
1670 newtComponent bEdit;
1671 newtComponent bAdd;
1672 newtComponent bDelete;
1673 newtComponent b_res;
1674 newtComponent unallocListbox, allocListbox;
1675 newtComponent bLevel, sLevel;
1676 newtComponent bStripeSize, sStripeSize;
1677 newtComponent bAlloc, bUnalloc;
1678
1679 void *keylist[ARBITRARY_MAXIMUM];
1680 void *curr_choice_a, *curr_choice_u;
1681 int currline_a, currline_u;
1682
1683 char *p = NULL;
1684 char *tmp = NULL;
1685 char *entry = NULL;
1686
1687 struct mountlist_itself *unallocparts;
1688
1689 unallocparts = malloc(sizeof(struct mountlist_itself));
1690
1691 log_it("Started edit_raidlist_entry");
1692 memcpy((void *) &bkp_raidrec, (void *) raidrec,
1693 sizeof(struct vinum_plex));
1694 mr_asprintf(title_of_editraidForm_window, "%s.p%i", raidlist->el[currline].volname, currline2);
1695 newtPushHelpLine
1696 (" Please select a subdisk to edit, or edit this plex's parameters");
1697 newtOpenWindow(13, 3, 54, 18, title_of_editraidForm_window);
1698 mr_free(title_of_editraidForm_window);
1699
1700 for (;;) {
1701 int i;
1702
1703 switch (raidrec->raidlevel) {
1704 case -1:
1705 mr_asprintf(tmp, "concat");
1706 break;
1707 case 0:
1708 mr_asprintf(tmp, "striped");
1709 break;
1710 case 5:
1711 mr_asprintf(tmp, "raid5");
1712 break;
1713 default:
1714 mr_asprintf(tmp, "unknown (%i)", raidrec->raidlevel);
1715 break;
1716 }
1717 bLevel = newtCompactButton(2, 2, " RAID level ");
1718 sLevel = newtLabel(19, 2, tmp);
1719 mr_free(tmp);
1720
1721 if (raidrec->raidlevel >= 0) {
1722 mr_asprintf(tmp, "%ik", raidrec->stripesize);
1723 bStripeSize = newtCompactButton(2, 4, " Stripe size ");
1724 } else {
1725 mr_asprintf(tmp, "N/A");
1726 bStripeSize = newtLabel(2, 4, "Stripe size:");
1727 }
1728 sStripeSize = newtLabel(19, 4, tmp);
1729 mr_free(tmp);
1730
1731 bOK = newtCompactButton(2, 16, " OK ");
1732 bCancel = newtCompactButton(12, 16, "Cancel");
1733 bAdd = newtCompactButton(22, 16, " Add ");
1734 bEdit = newtCompactButton(32, 16, " Edit ");
1735 bDelete = newtCompactButton(42, 16, "Delete");
1736
1737
1738 unallocListbox =
1739 newtListbox(2, 7, 7, NEWT_FLAG_SCROLL | NEWT_FLAG_RETURNEXIT);
1740 allocListbox =
1741 newtListbox(33, 7, 7, NEWT_FLAG_SCROLL | NEWT_FLAG_RETURNEXIT);
1742 bAlloc = newtButton(23, 7, " -> ");
1743 bUnalloc = newtButton(23, 11, " <- ");
1744
1745 editraidForm = newtForm(NULL, NULL, 0);
1746
1747 newtListboxClear(allocListbox);
1748 newtListboxClear(unallocListbox);
1749 bzero(unallocparts, sizeof(struct mountlist_itself));
1750 make_list_of_unallocated_raid_partitions(unallocparts, mountlist,
1751 raidlist);
1752 for (i = 0; i < ARBITRARY_MAXIMUM; ++i) {
1753 keylist[i] = (void *) i;
1754 if (i < raidrec->subdisks) {
1755 mr_asprintf(entry, "%-17s", find_dev_entry_for_raid_device_name(raidlist, raidrec->sd[i].which_device));
1756 newtListboxAppendEntry(allocListbox, entry, keylist[i]);
1757 mr_free(entry);
1758 }
1759 if (i < unallocparts->entries) {
1760 mr_asprintf(entry, "%-17s", unallocparts->el[i].device);
1761 newtListboxAppendEntry(unallocListbox, entry, keylist[i]);
1762 mr_free(entry);
1763 }
1764 }
1765
1766#define COMP(x) newtFormAddComponent (editraidForm, x)
1767#define UCOMP(x) if (unallocparts->entries > 0) COMP(x)
1768#define ACOMP(x) if (raidrec->subdisks > 0) COMP(x)
1769 editraidForm = newtForm(NULL, NULL, 0);
1770 UCOMP(unallocListbox);
1771 UCOMP(bAlloc);
1772 ACOMP(allocListbox);
1773 ACOMP(bUnalloc);
1774 COMP(bOK);
1775 COMP(bCancel);
1776 COMP(bLevel);
1777 COMP(sLevel);
1778 if (raidrec->raidlevel != -1) {
1779 COMP(bStripeSize);
1780 COMP(sStripeSize);
1781 }
1782#undef COMP
1783#undef UCOMP
1784#undef ACOMP
1785
1786 newtDrawForm(editraidForm);
1787 newtRefresh();
1788 b_res = newtRunForm(editraidForm);
1789 if (b_res == bOK || b_res == bCancel) {
1790 break;
1791 }
1792
1793 curr_choice_a = (raidrec->subdisks > 0) ?
1794 newtListboxGetCurrent(allocListbox) : (void *) 1234;
1795 curr_choice_u = (unallocparts->entries > 0) ?
1796 newtListboxGetCurrent(unallocListbox) : (void *) 1234;
1797 for (currline_a = 0; currline_a < raidrec->subdisks; ++currline_a) {
1798 if (currline_a > ARBITRARY_MAXIMUM)
1799 break;
1800 if (keylist[currline_a] == curr_choice_a)
1801 break;
1802 }
1803 for (currline_u = 0; currline_u < unallocparts->entries;
1804 ++currline_u) {
1805 if (currline_u > ARBITRARY_MAXIMUM)
1806 break;
1807 if (keylist[currline_u] == curr_choice_u)
1808 break;
1809 }
1810 if (b_res == bLevel) {
1811 choose_raid_level(raidrec);
1812 } else if (b_res == bStripeSize) {
1813 char tmp1[64];
1814 sprintf(tmp1, "%i", raidrec->stripesize);
1815 if (popup_and_get_string
1816 ("Stripe size",
1817 "Please enter the stripe size in kilobytes.", tmp1, 20)) {
1818 raidrec->stripesize = atoi(tmp1);
1819 }
1820 } else if ((b_res == bAlloc) || (b_res == unallocListbox)) {
1821 if (currline_u <= unallocparts->entries)
1822 add_raid_subdisk(raidlist, raidrec,
1823 unallocparts->el[currline_u].device);
1824 } else if ((b_res == bUnalloc) || (b_res == allocListbox)) {
1825 if (currline_a <= raidrec->subdisks) {
1826 memcpy((void *) &raidrec->sd[currline_a],
1827 (void *) &raidrec->sd[raidrec->subdisks - 1],
1828 sizeof(struct vinum_subdisk));
1829 raidrec->subdisks--;
1830 }
1831 }
1832 newtFormDestroy(editraidForm);
1833 newtRefresh();
1834}
1835
1836if (b_res == bCancel) {
1837 memcpy((void *) raidrec, (void *) &bkp_raidrec, sizeof(struct vinum_plex));
1838}
1839newtPopWindow();
1840newtPopHelpLine();
1841}
1842#else
1843/**
1844 * Edit additional RAID variable number @p lino.
1845 * @param raidrec The RAID device record to edit the variable in.
1846 * @param lino The line number (starting from 0) of the variable to edit.
1847 * @ingroup restoreGuiVarslist
1848 */
1849void edit_varslist_entry(struct raid_device_record *raidrec, int lino)
1850{
1851
1852 /** buffers ***********************************************************/
1853 char *header = NULL;
1854 char *comment = NULL;
1855 char sz_out[MAX_STR_LEN];
1856
1857 assert(raidrec != 0);
1858 assert(lino >= 0);
1859
1860 strcpy(sz_out, raidrec->additional_vars.el[lino].value);
1861 mr_asprintf(header, "Edit %s", raidrec->additional_vars.el[lino].label);
1862 mr_asprintf(comment, "Please set %s's value (currently '%s')", raidrec->additional_vars.el[lino].label, sz_out);
1863 if (popup_and_get_string(header, comment, sz_out, MAX_STR_LEN)) {
1864 strip_spaces(sz_out);
1865 strcpy(raidrec->additional_vars.el[lino].value, sz_out);
1866 }
1867 mr_free(header);
1868 mr_free(comment);
1869}
1870
1871#endif
1872
1873/**
1874 * Edit the mountlist using Newt.
1875 * @param mountlist The mountlist to edit.
1876 * @param raidlist The raidlist that goes with @p mountlist.
1877 * @return 0 if the user pressed OK, 1 if they pressed Cancel.
1878 */
1879int
1880edit_mountlist_in_newt(char *mountlist_fname,
1881 struct mountlist_itself *mountlist,
1882 struct raidlist_itself *raidlist)
1883{
1884
1885 /** newt **************************************************************/
1886 newtComponent myForm;
1887 newtComponent bAdd;
1888 newtComponent bEdit;
1889 newtComponent bDelete;
1890 newtComponent bOK;
1891 newtComponent bCancel;
1892 newtComponent b_res = NULL;
1893 newtComponent partitionsListbox;
1894 newtComponent headerMsg;
1895 newtComponent flawsLabelA;
1896 newtComponent flawsLabelB;
1897 newtComponent flawsLabelC;
1898 newtComponent bReload;
1899
1900 /** ???? *************************************************************/
1901 void *curr_choice;
1902 void *keylist[ARBITRARY_MAXIMUM];
1903
1904 /** int **************************************************************/
1905 int i = 0;
1906 int currline = 0;
1907 int finished = FALSE;
1908
1909 /** buffers **********************************************************/
1910 char *tmp = NULL;
1911 char *flaws_str = NULL;
1912 char *flaws_str_A = NULL;
1913 char *flaws_str_B = NULL;
1914 char *flaws_str_C = NULL;
1915
1916 assert(mountlist != NULL);
1917 assert(raidlist != NULL);
1918
1919 if (mountlist->entries > ARBITRARY_MAXIMUM) {
1920 log_to_screen("Arbitrary limits suck, man!");
1921 finish(1);
1922 }
1923 newtPushHelpLine("WARNING: No LVM modification possible here. Edit /tmp/i-want-my-lvm instead");
1924 i = 4;
1925 bAdd = newtCompactButton(i, 17, " Add ");
1926 bEdit = newtCompactButton(i += 11, 17, " Edit ");
1927 bDelete = newtCompactButton(i += 12, 17, "Delete");
1928 bReload = newtCompactButton(i += 12, 17, "Reload");
1929 bCancel = newtCompactButton(i += 12, 17, "Cancel");
1930 bOK = newtCompactButton(i += 12, 17, " OK ");
1931 mr_asprintf(tmp, "%-24s %-24s %-8s %s", "Device", "Mountpoint", "Format", "Size (MB)");
1932 headerMsg = newtLabel(2, 1, tmp);
1933 mr_free(tmp);
1934
1935 flawsLabelA = newtLabel(2, 13, " ");
1936 flawsLabelB = newtLabel(2, 14, " ");
1937 flawsLabelC = newtLabel(2, 15, " ");
1938 partitionsListbox = newtListbox(2, 2, 10, NEWT_FLAG_SCROLL | NEWT_FLAG_RETURNEXIT);
1939 redraw_mountlist(mountlist, keylist, partitionsListbox);
1940 newtOpenWindow(1, 3, 77, 18, "Editing mountlist");
1941 myForm = newtForm(NULL, NULL, 0);
1942 newtFormAddComponents(myForm, headerMsg, partitionsListbox,
1943 flawsLabelA, flawsLabelB, flawsLabelC, bAdd,
1944 bEdit, bDelete, bReload, bCancel, bOK, NULL);
1945 while (!finished) {
1946 flaws_str = evaluate_mountlist(mountlist);
1947 /* flaws_str can be NULL */
1948 if ((flaws_str == NULL) || (strlen(flaws_str) == 0)) {
1949 mr_asprintf(flaws_str_A, "");
1950 } else {
1951 mr_asprintf(flaws_str_A, "%s", flaws_str + 1);
1952 }
1953 if (strlen(flaws_str_A) >= 74) {
1954 for (i = 74; flaws_str_A[i] != ' '; i--);
1955 mr_asprintf(flaws_str_B, "%s", flaws_str_A + i + 1);
1956 flaws_str_A[i] = '\0';
1957 } else {
1958 mr_asprintf(flaws_str_B, "");
1959 }
1960 if (strlen(flaws_str_B) >= 74) {
1961 for (i = 74; flaws_str_B[i] != ' '; i--);
1962 mr_asprintf(flaws_str_C, "%s", flaws_str_B + i + 1);
1963 flaws_str_B[i] = '\0';
1964 } else {
1965 mr_asprintf(flaws_str_C, "");
1966 }
1967
1968 newtLabelSetText(flawsLabelA, flaws_str_A);
1969 newtLabelSetText(flawsLabelB, flaws_str_B);
1970 newtLabelSetText(flawsLabelC, flaws_str_C);
1971 b_res = newtRunForm(myForm);
1972 mr_free(flaws_str_A);
1973 mr_free(flaws_str_B);
1974 mr_free(flaws_str_C);
1975
1976 if (b_res == bOK) {
1977 if (flaws_str != NULL) {
1978 finished = ask_me_yes_or_no("Your mountlist might not work. Continue anyway?");
1979 } else {
1980 finished = ask_me_yes_or_no("Are you sure you want to save your mountlist and continue? (No changes will be made to your partition table at this time.)");
1981 }
1982 } else if (b_res == bCancel) {
1983 finished = TRUE;
1984 } else if (b_res == bReload) {
1985 if (ask_me_yes_or_no("Reload original mountlist?")) {
1986 load_mountlist(mountlist, mountlist_fname);
1987 load_raidtab_into_raidlist(raidlist, RAIDTAB_FNAME);
1988 redraw_mountlist(mountlist, keylist, partitionsListbox);
1989 }
1990 } else {
1991 curr_choice = newtListboxGetCurrent(partitionsListbox);
1992 for (i = 0; i < mountlist->entries && keylist[i] != curr_choice; i++);
1993 if (i == mountlist->entries && mountlist->entries > 0) {
1994 log_to_screen("I don't know what that button does!");
1995 } else {
1996 currline = i;
1997 if (b_res == bAdd) {
1998 add_mountlist_entry(mountlist, raidlist,
1999 partitionsListbox, currline,
2000 keylist);
2001 } else if (b_res == bDelete) {
2002 delete_mountlist_entry(mountlist, raidlist,
2003 partitionsListbox, currline,
2004 keylist);
2005 } else {
2006 if (mountlist->entries > 0) {
2007 edit_mountlist_entry(mountlist, raidlist,
2008 partitionsListbox, currline,
2009 keylist);
2010 } else {
2011 popup_and_OK
2012 ("Please add an entry. Then press ENTER to edit it.");
2013 }
2014 }
2015 }
2016 }
2017 mr_free(flaws_str);
2018 }
2019 newtFormDestroy(myForm);
2020 newtPopWindow();
2021 newtPopHelpLine();
2022 if (b_res == bOK) {
2023 log_it("You pushed 'OK'. I shall now continue.");
2024 return (0);
2025 } else {
2026 /* popup_and_OK("You pushed 'cancel'. I shall now abort."); */
2027 return (1);
2028 }
2029}
2030
2031
2032
2033/**
2034 * Edit the mountlist.
2035 * @param mountlist The mountlist to edit.
2036 * @param raidlist The raidlist that goes with @p mountlist.
2037 * @return 0 if the user pressed OK, 1 if they pressed Cancel.
2038 */
2039int
2040edit_mountlist(char *mountlist_fname, struct mountlist_itself *mountlist,
2041 struct raidlist_itself *raidlist)
2042{
2043 int res = 0;
2044
2045 log_it("entering eml");
2046
2047 if (g_text_mode) {
2048 fatal_error("Don't call edit_mountlist() in text mode");
2049 } else {
2050 log_it("I'm in GUI mode, so I shall edit mountlist using edit_mountlist()");
2051 res = edit_mountlist_in_newt(mountlist_fname, mountlist, raidlist);
2052 }
2053 log_it("leaving eml");
2054 return (res);
2055}
2056
2057
2058
2059
2060#ifndef __FreeBSD__
2061/**
2062 * Edit the additional RAID variables in @p raidrec.
2063 * @param raidrec The RAID device record to edit the RAID variables in.
2064 * @ingroup restoreGuiVarslist
2065 */
2066void edit_raidrec_additional_vars(struct raid_device_record *raidrec)
2067{
2068
2069 /** structure *********************************************************/
2070 struct raid_device_record bkp_raidrec;
2071
2072 /** newt **************************************************************/
2073 newtComponent myForm;
2074 newtComponent bAdd;
2075 newtComponent bEdit;
2076 newtComponent bDelete;
2077 newtComponent bOK;
2078 newtComponent bCancel;
2079 newtComponent b_res;
2080 newtComponent varsListbox;
2081 newtComponent headerMsg;
2082
2083 /** ?? ***************************************************************/
2084 void *keylist[ARBITRARY_MAXIMUM], *curr_choice;
2085
2086 /** buffers **********************************************************/
2087 char title_of_window[MAX_STR_LEN];
2088
2089 /** int **************************************************************/
2090 int i = 0;
2091 int currline = 0;
2092
2093
2094 assert(raidrec != NULL);
2095
2096 memcpy((void *) &bkp_raidrec, (void *) raidrec,
2097 sizeof(struct raid_device_record));
2098 sprintf(title_of_window, "Additional variables");
2099 newtPushHelpLine
2100 (" Edit the additional fields to your heart's content, then click OK or Cancel.");
2101 headerMsg = newtLabel(1, 1, "Label Value");
2102 varsListbox =
2103 newtListbox(1, 2, 6, NEWT_FLAG_SCROLL | NEWT_FLAG_RETURNEXIT);
2104 i = 1;
2105 bAdd = newtCompactButton(i, 9, " Add ");
2106 bEdit = newtCompactButton(i += 8, 9, " Edit ");
2107 bDelete = newtCompactButton(i += 9, 9, "Delete");
2108 bOK = newtCompactButton(i += 9, 9, " OK ");
2109 bCancel = newtCompactButton(i += 9, 9, "Cancel");
2110 newtOpenWindow(17, 7, 46, 10, title_of_window);
2111 myForm = newtForm(NULL, NULL, 0);
2112 newtFormAddComponents(myForm, headerMsg, varsListbox, bAdd, bEdit,
2113 bDelete, bOK, bCancel, NULL);
2114 insert_essential_additionalvars(raidrec);
2115 redraw_varslist(&raidrec->additional_vars, keylist, varsListbox);
2116 for (b_res = NULL; b_res != bOK && b_res != bCancel;) {
2117 b_res = newtRunForm(myForm);
2118 curr_choice = newtListboxGetCurrent(varsListbox);
2119 for (currline = 0;
2120 currline < raidrec->additional_vars.entries
2121 && keylist[currline] != curr_choice; currline++);
2122 if (currline == raidrec->additional_vars.entries
2123 && raidrec->additional_vars.entries > 0) {
2124 log_it("Warning - I don't know what this button does");
2125 }
2126 if (b_res == bOK) { /* do nothing */
2127 } else if (b_res == bCancel) { /* do nothing */
2128 } else if (b_res == bAdd) {
2129 add_varslist_entry(raidrec);
2130 } else if (b_res == bDelete) {
2131 delete_varslist_entry(raidrec, currline);
2132 } else {
2133 edit_varslist_entry(raidrec, currline);
2134 }
2135 redraw_varslist(&raidrec->additional_vars, keylist, varsListbox);
2136 }
2137 remove_essential_additionalvars(raidrec);
2138 newtFormDestroy(myForm);
2139 newtPopWindow();
2140 newtPopHelpLine();
2141 if (b_res == bCancel) {
2142 memcpy((void *) raidrec, (void *) &bkp_raidrec,
2143 sizeof(struct raid_device_record));
2144 }
2145 return;
2146}
2147#endif
2148
2149
2150/**
2151 * Find the next free location to place a disk in @p disklist.
2152 * @param disklist The disklist to operate on.
2153 * @return The next free location (starting from 0).
2154 * @ingroup restoreGuiDisklist
2155 */
2156int find_next_free_index_in_disklist(struct list_of_disks *disklist)
2157{
2158
2159 /** int ***************************************************************/
2160 int index = -1;
2161 int pos = 0;
2162
2163 /** bool **************************************************************/
2164 bool done;
2165
2166 assert(disklist != NULL);
2167
2168 for (done = FALSE; !done;) {
2169 for (pos = 0;
2170 pos < disklist->entries && disklist->el[pos].index <= index;
2171 pos++);
2172 if (pos >= disklist->entries) {
2173 done = TRUE;
2174 } else {
2175 index = disklist->el[pos].index;
2176 }
2177 }
2178 return (index + 1);
2179}
2180
2181
2182
2183/**
2184 * Locate @p device in @p raidlist.
2185 * @param raidlist The raidlist ot search in.
2186 * @param device The RAID device to search for.
2187 * @return The index of the device, or -1 if it could not be found.
2188 * @ingroup restoreGuiMountlist
2189 */
2190int
2191find_raid_device_in_raidlist(struct raidlist_itself *raidlist,
2192 char *device)
2193{
2194
2195 /** int ***************************************************************/
2196 int i = 0;
2197#ifdef __FreeBSD__
2198 char *vdev = NULL;
2199 int res = 0;
2200#else
2201// Linux
2202#endif
2203
2204 assert(raidlist != NULL);
2205 assert_string_is_neither_NULL_nor_zerolength(device);
2206
2207#ifdef __FreeBSD__
2208 for (i = 0; i < raidlist->entries; i++) {
2209 mr_asprintf(vdev, "/dev/vinum/%s", raidlist->el[i].volname);
2210 res = strcmp(device, vdev);
2211 mr_free(vdev);
2212
2213 if (!res)
2214 break;
2215 }
2216#else
2217
2218 for (i = 0;
2219 strcmp(raidlist->el[i].raid_device, device)
2220 && i < raidlist->entries; i++);
2221#endif
2222 if (i == raidlist->entries) {
2223 return (-1);
2224 } else {
2225 return (i);
2226 }
2227}
2228
2229
2230/**
2231 * Create a new raidtab entry for @p device in @p raidlist.
2232 * @param raidlist The raidlist to add the device to.
2233 * @param mountlist The mountlist containing information about the user's partitions.
2234 * @param currline The selected line in the mountlist.
2235 * @param device The RAID device (e.g. /dev/md0) to use.
2236 * @ingroup restoreGuiMountlist
2237 */
2238void
2239initiate_new_raidlist_entry(struct raidlist_itself *raidlist,
2240 struct mountlist_itself *mountlist,
2241 int currline, char *device)
2242{
2243
2244 /** structure *********************************************************/
2245 struct OSSWAP (raid_device_record, vinum_volume) * raidrec;
2246
2247 /** int ***************************************************************/
2248 int pos_in_raidlist = 0;
2249
2250 assert(raidlist != NULL);
2251 assert(mountlist != NULL);
2252 assert_string_is_neither_NULL_nor_zerolength(device);
2253
2254 pos_in_raidlist =
2255 find_raid_device_in_raidlist(raidlist,
2256 mountlist->el[currline].device);
2257 if (pos_in_raidlist >= 0) {
2258 fatal_error("Sorry, that RAID device already exists. Weird.");
2259 }
2260 pos_in_raidlist = raidlist->entries++;
2261 raidrec = &raidlist->el[pos_in_raidlist];
2262 initialize_raidrec(raidrec);
2263 strcpy(raidrec->OSSWAP(raid_device, volname), OSSWAP(device, basename(device)));
2264#ifndef __FreeBSD__
2265 choose_raid_level(raidrec);
2266 select_raid_disks(mountlist, raidlist, raidrec, "data",
2267 &raidrec->data_disks);
2268#endif
2269 edit_raidlist_entry(mountlist, raidlist, raidrec, currline);
2270}
2271
2272
2273#ifndef __FreeBSD__
2274/**
2275 * Insert the RAID variables not stored in the "additional RAID variables" list there too.
2276 * @param raidrec The RAID device record to operate on.
2277 * @ingroup restoreGuiVarslist
2278 */
2279void insert_essential_additionalvars(struct raid_device_record *raidrec)
2280{
2281
2282 /** int **************************************************************/
2283 int items = 0;
2284
2285 assert(raidrec != NULL);
2286
2287 items = raidrec->additional_vars.entries;
2288 write_variableINT_to_raid_var_line(raidrec, items++,
2289 "persistent-superblock",
2290 raidrec->persistent_superblock);
2291 write_variableINT_to_raid_var_line(raidrec, items++, "chunk-size",
2292 raidrec->chunk_size);
2293 raidrec->additional_vars.entries = items;
2294}
2295
2296#endif
2297
2298/**
2299 * Dummy function that proves that we can get to the point where Mondo is run.
2300 */
2301void nuke_mode_dummy()
2302{
2303
2304 /** newt *************************************************************/
2305 newtComponent myForm;
2306 newtComponent b1;
2307 newtComponent b2;
2308 newtComponent b3;
2309
2310
2311 newtPushHelpLine
2312 ("This is where I nuke your hard drives. Mhahahahaha. No-one can stop Mojo Jojo!");
2313 newtOpenWindow(24, 3, 32, 13, "Nuking");
2314 b1 = newtButton(7, 1, "Slowly");
2315 b2 = newtButton(7, 5, "Medium");
2316 b3 = newtButton(7, 9, "Quickly");
2317 myForm = newtForm(NULL, NULL, 0);
2318 newtFormAddComponents(myForm, b1, b2, b3, NULL);
2319 newtFormDestroy(myForm);
2320 newtPopWindow();
2321 newtPopHelpLine();
2322}
2323
2324
2325
2326/**
2327 * Redraw the disklist.
2328 * @param disklist The disklist to read from.
2329 * @param keylist The list of keys for @p listbox.
2330 * @param listbox The Newt listbox component to redraw.
2331 * @ingroup restoreGuiDisklist
2332 */
2333void
2334redraw_disklist(struct list_of_disks *disklist,
2335 void *keylist[ARBITRARY_MAXIMUM], newtComponent listbox)
2336{
2337
2338 /** long **************************************************************/
2339 long i = 0;
2340 char *tmp = NULL;
2341
2342 assert(disklist != NULL);
2343 assert(keylist != NULL);
2344 assert(listbox != NULL);
2345
2346 newtListboxClear(listbox);
2347
2348 for (i = 0; i < ARBITRARY_MAXIMUM; i++) {
2349 keylist[i] = (void *) i;
2350 }
2351 for (i = 0; i < disklist->entries; i++) {
2352 tmp = disklist_entry_to_string(disklist, i);
2353 newtListboxAppendEntry(listbox, tmp, keylist[i]);
2354 mr_free(tmp);
2355 }
2356}
2357
2358
2359/**
2360 * Redraw the mountlist.
2361 * @param mountlist The mountlist to read from.
2362 * @param keylist The list of keys for @p listbox.
2363 * @param listbox The Newt listbox component to redraw.
2364 * @ingroup restoreGuiMountlist
2365 */
2366void
2367redraw_mountlist(struct mountlist_itself *mountlist,
2368 void *keylist[ARBITRARY_MAXIMUM], newtComponent listbox)
2369{
2370
2371 /** long **************************************************************/
2372 long i = 0;
2373 char * tmp = NULL;
2374
2375 assert(mountlist != NULL);
2376 assert(keylist != NULL);
2377 assert(listbox != NULL);
2378
2379 newtListboxClear(listbox);
2380// sort_mountlist_by_device (mountlist);
2381 for (i = 0; i < ARBITRARY_MAXIMUM; i++) {
2382 keylist[i] = (void *) i;
2383 }
2384 for (i = 0; i < mountlist->entries; i++) {
2385 tmp = mountlist_entry_to_string(mountlist, i);
2386 newtListboxAppendEntry(listbox, tmp, keylist[i]);
2387 mr_free(tmp);
2388 }
2389}
2390
2391
2392
2393
2394/**
2395 * Redraw the list of unallocated RAID partitions.
2396 * @param unallocated_raid_partitions The mountlist containing unallocated RAID partitions.
2397 * @param keylist The list of keys for @p listbox.
2398 * @param listbox The Newt listbox component to redraw.
2399 * @ingroup restoreGuiDisklist
2400 */
2401void redraw_unallocpartnslist(struct mountlist_itself
2402 *unallocated_raid_partitions,
2403 void *keylist[ARBITRARY_MAXIMUM],
2404 newtComponent listbox)
2405{
2406
2407 /** long *************************************************************/
2408 long i = 0;
2409
2410 /** buffers **********************************************************/
2411 char tmp[MAX_STR_LEN];
2412
2413 assert(unallocated_raid_partitions != NULL);
2414 assert(keylist != NULL);
2415 assert(listbox != NULL);
2416
2417 newtListboxClear(listbox);
2418 for (i = 0; i < ARBITRARY_MAXIMUM; i++) {
2419 keylist[i] = (void *) i;
2420 }
2421 for (i = 0; i < unallocated_raid_partitions->entries; i++) {
2422 sprintf(tmp, "%-22s %8lld",
2423 unallocated_raid_partitions->el[i].device,
2424 unallocated_raid_partitions->el[i].size / 1024L);
2425 newtListboxAppendEntry(listbox, tmp, keylist[i]);
2426 }
2427}
2428
2429#ifndef __FreeBSD__
2430/**
2431 * Redraw the list of additional RAID variables.
2432 * @param additional_vars The list of additional RAID varibals.
2433 * @param keylist The list of keys for @p listbox.
2434 * @param listbox The Newt listbox component to redraw.
2435 * @ingroup restoreGuiVarslist
2436 */
2437void
2438redraw_varslist(struct additional_raid_variables *additional_vars,
2439 void *keylist[], newtComponent listbox)
2440{
2441 /** long ************************************************************/
2442 long i = 0;
2443
2444 /** buffers *********************************************************/
2445 char tmp[MAX_STR_LEN];
2446
2447 assert(additional_vars != NULL);
2448 assert(keylist != NULL);
2449 assert(listbox != NULL);
2450
2451 newtListboxClear(listbox);
2452
2453 for (i = 0; i < ARBITRARY_MAXIMUM; i++) {
2454 keylist[i] = (void *) i;
2455 }
2456 for (i = 0; i < additional_vars->entries; i++) {
2457 sprintf(tmp, "%-32s %-8s", additional_vars->el[i].label,
2458 additional_vars->el[i].value);
2459 newtListboxAppendEntry(listbox, tmp, keylist[i]);
2460 }
2461}
2462
2463
2464/**
2465 * Remove variable @p label from the RAID variables list in @p raidrec.
2466 * @param raidrec The RAID device record to remove the variable from.
2467 * @param label The variable name to remove.
2468 * @return The value of the variable removed.
2469 * @ingroup restoreUtilityGroup
2470 */
2471int
2472read_variableINT_and_remove_from_raidvars(struct
2473 OSSWAP (raid_device_record,
2474 vinum_volume) * raidrec,
2475 char *label)
2476{
2477 /** int ***************************************************************/
2478 int i = 0;
2479 int res = 0;
2480
2481
2482 assert(raidrec != NULL);
2483 assert(label != NULL);
2484
2485 for (i = 0;
2486 i < raidrec->additional_vars.entries
2487 && strcmp(raidrec->additional_vars.el[i].label, label); i++);
2488 if (i == raidrec->additional_vars.entries) {
2489 res = -1;
2490 } else {
2491 res = atoi(raidrec->additional_vars.el[i].value);
2492 for (i++; i < raidrec->additional_vars.entries; i++) {
2493 memcpy((void *) &raidrec->additional_vars.el[i - 1],
2494 (void *) &raidrec->additional_vars.el[i],
2495 sizeof(struct raid_var_line));
2496 }
2497 raidrec->additional_vars.entries--;
2498 }
2499 return (res);
2500}
2501#endif
2502
2503/**
2504 * Change all RAID devices to use @p new_dev instead of @p old_dev.
2505 * @param raidlist The raidlist to make the changes in.
2506 * @param old_dev The old name of the device (what it used to be).
2507 * @param new_dev The new name of the device (what it is now).
2508 * @ingroup restoreGuiMountlist
2509 */
2510void rejig_partition_name_in_raidlist_if_necessary(struct raidlist_itself
2511 *raidlist,
2512 char *old_dev,
2513 char *new_dev)
2514{
2515 /** int ************************************************************/
2516 int pos = 0;
2517 int j = 0;
2518
2519 assert(raidlist != NULL);
2520 assert_string_is_neither_NULL_nor_zerolength(old_dev);
2521 assert_string_is_neither_NULL_nor_zerolength(new_dev);
2522
2523 pos = which_raid_device_is_using_this_partition(raidlist, old_dev);
2524 if (pos < 0) {
2525 log_it("No need to rejig %s in raidlist: it's not listed.", old_dev);
2526 } else {
2527 if ((j =
2528 where_in_drivelist_is_drive(&raidlist->
2529 OSSWAP(el[pos].data_disks, disks),
2530 old_dev)) >= 0) {
2531 strcpy(raidlist->OSSWAP(el[pos].data_disks, disks).el[j].device, new_dev);
2532 } else
2533 if ((j =
2534 where_in_drivelist_is_drive(&raidlist->
2535 OSSWAP(el[pos].spare_disks,
2536 spares),
2537 old_dev)) >= 0) {
2538 strcpy(raidlist->OSSWAP(el[pos].spare_disks, spares).el[j].device, new_dev);
2539 }
2540#ifndef __FreeBSD__
2541 else if ((j =
2542 where_in_drivelist_is_drive(&raidlist->el[pos].
2543 parity_disks,
2544 old_dev)) >= 0) {
2545 strcpy(raidlist->el[pos].parity_disks.el[j].device, new_dev);
2546 } else
2547 if ((j =
2548 where_in_drivelist_is_drive(&raidlist->el[pos].
2549 failed_disks,
2550 old_dev)) >= 0) {
2551 strcpy(raidlist->el[pos].failed_disks.el[j].device, new_dev);
2552 }
2553#endif
2554 else {
2555 log_it("%s is supposed to be listed in this raid dev but it's not...", old_dev);
2556 }
2557 }
2558}
2559
2560
2561#ifndef __FreeBSD__
2562/**
2563 * Remove the essential RAID variables from the "additional variables" section.
2564 * If they have been changed, set them in their normal locations too.
2565 * @param raidrec The RAID device record to operate on.
2566 * @ingroup restoreUtilityVarslist
2567 */
2568void remove_essential_additionalvars(struct raid_device_record *raidrec)
2569{
2570
2571 /** int **************************************************************/
2572 int res = 0;
2573
2574 assert(raidrec != NULL);
2575
2576 res =
2577 read_variableINT_and_remove_from_raidvars(raidrec,
2578 "persistent-superblock");
2579 if (res > 0) {
2580 raidrec->persistent_superblock = res;
2581 }
2582 res = read_variableINT_and_remove_from_raidvars(raidrec, "chunk-size");
2583 if (res > 0) {
2584 raidrec->chunk_size = res;
2585 }
2586 res = read_variableINT_and_remove_from_raidvars(raidrec, "block-size");
2587}
2588
2589/**
2590 * Select the RAID disks to use in @p raidrec.
2591 * @param mountlist_dontedit The mountlist (will not be edited).
2592 * @param raidlist The raidlist to modify.
2593 * @param raidrec The RAID device record in @p raidlist to work on.
2594 * @param description_of_list The type of disks we're selecting (e.g. "data").
2595 * @param disklist The disklist to put the user-selected disks in.
2596 * @ingroup restoreGuiMountlist
2597 */
2598void
2599select_raid_disks(struct mountlist_itself *mountlist_dontedit,
2600 struct raidlist_itself *raidlist,
2601 struct raid_device_record *raidrec,
2602 char *description_of_list,
2603 struct list_of_disks *disklist)
2604{
2605 void *curr_choice;
2606
2607 /** ??? ***************************************************************/
2608
2609 /** structures ********************************************************/
2610 struct raidlist_itself *bkp_raidlist;
2611 struct raid_device_record *bkp_raidrec;
2612 struct list_of_disks *bkp_disklist;
2613 struct mountlist_itself *unallocated_raid_partitions;
2614
2615 /** newt **************************************************************/
2616 newtComponent myForm = NULL;
2617 newtComponent bAdd = NULL;
2618 newtComponent bDelete = NULL;
2619 newtComponent bOK = NULL;
2620 newtComponent bCancel = NULL;
2621 newtComponent b_res = NULL;
2622 newtComponent partitionsListbox = NULL;
2623 newtComponent headerMsg = NULL;
2624
2625 /** buffers **********************************************************/
2626 void *keylist[ARBITRARY_MAXIMUM];
2627 char *tmp = NULL;
2628 char *help_text = NULL;
2629 char *title_of_window = NULL;
2630 char sz_res[MAX_STR_LEN];
2631 char *header_text = NULL;
2632
2633 /** int **************************************************************/
2634 int i = 0;
2635 int currline = 0;
2636
2637 assert(mountlist_dontedit != NULL);
2638 assert(raidlist != NULL);
2639 assert(raidrec != NULL);
2640 assert(description_of_list != NULL);
2641 assert(disklist != NULL);
2642
2643 log_it("malloc'ing");
2644 bkp_raidrec = mr_malloc(sizeof(struct raid_device_record));
2645 bkp_disklist = mr_malloc(sizeof(struct list_of_disks));
2646 bkp_raidlist = mr_malloc(sizeof(struct raidlist_itself));
2647 unallocated_raid_partitions = mr_malloc(sizeof(struct mountlist_itself));
2648
2649 memcpy((void *) bkp_raidlist, (void *) raidlist, sizeof(struct raidlist_itself));
2650 memcpy((void *) bkp_raidrec, (void *) raidrec, sizeof(struct raid_device_record));
2651 memcpy((void *) bkp_disklist, (void *) disklist, sizeof(struct list_of_disks));
2652
2653 log_it("Post-malloc");
2654 mr_asprintf(help_text, " Edit this RAID device's list of partitions. Choose OK or Cancel when done.");
2655 mr_asprintf(header_text, "%-24s %s", "Device", "Index");
2656 mr_asprintf(title_of_window, "%s contains...", raidrec->raid_device);
2657 newtPushHelpLine(help_text);
2658 for (b_res = (newtComponent) 12345; b_res != bOK && b_res != bCancel;) {
2659 headerMsg = newtLabel(1, 1, header_text);
2660 partitionsListbox =
2661 newtListbox(1, 2, 6, NEWT_FLAG_SCROLL | NEWT_FLAG_RETURNEXIT);
2662 redraw_disklist(disklist, keylist, partitionsListbox);
2663 i = 1;
2664 bAdd = newtCompactButton(i, 9, " Add ");
2665 bDelete = newtCompactButton(i += 8, 9, "Delete");
2666 bOK = newtCompactButton(i += 9, 9, " OK ");
2667 bCancel = newtCompactButton(i += 9, 9, "Cancel");
2668 newtOpenWindow(21, 7, 38, 10, title_of_window);
2669 myForm = newtForm(NULL, NULL, 0);
2670 if (disklist->entries == 0) {
2671 newtFormAddComponents(myForm, headerMsg, bAdd, bDelete, bOK,
2672 bCancel, NULL);
2673 } else {
2674 newtFormAddComponents(myForm, headerMsg, partitionsListbox,
2675 bAdd, bDelete, bOK, bCancel, NULL);
2676 }
2677 b_res = newtRunForm(myForm);
2678 if (b_res == bOK || b_res == bCancel) { /* do nothing */
2679// That's OK. At the end of this subroutine (after this do/while loop),
2680// we'll throw away the changes if Cancel was pushed.
2681 } else {
2682 curr_choice = newtListboxGetCurrent(partitionsListbox);
2683 for (i = 0; i < disklist->entries && keylist[i] != curr_choice;
2684 i++);
2685 if (i == disklist->entries && disklist->entries > 0) {
2686 log_to_screen("I don't know what that button does!");
2687 } else {
2688 currline = i;
2689 if (b_res == bAdd) {
2690 log_it("Making list of unallocated RAID slices");
2691 make_list_of_unallocated_raid_partitions
2692 (unallocated_raid_partitions, mountlist_dontedit,
2693 raidlist);
2694 if (unallocated_raid_partitions->entries <= 0) {
2695 popup_and_OK
2696 ("There are no unallocated partitions marked for RAID.");
2697 } else {
2698 log_it
2699 ("Done. The user may add one or more of the above to RAID device");
2700 add_disklist_entry(disklist, raidrec->raid_device,
2701 unallocated_raid_partitions);
2702 log_it("I have finished adding a disklist entry.");
2703 redraw_disklist(disklist, keylist,
2704 partitionsListbox);
2705 }
2706 } else if (b_res == bDelete) {
2707 delete_disklist_entry(disklist, raidrec->raid_device,
2708 currline);
2709 redraw_disklist(disklist, keylist, partitionsListbox);
2710 } else {
2711 mr_asprintf(tmp, "%s's index is %d. What should it be?", raidrec->raid_device, disklist->el[currline].index);
2712 sprintf(sz_res, "%d", disklist->el[currline].index);
2713 if (popup_and_get_string("Set index", tmp, sz_res, 10)) {
2714 disklist->el[currline].index = atoi(sz_res);
2715 }
2716 mr_free(tmp);
2717
2718 redraw_disklist(disklist, keylist, partitionsListbox);
2719 }
2720 }
2721 }
2722 newtFormDestroy(myForm);
2723 newtPopWindow();
2724 }
2725 newtPopHelpLine();
2726 mr_free(help_text);
2727 mr_free(header_text);
2728 mr_free(title_of_window);
2729
2730 if (b_res == bCancel) {
2731 memcpy((void *) raidlist, (void *) bkp_raidlist, sizeof(struct raidlist_itself));
2732 memcpy((void *) raidrec, (void *) bkp_raidrec, sizeof(struct raid_device_record));
2733 memcpy((void *) disklist, (void *) bkp_disklist, sizeof(struct list_of_disks));
2734 }
2735 mr_free(bkp_raidrec);
2736 mr_free(bkp_disklist);
2737 mr_free(bkp_raidlist);
2738 mr_free(unallocated_raid_partitions);
2739}
2740#endif
2741
2742
2743
2744/**
2745 * Ask the user which restore mode (nuke, interactive, or compare) we should use.
2746 * @return The mode selected: 'I' for interactive, 'N' for nuke, 'C' for compare,
2747 * or 'E' (or any other letter) for exit.
2748 */
2749char which_restore_mode()
2750{
2751
2752 /** char *************************************************************/
2753 char output = '\0';
2754 char *tmp = NULL;
2755
2756 /** newt *************************************************************/
2757
2758 newtComponent b1;
2759 newtComponent b2;
2760 newtComponent b3;
2761 newtComponent b4;
2762 newtComponent b_res;
2763 newtComponent myForm;
2764
2765 if (g_text_mode) {
2766 while (!strchr("AICE", output)) {
2767 printf("Which mode - (A)utomatic, (I)nteractive, \n(C)ompare only, or (E)xit to shell?\n--> ");
2768 mr_getline(tmp, stdin);
2769 output = tmp[0];
2770 mr_free(tmp);
2771 }
2772 return (output);
2773 }
2774
2775 newtPushHelpLine(" Do you want to 'nuke' your system, restore interactively, or just compare?");
2776 newtOpenWindow(24, 3, 32, 17, "How should I restore?");
2777 b1 = newtButton(7, 1, "Automatically");
2778 b2 = newtButton(7, 5, "Interactively");
2779 b3 = newtButton(7, 9, "Compare only!");
2780 b4 = newtButton(7, 13, "Exit to shell");
2781 myForm = newtForm(NULL, NULL, 0);
2782 newtFormAddComponents(myForm, b1, b2, b3, b4, NULL);
2783 b_res = newtRunForm(myForm);
2784 newtFormDestroy(myForm);
2785 newtPopWindow();
2786 if (b_res == b1) {
2787 output = 'N';
2788 }
2789 if (b_res == b2) {
2790 output = 'I';
2791 }
2792 if (b_res == b3) {
2793 output = 'C';
2794 }
2795 if (b_res == b4) {
2796 output = 'E';
2797 }
2798 newtPopHelpLine();
2799 return (output);
2800}
Note: See TracBrowser for help on using the repository browser.