source: MondoRescue/branches/stable/mondo/src/mondorestore/mondo-rstr-newt.c@ 1125

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

Still linker fixes (grrr)

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