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

Last change on this file since 558 was 541, checked in by bcornec, 18 years ago

Stable is reverted to r436 (2.0.7) to put it in line with 2.0.8 and start from there over

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