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

Last change on this file since 705 was 705, checked in by andree, 18 years ago

Fixed bug where image partitions (e.g. NTFS) would change size if Ok was
pressed in edit mountlist item dialog.

  • 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 705 2006-07-22 02:24:31Z andree $
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 705 2006-07-22 02:24:31Z andree $";
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 (strcmp(mountlist->el[currline].mountpoint, "image")) {
1367 if (strstr(mountlist->el[currline].device, RAID_DEVICE_STUB)) {
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 }
1375 newtListboxSetEntry(listbox, (int) keylist[currline],
1376 mountlist_entry_to_string(mountlist, currline));
1377 /* if new /dev/md RAID device then do funky stuff */
1378 if (strstr(mountlist->el[currline].device, RAID_DEVICE_STUB)
1379 && !strstr(device_used_to_be, RAID_DEVICE_STUB)) {
1380 initiate_new_raidlist_entry(raidlist, mountlist, currline,
1381 device_str);
1382 }
1383 /* if moving from RAID to non-RAID then do funky stuff */
1384 else if (strstr(device_used_to_be, RAID_DEVICE_STUB)
1385 && !strstr(device_str, RAID_DEVICE_STUB)) {
1386 delete_raidlist_entry(mountlist, raidlist, device_str);
1387 }
1388 /* if moving a non-RAID to another non-RAID then re-jig any RAID disks, if necessary */
1389 else if (!strstr(device_used_to_be, RAID_DEVICE_STUB)
1390 && !strstr(device_str, RAID_DEVICE_STUB)) {
1391 rejig_partition_name_in_raidlist_if_necessary(raidlist,
1392 device_used_to_be,
1393 device_str);
1394 }
1395/* else, moving a RAID to another RAID; bad idea, or so I thought */
1396#ifndef __FreeBSD__ /* It works fine under FBSD. */
1397 else if (strcmp(device_used_to_be, device_str)) {
1398 popup_and_OK
1399 ("You are renaming a RAID device as another RAID device. I don't like it but I'll allow it.");
1400 }
1401#endif
1402 redraw_mountlist(mountlist, keylist, listbox);
1403}
1404
1405
1406#if __FreeBSD__
1407/**
1408 * Add a subdisk to @p raidrec.
1409 * @param raidlist The raidlist containing information about RAID partitions.
1410 * @param raidrec The RAID device record to add the subdisk to.
1411 * @param temp The device name of the RAID disk to add it to.
1412 * @author Joshua Oreman
1413 * @ingroup restoreGuiMountlist
1414 */
1415void
1416add_raid_subdisk(struct raidlist_itself *raidlist,
1417 struct vinum_plex *raidrec, char *temp)
1418{
1419 int i;
1420 bool found = FALSE;
1421
1422 for (i = 0; i < raidlist->disks.entries; ++i) {
1423 if (!strcmp(raidlist->disks.el[i].device, temp)) {
1424 strcpy(raidrec->sd[raidrec->subdisks].which_device,
1425 raidlist->disks.el[i].name);
1426 found = TRUE;
1427 }
1428 }
1429 if (!found) {
1430 sprintf(raidlist->disks.el[raidlist->disks.entries].name,
1431 "drive%i", raidlist->disks.entries);
1432 sprintf(raidrec->sd[raidrec->subdisks].which_device, "drive%i",
1433 raidlist->disks.entries);
1434 strcpy(raidlist->disks.el[raidlist->disks.entries++].device, temp);
1435 }
1436 raidrec->subdisks++;
1437}
1438
1439
1440/**
1441 * Determine the /dev entry for @p vinum_name.
1442 * @param raidlist The raidlist containing information about RAID devices.
1443 * @param vinum_name The name of the Vinum drive to map to a /dev entry.
1444 * @return The /dev entry, or NULL if none was found.
1445 * @note The returned string points to static storage that will be overwritten with each call.
1446 * @author Joshua Oreman
1447 * @ingroup restoreUtilityGroup
1448 */
1449char *find_dev_entry_for_raid_device_name(struct raidlist_itself *raidlist,
1450 char *vinum_name)
1451{
1452 int i;
1453 for (i = 0; i < raidlist->disks.entries; ++i) {
1454 if (!strcmp(raidlist->disks.el[i].name, vinum_name)) {
1455 return raidlist->disks.el[i].device;
1456 }
1457 }
1458 return NULL;
1459}
1460
1461void
1462edit_raidlist_plex(struct mountlist_itself *mountlist,
1463 struct raidlist_itself *raidlist,
1464 struct vinum_plex *raidrec, int currline,
1465 int currline2);
1466
1467#endif
1468
1469
1470/**
1471 * Edit the entry for @p raidrec in @p raidlist.
1472 * @param mountlist The mountlist to get some information from.
1473 * @param raidlist The raidlist containing information about RAID devices.
1474 * @param raidrec The RAID device record for this partition.
1475 * @param currline The line number (starting from 0) in the mountlist of the RAID device.
1476 * @ingroup restoreGuiMountlist
1477 */
1478void
1479edit_raidlist_entry(struct mountlist_itself *mountlist,
1480 struct raidlist_itself *raidlist,
1481 struct OSSWAP (raid_device_record,
1482 vinum_volume) * raidrec, int currline)
1483{
1484
1485#ifdef __FreeBSD__
1486 /** structures ********************************************************/
1487 struct vinum_volume bkp_raidrec;
1488
1489
1490 /** buffers ***********************************************************/
1491 char title_of_editraidForm_window[MAX_STR_LEN];
1492
1493 /** newt **************************************************************/
1494 newtComponent editraidForm;
1495 newtComponent bOK;
1496 newtComponent bCancel;
1497 newtComponent bEdit;
1498 newtComponent bAdd;
1499 newtComponent bDelete;
1500 newtComponent b_res;
1501 newtComponent plexesListbox;
1502 newtComponent plexesHeader;
1503
1504 void *keylist[10];
1505 void *curr_choice;
1506
1507 int currline2 = 0;
1508
1509 log_it("Started edit_raidlist_entry");
1510 memcpy((void *) &bkp_raidrec, (void *) raidrec,
1511 sizeof(struct vinum_volume));
1512 sprintf(title_of_editraidForm_window, "Plexes on %s",
1513 raidrec->volname);
1514 newtPushHelpLine(" Please select a plex to edit");
1515 newtOpenWindow(13, 5, 54, 15, title_of_editraidForm_window);
1516 for (;;) {
1517 int i;
1518 char headerstr[MAX_STR_LEN];
1519 snprintf(headerstr, MAX_STR_LEN, "%-14s %-8s %11s %8s",
1520 "Plex", "Level", "Stripe Size", "Subdisks");
1521
1522 bOK = newtCompactButton(2, 13, " OK ");
1523 bCancel = newtCompactButton(12, 13, "Cancel");
1524 bAdd = newtCompactButton(22, 13, " Add ");
1525 bEdit = newtCompactButton(32, 13, " Edit ");
1526 bDelete = newtCompactButton(42, 13, "Delete");
1527
1528 plexesListbox =
1529 newtListbox(2, 3, 9, NEWT_FLAG_SCROLL | NEWT_FLAG_RETURNEXIT);
1530 plexesHeader = newtLabel(2, 2, headerstr);
1531 editraidForm = newtForm(NULL, NULL, 0);
1532
1533 newtListboxClear(plexesListbox);
1534 for (i = 0; i < 10; ++i) {
1535 keylist[i] = (void *) i;
1536 if (i < raidrec->plexes) {
1537 char pname[64], entry[MAX_STR_LEN], raidlevel[64],
1538 chunksize[64];
1539 switch (raidrec->plex[i].raidlevel) {
1540 case -1:
1541 strcpy(raidlevel, "concat");
1542 break;
1543 case 0:
1544 strcpy(raidlevel, "striped");
1545 break;
1546 case 5:
1547 strcpy(raidlevel, "raid5");
1548 break;
1549 default:
1550 sprintf(raidlevel, "raid%i",
1551 raidrec->plex[i].raidlevel);
1552 break;
1553 }
1554
1555 if (raidrec->plex[i].raidlevel == -1) {
1556 strcpy(chunksize, "N/A");
1557 } else {
1558 sprintf(chunksize, "%dk", raidrec->plex[i].stripesize);
1559 }
1560 snprintf(pname, 64, "%s.p%i", raidrec->volname, i);
1561 snprintf(entry, MAX_STR_LEN, "%-14s %-8s %11s %8d",
1562 pname, raidlevel, chunksize,
1563 raidrec->plex[i].subdisks);
1564 newtListboxAppendEntry(plexesListbox, entry, keylist[i]);
1565 }
1566 }
1567
1568 newtFormAddComponents(editraidForm, bOK, bCancel, bAdd, bEdit,
1569 bDelete, plexesListbox, plexesHeader, NULL);
1570
1571 b_res = newtRunForm(editraidForm);
1572 if (b_res == bOK || b_res == bCancel) {
1573 break;
1574 }
1575
1576 curr_choice = newtListboxGetCurrent(plexesListbox);
1577 for (currline2 = 0; currline2 < raidrec->plexes; ++currline2) {
1578 if (currline2 > 9)
1579 break;
1580 if (keylist[currline2] == curr_choice)
1581 break;
1582 }
1583
1584 if (b_res == bDelete) {
1585 char msg[MAX_STR_LEN];
1586 sprintf(msg, "Are you sure you want to delete %s.p%i?",
1587 raidrec->volname, currline2);
1588 if (ask_me_yes_or_no(msg)) {
1589 log_it("Deleting RAID plex");
1590 memcpy((void *) &raidrec->plex[currline2],
1591 (void *) &raidrec->plex[raidrec->plexes - 1],
1592 sizeof(struct vinum_plex));
1593 raidrec->plexes--;
1594 }
1595 continue;
1596 }
1597 if (b_res == bAdd) {
1598 raidrec->plex[raidrec->plexes].raidlevel = 0;
1599 raidrec->plex[raidrec->plexes].stripesize = 279;
1600 raidrec->plex[raidrec->plexes].subdisks = 0;
1601 currline2 = raidrec->plexes++;
1602 }
1603 edit_raidlist_plex(mountlist, raidlist, &raidrec->plex[currline2],
1604 currline, currline2);
1605 newtFormDestroy(editraidForm);
1606 }
1607 if (b_res == bCancel) {
1608 memcpy((void *) raidrec, (void *) &bkp_raidrec,
1609 sizeof(struct vinum_volume));
1610 }
1611 newtPopHelpLine();
1612 newtPopWindow();
1613 mountlist->el[currline].size =
1614 calculate_raid_device_size(mountlist, raidlist, raidrec->volname);
1615#else
1616 /** structures ********************************************************/
1617 struct raid_device_record *bkp_raidrec;
1618
1619
1620 /** buffers ***********************************************************/
1621 char *title_of_editraidForm_window;
1622 char *sz_raid_level;
1623 char *sz_data_disks;
1624 char *sz_spare_disks;
1625 char *sz_parity_disks;
1626 char *sz_failed_disks;
1627
1628 /** newt **************************************************************/
1629 newtComponent editraidForm;
1630 newtComponent bOK;
1631 newtComponent bCancel;
1632 newtComponent bAdditional;
1633 newtComponent bChangeRaid;
1634 newtComponent bSelectData;
1635 newtComponent bSelectSpare;
1636 newtComponent bSelectParity;
1637 newtComponent bSelectFailed;
1638 newtComponent b_res;
1639
1640 assert(mountlist != NULL);
1641 assert(raidlist != NULL);
1642 assert(raidrec != NULL);
1643
1644 malloc_string(title_of_editraidForm_window);
1645 malloc_string(sz_raid_level);
1646 malloc_string(sz_data_disks);
1647 malloc_string(sz_spare_disks);
1648 malloc_string(sz_parity_disks);
1649 malloc_string(sz_failed_disks);
1650 if (!(bkp_raidrec = malloc(sizeof(struct raid_device_record)))) {
1651 fatal_error("Cannot malloc space for raidrec");
1652 }
1653
1654 log_it("Started edit_raidlist_entry");
1655
1656 memcpy((void *) bkp_raidrec, (void *) raidrec,
1657 sizeof(struct raid_device_record));
1658 sprintf(title_of_editraidForm_window, "%s", raidrec->raid_device);
1659 log_msg(2, "Opening newt window");
1660 newtOpenWindow(20, 5, 40, 14, title_of_editraidForm_window);
1661 for (;;) {
1662 log_msg(2, "Main loop");
1663 sprintf(title_of_editraidForm_window, "Edit %s",
1664 raidrec->raid_device);
1665 strcpy(sz_raid_level,
1666 turn_raid_level_number_to_string(raidrec->raid_level));
1667 strcpy(sz_data_disks,
1668 number_of_disks_as_string(raidrec->data_disks.entries,
1669 "data"));
1670 strcpy(sz_spare_disks,
1671 number_of_disks_as_string(raidrec->spare_disks.entries,
1672 "spare"));
1673 strcpy(sz_parity_disks,
1674 number_of_disks_as_string(raidrec->parity_disks.entries,
1675 "parity"));
1676 strcpy(sz_failed_disks,
1677 number_of_disks_as_string(raidrec->failed_disks.entries,
1678 "failed"));
1679 bSelectData = newtButton(1, 1, sz_data_disks);
1680 bSelectSpare = newtButton(20, 1, sz_spare_disks);
1681 bSelectParity = newtButton(1, 5, sz_parity_disks);
1682 bSelectFailed = newtButton(20, 5, sz_failed_disks);
1683 bChangeRaid = newtButton(1, 9, sz_raid_level);
1684 bOK = newtButton(16 + (raidrec->raid_level == -1), 9, " OK ");
1685 bCancel = newtButton(28, 9, "Cancel");
1686 bAdditional =
1687 newtCompactButton(1, 13,
1688 "Additional settings and information");
1689 newtPushHelpLine
1690 (" Edit the RAID device's settings to your heart's content, then hit OK/Cancel.");
1691 editraidForm = newtForm(NULL, NULL, 0);
1692 newtFormAddComponents(editraidForm, bSelectData, bSelectParity,
1693 bChangeRaid, bSelectSpare, bSelectFailed,
1694 bOK, bCancel, bAdditional);
1695 b_res = newtRunForm(editraidForm);
1696 if (b_res == bChangeRaid) {
1697 choose_raid_level(raidrec);
1698 } else if (b_res == bSelectData) {
1699 select_raid_disks(mountlist, raidlist, raidrec, "data",
1700 &raidrec->data_disks);
1701 } else if (b_res == bSelectSpare) {
1702 select_raid_disks(mountlist, raidlist, raidrec, "spare",
1703 &raidrec->spare_disks);
1704 } else if (b_res == bSelectParity) {
1705 select_raid_disks(mountlist, raidlist, raidrec, "parity",
1706 &raidrec->parity_disks);
1707 } else if (b_res == bSelectFailed) {
1708 select_raid_disks(mountlist, raidlist, raidrec, "failed",
1709 &raidrec->failed_disks);
1710 } else if (b_res == bAdditional) {
1711 edit_raidrec_additional_vars(raidrec);
1712 }
1713 newtFormDestroy(editraidForm);
1714 if (b_res == bOK || b_res == bCancel) {
1715 break;
1716 }
1717 }
1718 if (b_res == bCancel) {
1719 memcpy((void *) raidrec, (void *) bkp_raidrec,
1720 sizeof(struct raid_device_record));
1721 }
1722 newtPopHelpLine();
1723 newtPopWindow();
1724 mountlist->el[currline].size =
1725 calculate_raid_device_size(mountlist, raidlist,
1726 raidrec->raid_device);
1727 paranoid_free(title_of_editraidForm_window);
1728 paranoid_free(sz_raid_level);
1729 paranoid_free(sz_data_disks);
1730 paranoid_free(sz_spare_disks);
1731 paranoid_free(sz_parity_disks);
1732 paranoid_free(sz_failed_disks);
1733 paranoid_free(bkp_raidrec);
1734#endif
1735}
1736
1737#ifdef __FreeBSD__
1738
1739/**
1740 * Edit the plex @p raidrec in @p raidlist.
1741 * @param mountlist The mountlist to get some of the information from.
1742 * @param raidlist The raidlist containing information about RAID devices.
1743 * @param raidrec The plex to edit.
1744 * @param currline The line number (starting from 0) of the RAID device in @p mountlist.
1745 * @param currline2 The line number (starting from 0) of the plex within the RAID device.
1746 * @author Joshua Oreman
1747 * @ingroup restoreGuiMountlist
1748 */
1749void
1750edit_raidlist_plex(struct mountlist_itself *mountlist,
1751 struct raidlist_itself *raidlist,
1752 struct vinum_plex *raidrec, int currline, int currline2)
1753{
1754
1755 /** structures ********************************************************/
1756 struct vinum_plex bkp_raidrec;
1757
1758
1759 /** buffers ***********************************************************/
1760 char title_of_editraidForm_window[MAX_STR_LEN];
1761
1762 /** newt **************************************************************/
1763 newtComponent editraidForm;
1764 newtComponent bOK;
1765 newtComponent bCancel;
1766 newtComponent bEdit;
1767 newtComponent bAdd;
1768 newtComponent bDelete;
1769 newtComponent b_res;
1770 newtComponent unallocListbox, allocListbox;
1771 newtComponent bLevel, sLevel;
1772 newtComponent bStripeSize, sStripeSize;
1773 newtComponent bAlloc, bUnalloc;
1774
1775 void *keylist[ARBITRARY_MAXIMUM];
1776 void *curr_choice_a, *curr_choice_u;
1777 int currline_a, currline_u;
1778
1779 struct mountlist_itself *unallocparts;
1780
1781 unallocparts = malloc(sizeof(struct mountlist_itself));
1782
1783 log_it("Started edit_raidlist_entry");
1784 memcpy((void *) &bkp_raidrec, (void *) raidrec,
1785 sizeof(struct vinum_plex));
1786 sprintf(title_of_editraidForm_window, "%s.p%i",
1787 raidlist->el[currline].volname, currline2);
1788 newtPushHelpLine
1789 (" Please select a subdisk to edit, or edit this plex's parameters");
1790 newtOpenWindow(13, 3, 54, 18, title_of_editraidForm_window);
1791 for (;;) {
1792 int i;
1793 char headerstr[MAX_STR_LEN];
1794 char tmp[64];
1795 snprintf(headerstr, MAX_STR_LEN, "%-24s %s", "Subdisk", "Device");
1796
1797
1798 switch (raidrec->raidlevel) {
1799 case -1:
1800 strcpy(tmp, "concat");
1801 break;
1802 case 0:
1803 strcpy(tmp, "striped");
1804 break;
1805 case 5:
1806 strcpy(tmp, "raid5");
1807 break;
1808 default:
1809 sprintf(tmp, "unknown (%i)", raidrec->raidlevel);
1810 break;
1811 }
1812 bLevel = newtCompactButton(2, 2, " RAID level ");
1813 sLevel = newtLabel(19, 2, tmp);
1814
1815 if (raidrec->raidlevel >= 0) {
1816 sprintf(tmp, "%ik", raidrec->stripesize);
1817 bStripeSize = newtCompactButton(2, 4, " Stripe size ");
1818 } else {
1819 strcpy(tmp, "N/A");
1820 bStripeSize = newtLabel(2, 4, "Stripe size:");
1821 }
1822 sStripeSize = newtLabel(19, 4, tmp);
1823
1824 bOK = newtCompactButton(2, 16, " OK ");
1825 bCancel = newtCompactButton(12, 16, "Cancel");
1826 bAdd = newtCompactButton(22, 16, " Add ");
1827 bEdit = newtCompactButton(32, 16, " Edit ");
1828 bDelete = newtCompactButton(42, 16, "Delete");
1829
1830
1831 // plexesListbox = newtListbox (2, 7, 9, NEWT_FLAG_SCROLL | NEWT_FLAG_RETURNEXIT);
1832 // plexesHeader = newtLabel (2, 6, headerstr);
1833 unallocListbox =
1834 newtListbox(2, 7, 7, NEWT_FLAG_SCROLL | NEWT_FLAG_RETURNEXIT);
1835 allocListbox =
1836 newtListbox(33, 7, 7, NEWT_FLAG_SCROLL | NEWT_FLAG_RETURNEXIT);
1837 bAlloc = newtButton(23, 7, " -> ");
1838 bUnalloc = newtButton(23, 11, " <- ");
1839
1840 editraidForm = newtForm(NULL, NULL, 0);
1841
1842 newtListboxClear(allocListbox);
1843 newtListboxClear(unallocListbox);
1844 bzero(unallocparts, sizeof(struct mountlist_itself));
1845 make_list_of_unallocated_raid_partitions(unallocparts, mountlist,
1846 raidlist);
1847 for (i = 0; i < ARBITRARY_MAXIMUM; ++i) {
1848 char entry[MAX_STR_LEN];
1849 keylist[i] = (void *) i;
1850 if (i < raidrec->subdisks) {
1851 snprintf(entry, MAX_STR_LEN, "%-17s",
1852 find_dev_entry_for_raid_device_name(raidlist,
1853 raidrec->
1854 sd[i].
1855 which_device));
1856 newtListboxAppendEntry(allocListbox, entry, keylist[i]);
1857 }
1858 if (i < unallocparts->entries) {
1859 snprintf(entry, MAX_STR_LEN, "%-17s",
1860 unallocparts->el[i].device);
1861 newtListboxAppendEntry(unallocListbox, entry, keylist[i]);
1862 }
1863 }
1864
1865#define COMP(x) newtFormAddComponent (editraidForm, x)
1866#define UCOMP(x) if (unallocparts->entries > 0) COMP(x)
1867#define ACOMP(x) if (raidrec->subdisks > 0) COMP(x)
1868 editraidForm = newtForm(NULL, NULL, 0);
1869 UCOMP(unallocListbox);
1870 UCOMP(bAlloc);
1871 ACOMP(allocListbox);
1872 ACOMP(bUnalloc);
1873 COMP(bOK);
1874 COMP(bCancel);
1875 COMP(bLevel);
1876 COMP(sLevel);
1877 if (raidrec->raidlevel != -1) {
1878 COMP(bStripeSize);
1879 COMP(sStripeSize);
1880 }
1881#undef COMP
1882#undef UCOMP
1883#undef ACOMP
1884
1885 newtRefresh();
1886 b_res = newtRunForm(editraidForm);
1887 if (b_res == bOK || b_res == bCancel) {
1888 break;
1889 }
1890
1891 curr_choice_a = (raidrec->subdisks > 0) ?
1892 newtListboxGetCurrent(allocListbox) : (void *) 1234;
1893 curr_choice_u = (unallocparts->entries > 0) ?
1894 newtListboxGetCurrent(unallocListbox) : (void *) 1234;
1895 for (currline_a = 0; currline_a < raidrec->subdisks; ++currline_a) {
1896 if (currline_a > ARBITRARY_MAXIMUM)
1897 break;
1898 if (keylist[currline_a] == curr_choice_a)
1899 break;
1900 }
1901 for (currline_u = 0; currline_u < unallocparts->entries;
1902 ++currline_u) {
1903 if (currline_u > ARBITRARY_MAXIMUM)
1904 break;
1905 if (keylist[currline_u] == curr_choice_u)
1906 break;
1907 }
1908 if (b_res == bLevel) {
1909 choose_raid_level(raidrec);
1910 } else if (b_res == bStripeSize) {
1911 char tmp[64];
1912 sprintf(tmp, "%i", raidrec->stripesize);
1913 if (popup_and_get_string
1914 ("Stripe size",
1915 "Please enter the stripe size in kilobytes.", tmp, 20)) {
1916 raidrec->stripesize = atoi(tmp);
1917 }
1918 } else if ((b_res == bAlloc) || (b_res == unallocListbox)) {
1919 if (currline_u <= unallocparts->entries)
1920 add_raid_subdisk(raidlist, raidrec,
1921 unallocparts->el[currline_u].device);
1922 } else if ((b_res == bUnalloc) || (b_res == allocListbox)) {
1923 if (currline_a <= raidrec->subdisks) {
1924 memcpy((void *) &raidrec->sd[currline_a],
1925 (void *) &raidrec->sd[raidrec->subdisks - 1],
1926 sizeof(struct vinum_subdisk));
1927 raidrec->subdisks--;
1928 }
1929 }
1930#if 0
1931 } else {
1932 edit_raid_subdisk(raidlist, raidrec, &raidrec->sd[currline3],
1933 currline3);
1934 }
1935#endif
1936 newtFormDestroy(editraidForm);
1937 newtRefresh();
1938}
1939
1940if (b_res == bCancel) {
1941 memcpy((void *) raidrec, (void *) &bkp_raidrec,
1942 sizeof(struct vinum_plex));
1943}
1944newtPopWindow();
1945newtPopHelpLine();
1946}
1947#else
1948/**
1949 * Edit additional RAID variable number @p lino.
1950 * @param raidrec The RAID device record to edit the variable in.
1951 * @param lino The line number (starting from 0) of the variable to edit.
1952 * @ingroup restoreGuiVarslist
1953 */
1954void edit_varslist_entry(struct raid_device_record *raidrec, int lino)
1955{
1956
1957 /** buffers ***********************************************************/
1958 char header[MAX_STR_LEN];
1959 char comment[MAX_STR_LEN];
1960 char sz_out[MAX_STR_LEN];
1961
1962 assert(raidrec != 0);
1963 assert(lino >= 0);
1964
1965 strcpy(sz_out, raidrec->additional_vars.el[lino].value);
1966 sprintf(header, "Edit %s", raidrec->additional_vars.el[lino].label);
1967 sprintf(comment, "Please set %s's value (currently '%s')",
1968 raidrec->additional_vars.el[lino].label, sz_out);
1969 if (popup_and_get_string(header, comment, sz_out, MAX_STR_LEN)) {
1970 strip_spaces(sz_out);
1971 strcpy(raidrec->additional_vars.el[lino].value, sz_out);
1972 }
1973}
1974
1975
1976/* I'm not racist against white people. I just don't like people who think Liberia is near Spain. - Hugo, 09/01/2001 */
1977
1978#endif
1979
1980/**
1981 * Edit the mountlist using Newt.
1982 * @param mountlist The mountlist to edit.
1983 * @param raidlist The raidlist that goes with @p mountlist.
1984 * @return 0 if the user pressed OK, 1 if they pressed Cancel.
1985 */
1986int
1987edit_mountlist_in_newt(char *mountlist_fname,
1988 struct mountlist_itself *mountlist,
1989 struct raidlist_itself *raidlist)
1990{
1991
1992 /** newt **************************************************************/
1993 newtComponent myForm;
1994 newtComponent bAdd;
1995 newtComponent bEdit;
1996 newtComponent bDelete;
1997 newtComponent bOK;
1998 newtComponent bCancel;
1999 newtComponent b_res = NULL;
2000 newtComponent partitionsListbox;
2001 newtComponent headerMsg;
2002 newtComponent flawsLabelA;
2003 newtComponent flawsLabelB;
2004 newtComponent flawsLabelC;
2005 newtComponent bReload;
2006
2007 /** ???? *************************************************************/
2008 void *curr_choice;
2009 void *keylist[ARBITRARY_MAXIMUM];
2010
2011 /** int **************************************************************/
2012 int i = 0;
2013 int currline = 0;
2014 int finished = FALSE;
2015
2016 /** buffers **********************************************************/
2017 char tmp[MAX_STR_LEN];
2018 char flaws_str_A[MAX_STR_LEN];
2019 char flaws_str_B[MAX_STR_LEN];
2020 char flaws_str_C[MAX_STR_LEN];
2021
2022 assert(mountlist != NULL);
2023 assert(raidlist != NULL);
2024
2025 strcpy(flaws_str_A, "xxxxxxxxx");
2026 strcpy(flaws_str_B, "xxxxxxxxx");
2027 strcpy(flaws_str_C, "xxxxxxxxx");
2028 if (mountlist->entries > ARBITRARY_MAXIMUM) {
2029 log_to_screen("Arbitrary limits suck, man!");
2030 finish(1);
2031 }
2032 newtPushHelpLine
2033 (" Please edit the mountlist to your satisfaction, then click OK or Cancel.");
2034 i = 4;
2035 bAdd = newtCompactButton(i, 17, " Add ");
2036 bEdit = newtCompactButton(i += 11, 17, " Edit ");
2037 bDelete = newtCompactButton(i += 12, 17, "Delete");
2038 bReload = newtCompactButton(i += 12, 17, "Reload");
2039 bCancel = newtCompactButton(i += 12, 17, "Cancel");
2040 bOK = newtCompactButton(i += 12, 17, " OK ");
2041 sprintf(tmp, "%-24s %-24s %-8s %s", "Device", "Mountpoint", "Format",
2042 "Size (MB)");
2043 headerMsg = newtLabel(2, 1, tmp);
2044 flawsLabelA = newtLabel(2, 13, flaws_str_A);
2045 flawsLabelB = newtLabel(2, 14, flaws_str_B);
2046 flawsLabelC = newtLabel(2, 15, flaws_str_C);
2047 partitionsListbox =
2048 newtListbox(2, 2, 10, NEWT_FLAG_SCROLL | NEWT_FLAG_RETURNEXIT);
2049 redraw_mountlist(mountlist, keylist, partitionsListbox);
2050 newtOpenWindow(1, 3, 77, 18, "Editing mountlist");
2051 myForm = newtForm(NULL, NULL, 0);
2052 newtFormAddComponents(myForm, headerMsg, partitionsListbox,
2053 flawsLabelA, flawsLabelB, flawsLabelC, bAdd,
2054 bEdit, bDelete, bReload, bCancel, bOK, NULL);
2055 while (!finished) {
2056 evaluate_mountlist(mountlist, flaws_str_A, flaws_str_B,
2057 flaws_str_C);
2058 newtLabelSetText(flawsLabelA, flaws_str_A);
2059 newtLabelSetText(flawsLabelB, flaws_str_B);
2060 newtLabelSetText(flawsLabelC, flaws_str_C);
2061 b_res = newtRunForm(myForm);
2062 if (b_res == bOK) {
2063 if (!evaluate_mountlist
2064 (mountlist, flaws_str_A, flaws_str_B, flaws_str_C)) {
2065 finished =
2066 ask_me_yes_or_no
2067 ("Your mountlist might not work. Continue anyway?");
2068 } else {
2069 finished =
2070 ask_me_yes_or_no
2071 ("Are you sure you want to save your mountlist and continue? (No changes will be made to your partition table at this time.)");
2072 }
2073 } else if (b_res == bCancel) {
2074 finished = TRUE;
2075 } else if (b_res == bReload) {
2076 if (ask_me_yes_or_no("Reload original mountlist?")) {
2077/*
2078This would be really dumb. RAIDTAB_FNAME is #define'd. --- Hugo, 2003/04/24
2079 if (!RAIDTAB_FNAME[0])
2080 {
2081 strcpy(RAIDTAB_FNAME, "/etc/raidtab");
2082 log_it("Warning - raidtab_fname is blank. Assuming %s", g_raidtab_fname);
2083 }
2084*/
2085 load_mountlist(mountlist, mountlist_fname);
2086 load_raidtab_into_raidlist(raidlist, RAIDTAB_FNAME);
2087 redraw_mountlist(mountlist, keylist, partitionsListbox);
2088 }
2089 } else {
2090 curr_choice = newtListboxGetCurrent(partitionsListbox);
2091 for (i = 0;
2092 i < mountlist->entries && keylist[i] != curr_choice; i++);
2093 if (i == mountlist->entries && mountlist->entries > 0) {
2094 log_to_screen("I don't know what that button does!");
2095 } else {
2096 currline = i;
2097 if (b_res == bAdd) {
2098 add_mountlist_entry(mountlist, raidlist,
2099 partitionsListbox, currline,
2100 keylist);
2101 } else if (b_res == bDelete) {
2102 delete_mountlist_entry(mountlist, raidlist,
2103 partitionsListbox, currline,
2104 keylist);
2105 } else {
2106 if (mountlist->entries > 0) {
2107 edit_mountlist_entry(mountlist, raidlist,
2108 partitionsListbox, currline,
2109 keylist);
2110 } else {
2111 popup_and_OK
2112 ("Please add an entry. Then press ENTER to edit it.");
2113 }
2114 }
2115 }
2116 }
2117 }
2118 newtFormDestroy(myForm);
2119 newtPopWindow();
2120 newtPopHelpLine();
2121 if (b_res == bOK) {
2122 log_it("You pushed 'OK'. I shall now continue.");
2123 return (0);
2124 } else {
2125 /* popup_and_OK("You pushed 'cancel'. I shall now abort."); */
2126 return (1);
2127 }
2128}
2129
2130
2131
2132/**
2133 * Edit the mountlist.
2134 * @param mountlist The mountlist to edit.
2135 * @param raidlist The raidlist that goes with @p mountlist.
2136 * @return 0 if the user pressed OK, 1 if they pressed Cancel.
2137 */
2138int
2139edit_mountlist(char *mountlist_fname, struct mountlist_itself *mountlist,
2140 struct raidlist_itself *raidlist)
2141{
2142 int res = 0;
2143// char tmp[MAX_STR_LEN];
2144
2145 iamhere("entering eml");
2146
2147 if (g_text_mode) {
2148 fatal_error("Don't call edit_mountlist() in text mode");
2149 } else {
2150 log_it
2151 ("I'm in GUI mode, so I shall edit mountlist using edit_mountlist()");
2152 res = edit_mountlist_in_newt(mountlist_fname, mountlist, raidlist);
2153 }
2154 iamhere("leaving eml");
2155 return (res);
2156}
2157
2158
2159
2160
2161#ifndef __FreeBSD__
2162/**
2163 * Edit the additional RAID variables in @p raidrec.
2164 * @param raidrec The RAID device record to edit the RAID variables in.
2165 * @ingroup restoreGuiVarslist
2166 */
2167void edit_raidrec_additional_vars(struct raid_device_record *raidrec)
2168{
2169
2170 /** structure *********************************************************/
2171 struct raid_device_record bkp_raidrec;
2172
2173 /** newt **************************************************************/
2174 newtComponent myForm;
2175 newtComponent bAdd;
2176 newtComponent bEdit;
2177 newtComponent bDelete;
2178 newtComponent bOK;
2179 newtComponent bCancel;
2180 newtComponent b_res;
2181 newtComponent varsListbox;
2182 newtComponent headerMsg;
2183
2184 /** ?? ***************************************************************/
2185 void *keylist[ARBITRARY_MAXIMUM], *curr_choice;
2186
2187 /** buffers **********************************************************/
2188 char title_of_window[MAX_STR_LEN];
2189
2190 /** int **************************************************************/
2191 int i = 0;
2192 int currline = 0;
2193
2194
2195 assert(raidrec != NULL);
2196
2197 memcpy((void *) &bkp_raidrec, (void *) raidrec,
2198 sizeof(struct raid_device_record));
2199 sprintf(title_of_window, "Additional variables");
2200 newtPushHelpLine
2201 (" Edit the additional fields to your heart's content, then click OK or Cancel.");
2202 headerMsg = newtLabel(1, 1, "Label Value");
2203 varsListbox =
2204 newtListbox(1, 2, 6, NEWT_FLAG_SCROLL | NEWT_FLAG_RETURNEXIT);
2205 i = 1;
2206 bAdd = newtCompactButton(i, 9, " Add ");
2207 bEdit = newtCompactButton(i += 8, 9, " Edit ");
2208 bDelete = newtCompactButton(i += 9, 9, "Delete");
2209 bOK = newtCompactButton(i += 9, 9, " OK ");
2210 bCancel = newtCompactButton(i += 9, 9, "Cancel");
2211 newtOpenWindow(17, 7, 46, 10, title_of_window);
2212 myForm = newtForm(NULL, NULL, 0);
2213 newtFormAddComponents(myForm, headerMsg, varsListbox, bAdd, bEdit,
2214 bDelete, bOK, bCancel, NULL);
2215 insert_essential_additionalvars(raidrec);
2216 redraw_varslist(&raidrec->additional_vars, keylist, varsListbox);
2217 for (b_res = NULL; b_res != bOK && b_res != bCancel;) {
2218 b_res = newtRunForm(myForm);
2219 curr_choice = newtListboxGetCurrent(varsListbox);
2220 for (currline = 0;
2221 currline < raidrec->additional_vars.entries
2222 && keylist[currline] != curr_choice; currline++);
2223 if (currline == raidrec->additional_vars.entries
2224 && raidrec->additional_vars.entries > 0) {
2225 log_it("Warning - I don't know what this button does");
2226 }
2227 if (b_res == bOK) { /* do nothing */
2228 } else if (b_res == bCancel) { /* do nothing */
2229 } else if (b_res == bAdd) {
2230 add_varslist_entry(raidrec);
2231 } else if (b_res == bDelete) {
2232 delete_varslist_entry(raidrec, currline);
2233 } else {
2234 edit_varslist_entry(raidrec, currline);
2235 }
2236 redraw_varslist(&raidrec->additional_vars, keylist, varsListbox);
2237 }
2238 remove_essential_additionalvars(raidrec);
2239 newtFormDestroy(myForm);
2240 newtPopWindow();
2241 newtPopHelpLine();
2242 if (b_res == bCancel) {
2243 memcpy((void *) raidrec, (void *) &bkp_raidrec,
2244 sizeof(struct raid_device_record));
2245 }
2246 return;
2247}
2248#endif
2249
2250
2251/**
2252 * Find the next free location to place a disk in @p disklist.
2253 * @param disklist The disklist to operate on.
2254 * @return The next free location (starting from 0).
2255 * @ingroup restoreGuiDisklist
2256 */
2257int find_next_free_index_in_disklist(struct list_of_disks *disklist)
2258{
2259
2260 /** int ***************************************************************/
2261 int index = -1;
2262 int pos = 0;
2263
2264 /** bool **************************************************************/
2265 bool done;
2266
2267 assert(disklist != NULL);
2268
2269 for (done = FALSE; !done;) {
2270 for (pos = 0;
2271 pos < disklist->entries && disklist->el[pos].index <= index;
2272 pos++);
2273 if (pos >= disklist->entries) {
2274 done = TRUE;
2275 } else {
2276 index = disklist->el[pos].index;
2277 }
2278 }
2279 return (index + 1);
2280}
2281
2282
2283
2284/**
2285 * Locate @p device in @p raidlist.
2286 * @param raidlist The raidlist ot search in.
2287 * @param device The RAID device to search for.
2288 * @return The index of the device, or -1 if it could not be found.
2289 * @ingroup restoreGuiMountlist
2290 */
2291int
2292find_raid_device_in_raidlist(struct raidlist_itself *raidlist,
2293 char *device)
2294{
2295
2296 /** int ***************************************************************/
2297 int i = 0;
2298#ifdef __FreeBSD__
2299 char vdev[64];
2300#else
2301// Linux
2302#endif
2303
2304 assert(raidlist != NULL);
2305 assert_string_is_neither_NULL_nor_zerolength(device);
2306
2307#ifdef __FreeBSD__
2308 for (i = 0; i < raidlist->entries; i++) {
2309 sprintf(vdev, "/dev/vinum/%s", raidlist->el[i].volname);
2310 if (!strcmp(device, vdev))
2311 break;
2312 }
2313#else
2314
2315 for (i = 0;
2316 strcmp(raidlist->el[i].raid_device, device)
2317 && i < raidlist->entries; i++);
2318#endif
2319 if (i == raidlist->entries) {
2320 return (-1);
2321 } else {
2322 return (i);
2323 }
2324}
2325
2326
2327/**
2328 * Get information about the location of ISO images from the user.
2329 * @param isodir_device Where to put the device (e.g. /dev/hda4) the user enters.
2330 * @param isodir_format Where to put the format (e.g. ext2) the user enters.
2331 * @param isodir_path Where to put the path (e.g. /root/images/mondo) the user enters.
2332 * @param nuke_me_please Whether we're planning on nuking or not.
2333 * @return TRUE if OK was pressed, FALSE otherwise.
2334 */
2335bool
2336get_isodir_info(char *isodir_device, char *isodir_format,
2337 char *isodir_path, bool nuke_me_please)
2338{
2339
2340 /** initialize ********************************************************/
2341
2342 assert(isodir_device != NULL);
2343 assert(isodir_format != NULL);
2344 assert(isodir_path != NULL);
2345
2346 log_it("%d - AAA - isodir_path = %s", isodir_path);
2347 isodir_format[0] = '\0';
2348 if (isodir_device[0] == '\0') {
2349 strcpy(isodir_device, "/dev/");
2350 }
2351 if (isodir_path[0] == '\0') {
2352 strcpy(isodir_path, "/");
2353 }
2354 if (does_file_exist("/tmp/NFS-SERVER-PATH")) {
2355 strcpy(isodir_device, last_line_of_file("/tmp/NFS-SERVER-MOUNT"));
2356 strcpy(isodir_format, "nfs");
2357 strcpy(isodir_path, last_line_of_file("/tmp/NFS-SERVER-PATH"));
2358 }
2359 if (nuke_me_please) {
2360 return (TRUE);
2361 }
2362
2363 if (popup_and_get_string
2364 ("ISO Mode - device", "On what device do the ISO files live?",
2365 isodir_device, MAX_STR_LEN / 4)) {
2366 if (popup_and_get_string
2367 ("ISO Mode - format",
2368 "What is the disk format of the device? (Hit ENTER if you don't know.)",
2369 isodir_format, 16)) {
2370 if (popup_and_get_string
2371 ("ISO Mode - path",
2372 "At what path on this device can the ISO files be found?",
2373 isodir_path, MAX_STR_LEN / 4)) {
2374 strip_spaces(isodir_device);
2375 strip_spaces(isodir_format);
2376 strip_spaces(isodir_path);
2377 log_it("%d - BBB - isodir_path = %s", isodir_path);
2378 return (TRUE);
2379 }
2380 }
2381 }
2382 return (FALSE);
2383}
2384
2385
2386/**
2387 * Create a new raidtab entry for @p device in @p raidlist.
2388 * @param raidlist The raidlist to add the device to.
2389 * @param mountlist The mountlist containing information about the user's partitions.
2390 * @param currline The selected line in the mountlist.
2391 * @param device The RAID device (e.g. /dev/md0) to use.
2392 * @ingroup restoreGuiMountlist
2393 */
2394void
2395initiate_new_raidlist_entry(struct raidlist_itself *raidlist,
2396 struct mountlist_itself *mountlist,
2397 int currline, char *device)
2398{
2399
2400 /** structure *********************************************************/
2401 struct OSSWAP (raid_device_record, vinum_volume) * raidrec;
2402
2403 /** int ***************************************************************/
2404 int pos_in_raidlist = 0;
2405
2406 assert(raidlist != NULL);
2407 assert(mountlist != NULL);
2408 assert_string_is_neither_NULL_nor_zerolength(device);
2409
2410 pos_in_raidlist =
2411 find_raid_device_in_raidlist(raidlist,
2412 mountlist->el[currline].device);
2413 if (pos_in_raidlist >= 0) {
2414 fatal_error("Sorry, that RAID device already exists. Weird.");
2415 }
2416 pos_in_raidlist = raidlist->entries++;
2417 raidrec = &raidlist->el[pos_in_raidlist];
2418 initialize_raidrec(raidrec);
2419 strcpy(raidrec->OSSWAP(raid_device, volname),
2420 OSSWAP(device, basename(device)));
2421#ifndef __FreeBSD__
2422 choose_raid_level(raidrec);
2423 select_raid_disks(mountlist, raidlist, raidrec, "data",
2424 &raidrec->data_disks);
2425#endif
2426 edit_raidlist_entry(mountlist, raidlist, raidrec, currline);
2427}
2428
2429
2430#ifndef __FreeBSD__
2431/**
2432 * Insert the RAID variables not stored in the "additional RAID variables" list there too.
2433 * @param raidrec The RAID device record to operate on.
2434 * @ingroup restoreGuiVarslist
2435 */
2436void insert_essential_additionalvars(struct raid_device_record *raidrec)
2437{
2438
2439 /** int **************************************************************/
2440 int items = 0;
2441
2442 assert(raidrec != NULL);
2443
2444 items = raidrec->additional_vars.entries;
2445 write_variableINT_to_raid_var_line(raidrec, items++,
2446 "persistent-superblock",
2447 raidrec->persistent_superblock);
2448 write_variableINT_to_raid_var_line(raidrec, items++, "chunk-size",
2449 raidrec->chunk_size);
2450 raidrec->additional_vars.entries = items;
2451}
2452
2453#endif
2454
2455/**
2456 * Dummy function that proves that we can get to the point where Mondo is run.
2457 */
2458void nuke_mode_dummy()
2459{
2460
2461 /** newt *************************************************************/
2462 newtComponent myForm;
2463 newtComponent b1;
2464 newtComponent b2;
2465 newtComponent b3;
2466 newtComponent b_res;
2467
2468
2469 newtPushHelpLine
2470 ("This is where I nuke your hard drives. Mhahahahaha. No-one can stop Mojo Jojo!");
2471 newtOpenWindow(24, 3, 32, 13, "Nuking");
2472 b1 = newtButton(7, 1, "Slowly");
2473 b2 = newtButton(7, 5, "Medium");
2474 b3 = newtButton(7, 9, "Quickly");
2475 myForm = newtForm(NULL, NULL, 0);
2476 newtFormAddComponents(myForm, b1, b2, b3, NULL);
2477 b_res = newtRunForm(myForm);
2478 newtFormDestroy(myForm);
2479 newtPopWindow();
2480 newtPopHelpLine();
2481}
2482
2483
2484
2485/**
2486 * Redraw the disklist.
2487 * @param disklist The disklist to read from.
2488 * @param keylist The list of keys for @p listbox.
2489 * @param listbox The Newt listbox component to redraw.
2490 * @ingroup restoreGuiDisklist
2491 */
2492void
2493redraw_disklist(struct list_of_disks *disklist,
2494 void *keylist[ARBITRARY_MAXIMUM], newtComponent listbox)
2495{
2496
2497 /** int *************************************************************/
2498 int i = 0;
2499
2500 assert(disklist != NULL);
2501 assert(keylist != NULL);
2502 assert(listbox != NULL);
2503
2504 newtListboxClear(listbox);
2505
2506 for (i = 0; i < ARBITRARY_MAXIMUM; i++) {
2507 keylist[i] = (void *) i;
2508 }
2509 for (i = 0; i < disklist->entries; i++) {
2510 newtListboxAppendEntry(listbox,
2511 disklist_entry_to_string(disklist, i),
2512 keylist[i]);
2513 }
2514}
2515
2516
2517/**
2518 * Redraw the mountlist.
2519 * @param mountlist The mountlist to read from.
2520 * @param keylist The list of keys for @p listbox.
2521 * @param listbox The Newt listbox component to redraw.
2522 * @ingroup restoreGuiMountlist
2523 */
2524void
2525redraw_mountlist(struct mountlist_itself *mountlist,
2526 void *keylist[ARBITRARY_MAXIMUM], newtComponent listbox)
2527{
2528
2529 /** int **************************************************************/
2530 int i = 0;
2531
2532 assert(mountlist != NULL);
2533 assert(keylist != NULL);
2534 assert(listbox != NULL);
2535
2536 newtListboxClear(listbox);
2537// sort_mountlist_by_device (mountlist);
2538 for (i = 0; i < ARBITRARY_MAXIMUM; i++) {
2539 keylist[i] = (void *) i;
2540 }
2541 for (i = 0; i < mountlist->entries; i++) {
2542 newtListboxAppendEntry(listbox,
2543 mountlist_entry_to_string(mountlist, i),
2544 keylist[i]);
2545 }
2546}
2547
2548
2549
2550
2551/**
2552 * Redraw the list of unallocated RAID partitions.
2553 * @param unallocated_raid_partitions The mountlist containing unallocated RAID partitions.
2554 * @param keylist The list of keys for @p listbox.
2555 * @param listbox The Newt listbox component to redraw.
2556 * @ingroup restoreGuiDisklist
2557 */
2558void redraw_unallocpartnslist(struct mountlist_itself
2559 *unallocated_raid_partitions,
2560 void *keylist[ARBITRARY_MAXIMUM],
2561 newtComponent listbox)
2562{
2563
2564 /** int **************************************************************/
2565 int i = 0;
2566
2567 /** buffers **********************************************************/
2568 char tmp[MAX_STR_LEN];
2569
2570 assert(unallocated_raid_partitions != NULL);
2571 assert(keylist != NULL);
2572 assert(listbox != NULL);
2573
2574 newtListboxClear(listbox);
2575 for (i = 0; i < ARBITRARY_MAXIMUM; i++) {
2576 keylist[i] = (void *) i;
2577 }
2578 for (i = 0; i < unallocated_raid_partitions->entries; i++) {
2579 sprintf(tmp, "%-22s %8lld",
2580 unallocated_raid_partitions->el[i].device,
2581 unallocated_raid_partitions->el[i].size / 1024);
2582 newtListboxAppendEntry(listbox, tmp, keylist[i]);
2583 }
2584}
2585
2586#ifndef __FreeBSD__
2587/**
2588 * Redraw the list of additional RAID variables.
2589 * @param additional_vars The list of additional RAID varibals.
2590 * @param keylist The list of keys for @p listbox.
2591 * @param listbox The Newt listbox component to redraw.
2592 * @ingroup restoreGuiVarslist
2593 */
2594void
2595redraw_varslist(struct additional_raid_variables *additional_vars,
2596 void *keylist[], newtComponent listbox)
2597{
2598 /** int *************************************************************/
2599 int i = 0;
2600
2601 /** buffers *********************************************************/
2602 char tmp[MAX_STR_LEN];
2603
2604 assert(additional_vars != NULL);
2605 assert(keylist != NULL);
2606 assert(listbox != NULL);
2607
2608 newtListboxClear(listbox);
2609
2610 for (i = 0; i < ARBITRARY_MAXIMUM; i++) {
2611 keylist[i] = (void *) i;
2612 }
2613 for (i = 0; i < additional_vars->entries; i++) {
2614 sprintf(tmp, "%-32s %-8s", additional_vars->el[i].label,
2615 additional_vars->el[i].value);
2616 newtListboxAppendEntry(listbox, tmp, keylist[i]);
2617 }
2618}
2619
2620
2621/**
2622 * Remove variable @p label from the RAID variables list in @p raidrec.
2623 * @param raidrec The RAID device record to remove the variable from.
2624 * @param label The variable name to remove.
2625 * @return The value of the variable removed.
2626 * @ingroup restoreUtilityGroup
2627 */
2628int
2629read_variableINT_and_remove_from_raidvars(struct
2630 OSSWAP (raid_device_record,
2631 vinum_volume) * raidrec,
2632 char *label)
2633{
2634 /** int ***************************************************************/
2635 int i = 0;
2636 int res = 0;
2637
2638
2639 assert(raidrec != NULL);
2640 assert(label != NULL);
2641
2642 for (i = 0;
2643 i < raidrec->additional_vars.entries
2644 && strcmp(raidrec->additional_vars.el[i].label, label); i++);
2645 if (i == raidrec->additional_vars.entries) {
2646 res = -1;
2647 } else {
2648 res = atoi(raidrec->additional_vars.el[i].value);
2649 for (i++; i < raidrec->additional_vars.entries; i++) {
2650 memcpy((void *) &raidrec->additional_vars.el[i - 1],
2651 (void *) &raidrec->additional_vars.el[i],
2652 sizeof(struct raid_var_line));
2653 }
2654 raidrec->additional_vars.entries--;
2655 }
2656 return (res);
2657}
2658#endif
2659
2660/**
2661 * Change all RAID devices to use @p new_dev instead of @p old_dev.
2662 * @param raidlist The raidlist to make the changes in.
2663 * @param old_dev The old name of the device (what it used to be).
2664 * @param new_dev The new name of the device (what it is now).
2665 * @ingroup restoreGuiMountlist
2666 */
2667void rejig_partition_name_in_raidlist_if_necessary(struct raidlist_itself
2668 *raidlist,
2669 char *old_dev,
2670 char *new_dev)
2671{
2672 /** buffers ********************************************************/
2673 char tmp[MAX_STR_LEN];
2674
2675 /** int ************************************************************/
2676 int pos = 0;
2677 int j = 0;
2678
2679 assert(raidlist != NULL);
2680 assert_string_is_neither_NULL_nor_zerolength(old_dev);
2681 assert_string_is_neither_NULL_nor_zerolength(new_dev);
2682
2683 pos = which_raid_device_is_using_this_partition(raidlist, old_dev);
2684 if (pos < 0) {
2685 sprintf(tmp, "No need to rejig %s in raidlist: it's not listed.",
2686 old_dev);
2687 log_it(tmp);
2688 } else {
2689 if ((j =
2690 where_in_drivelist_is_drive(&raidlist->
2691 OSSWAP(el[pos].data_disks, disks),
2692 old_dev)) >= 0) {
2693 strcpy(raidlist->OSSWAP(el[pos].data_disks, disks).el[j].
2694 device, new_dev);
2695 } else
2696 if ((j =
2697 where_in_drivelist_is_drive(&raidlist->
2698 OSSWAP(el[pos].spare_disks,
2699 spares),
2700 old_dev)) >= 0) {
2701 strcpy(raidlist->OSSWAP(el[pos].spare_disks, spares).el[j].
2702 device, new_dev);
2703 }
2704#ifndef __FreeBSD__
2705 else if ((j =
2706 where_in_drivelist_is_drive(&raidlist->el[pos].
2707 parity_disks,
2708 old_dev)) >= 0) {
2709 strcpy(raidlist->el[pos].parity_disks.el[j].device, new_dev);
2710 } else
2711 if ((j =
2712 where_in_drivelist_is_drive(&raidlist->el[pos].
2713 failed_disks,
2714 old_dev)) >= 0) {
2715 strcpy(raidlist->el[pos].failed_disks.el[j].device, new_dev);
2716 }
2717#endif
2718 else {
2719 sprintf(tmp,
2720 "%s is supposed to be listed in this raid dev but it's not...",
2721 old_dev);
2722 log_it(tmp);
2723 }
2724 }
2725}
2726
2727
2728#ifndef __FreeBSD__
2729/**
2730 * Remove the essential RAID variables from the "additional variables" section.
2731 * If they have been changed, set them in their normal locations too.
2732 * @param raidrec The RAID device record to operate on.
2733 * @ingroup restoreUtilityVarslist
2734 */
2735void remove_essential_additionalvars(struct raid_device_record *raidrec)
2736{
2737
2738 /** int **************************************************************/
2739 int res = 0;
2740
2741 assert(raidrec != NULL);
2742
2743 res =
2744 read_variableINT_and_remove_from_raidvars(raidrec,
2745 "persistent-superblock");
2746 if (res > 0) {
2747 raidrec->persistent_superblock = res;
2748 }
2749 res = read_variableINT_and_remove_from_raidvars(raidrec, "chunk-size");
2750 if (res > 0) {
2751 raidrec->chunk_size = res;
2752 }
2753 res = read_variableINT_and_remove_from_raidvars(raidrec, "block-size");
2754}
2755
2756/**
2757 * Select the RAID disks to use in @p raidrec.
2758 * @param mountlist_dontedit The mountlist (will not be edited).
2759 * @param raidlist The raidlist to modify.
2760 * @param raidrec The RAID device record in @p raidlist to work on.
2761 * @param description_of_list The type of disks we're selecting (e.g. "data").
2762 * @param disklist The disklist to put the user-selected disks in.
2763 * @ingroup restoreGuiMountlist
2764 */
2765void
2766select_raid_disks(struct mountlist_itself *mountlist_dontedit,
2767 struct raidlist_itself *raidlist,
2768 struct raid_device_record *raidrec,
2769 char *description_of_list,
2770 struct list_of_disks *disklist)
2771{
2772 void *curr_choice;
2773
2774 /** ??? ***************************************************************/
2775
2776 /** structures ********************************************************/
2777 struct raidlist_itself *bkp_raidlist;
2778 struct raid_device_record *bkp_raidrec;
2779 struct list_of_disks *bkp_disklist;
2780 struct mountlist_itself *unallocated_raid_partitions;
2781
2782 /** newt **************************************************************/
2783 newtComponent myForm = NULL;
2784 newtComponent bAdd = NULL;
2785 newtComponent bDelete = NULL;
2786 newtComponent bOK = NULL;
2787 newtComponent bCancel = NULL;
2788 newtComponent b_res = NULL;
2789 newtComponent partitionsListbox = NULL;
2790 newtComponent headerMsg = NULL;
2791
2792 /** buffers **********************************************************/
2793 void *keylist[ARBITRARY_MAXIMUM];
2794 char *tmp;
2795 char *help_text;
2796 char *title_of_window;
2797 char *sz_res;
2798 char *header_text;
2799
2800 /** int **************************************************************/
2801 int i = 0;
2802 int currline = 0;
2803
2804 assert(mountlist_dontedit != NULL);
2805 assert(raidlist != NULL);
2806 assert(raidrec != NULL);
2807 assert(description_of_list != NULL);
2808 assert(disklist != NULL);
2809
2810 iamhere("malloc'ing");
2811 malloc_string(tmp);
2812 malloc_string(help_text);
2813 malloc_string(title_of_window);
2814 malloc_string(sz_res);
2815 malloc_string(header_text);
2816 if (!(bkp_raidrec = malloc(sizeof(struct raid_device_record)))) {
2817 fatal_error("Cannot malloc space for raidrec");
2818 }
2819 if (!(bkp_disklist = malloc(sizeof(struct list_of_disks)))) {
2820 fatal_error("Cannot malloc space for disklist");
2821 }
2822 if (!(bkp_raidlist = malloc(sizeof(struct raidlist_itself)))) {
2823 fatal_error("Cannot malloc space for raidlist");
2824 }
2825 if (!
2826 (unallocated_raid_partitions =
2827 malloc(sizeof(struct mountlist_itself)))) {
2828 fatal_error("Cannot malloc space for unallocated_raid_partitions");
2829 }
2830
2831 memcpy((void *) bkp_raidlist, (void *) raidlist,
2832 sizeof(struct raidlist_itself));
2833 memcpy((void *) bkp_raidrec, (void *) raidrec,
2834 sizeof(struct raid_device_record));
2835 memcpy((void *) bkp_disklist, (void *) disklist,
2836 sizeof(struct list_of_disks));
2837
2838 iamhere("Post-malloc");
2839 strcpy(help_text,
2840 " Edit this RAID device's list of partitions. Choose OK or Cancel when done.");
2841 sprintf(header_text, "%-24s %s", "Device", "Index");
2842 sprintf(title_of_window, "%s contains...", raidrec->raid_device);
2843 newtPushHelpLine(help_text);
2844 for (b_res = (newtComponent) 12345; b_res != bOK && b_res != bCancel;) {
2845 headerMsg = newtLabel(1, 1, header_text);
2846 partitionsListbox =
2847 newtListbox(1, 2, 6, NEWT_FLAG_SCROLL | NEWT_FLAG_RETURNEXIT);
2848 redraw_disklist(disklist, keylist, partitionsListbox);
2849 i = 1;
2850 bAdd = newtCompactButton(i, 9, " Add ");
2851 bDelete = newtCompactButton(i += 8, 9, "Delete");
2852 bOK = newtCompactButton(i += 9, 9, " OK ");
2853 bCancel = newtCompactButton(i += 9, 9, "Cancel");
2854 newtOpenWindow(21, 7, 38, 10, title_of_window);
2855 myForm = newtForm(NULL, NULL, 0);
2856 if (disklist->entries == 0) {
2857 newtFormAddComponents(myForm, headerMsg, bAdd, bDelete, bOK,
2858 bCancel, NULL);
2859 } else {
2860 newtFormAddComponents(myForm, headerMsg, partitionsListbox,
2861 bAdd, bDelete, bOK, bCancel, NULL);
2862 }
2863 b_res = newtRunForm(myForm);
2864 if (b_res == bOK || b_res == bCancel) { /* do nothing */
2865// That's OK. At the end of this subroutine (after this do/while loop),
2866// we'll throw away the changes if Cancel was pushed.
2867 } else {
2868 curr_choice = newtListboxGetCurrent(partitionsListbox);
2869 for (i = 0; i < disklist->entries && keylist[i] != curr_choice;
2870 i++);
2871 if (i == disklist->entries && disklist->entries > 0) {
2872 log_to_screen("I don't know what that button does!");
2873 } else {
2874 currline = i;
2875 if (b_res == bAdd) {
2876 log_it("Making list of unallocated RAID slices");
2877 make_list_of_unallocated_raid_partitions
2878 (unallocated_raid_partitions, mountlist_dontedit,
2879 raidlist);
2880 if (unallocated_raid_partitions->entries <= 0) {
2881 popup_and_OK
2882 ("There are no unallocated partitions marked for RAID.");
2883 } else {
2884 log_it
2885 ("Done. The user may add one or more of the above to RAID device");
2886 add_disklist_entry(disklist, raidrec->raid_device,
2887 unallocated_raid_partitions);
2888 log_it("I have finished adding a disklist entry.");
2889 redraw_disklist(disklist, keylist,
2890 partitionsListbox);
2891 }
2892 } else if (b_res == bDelete) {
2893 delete_disklist_entry(disklist, raidrec->raid_device,
2894 currline);
2895 redraw_disklist(disklist, keylist, partitionsListbox);
2896 } else {
2897 sprintf(tmp, "%s's index is %d. What should it be?",
2898 raidrec->raid_device,
2899 disklist->el[currline].index);
2900 sprintf(sz_res, "%d", disklist->el[currline].index);
2901 if (popup_and_get_string("Set index", tmp, sz_res, 10)) {
2902 disklist->el[currline].index = atoi(sz_res);
2903 }
2904 redraw_disklist(disklist, keylist, partitionsListbox);
2905 }
2906 }
2907 }
2908 newtFormDestroy(myForm);
2909 newtPopWindow();
2910 }
2911 newtPopHelpLine();
2912 if (b_res == bCancel) {
2913 memcpy((void *) raidlist, (void *) bkp_raidlist,
2914 sizeof(struct raidlist_itself));
2915 memcpy((void *) raidrec, (void *) bkp_raidrec,
2916 sizeof(struct raid_device_record));
2917 memcpy((void *) disklist, (void *) bkp_disklist,
2918 sizeof(struct list_of_disks));
2919 }
2920 paranoid_free(tmp);
2921 paranoid_free(help_text);
2922 paranoid_free(title_of_window);
2923 paranoid_free(sz_res);
2924 paranoid_free(header_text);
2925 paranoid_free(bkp_raidrec);
2926 paranoid_free(bkp_disklist);
2927 paranoid_free(bkp_raidlist);
2928 paranoid_free(unallocated_raid_partitions);
2929}
2930#endif
2931
2932
2933
2934/**
2935 * Ask the user which restore mode (nuke, interactive, or compare) we should use.
2936 * @return The mode selected: 'I' for interactive, 'N' for nuke, 'C' for compare,
2937 * or 'E' (or any other letter) for exit.
2938 */
2939char which_restore_mode()
2940{
2941
2942 /** char *************************************************************/
2943 char output = '\0';
2944 char tmp[MAX_STR_LEN];
2945
2946 /** newt *************************************************************/
2947
2948 newtComponent b1;
2949 newtComponent b2;
2950 newtComponent b3;
2951 newtComponent b4;
2952 newtComponent b_res;
2953 newtComponent myForm;
2954
2955 if (g_text_mode) {
2956 for (output = 'z'; !strchr("AICE", output); output = tmp[0]) {
2957 printf
2958 ("Which mode - (A)utomatic, (I)nteractive, \n(C)ompare only, or (E)xit to shell?\n--> ");
2959 fgets(tmp, MAX_STR_LEN - 1, stdin);
2960 }
2961 return (output);
2962 }
2963
2964 newtPushHelpLine
2965 (" Do you want to 'nuke' your system, restore interactively, or just compare?");
2966 newtOpenWindow(24, 3, 32, 17, "How should I restore?");
2967 b1 = newtButton(7, 1, "Automatically");
2968 b2 = newtButton(7, 5, "Interactively");
2969 b3 = newtButton(7, 9, "Compare only!");
2970 b4 = newtButton(7, 13, "Exit to shell");
2971 myForm = newtForm(NULL, NULL, 0);
2972 newtFormAddComponents(myForm, b1, b2, b3, b4, NULL);
2973 b_res = newtRunForm(myForm);
2974 newtFormDestroy(myForm);
2975 newtPopWindow();
2976 if (b_res == b1) {
2977 output = 'N';
2978 }
2979 if (b_res == b2) {
2980 output = 'I';
2981 }
2982 if (b_res == b3) {
2983 output = 'C';
2984 }
2985 if (b_res == b4) {
2986 output = 'E';
2987 }
2988 newtPopHelpLine();
2989 return (output);
2990}
Note: See TracBrowser for help on using the repository browser.