source: MondoRescue/trunk/mondo/src/mondorestore/mondo-rstr-newt.c@ 900

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

Huge patch to introduce low level functions that will bw used everywhere (mr_free, mr_asprintf, ...)
Nearly linking now due to that.

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