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

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

MDSTAT_FILE is used everywhere (replacing /proc/mdstat strings)

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