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

Last change on this file since 30 was 30, checked in by bcornec, 19 years ago

Id property added on files to allow for better conf. management

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