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

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

trunk in parity with stable

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