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

Last change on this file since 1842 was 1770, checked in by Bruno Cornec, 16 years ago
  • Better output for mindi-busybox revision
  • Remove dummy file created on NFS - report from Arnaud Tiger <arnaud.tiger_at_hp.com>
  • strace useful for debug
  • fix new versions for pb (2.0.0 for mindi and 1.7.2 for mindi-busybox)
  • fix build process for mindi-busybox + options used in that version (dd for label-partitions-as-necessary)
  • fix typo in label-partitions-as-necessary which doesn't seem to work
  • Update to busybox 1.7.2
  • perl is now required at restore time to support uuid swap partitions (and will be used for many other thigs

in the future for sure)

  • next mindi version will be 2.0.0 due to all the changes made in it (udev may break working distros)
  • small optimization in mindi on keyboard handling (one single find instead of multiple)
  • better interaction for USB device when launching mindi manually
  • attempt to automatically guess block disk size for ramdisk
  • fix typos in bkphw
  • Fix the remaining problem with UUID support for swap partitions
  • Updates mondoarchive man page for USB support
  • Adds preliminary Hardware support to mindi (Proliant SSSTK)
  • Tries to add udev support also for rhel4
  • Fix UUID support which was still broken.
  • Be conservative in test for the start-nfs script
  • Update config file for mindi-busybox for 1.7.2 migration
  • Try to run around a busybox bug (1.2.2 pb on inexistant links)
  • Add build content for mindi-busybox in pb
  • Remove distributions content for mindi-busybox
  • Fix a warning on inexistant raidtab
  • Solve problem on tmpfs in restore init (Problem of inexistant symlink and busybox)
  • Create MONDO_CACHE and use it everywhere + creation at start
  • Really never try to eject a USB device
  • Fix a issue with &> usage (replaced with 1> and 2>)
  • Adds magic file to depllist in order to have file working + ldd which helps for debugging issues
  • tty modes correct to avoid sh error messages
  • Use ext3 normally and not ext2 instead
  • USB device should be corrected after reading (take 1st part)
  • Adds a mount_USB_here function derived from mount_CDROM_here
  • usb detection place before /dev detection in device name at restore time
  • Fix when restoring from USB: media is asked in interactive mode
  • Adds USB support for mondorestore
  • mount_cdrom => mount_media
  • elilo.efi is now searched throughout /boot/efi and not in a fixed place as there is no standard
  • untar-and-softlink => untar (+ interface change)
  • suppress useless softlinks creation/removal in boot process
  • avoids udevd messages on groups
  • Increase # of disks to 99 as in mindi at restore time (should be a conf file parameter)
  • skip existing big file creation
  • seems to work correctly for USB mindi boot
  • Adds group and tty link to udev conf
  • Always load usb-torage (even 2.6) to initiate USB bus discovery
  • Better printing of messages
  • Attempt to fix a bug in supporting OpenSusE 10.3 kernel for initramfs (mindi may now use multiple regex for kernel initrd detection)
  • Links were not correctly done as non relative for modules in mindi
  • exclusion of modules denied now works
  • Also create modules in their ordinary place, so that classical modprobe works + copy modules.dep
  • Fix bugs for DENY_MODS handling
  • Add device /dev/console for udev
  • ide-generic should now really be excluded
  • Fix a bug in major number for tty
  • If udev then adds modprobe/insmod to rootfs
  • tty0 is also cretaed with udev
  • ide-generic put rather in DENY_MODS
  • udevd remove from deplist s handled in mindi directly
  • better default for mindi when using --usb
  • Handles dynamically linked busybox (in case we want to use it soon ;-)
  • Adds fixed devices to create for udev
  • ide-generic should not be part of the initrd when using libata v2
  • support a dynamically linked udev (case on Ubuntu 7.10 and Mandriva 2008.0 so should be quite generic) This will give incitation to move to dyn. linked binaries in the initrd which will help for other tasks (ia6 4)
  • Improvement in udev support (do not use cl options not available in busybox)
  • Udev in mindi
    • auto creation of the right links at boot time with udev-links.conf(from Mandriva 2008.0)
    • rework startup of udev as current makes kernel crash (from Mandriva 2008.0)
    • add support for 64 bits udev
  • Try to render MyInsmod silent at boot time
  • Adds udev support (mandatory for newest distributions to avoid remapping of devices in a different way as on the original system)
  • We also need vaft format support for USB boot
  • Adds libusual support (Ubuntu 7.10 needs it for USB)
  • Improve Ubuntu/Debian keyboard detection and support
  • pbinit adapted to new pb (0.8.10). Filtering of docs done in it
  • Suppress some mondo warnings and errors on USB again
  • Tries to fix lack of files in deb mindi package
  • Verify should now work for USB devices
  • More log/mesages improvement for USB support
  • - Supress g_erase_tmpdir_and_scratchdir
  • Improve some log messages for USB support
  • Try to improve install in mindi to avoid issues with isolinux.cfg not installed vene if in the pkg :-(
  • Improve mindi-busybox build
  • In conformity with pb 0.8.9
  • Add support for Ubuntu 7.10 in build process
  • Add USB Key button to Menu UI (CD streamer removed)
  • Attempt to fix error messages on tmp/scratch files at the end by removing those dir at the latest possible.
  • Fix a bug linked to the size of the -E param which could be used (Arnaud Tiger/René Ribaud).
  • Integrate ~/.pbrc content into mondorescue.pb (required project-builder >= 0.8.7)
  • Put mondorescue in conformity with new pb filtering rules
  • Add USB support at restore time (no test done yet). New start-usb script PB varibale added where useful
  • Unmounting USB device before removal of temporary scratchdir
  • Stil refining USB copy back to mondo (one command was not executed)
  • No need to have the image subdor in the csratchdir when USB.
  • umount the USB partition before attempting to use it
  • Remove useless copy from mindi to mondo at end of USB handling

(risky merge, we are raising the limits of 2 diverging branches. The status of stable is not completely sure as such. Will need lots of tests, but it's not yet done :-()
(merge -r1692:1769 $SVN_M/branches/2.2.5)

  • Property svn:keywords set to Id
File size: 86.7 KB
Line 
1/*
2 * $Id: mondo-rstr-newt.c 1770 2007-11-06 10:01:53Z bruno $
3*/
4
5#include "mr_mem.h"
6#include "mr_msg.h"
7#include "mr_str.h"
8#include "mr_gettext.h"
9
10extern char *g_mondo_cfg_file; // where m*ndo-restore.cfg (the config file) is stored
11
12/**
13 * @file
14 * Functions for handling GUI interfaces in the restore.
15 */
16
17#ifdef __FreeBSD__
18#define OSSWAP(linux,fbsd) fbsd
19#else
20#define OSSWAP(linux,fbsd) linux
21#endif
22
23#include "mondo-rstr-newt.h"
24
25//static char cvsid[] = "$Id: mondo-rstr-newt.c 1770 2007-11-06 10:01:53Z bruno $";
26
27extern char err_log_lines[NOOF_ERR_LINES][MAX_STR_LEN];
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
59add_disklist_entry(struct list_of_disks *disklist, char *raid_device,
60 struct mountlist_itself *unallocated_raid_partitions)
61{
62 /** buffers ***********************************************************/
63 char *tmp = NULL;
64
65 /** newt **************************************************************/
66 newtComponent myForm;
67 newtComponent bOK;
68 newtComponent bCancel;
69 newtComponent b_res;
70 newtComponent partitionsListbox;
71 newtComponent headerMsg;
72
73 /** prototypes *********************************************************/
74 void *keylist[ARBITRARY_MAXIMUM];
75 void *curr_choice;
76
77 /** int ****************************************************************/
78 int i = 0;
79 int idx = 0;
80 int currline = 0;
81 int items = 0;
82
83 assert(disklist != NULL);
84 assert_string_is_neither_NULL_nor_zerolength(raid_device);
85 assert(unallocated_raid_partitions != NULL);
86
87 newtPushHelpLine
88 (_
89 (" Add one of the following unallocated RAID partitions to this RAID device."));
90 mr_asprintf(&tmp, "%-26s %s", _("Device"), _("Size"));
91 headerMsg = newtLabel(1, 1, tmp);
92 mr_free(tmp);
93
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;
99 bOK = newtCompactButton(i, 9, _(" OK "));
100 bCancel = newtCompactButton(i += 9, 9, _("Cancel"));
101 newtOpenWindow(22, 6, 36, 10, _("Unallocated RAID partitions"));
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 {
115 idx = find_next_free_index_in_disklist(disklist);
116
117 items = disklist->entries;
118 strcpy(disklist->el[items].device,
119 unallocated_raid_partitions->el[currline].device);
120 disklist->el[items].index = idx;
121 disklist->entries = ++items;
122
123 }
124 }
125 newtFormDestroy(myForm);
126 newtPopWindow();
127 newtPopHelpLine();
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
141add_mountlist_entry(struct mountlist_itself *mountlist,
142 struct raidlist_itself *raidlist,
143 newtComponent listbox, int currline, void *keylist[])
144{
145
146 /** int **************************************************************/
147 int i = 0;
148 int num_to_add = 0;
149
150 /** newt *************************************************************/
151 newtComponent myForm;
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
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;
173
174 assert(mountlist != NULL);
175 assert(raidlist != NULL);
176 assert(listbox != NULL);
177 assert(keylist != NULL);
178
179 mr_asprintf(&device_str, "/dev/");
180 mr_asprintf(&mountpoint_str, "/");
181#ifdef __FreeBSD__
182 mr_asprintf(&format_str, "ufs");
183#else
184 mr_asprintf(&format_str, "ext3");
185#endif
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: "));
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);
195
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);
199 bOK = newtButton(5, 6, _(" OK "));
200 bCancel = newtButton(17, 6, _("Cancel"));
201 newtPushHelpLine
202 (_
203 ("To add an entry to the mountlist, please fill in these fields and then hit 'OK'"));
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);
210
211 mr_free(device_str);
212 mr_asprintf(&device_str, device_here);
213 mr_strip_spaces(device_str);
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);
221 mr_strip_spaces(mountpoint_str);
222
223 mr_free(size_str);
224 mr_asprintf(&size_str, size_here);
225 mr_strip_spaces(size_str);
226
227 if (b_res == bOK) {
228 if (device_str[strlen(device_str) - 1] == '/') {
229 popup_and_OK(_("You left the device nearly blank!"));
230 b_res = NULL;
231 }
232 if (size_of_specific_device_in_mountlist(mountlist, device_str)
233 >= 0) {
234 popup_and_OK(_
235 ("Can't add this - you've got one already!"));
236 b_res = NULL;
237 }
238 }
239 }
240 newtFormDestroy(myForm);
241 newtPopHelpLine();
242 newtPopWindow();
243 if (b_res == bCancel) {
244 mr_free(device_str);
245 mr_free(format_str);
246 mr_free(mountpoint_str);
247 mr_free(size_str);
248 return;
249 }
250 mr_asprintf(&drive_to_add, device_str);
251 for (i = strlen(drive_to_add); isdigit(drive_to_add[i - 1]); i--);
252 num_to_add = atoi(drive_to_add + i);
253 mr_free(drive_to_add);
254
255 currline = mountlist->entries;
256 strcpy(mountlist->el[currline].device, device_str);
257 strcpy(mountlist->el[currline].mountpoint, mountpoint_str);
258 mr_free(mountpoint_str);
259
260 strcpy(mountlist->el[currline].format, format_str);
261 mr_free(format_str);
262
263 mountlist->el[currline].size = atol(size_str) * 1024;
264 mr_free(size_str);
265
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 }
271 mr_free(device_str);
272 redraw_mountlist(mountlist, keylist, listbox);
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 */
282void add_varslist_entry(struct raid_device_record *raidrec)
283{
284
285 /** buffers ***********************************************************/
286 char *sz_out = NULL;
287
288 /** int ****************************************************************/
289 int items = 0;
290 int i = 0;
291
292 assert(raidrec != NULL);
293
294 malloc_string(sz_out);
295 if (popup_and_get_string
296 ("Add variable", _("Enter the name of the variable to add"), sz_out,
297 MAX_STR_LEN)) {
298 mr_strip_spaces(sz_out);
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
305 (_
306 ("No need to add that variable. It is already listed here."));
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 }
312 }
313 mr_free(sz_out);
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
326calculate_raid_device_size(struct mountlist_itself *mountlist,
327 struct raidlist_itself *raidlist,
328 char *raid_device)
329{
330#ifdef __FreeBSD__
331 /** FreeBSD-specific version of calculate_raid_device_size() **/
332
333 /** structures ********************************************************/
334 struct vinum_volume *raidrec = NULL;
335
336 int i = 0, j = 0;
337 int noof_partitions = 0;
338
339 long total_size = 0L;
340 long plex_size = 0L;
341 long smallest_partition = 999999999;
342 long smallest_plex = 999999999;
343 long sp = 0L;
344
345 char *devname = NULL;
346
347 for (i = 0;
348 i < raidlist->entries
349 && strcmp(raidlist->el[i].volname, basename(raid_device)); i++);
350 if (i == raidlist->entries) {
351 log_it("Cannot calc size of raid device %s - cannot find it in raidlist",
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) {
364 mr_asprintf(&devname, raidrec->plex[j].sd[k].which_device);
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 }
392 mr_free(devname);
393 }
394
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;
409
410 smallest_partition = 999999999;
411 }
412
413 log_it("I have calculated %s's real size to be %ld", raid_device,
414 (long) smallest_plex);
415 return (smallest_plex);
416#else
417 /** Linux-specific version of calculate_raid_device_size() **/
418
419 /** structures ********************************************************/
420 struct raid_device_record *raidrec = NULL;
421
422 /** int ***************************************************************/
423 int i = 0;
424 int noof_partitions = 0;
425
426 /** long **************************************************************/
427 long total_size = 0;
428 long smallest_partition = 999999999;
429 long sp = 0;
430
431 assert(mountlist != NULL);
432 assert(raidlist != NULL);
433 assert_string_is_neither_NULL_nor_zerolength(raid_device);
434
435 for (i = 0;
436 i < raidlist->entries
437 && strcmp(raidlist->el[i].raid_device, raid_device); i++);
438 if (i == raidlist->entries) {
439 log_it("Cannot calc size of raid device %s - cannot find it in raidlist",
440 raid_device);
441 return (999999999);
442 }
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);
462 }
463 log_it("I have calculated %s's real size to be %ld", raid_device,
464 (long) total_size);
465 return (total_size);
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
476choose_raid_level(struct OSSWAP (raid_device_record, vinum_plex) * raidrec)
477{
478
479#ifdef __FreeBSD__
480
481 /** int ***************************************************************/
482 int res = 0;
483 int out = 0;
484
485 /** buffers ***********************************************************/
486 char *tmp = NULL;
487 char *prompt = NULL;
488 char *sz = NULL;
489
490 malloc_string(tmp);
491 mr_asprintf(&prompt,
492 _
493 ("Please enter the RAID level you want. (concat, striped, raid5)"));
494 if (raidrec->raidlevel == -1) {
495 strcpy(tmp, "concat");
496 } else if (raidrec->raidlevel == 0) {
497 strcpy(tmp, "striped");
498 } else {
499 strcpy(tmp, "raid%i", raidrec->raidlevel);
500 }
501 for (out = 999; out == 999;) {
502 res = popup_and_get_string(_("Specify RAID level"), prompt, tmp, 10);
503 if (!res) {
504 mr_free(tmp);
505 mr_free(prompt);
506 return;
507 }
508 mr_strip_spaces(tmp);
509 /* BERLIOS: Useless ??? */
510 if (tmp[0] == '[' && tmp[strlen(tmp) - 1] == ']') {
511 mr_asprintf(&sz, tmp);
512 strncpy(tmp, sz + 1, strlen(sz) - 2);
513 tmp[strlen(sz) - 2] = '\0';
514 mr_free(sz);
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;
522 } else {
523 continue;
524 }
525 log_it(tmp);
526
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
532 (_("You have chosen a RAID personality which is not registered with the kernel. Make another selection?")))
533 {
534 out = 999;
535 }
536 }
537 }
538 mr_free(prompt);
539 mr_free(tmp);
540 raidrec->raidlevel = out;
541#else
542 /** buffers ***********************************************************/
543 char *tmp = NULL;
544 char *personalities = NULL;
545 char *prompt = NULL;
546 char *sz = NULL;
547 int out = 0, res = 0;
548
549 malloc_string(tmp);
550 assert(raidrec != NULL);
551 mr_asprintf(&tmp,"grep Pers %s > /tmp/raid-personalities.txt 2> /dev/null", MDSTAT_FILE);
552 system(tmp);
553 mr_free(tmp);
554 mr_asprintf(&personalities,
555 last_line_of_file("/tmp/raid-personalities.txt"));
556 mr_asprintf(&prompt, _("Please enter the RAID level you want. %s"),
557 personalities);
558 mr_free(personalities);
559
560 if (raidrec->raid_level == -1) {
561 strcpy(tmp, "linear");
562 } else {
563 sprintf(tmp, "%d", raidrec->raid_level);
564 }
565 for (out = 999;
566 out != -1 && out != 0 && out != 1 && out != 4 && out != 5
567 && out != 10;) {
568 res = popup_and_get_string(_("Specify RAID level"), prompt, tmp, 10);
569 if (!res) {
570 return;
571 }
572 mr_strip_spaces(tmp);
573 /* BERLIOS: Useless ??? */
574 if (tmp[0] == '[' && tmp[strlen(tmp) - 1] == ']') {
575 mr_asprintf(&sz, tmp);
576 strncpy(tmp, sz + 1, strlen(sz) - 2);
577 tmp[strlen(sz) - 2] = '\0';
578 mr_free(sz);
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
593 (_
594 ("You have chosen a RAID personality which is not registered with the kernel. Make another selection?")))
595 {
596 out = 999;
597 }
598 }
599 }
600 mr_free(tmp);
601 mr_free(prompt);
602 raidrec->raid_level = out;
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
616del_partns_listed_in_disklist(struct mountlist_itself *mountlist,
617 struct raidlist_itself *raidlist,
618 struct list_of_disks *disklist)
619{
620
621 /** int ***************************************************************/
622 int i = 0;
623 int pos = 0;
624
625 assert(mountlist != NULL);
626 assert(raidlist != NULL);
627 assert(disklist != NULL);
628
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) {
635 log_it("Deleting partition %s cos it was part of a now-defunct RAID",
636 mountlist->el[pos].device);
637 memcpy((void *) &mountlist->el[pos],
638 (void *) &mountlist->el[mountlist->entries - 1],
639 sizeof(struct mountlist_line));
640 mountlist->entries--;
641 }
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
655delete_disklist_entry(struct list_of_disks *disklist, char *raid_device,
656 int currline)
657{
658
659 /** int ***************************************************************/
660 int pos = 0;
661
662 /** buffers ***********************************************************/
663 char *tmp = NULL;
664
665 assert(disklist != NULL);
666 assert_string_is_neither_NULL_nor_zerolength(raid_device);
667
668 mr_asprintf(&tmp, _("Delete %s from RAID device %s - are you sure?"),
669 disklist->el[currline].device, raid_device);
670 if (!ask_me_yes_or_no(tmp)) {
671 mr_free(tmp);
672 return;
673 }
674 mr_free(tmp);
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--;
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
693delete_mountlist_entry(struct mountlist_itself *mountlist,
694 struct raidlist_itself *raidlist,
695 newtComponent listbox, int currline,
696 void *keylist[])
697{
698
699 /** int ***************************************************************/
700 int pos = 0;
701
702 /** buffers ***********************************************************/
703 char *tmp = NULL;
704 char *device = NULL;
705
706 assert(mountlist != NULL);
707 assert(raidlist != NULL);
708 assert(listbox != NULL);
709 assert(keylist != NULL);
710
711 pos =
712 which_raid_device_is_using_this_partition(raidlist,
713 mountlist->el[currline].
714 device);
715 if (pos >= 0) {
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));
720 popup_and_OK(tmp);
721 mr_free(tmp);
722 return;
723 }
724 mr_asprintf(&tmp, _("Delete %s - are you sure?"),
725 mountlist->el[currline].device);
726 if (!ask_me_yes_or_no(tmp)) {
727 mr_free(tmp);
728 return;
729 }
730 mr_free(tmp);
731
732 if (strstr(mountlist->el[currline].device, RAID_DEVICE_STUB)) {
733 mr_asprintf(&device, mountlist->el[currline].device);
734 delete_raidlist_entry(mountlist, raidlist, device);
735 for (currline = 0;
736 currline < mountlist->entries
737 && strcmp(mountlist->el[currline].device, device);
738 currline++);
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);
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);
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
762delete_raidlist_entry(struct mountlist_itself *mountlist,
763 struct raidlist_itself *raidlist, char *device)
764{
765
766 /** int ***************************************************************/
767 int i = 0;
768 int items = 0;
769
770 /** bool **************************************************************/
771 bool delete_partitions_too;
772
773 /** buffers ***********************************************************/
774 char *tmp = NULL;
775
776 assert(mountlist != NULL);
777 assert(raidlist != NULL);
778 assert_string_is_neither_NULL_nor_zerolength(device);
779
780 i = find_raid_device_in_raidlist(raidlist, device);
781 if (i < 0) {
782 return;
783 }
784 mr_asprintf(&tmp,
785 _("Do you want me to delete %s's partitions, too?"), device);
786 delete_partitions_too = ask_me_yes_or_no(tmp);
787 if (delete_partitions_too) {
788#ifdef __FreeBSD__
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);
808#else
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);
817#endif
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 }
829 mr_free(tmp);
830
831 raidlist->entries = items;
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 */
842void delete_varslist_entry(struct raid_device_record *raidrec, int lino)
843{
844
845 /** buffers ************************************************************/
846 char *tmp = NULL;
847
848 /** structures *********************************************************/
849 struct additional_raid_variables *av = NULL;
850
851 assert(raidrec != NULL);
852
853 av = &raidrec->additional_vars;
854 mr_asprintf(&tmp, _("Delete %s - are you sure?"), av->el[lino].label);
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")) {
858 mr_free(tmp);
859 mr_asprintf(&tmp, _("%s must not be deleted. It would be bad."),
860 av->el[lino].label);
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 }
866 }
867 mr_free(tmp);
868}
869#endif
870
871
872/**
873 * Redraw the filelist display.
874 * @param filelist The filelist structure to edit.
875 * @param keylist The list of keys for @p listbox.
876 * @param listbox The Newt listbox component containing some of the filelist entries.
877 * @return The number of lines currently being displayed.
878 * @ingroup restoreGuiGroup
879 */
880int
881redraw_filelist(struct s_node *filelist, void *keylist[ARBITRARY_MAXIMUM],
882 newtComponent listbox)
883{
884
885 /** int ***************************************************************/
886 static int lines_in_flist_window = 0;
887 static int depth = 0;
888
889 /** long **************************************************************/
890 long i = 0L;
891
892 /** structures *******************************************************/
893 struct s_node *node = NULL;
894
895 /** buffers **********************************************************/
896 static char current_filename[MAX_STR_LEN];
897 char *tmp = NULL;
898
899 /** bool *************************************************************/
900 bool dummybool = FALSE;
901 static bool warned_already = FALSE;
902
903 assert(filelist != NULL);
904 assert(keylist != NULL);
905 assert(listbox != NULL);
906
907 if (depth == 0) {
908 lines_in_flist_window = 0;
909 warned_already = FALSE;
910 for (i = 0; i < ARBITRARY_MAXIMUM; i++) {
911 g_strings_of_flist_window[i][0] = '\0';
912 g_is_path_selected[i] = FALSE;
913 }
914 }
915 for (node = filelist; node != NULL; node = node->right) {
916 current_filename[depth] = node->ch;
917 if (node->down) {
918 depth++;
919 i = redraw_filelist(node->down, keylist, listbox);
920 depth--;
921 }
922 if (node->ch == '\0' && node->expanded) {
923 if (lines_in_flist_window == ARBITRARY_MAXIMUM) {
924 if (!warned_already) {
925 warned_already = TRUE;
926 mr_asprintf(&tmp,
927 _
928 ("Too many lines. Displaying first %d entries only. Close a directory to see more."),
929 ARBITRARY_MAXIMUM);
930 popup_and_OK(tmp);
931 mr_free(tmp);
932 }
933 } else {
934 strcpy(g_strings_of_flist_window[lines_in_flist_window],
935 current_filename);
936 g_is_path_selected[lines_in_flist_window] = node->selected;
937 lines_in_flist_window++;
938 }
939 }
940 }
941 if (depth == 0) {
942 if (lines_in_flist_window > ARBITRARY_MAXIMUM) {
943 lines_in_flist_window = ARBITRARY_MAXIMUM;
944 }
945 /* do an elementary sort */
946 for (i = 1; i < lines_in_flist_window; i++) {
947 if (strcmp
948 (g_strings_of_flist_window[i],
949 g_strings_of_flist_window[i - 1]) < 0) {
950 mr_asprintf(&tmp, g_strings_of_flist_window[i]);
951 strcpy(g_strings_of_flist_window[i],
952 g_strings_of_flist_window[i - 1]);
953 strcpy(g_strings_of_flist_window[i - 1], tmp);
954 mr_free(tmp);
955
956 dummybool = g_is_path_selected[i];
957 g_is_path_selected[i] = g_is_path_selected[i - 1];
958 g_is_path_selected[i - 1] = dummybool;
959 i = 0;
960 }
961 }
962 /* write list to screen */
963 newtListboxClear(listbox);
964 for (i = 0; i < lines_in_flist_window; i++) {
965 mr_asprintf(&tmp, "%c%c %-80s",
966 (g_is_path_selected[i] ? '*' : ' '),
967 (g_is_path_expanded[i] ? '+' : '-'),
968 strip_path(g_strings_of_flist_window[i]));
969 if (strlen(tmp) > 71) {
970 tmp[70] = '\0';
971 }
972 keylist[i] = (void *) i;
973 newtListboxAppendEntry(listbox, tmp, keylist[i]);
974 mr_free(tmp);
975 }
976 return (lines_in_flist_window);
977 } else {
978 return (0);
979 }
980}
981
982
983/**
984 * Strip a path to the bare minimum (^ pointing to the directory above, plus filename).
985 * @param tmp The path to strip.
986 * @return The stripped path.
987 * @author Conor Daly
988 * @ingroup restoreUtilityGroup
989 */
990char *strip_path(char *tmp)
991{
992
993 int i = 0, j = 0, slashcount = 0;
994 int slashloc = 0, lastslashloc = 0;
995
996 while (tmp[i] != '\0') { /* Count the slashes in tmp
997 1 slash per dir */
998 if (tmp[i] == '/') {
999 slashcount++;
1000 lastslashloc = slashloc;
1001 slashloc = i;
1002 if (tmp[i + 1] == '\0') { /* if this slash is last char, back off */
1003 slashcount--;
1004 slashloc = lastslashloc;
1005 }
1006 }
1007 i++;
1008 }
1009 if (slashcount > 0)
1010 slashcount--; /* Keep one slash 'cos Hugh does... */
1011
1012 /* BERLIOS: tmpnopath and prev not defined !! How can this compile ?? */
1013 for (i = 0; i < slashcount; i++) { /* Replace each dir with a space char */
1014 tmpnopath[i] = ' ';
1015 }
1016
1017 i = slashloc;
1018 j = slashcount;
1019 while (tmp[i] != '\0') { /* Now add what's left of tmp */
1020 if ((tmpprevpath[j] == ' ' || tmpprevpath[j] == '^')
1021 && tmp[i] == '/' && tmpnopath[j - 1] != '^' && j != 0) { /* Add a pointer upwards if this is not in the same dir as line above */
1022 tmpnopath[j - 1] = '^';
1023 } else {
1024 tmpnopath[j++] = tmp[i++];
1025 }
1026 }
1027 tmpnopath[j] = '\0';
1028
1029 strcpy(tmpprevpath, tmpnopath); /* Make a copy for next iteration */
1030
1031 return (tmpnopath);
1032}
1033
1034
1035/**
1036 * Allow the user to edit the filelist and choose which files to restore.
1037 * @param filelist The node structure containing the filelist.
1038 * @return 0 if the user pressed OK, 1 if they pressed Cancel.
1039 */
1040int edit_filelist(struct s_node *filelist)
1041{
1042
1043 /** newt **************************************************************/
1044 newtComponent myForm;
1045 newtComponent bLess = NULL;
1046 newtComponent bMore = NULL;
1047 newtComponent bToggle = NULL;
1048 newtComponent bOK = NULL;
1049 newtComponent bCancel = NULL;
1050 newtComponent b_res = NULL;
1051 newtComponent filelistListbox = NULL;
1052 newtComponent bRegex = NULL;
1053
1054 /** int ***************************************************************/
1055 int finished = FALSE;
1056 int lines_in_flist_window = 0;
1057 int indexno = 0;
1058 int j = 0;
1059
1060 /** ???? **************************************************************/
1061 void *curr_choice = NULL;
1062 void *keylist[ARBITRARY_MAXIMUM];
1063
1064 /** bool **************************************************************/
1065 bool dummybool = FALSE;
1066
1067
1068 assert(filelist != NULL);
1069
1070 log_to_screen(_("Editing filelist"));
1071 newtPushHelpLine
1072 (_
1073 (" Please edit the filelist to your satisfaction, then click OK or Cancel."));
1074 j = 4;
1075 bLess = newtCompactButton(j, 17, _(" Less "));
1076 bMore = newtCompactButton(j += 12, 17, _(" More "));
1077 bToggle = newtCompactButton(j += 12, 17, _("Toggle"));
1078 bRegex = newtCompactButton(j += 12, 17, _("RegEx"));
1079 bCancel = newtCompactButton(j += 12, 17, _("Cancel"));
1080 bOK = newtCompactButton(j += 12, 17, _(" OK "));
1081 filelistListbox =
1082 newtListbox(2, 1, 15, NEWT_FLAG_SCROLL | NEWT_FLAG_RETURNEXIT);
1083 toggle_all_root_dirs_on(filelist);
1084 lines_in_flist_window =
1085 redraw_filelist(filelist, keylist, filelistListbox);
1086 newtOpenWindow(1, 3, 77, 18, _("Editing filelist"));
1087 myForm = newtForm(NULL, NULL, 0);
1088 newtFormAddComponents(myForm, filelistListbox, bLess, bMore, bToggle,
1089 bRegex, bCancel, bOK, NULL);
1090 while (!finished) {
1091 b_res = newtRunForm(myForm);
1092 if (b_res == bOK) {
1093 finished =
1094 ask_me_yes_or_no
1095 (_("Are you happy with your file selection?"));
1096 } else if (b_res == bCancel) {
1097 finished = TRUE;
1098 } else if (b_res == bRegex) {
1099 popup_and_OK(_("I haven't implemented this yet..."));
1100 } else {
1101 curr_choice = newtListboxGetCurrent(filelistListbox);
1102 for (indexno = 0;
1103 indexno < lines_in_flist_window
1104 && keylist[indexno] != curr_choice; indexno++);
1105 if (indexno == lines_in_flist_window) {
1106 log_it
1107 ("I don't know what this button does; assuming I am to toggle 1st entry");
1108 indexno = 0;
1109 }
1110 log_it("You selected '%s'",
1111 g_strings_of_flist_window[indexno]);
1112 if (b_res == bMore) {
1113 g_is_path_expanded[indexno] = TRUE;
1114 toggle_path_expandability(filelist,
1115 g_strings_of_flist_window
1116 [indexno], TRUE);
1117 lines_in_flist_window =
1118 redraw_filelist(filelist, keylist, filelistListbox);
1119 newtListboxSetCurrentByKey(filelistListbox, curr_choice);
1120 } else if (b_res == bLess) {
1121 g_is_path_expanded[indexno] = FALSE;
1122 toggle_path_expandability(filelist,
1123 g_strings_of_flist_window
1124 [indexno], FALSE);
1125 lines_in_flist_window =
1126 redraw_filelist(filelist, keylist, filelistListbox);
1127 newtListboxSetCurrentByKey(filelistListbox, curr_choice);
1128 } else {
1129 if (!strcmp(g_strings_of_flist_window[indexno], "/")) {
1130 dummybool = !g_is_path_selected[indexno];
1131 for (j = 1; j < lines_in_flist_window; j++) {
1132 toggle_path_selection(filelist,
1133 g_strings_of_flist_window[j],
1134 dummybool);
1135 }
1136 } else {
1137 toggle_path_selection(filelist,
1138 g_strings_of_flist_window
1139 [indexno],
1140 !g_is_path_selected[indexno]);
1141 lines_in_flist_window =
1142 redraw_filelist(filelist, keylist,
1143 filelistListbox);
1144 }
1145 newtListboxSetCurrentByKey(filelistListbox, curr_choice);
1146 }
1147 for (indexno = 0;
1148 indexno < lines_in_flist_window
1149 && keylist[indexno] != curr_choice; indexno++);
1150 if (indexno == lines_in_flist_window) {
1151 log_it
1152 ("Layout of table has changed. Y pointer is reverting to zero.");
1153 indexno = 0;
1154 }
1155 }
1156 }
1157 newtFormDestroy(myForm);
1158 newtPopWindow();
1159 newtPopHelpLine();
1160 if (b_res == bOK) {
1161 return (0);
1162 } else {
1163 return (1);
1164 }
1165}
1166
1167
1168/**
1169 * Edit an entry in @p mountlist.
1170 * @param mountlist The mountlist containing information about the user's partitions.
1171 * @param raidlist The raidlist to accompany @p mountlist.
1172 * @param listbox The Newt listbox component in the mountlist editor.
1173 * @param currline The selected line (starting from 0) in @p listbox.
1174 * @param keylist The list of keys for @p listbox.
1175 * @ingroup restoreGuiMountlist
1176 */
1177void
1178edit_mountlist_entry(struct mountlist_itself *mountlist,
1179 struct raidlist_itself *raidlist,
1180 newtComponent listbox, int currline, void *keylist[])
1181{
1182
1183 /** structures ********************************************************/
1184 static struct raidlist_itself bkp_raidlist;
1185
1186 /** newt **************************************************************/
1187 newtComponent myForm;
1188 newtComponent bOK;
1189 newtComponent bCancel;
1190 newtComponent b_res;
1191 newtComponent mountpointComp;
1192 newtComponent label0;
1193 newtComponent label1;
1194 newtComponent label2;
1195 newtComponent label3;
1196 newtComponent sizeComp;
1197 newtComponent deviceComp;
1198 newtComponent formatComp;
1199 newtComponent b_raid = NULL;
1200
1201 char *device_str = NULL;
1202 char *mountpoint_str = NULL;
1203 char *size_str = NULL;
1204 char *format_str = NULL;
1205 char *tmp = NULL;
1206 char *device_used_to_be = NULL;
1207 char *mountpt_used_to_be = NULL;
1208 char *device_here = NULL;
1209 char *mountpoint_here = NULL;
1210 char *size_here = NULL;
1211 char *format_here = NULL;
1212
1213 int j = 0;
1214
1215 assert(mountlist != NULL);
1216 assert(raidlist != NULL);
1217 assert(listbox != NULL);
1218 assert(keylist != NULL);
1219
1220 memcpy((void *) &bkp_raidlist, (void *) raidlist,
1221 sizeof(struct raidlist_itself));
1222 mr_asprintf(&device_str, mountlist->el[currline].device);
1223 mr_asprintf(&device_used_to_be, mountlist->el[currline].device);
1224 mr_asprintf(&mountpoint_str, mountlist->el[currline].mountpoint);
1225 mr_asprintf(&mountpt_used_to_be, mountlist->el[currline].mountpoint);
1226 mr_asprintf(&format_str, mountlist->el[currline].format);
1227 mr_asprintf(&size_str, "%lld", mountlist->el[currline].size / 1024);
1228
1229 newtOpenWindow(20, 5, 48, 10, _("Edit entry"));
1230 label0 = newtLabel(2, 1, _("Device:"));
1231 label1 = newtLabel(2, 2, _("Mountpoint:"));
1232 label2 = newtLabel(2, 3, _("Size (MB): "));
1233 label3 = newtLabel(2, 4, _("Format: "));
1234 deviceComp =
1235 newtEntry(14, 1, device_str, 30, (void *) &device_here, 0);
1236 mr_free(device_str);
1237
1238 mountpointComp =
1239 newtEntry(14, 2, mountpoint_str, 30, (void *) &mountpoint_here, 0);
1240 mr_free(mountpoint_str);
1241
1242 formatComp =
1243 newtEntry(14, 4, format_str, 15, (void *) &format_here, 0);
1244 mr_free(format_str);
1245
1246 if (strstr(mountlist->el[currline].device, RAID_DEVICE_STUB)
1247 || !strcmp(mountlist->el[currline].mountpoint, "image")) {
1248 sizeComp = newtLabel(14, 3, size_str);
1249 } else {
1250 sizeComp = newtEntry(14, 3, size_str, 10, (void *) &size_here, 0);
1251 }
1252 mr_free(size_str);
1253
1254 bOK = newtButton(2, 6, _(" OK "));
1255 bCancel = newtButton(14, 6, _("Cancel"));
1256 if (strstr(mountlist->el[currline].device, RAID_DEVICE_STUB)) {
1257 b_raid = newtButton(26, 6, "RAID..");
1258 }
1259 newtPushHelpLine
1260 (_
1261 (" Edit this partition's mountpoint, size and format; then click 'OK'."));
1262 myForm = newtForm(NULL, NULL, 0);
1263 newtFormAddComponents(myForm, deviceComp, mountpointComp, sizeComp,
1264 formatComp, label0, label1, label2, label3, bOK,
1265 bCancel, b_raid, NULL);
1266 for (b_res = NULL; b_res != bOK && b_res != bCancel;) {
1267 b_res = newtRunForm(myForm);
1268 mr_free(device_str);
1269 mr_asprintf(&device_str, device_here);
1270 mr_strip_spaces(device_str);
1271
1272 mr_free(mountpoint_str);
1273 mr_asprintf(&mountpoint_str, mountpoint_here);
1274 mr_strip_spaces(mountpoint_str);
1275
1276 mr_free(format_str);
1277 mr_asprintf(&format_str, format_here);
1278 mr_strip_spaces(format_str);
1279
1280 if (b_res == bOK && strstr(device_str, RAID_DEVICE_STUB)
1281 && strstr(device_used_to_be, RAID_DEVICE_STUB)
1282 && strcmp(device_str, device_used_to_be)) {
1283 popup_and_OK(_("You can't change /dev/mdX to /dev/mdY."));
1284 b_res = NULL;
1285 continue;
1286 } else if (b_res == bOK && !strcmp(mountpoint_str, "image")
1287 && strcmp(mountpt_used_to_be, "image")) {
1288 popup_and_OK(_
1289 ("You can't change a regular device to an image."));
1290 b_res = NULL;
1291 continue;
1292 }
1293 mr_free(mountpt_used_to_be);
1294
1295 mr_free(size_str);
1296 if (!strstr(mountlist->el[currline].device, RAID_DEVICE_STUB)
1297 && strcmp(mountlist->el[currline].mountpoint, "image")) {
1298 mr_asprintf(&size_str, size_here);
1299 mr_strip_spaces(size_str);
1300 } else {
1301 mr_asprintf(&size_str, "%ld",
1302 calculate_raid_device_size(mountlist, raidlist,
1303 mountlist->el[currline].
1304 device) / 1024);
1305 newtLabelSetText(sizeComp, size_str);
1306 }
1307
1308 /* do not let user click RAID button if user has changed device_str */
1309 if (b_res == b_raid) {
1310 if (strcmp(device_str, mountlist->el[currline].device)) {
1311 /*
1312 can't change mountlist's entry from /dex/mdX to /dev/mdY: it would ugly
1313 when you try to map the changes over to the raidtab list, trust me
1314 */
1315 popup_and_OK
1316 (_
1317 ("You cannot edit the RAID settings until you have OK'd your change to the device node."));
1318 } else {
1319 j = find_raid_device_in_raidlist(raidlist,
1320 mountlist->el[currline].
1321 device);
1322 if (j < 0) {
1323 mr_asprintf(&tmp,
1324 _
1325 ("/etc/raidtab does not have an entry for %s; please delete it and add it again"),
1326 mountlist->el[currline].device);
1327 popup_and_OK(tmp);
1328 mr_free(tmp);
1329 } else {
1330 log_it(_("edit_raidlist_entry - calling"));
1331 edit_raidlist_entry(mountlist, raidlist,
1332 &raidlist->el[j], currline);
1333 }
1334 }
1335 }
1336 }
1337 newtFormDestroy(myForm);
1338 newtPopHelpLine();
1339 newtPopWindow();
1340 if (b_res == bCancel) {
1341 memcpy((void *) raidlist, (void *) &bkp_raidlist,
1342 sizeof(struct raidlist_itself));
1343 return;
1344 }
1345 strcpy(mountlist->el[currline].device, device_str);
1346 strcpy(mountlist->el[currline].mountpoint, mountpoint_str);
1347 mr_free(mountpoint_str);
1348
1349 strcpy(mountlist->el[currline].format, format_str);
1350 mr_free(format_str);
1351
1352 if (strcmp(mountlist->el[currline].mountpoint, "image")) {
1353 if (strstr(mountlist->el[currline].device, RAID_DEVICE_STUB)) {
1354 mountlist->el[currline].size =
1355 calculate_raid_device_size(mountlist, raidlist,
1356 mountlist->el[currline].device);
1357 } else {
1358 mountlist->el[currline].size = atol(size_str) * 1024;
1359 }
1360 }
1361 mr_free(size_str);
1362
1363 newtListboxSetEntry(listbox, (long) keylist[currline],
1364 mountlist_entry_to_string(mountlist, currline));
1365 /* if new /dev/md RAID device then do funky stuff */
1366 if (strstr(mountlist->el[currline].device, RAID_DEVICE_STUB)
1367 && !strstr(device_used_to_be, RAID_DEVICE_STUB)) {
1368 initiate_new_raidlist_entry(raidlist, mountlist, currline,
1369 device_str);
1370 }
1371 /* if moving from RAID to non-RAID then do funky stuff */
1372 else if (strstr(device_used_to_be, RAID_DEVICE_STUB)
1373 && !strstr(device_str, RAID_DEVICE_STUB)) {
1374 delete_raidlist_entry(mountlist, raidlist, device_str);
1375 }
1376 /* if moving a non-RAID to another non-RAID then re-jig any RAID disks, if necessary */
1377 else if (!strstr(device_used_to_be, RAID_DEVICE_STUB)
1378 && !strstr(device_str, RAID_DEVICE_STUB)) {
1379 rejig_partition_name_in_raidlist_if_necessary(raidlist,
1380 device_used_to_be,
1381 device_str);
1382 }
1383/* else, moving a RAID to another RAID; bad idea, or so I thought */
1384#ifndef __FreeBSD__ /* It works fine under FBSD. */
1385 else if (strcmp(device_used_to_be, device_str)) {
1386 popup_and_OK
1387 (_
1388 ("You are renaming a RAID device as another RAID device. I don't like it but I'll allow it."));
1389 }
1390#endif
1391 redraw_mountlist(mountlist, keylist, listbox);
1392 mr_free(device_str);
1393 mr_free(device_used_to_be);
1394}
1395
1396
1397#if __FreeBSD__
1398/**
1399 * Add a subdisk to @p raidrec.
1400 * @param raidlist The raidlist containing information about RAID partitions.
1401 * @param raidrec The RAID device record to add the subdisk to.
1402 * @param temp The device name of the RAID disk to add it to.
1403 * @author Joshua Oreman
1404 * @ingroup restoreGuiMountlist
1405 */
1406void
1407add_raid_subdisk(struct raidlist_itself *raidlist,
1408 struct vinum_plex *raidrec, char *temp)
1409{
1410 int i = 0;
1411 bool found = FALSE;
1412
1413 for (i = 0; i < raidlist->disks.entries; ++i) {
1414 if (!strcmp(raidlist->disks.el[i].device, temp)) {
1415 strcpy(raidrec->sd[raidrec->subdisks].which_device,
1416 raidlist->disks.el[i].name);
1417 found = TRUE;
1418 }
1419 }
1420 if (!found) {
1421 sprintf(raidlist->disks.el[raidlist->disks.entries].name,
1422 "drive%i", raidlist->disks.entries);
1423 sprintf(raidrec->sd[raidrec->subdisks].which_device, "drive%i",
1424 raidlist->disks.entries);
1425 strcpy(raidlist->disks.el[raidlist->disks.entries++].device, temp);
1426 }
1427 raidrec->subdisks++;
1428}
1429
1430
1431/**
1432 * Determine the /dev entry for @p vinum_name.
1433 * @param raidlist The raidlist containing information about RAID devices.
1434 * @param vinum_name The name of the Vinum drive to map to a /dev entry.
1435 * @return The /dev entry, or NULL if none was found.
1436 * @note The returned string points to static storage that will be overwritten with each call.
1437 * @author Joshua Oreman
1438 * @ingroup restoreUtilityGroup
1439 */
1440char *find_dev_entry_for_raid_device_name(struct raidlist_itself *raidlist,
1441 char *vinum_name)
1442{
1443 int i;
1444 for (i = 0; i < raidlist->disks.entries; ++i) {
1445 if (!strcmp(raidlist->disks.el[i].name, vinum_name)) {
1446 return raidlist->disks.el[i].device;
1447 }
1448 }
1449 return NULL;
1450}
1451
1452
1453void
1454edit_raidlist_plex(struct mountlist_itself *mountlist,
1455 struct raidlist_itself *raidlist,
1456 struct vinum_plex *raidrec, int currline,
1457 int currline2);
1458
1459#endif
1460
1461
1462/**
1463 * Edit the entry for @p raidrec in @p raidlist.
1464 * @param mountlist The mountlist to get some information from.
1465 * @param raidlist The raidlist containing information about RAID devices.
1466 * @param raidrec The RAID device record for this partition.
1467 * @param currline The line number (starting from 0) in the mountlist of the RAID device.
1468 * @ingroup restoreGuiMountlist
1469 */
1470void
1471edit_raidlist_entry(struct mountlist_itself *mountlist,
1472 struct raidlist_itself *raidlist,
1473 struct OSSWAP (raid_device_record,
1474 vinum_volume) * raidrec, int currline)
1475{
1476
1477#ifdef __FreeBSD__
1478 /** structures ********************************************************/
1479 struct vinum_volume bkp_raidrec;
1480
1481
1482 /** buffers ***********************************************************/
1483 char *title_of_editraidForm_window = NULL;
1484
1485 /** newt **************************************************************/
1486 newtComponent editraidForm;
1487 newtComponent bOK;
1488 newtComponent bCancel;
1489 newtComponent bEdit;
1490 newtComponent bAdd;
1491 newtComponent bDelete;
1492 newtComponent b_res;
1493 newtComponent plexesListbox;
1494 newtComponent plexesHeader;
1495
1496 void *keylist[10];
1497 void *curr_choice = NULL;
1498
1499 int currline2 = 0;
1500 char *pname = NULL;
1501 char *raidlevel = NULL;
1502 char *chunksize = NULL;
1503 char *entry = NULL;
1504 char *msg = NULL;
1505 int i = 0;
1506 char *headerstr = NULL;
1507
1508 log_it(_("Started edit_raidlist_entry"));
1509 memcpy((void *) &bkp_raidrec, (void *) raidrec,
1510 sizeof(struct vinum_volume));
1511 mr_asprintf(&title_of_editraidForm_window, _("Plexes on %s"),
1512 raidrec->volname);
1513 newtPushHelpLine(_(" Please select a plex to edit"));
1514 newtOpenWindow(13, 5, 54, 15, title_of_editraidForm_window);
1515 mr_free(title_of_editraidForm_window);
1516
1517 for (;;) {
1518 mr_asprintf(&headerstr, "%-14s %-8s %11s %8s", _("Plex"), _("Level",) _("Stripe Size"), _("Subdisks"));
1519
1520 bOK = newtCompactButton(2, 13, _(" OK "));
1521 bCancel = newtCompactButton(12, 13, _("Cancel"));
1522 bAdd = newtCompactButton(22, 13, _(" Add "));
1523 bEdit = newtCompactButton(32, 13, _(" Edit "));
1524 bDelete = newtCompactButton(42, 13, _("Delete"));
1525
1526 plexesListbox =
1527 newtListbox(2, 3, 9, NEWT_FLAG_SCROLL | NEWT_FLAG_RETURNEXIT);
1528 plexesHeader = newtLabel(2, 2, headerstr);
1529 mr_free(headerstr);
1530
1531 editraidForm = newtForm(NULL, NULL, 0);
1532
1533 newtListboxClear(plexesListbox);
1534 for (i = 0; i < 10; ++i) {
1535 keylist[i] = (void *) i;
1536 if (i < raidrec->plexes) {
1537 switch (raidrec->plex[i].raidlevel) {
1538 case -1:
1539 mr_asprintf(&raidlevel, "concat");
1540 break;
1541 case 0:
1542 mr_asprintf(&raidlevel, "striped");
1543 break;
1544 case 5:
1545 mr_asprintf(&raidlevel, "raid5");
1546 break;
1547 default:
1548 mr_asprintf(&raidlevel, "raid%i",
1549 raidrec->plex[i].raidlevel);
1550 break;
1551 }
1552
1553 if (raidrec->plex[i].raidlevel == -1) {
1554 mr_asprintf(&chunksize, "N/A");
1555 } else {
1556 mr_asprintf(&chunksize, "%dk", raidrec->plex[i].stripesize);
1557 }
1558 mr_asprintf(&pname, "%s.p%i", raidrec->volname, i);
1559 mr_asprintf(&entry, "%-14s %-8s %11s %8d",
1560 pname, raidlevel, chunksize,
1561 raidrec->plex[i].subdisks);
1562 mr_free(pname);
1563 mr_free(chunksize);
1564 mr_free(raidlevel);
1565 newtListboxAppendEntry(plexesListbox, entry, keylist[i]);
1566 /* BERLIOS : hope it's not necessary anymore */
1567 mr_free(entry);
1568 }
1569 }
1570
1571 newtFormAddComponents(editraidForm, bOK, bCancel, bAdd, bEdit,
1572 bDelete, plexesListbox, plexesHeader, NULL);
1573
1574 b_res = newtRunForm(editraidForm);
1575 if (b_res == bOK || b_res == bCancel) {
1576 break;
1577 }
1578
1579 curr_choice = newtListboxGetCurrent(plexesListbox);
1580 for (currline2 = 0; currline2 < raidrec->plexes; ++currline2) {
1581 if (currline2 > 9)
1582 break;
1583 if (keylist[currline2] == curr_choice)
1584 break;
1585 }
1586
1587 if (b_res == bDelete) {
1588 mr_asprintf(&msg, _("Are you sure you want to delete %s.p%i?"),
1589 raidrec->volname, currline2);
1590 if (ask_me_yes_or_no(msg)) {
1591 log_it(_("Deleting RAID plex"));
1592 memcpy((void *) &raidrec->plex[currline2],
1593 (void *) &raidrec->plex[raidrec->plexes - 1],
1594 sizeof(struct vinum_plex));
1595 raidrec->plexes--;
1596 }
1597 mr_free(msg);
1598 continue;
1599 }
1600 if (b_res == bAdd) {
1601 raidrec->plex[raidrec->plexes].raidlevel = 0;
1602 raidrec->plex[raidrec->plexes].stripesize = 279;
1603 raidrec->plex[raidrec->plexes].subdisks = 0;
1604 currline2 = raidrec->plexes++;
1605 }
1606 edit_raidlist_plex(mountlist, raidlist, &raidrec->plex[currline2],
1607 currline, currline2);
1608 newtFormDestroy(editraidForm);
1609 }
1610 if (b_res == bCancel) {
1611 memcpy((void *) raidrec, (void *) &bkp_raidrec,
1612 sizeof(struct vinum_volume));
1613 }
1614 newtPopHelpLine();
1615 newtPopWindow();
1616 mountlist->el[currline].size =
1617 calculate_raid_device_size(mountlist, raidlist, raidrec->volname);
1618#else
1619 /** structures ********************************************************/
1620 struct raid_device_record *bkp_raidrec = NULL;
1621
1622
1623 /** buffers ***********************************************************/
1624 char *title_of_editraidForm_window = NULL;
1625 char *sz_raid_level = NULL;
1626 char *sz_data_disks = NULL;
1627 char *sz_spare_disks = NULL;
1628 char *sz_parity_disks = NULL;
1629 char *sz_failed_disks = NULL;
1630
1631 /** newt **************************************************************/
1632 newtComponent editraidForm;
1633 newtComponent bOK;
1634 newtComponent bCancel;
1635 newtComponent bAdditional;
1636 newtComponent bChangeRaid;
1637 newtComponent bSelectData;
1638 newtComponent bSelectSpare;
1639 newtComponent bSelectParity;
1640 newtComponent bSelectFailed;
1641 newtComponent b_res;
1642
1643 assert(mountlist != NULL);
1644 assert(raidlist != NULL);
1645 assert(raidrec != NULL);
1646
1647 bkp_raidrec = mr_malloc(sizeof(struct raid_device_record));
1648
1649 log_it("Started edit_raidlist_entry");
1650
1651 memcpy((void *) bkp_raidrec, (void *) raidrec,
1652 sizeof(struct raid_device_record));
1653 mr_asprintf(&title_of_editraidForm_window, _("Edit %s"), raidrec->raid_device);
1654 mr_msg(2, "Opening newt window");
1655 newtOpenWindow(20, 5, 40, 14, title_of_editraidForm_window);
1656 mr_free(title_of_editraidForm_window);
1657
1658 for (;;) {
1659 mr_msg(2, "Main loop");
1660 mr_asprintf(&sz_raid_level,
1661 turn_raid_level_number_to_string(raidrec->raid_level));
1662 mr_asprintf(&sz_data_disks,
1663 number_of_disks_as_string(raidrec->data_disks.entries,
1664 _("data")));
1665 mr_asprintf(&sz_spare_disks,
1666 number_of_disks_as_string(raidrec->spare_disks.entries,
1667 _("spare")));
1668 mr_asprintf(&sz_parity_disks,
1669 number_of_disks_as_string(raidrec->parity_disks.entries,
1670 _("parity")));
1671 mr_asprintf(&sz_failed_disks,
1672 number_of_disks_as_string(raidrec->failed_disks.entries,
1673 _("failed")));
1674 bSelectData = newtButton(1, 1, sz_data_disks);
1675 bSelectSpare = newtButton(20, 1, sz_spare_disks);
1676 bSelectParity = newtButton(1, 5, sz_parity_disks);
1677 bSelectFailed = newtButton(20, 5, sz_failed_disks);
1678 bChangeRaid = newtButton(1, 9, sz_raid_level);
1679 mr_free(sz_raid_level);
1680 mr_free(sz_data_disks);
1681 mr_free(sz_spare_disks);
1682 mr_free(sz_parity_disks);
1683 mr_free(sz_failed_disks);
1684
1685 bOK = newtButton(16 + (raidrec->raid_level == -1), 9, _(" OK "));
1686 bCancel = newtButton(28, 9, _("Cancel"));
1687 bAdditional =
1688 newtCompactButton(1, 13,
1689 _("Additional settings and information"));
1690 newtPushHelpLine
1691 (_
1692 (" Edit the RAID device's settings to your heart's content, then hit OK/Cancel."));
1693 editraidForm = newtForm(NULL, NULL, 0);
1694 newtFormAddComponents(editraidForm, bSelectData, bSelectParity,
1695 bChangeRaid, bSelectSpare, bSelectFailed,
1696 bOK, bCancel, bAdditional);
1697 b_res = newtRunForm(editraidForm);
1698 if (b_res == bChangeRaid) {
1699 choose_raid_level(raidrec);
1700 } else if (b_res == bSelectData) {
1701 select_raid_disks(mountlist, raidlist, raidrec, _("data"),
1702 &raidrec->data_disks);
1703 } else if (b_res == bSelectSpare) {
1704 select_raid_disks(mountlist, raidlist, raidrec, _("spare"),
1705 &raidrec->spare_disks);
1706 } else if (b_res == bSelectParity) {
1707 select_raid_disks(mountlist, raidlist, raidrec, _("parity"),
1708 &raidrec->parity_disks);
1709 } else if (b_res == bSelectFailed) {
1710 select_raid_disks(mountlist, raidlist, raidrec, _("failed"),
1711 &raidrec->failed_disks);
1712 } else if (b_res == bAdditional) {
1713 edit_raidrec_additional_vars(raidrec);
1714 }
1715 newtFormDestroy(editraidForm);
1716 if (b_res == bOK || b_res == bCancel) {
1717 break;
1718 }
1719 }
1720 if (b_res == bCancel) {
1721 memcpy((void *) raidrec, (void *) bkp_raidrec,
1722 sizeof(struct raid_device_record));
1723 }
1724 newtPopHelpLine();
1725 newtPopWindow();
1726 mountlist->el[currline].size =
1727 calculate_raid_device_size(mountlist, raidlist,
1728 raidrec->raid_device);
1729 mr_free(bkp_raidrec);
1730#endif
1731}
1732
1733
1734#ifdef __FreeBSD__
1735
1736/**
1737 * Edit the plex @p raidrec in @p raidlist.
1738 * @param mountlist The mountlist to get some of the information from.
1739 * @param raidlist The raidlist containing information about RAID devices.
1740 * @param raidrec The plex to edit.
1741 * @param currline The line number (starting from 0) of the RAID device in @p mountlist.
1742 * @param currline2 The line number (starting from 0) of the plex within the RAID device.
1743 * @author Joshua Oreman
1744 * @ingroup restoreGuiMountlist
1745 */
1746void
1747edit_raidlist_plex(struct mountlist_itself *mountlist,
1748 struct raidlist_itself *raidlist,
1749 struct vinum_plex *raidrec, int currline, int currline2)
1750{
1751
1752 /** structures ********************************************************/
1753 struct vinum_plex bkp_raidrec;
1754
1755
1756 /** buffers ***********************************************************/
1757 char *title_of_editraidForm_window = NULL;
1758 char *tmp = NULL;
1759 char *entry = NULL;
1760
1761 /** newt **************************************************************/
1762 newtComponent editraidForm;
1763 newtComponent bOK;
1764 newtComponent bCancel;
1765 newtComponent bEdit;
1766 newtComponent bAdd;
1767 newtComponent bDelete;
1768 newtComponent b_res;
1769 newtComponent unallocListbox, allocListbox;
1770 newtComponent bLevel, sLevel;
1771 newtComponent bStripeSize, sStripeSize;
1772 newtComponent bAlloc, bUnalloc;
1773
1774 void *keylist[ARBITRARY_MAXIMUM];
1775 void *curr_choice_a = NULL, *curr_choice_u = NULL;
1776 int currline_a = 0, currline_u = 0;
1777 int i = 0;
1778
1779 struct mountlist_itself *unallocparts = NULL;
1780
1781 unallocparts = mr_malloc(sizeof(struct mountlist_itself));
1782
1783 log_it("Started edit_raidlist_entry");
1784 memcpy((void *) &bkp_raidrec, (void *) raidrec,
1785 sizeof(struct vinum_plex));
1786 mr_asprintf(&title_of_editraidForm_window, "%s.p%i",
1787 raidlist->el[currline].volname, currline2);
1788 newtPushHelpLine
1789 (_
1790 (" Please select a subdisk to edit, or edit this plex's parameters"));
1791 newtOpenWindow(13, 3, 54, 18, title_of_editraidForm_window);
1792 mr_free(title_of_editraidForm_window);
1793
1794 for (;;) {
1795 switch (raidrec->raidlevel) {
1796 case -1:
1797 mr_asprintf(&tmp, _("concat"));
1798 break;
1799 case 0:
1800 mr_asprintf(&tmp, _("striped"));
1801 break;
1802 case 5:
1803 mr_asprintf(&tmp, _("raid5"));
1804 break;
1805 default:
1806 mr_asprintf(&tmp, _("unknown (%i)"), raidrec->raidlevel);
1807 break;
1808 }
1809 bLevel = newtCompactButton(2, 2, _(" RAID level "));
1810 sLevel = newtLabel(19, 2, tmp);
1811 mr_free(tmp);
1812
1813 if (raidrec->raidlevel >= 0) {
1814 mr_asprintf(&tmp, "%ik", raidrec->stripesize);
1815 bStripeSize = newtCompactButton(2, 4, _(" Stripe size "));
1816 } else {
1817 mr_asprintf(&tmp, "N/A");
1818 bStripeSize = newtLabel(2, 4, _("Stripe size:"));
1819 }
1820 sStripeSize = newtLabel(19, 4, tmp);
1821 mr_free(tmp);
1822
1823 bOK = newtCompactButton(2, 16, _(" OK "));
1824 bCancel = newtCompactButton(12, 16, _("Cancel"));
1825 bAdd = newtCompactButton(22, 16, _(" Add "));
1826 bEdit = newtCompactButton(32, 16, _(" Edit "));
1827 bDelete = newtCompactButton(42, 16, _("Delete"));
1828
1829 unallocListbox =
1830 newtListbox(2, 7, 7, NEWT_FLAG_SCROLL | NEWT_FLAG_RETURNEXIT);
1831 allocListbox =
1832 newtListbox(33, 7, 7, NEWT_FLAG_SCROLL | NEWT_FLAG_RETURNEXIT);
1833 bAlloc = newtButton(23, 7, " -> ");
1834 bUnalloc = newtButton(23, 11, " <- ");
1835
1836 editraidForm = newtForm(NULL, NULL, 0);
1837
1838 newtListboxClear(allocListbox);
1839 newtListboxClear(unallocListbox);
1840 bzero(unallocparts, sizeof(struct mountlist_itself));
1841 make_list_of_unallocated_raid_partitions(unallocparts, mountlist,
1842 raidlist);
1843 for (i = 0; i < ARBITRARY_MAXIMUM; ++i) {
1844 keylist[i] = (void *) i;
1845 if (i < raidrec->subdisks) {
1846 mr_asprintf(&entry, "%-17s",
1847 find_dev_entry_for_raid_device_name(raidlist,
1848 raidrec->
1849 sd[i].
1850 which_device));
1851 newtListboxAppendEntry(allocListbox, entry, keylist[i]);
1852 mr_free(entry);
1853 }
1854 if (i < unallocparts->entries) {
1855 mr_asprintf(&entry, "%-17s", unallocparts->el[i].device);
1856 newtListboxAppendEntry(unallocListbox, entry, keylist[i]);
1857 mr_free(entry);
1858 }
1859 }
1860
1861#define COMP(x) newtFormAddComponent (editraidForm, x)
1862#define UCOMP(x) if (unallocparts->entries > 0) COMP(x)
1863#define ACOMP(x) if (raidrec->subdisks > 0) COMP(x)
1864 editraidForm = newtForm(NULL, NULL, 0);
1865 UCOMP(unallocListbox);
1866 UCOMP(bAlloc);
1867 ACOMP(allocListbox);
1868 ACOMP(bUnalloc);
1869 COMP(bOK);
1870 COMP(bCancel);
1871 COMP(bLevel);
1872 COMP(sLevel);
1873 if (raidrec->raidlevel != -1) {
1874 COMP(bStripeSize);
1875 COMP(sStripeSize);
1876 }
1877#undef COMP
1878#undef UCOMP
1879#undef ACOMP
1880
1881 newtRefresh();
1882 b_res = newtRunForm(editraidForm);
1883 if (b_res == bOK || b_res == bCancel) {
1884 break;
1885 }
1886
1887 curr_choice_a = (raidrec->subdisks > 0) ?
1888 newtListboxGetCurrent(allocListbox) : (void *) 1234;
1889 curr_choice_u = (unallocparts->entries > 0) ?
1890 newtListboxGetCurrent(unallocListbox) : (void *) 1234;
1891 for (currline_a = 0; currline_a < raidrec->subdisks; ++currline_a) {
1892 if (currline_a > ARBITRARY_MAXIMUM)
1893 break;
1894 if (keylist[currline_a] == curr_choice_a)
1895 break;
1896 }
1897 for (currline_u = 0; currline_u < unallocparts->entries;
1898 ++currline_u) {
1899 if (currline_u > ARBITRARY_MAXIMUM)
1900 break;
1901 if (keylist[currline_u] == curr_choice_u)
1902 break;
1903 }
1904 if (b_res == bLevel) {
1905 choose_raid_level(raidrec);
1906 } else if (b_res == bStripeSize) {
1907 malloc_string(tmp);
1908 sprintf(tmp, "%i", raidrec->stripesize);
1909 if (popup_and_get_string
1910 (_("Stripe size"),
1911 _("Please enter the stripe size in kilobytes."), tmp, 20)) {
1912 raidrec->stripesize = atoi(tmp);
1913 }
1914 mr_free(tmp);
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);
1931 }
1932#endif
1933 newtFormDestroy(editraidForm);
1934 newtRefresh();
1935}
1936
1937if (b_res == bCancel) {
1938 memcpy((void *) raidrec, (void *) &bkp_raidrec,
1939 sizeof(struct vinum_plex));
1940}
1941newtPopWindow();
1942newtPopHelpLine();
1943}
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 */
1951void edit_varslist_entry(struct raid_device_record *raidrec, int lino)
1952{
1953
1954 /** buffers ***********************************************************/
1955 char *header = NULL;
1956 char *comment = NULL;
1957 char *sz_out = NULL;
1958
1959 assert(raidrec != 0);
1960 assert(lino >= 0);
1961
1962 malloc_string(sz_out);
1963 strcpy(sz_out, raidrec->additional_vars.el[lino].value);
1964 mr_asprintf(&header, _("Edit %s"), raidrec->additional_vars.el[lino].label);
1965 mr_asprintf(&comment, _("Please set %s's value (currently '%s')"),
1966 raidrec->additional_vars.el[lino].label, sz_out);
1967 if (popup_and_get_string(header, comment, sz_out, MAX_STR_LEN)) {
1968 mr_strip_spaces(sz_out);
1969 strcpy(raidrec->additional_vars.el[lino].value, sz_out);
1970 }
1971 mr_free(sz_out);
1972 mr_free(header);
1973 mr_free(comment);
1974}
1975#endif
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
1985edit_mountlist_in_newt(char *mountlist_fname,
1986 struct mountlist_itself *mountlist,
1987 struct raidlist_itself *raidlist)
1988{
1989
1990 /** newt **************************************************************/
1991 newtComponent myForm;
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 /** ???? *************************************************************/
2006 void *curr_choice = NULL;
2007 void *keylist[ARBITRARY_MAXIMUM];
2008
2009 /** int **************************************************************/
2010 int i = 0;
2011 int currline = 0;
2012 int finished = FALSE;
2013 int res = 0;
2014
2015 /** buffers **********************************************************/
2016 char *tmp = NULL;
2017 char *flaws_str_A = NULL;
2018 char *flaws_str_B = NULL;
2019 char *flaws_str_C = NULL;
2020
2021 assert(mountlist != NULL);
2022 assert(raidlist != NULL);
2023
2024 mr_asprintf(&flaws_str_A, "xxxxxxxxx");
2025 mr_asprintf(&flaws_str_B, "xxxxxxxxx");
2026 mr_asprintf(&flaws_str_C, "xxxxxxxxx");
2027 if (mountlist->entries > ARBITRARY_MAXIMUM) {
2028 log_to_screen(_("Arbitrary limits suck, man!"));
2029 finish(1);
2030 }
2031 newtPushHelpLine
2032 (_
2033 (" Please edit the mountlist to your satisfaction, then click OK or Cancel."));
2034 i = 4;
2035 bAdd = newtCompactButton(i, 17, _(" Add "));
2036 bEdit = newtCompactButton(i += 11, 17, _(" Edit "));
2037 bDelete = newtCompactButton(i += 12, 17, _("Delete"));
2038 bReload = newtCompactButton(i += 12, 17, _("Reload"));
2039 bCancel = newtCompactButton(i += 12, 17, _("Cancel"));
2040 bOK = newtCompactButton(i += 12, 17, _(" OK "));
2041 mr_asprintf(&tmp, "%-24s %-24s %-8s %s", _("Device"), _("Mountpoint"),
2042 _("Format"), _("Size (MB)"));
2043 headerMsg = newtLabel(2, 1, tmp);
2044 flawsLabelA = newtLabel(2, 13, flaws_str_A);
2045 flawsLabelB = newtLabel(2, 14, flaws_str_B);
2046 flawsLabelC = newtLabel(2, 15, flaws_str_C);
2047 mr_free(flaws_str_A);
2048 mr_free(flaws_str_B);
2049 mr_free(flaws_str_C);
2050
2051 partitionsListbox =
2052 newtListbox(2, 2, 10, NEWT_FLAG_SCROLL | NEWT_FLAG_RETURNEXIT);
2053 redraw_mountlist(mountlist, keylist, partitionsListbox);
2054 newtOpenWindow(1, 3, 77, 18, _("Editing mountlist"));
2055 myForm = newtForm(NULL, NULL, 0);
2056 newtFormAddComponents(myForm, headerMsg, partitionsListbox,
2057 flawsLabelA, flawsLabelB, flawsLabelC, bAdd,
2058 bEdit, bDelete, bReload, bCancel, bOK, NULL);
2059
2060 malloc_string(flaws_str_A);
2061 malloc_string(flaws_str_B);
2062 malloc_string(flaws_str_C);
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);
2069
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
2076 (_("Your mountlist might not work. Continue anyway?"));
2077 } else {
2078 finished =
2079 ask_me_yes_or_no
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.)"));
2082 }
2083 } else if (b_res == bCancel) {
2084 finished = TRUE;
2085 } else if (b_res == bReload) {
2086 if (ask_me_yes_or_no(_("Reload original mountlist?"))) {
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) {
2096 log_to_screen(_("I don't know what that button does!"));
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
2114 (_
2115 ("Please add an entry. Then press ENTER to edit it."));
2116 }
2117 }
2118 }
2119 }
2120 }
2121 newtFormDestroy(myForm);
2122 newtPopWindow();
2123 newtPopHelpLine();
2124 if (b_res == bOK) {
2125 log_it(_("You pushed 'OK'. I shall now continue."));
2126 return (0);
2127 } else {
2128 return (1);
2129 }
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
2140edit_mountlist(char *mountlist_fname, struct mountlist_itself *mountlist,
2141 struct raidlist_itself *raidlist)
2142{
2143 int res = 0;
2144
2145 iamhere("entering eml");
2146
2147 if (g_text_mode) {
2148 fatal_error("Don't call edit_mountlist() in text mode");
2149 } else {
2150 log_it
2151 ("I'm in GUI mode, so I shall edit mountlist using edit_mountlist()");
2152 res = edit_mountlist_in_newt(mountlist_fname, mountlist, raidlist);
2153 }
2154 iamhere("leaving eml");
2155 return (res);
2156}
2157
2158
2159#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 */
2165void edit_raidrec_additional_vars(struct raid_device_record *raidrec)
2166{
2167
2168 /** structure *********************************************************/
2169 struct raid_device_record bkp_raidrec;
2170
2171 /** newt **************************************************************/
2172 newtComponent myForm;
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 /** ?? ***************************************************************/
2183 void *keylist[ARBITRARY_MAXIMUM], *curr_choice = NULL;
2184
2185 /** buffers **********************************************************/
2186 char *title_of_window = NULL;
2187
2188 /** int **************************************************************/
2189 int i = 0;
2190 int currline = 0;
2191
2192
2193 assert(raidrec != NULL);
2194
2195 memcpy((void *) &bkp_raidrec, (void *) raidrec,
2196 sizeof(struct raid_device_record));
2197 mr_asprintf(&title_of_window, "Additional variables");
2198 newtPushHelpLine
2199 (_
2200 (" Edit the additional fields to your heart's content, then click OK or Cancel."));
2201 headerMsg =
2202 newtLabel(1, 1, _("Label Value"));
2203 varsListbox =
2204 newtListbox(1, 2, 6, NEWT_FLAG_SCROLL | NEWT_FLAG_RETURNEXIT);
2205 i = 1;
2206 bAdd = newtCompactButton(i, 9, _(" Add "));
2207 bEdit = newtCompactButton(i += 8, 9, _(" Edit "));
2208 bDelete = newtCompactButton(i += 9, 9, _("Delete"));
2209 bOK = newtCompactButton(i += 9, 9, _(" OK "));
2210 bCancel = newtCompactButton(i += 9, 9, _("Cancel"));
2211 newtOpenWindow(17, 7, 46, 10, title_of_window);
2212 mr_free(title_of_window);
2213
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);
2239 }
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));
2247 }
2248 return;
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 */
2259int find_next_free_index_in_disklist(struct list_of_disks *disklist)
2260{
2261
2262 /** int ***************************************************************/
2263 int idx = -1;
2264 int pos = 0;
2265
2266 /** bool **************************************************************/
2267 bool done = FALSE;
2268
2269 assert(disklist != NULL);
2270
2271 for (done = FALSE; !done;) {
2272 for (pos = 0;
2273 pos < disklist->entries && disklist->el[pos].index <= idx;
2274 pos++);
2275 if (pos >= disklist->entries) {
2276 done = TRUE;
2277 } else {
2278 idx = disklist->el[pos].index;
2279 }
2280 }
2281 return (idx + 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
2293find_raid_device_in_raidlist(struct raidlist_itself *raidlist,
2294 char *device)
2295{
2296
2297 /** int ***************************************************************/
2298 int i = 0;
2299#ifdef __FreeBSD__
2300 char *vdev = NULL;
2301#endif
2302
2303 assert(raidlist != NULL);
2304 assert_string_is_neither_NULL_nor_zerolength(device);
2305
2306#ifdef __FreeBSD__
2307 for (i = 0; i < raidlist->entries; i++) {
2308 mr_asprintf(&vdev, "/dev/vinum/%s", raidlist->el[i].volname);
2309 if (!strcmp(device, vdev)) {
2310 mr_free(vdev);
2311 break;
2312 }
2313 mr_free(vdev);
2314 }
2315#else
2316
2317 for (i = 0;
2318 strcmp(raidlist->el[i].raid_device, device)
2319 && i < raidlist->entries; i++);
2320#endif
2321 if (i == raidlist->entries) {
2322 return (-1);
2323 } else {
2324 return (i);
2325 }
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.
2333 * @param isodir_path Where to put the path (e.g. /var/cache/mondo) the user enters.
2334 * @param nuke_me_please Whether we're planning on nuking or not.
2335 * @return TRUE if OK was pressed, FALSE otherwise.
2336 */
2337bool
2338get_isodir_info(char *isodir_device, char *isodir_format,
2339 char *isodir_path, bool nuke_me_please)
2340{
2341 char *value = NULL;
2342
2343 /** initialize ********************************************************/
2344 malloc_string(value);
2345
2346 assert(isodir_device != NULL);
2347 assert(isodir_format != NULL);
2348 assert(isodir_path != NULL);
2349
2350 log_it("%d - AAA - isodir_path = %s", __LINE__, isodir_path);
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 }
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);
2360 strcpy(isodir_format, "nfs");
2361 strcpy(isodir_path, value);
2362 }
2363 mr_free(value);
2364
2365 if (nuke_me_please) {
2366 return (TRUE);
2367 }
2368
2369 if (popup_and_get_string
2370 (_("ISO Mode - device"), _("On what device do the ISO files live?"),
2371 isodir_device, MAX_STR_LEN / 4)) {
2372 if (popup_and_get_string
2373 (_("ISO Mode - format"),
2374 _("What is the disk format of the device? (Hit ENTER if you don't know.)"),
2375 isodir_format, 16)) {
2376 if (popup_and_get_string
2377 (_("ISO Mode - path"),
2378 _("At what path on this device can the ISO files be found?"),
2379 isodir_path, MAX_STR_LEN / 4)) {
2380 mr_strip_spaces(isodir_device);
2381 mr_strip_spaces(isodir_format);
2382 mr_strip_spaces(isodir_path);
2383 log_it("%d - BBB - isodir_path = %s", isodir_path);
2384 return (TRUE);
2385 }
2386 }
2387 }
2388 return (FALSE);
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
2401initiate_new_raidlist_entry(struct raidlist_itself *raidlist,
2402 struct mountlist_itself *mountlist,
2403 int currline, char *device)
2404{
2405 /** structure *********************************************************/
2406 struct OSSWAP (raid_device_record, vinum_volume) * raidrec;
2407
2408 /** int ***************************************************************/
2409 int pos_in_raidlist = 0;
2410
2411 assert(raidlist != NULL);
2412 assert(mountlist != NULL);
2413 assert_string_is_neither_NULL_nor_zerolength(device);
2414
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)));
2426#ifndef __FreeBSD__
2427 choose_raid_level(raidrec);
2428 select_raid_disks(mountlist, raidlist, raidrec, "data",
2429 &raidrec->data_disks);
2430#endif
2431 edit_raidlist_entry(mountlist, raidlist, raidrec, currline);
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 */
2441void insert_essential_additionalvars(struct raid_device_record *raidrec)
2442{
2443
2444 /** int **************************************************************/
2445 int items = 0;
2446
2447 assert(raidrec != NULL);
2448
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;
2456}
2457#endif
2458
2459
2460/**
2461 * Dummy function that proves that we can get to the point where Mondo is run.
2462 */
2463void nuke_mode_dummy(void)
2464{
2465
2466 /** newt *************************************************************/
2467 newtComponent myForm;
2468 newtComponent b1;
2469 newtComponent b2;
2470 newtComponent b3;
2471 newtComponent b_res;
2472
2473
2474 newtPushHelpLine
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"));
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();
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
2498redraw_disklist(struct list_of_disks *disklist,
2499 void *keylist[ARBITRARY_MAXIMUM], newtComponent listbox)
2500{
2501
2502 /** long **************************************************************/
2503 long i = 0;
2504
2505 assert(disklist != NULL);
2506 assert(keylist != NULL);
2507 assert(listbox != NULL);
2508
2509 newtListboxClear(listbox);
2510
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 }
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
2530redraw_mountlist(struct mountlist_itself *mountlist,
2531 void *keylist[ARBITRARY_MAXIMUM], newtComponent listbox)
2532{
2533
2534 /** long **************************************************************/
2535 long i = 0;
2536
2537 assert(mountlist != NULL);
2538 assert(keylist != NULL);
2539 assert(listbox != NULL);
2540
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 }
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 */
2560void redraw_unallocpartnslist(struct mountlist_itself
2561 *unallocated_raid_partitions,
2562 void *keylist[ARBITRARY_MAXIMUM],
2563 newtComponent listbox)
2564{
2565
2566 /** long *************************************************************/
2567 long i = 0;
2568
2569 /** buffers **********************************************************/
2570 char *tmp = NULL;
2571
2572 assert(unallocated_raid_partitions != NULL);
2573 assert(keylist != NULL);
2574 assert(listbox != NULL);
2575
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++) {
2581 mr_asprintf(&tmp, "%-22s %8lld",
2582 unallocated_raid_partitions->el[i].device,
2583 unallocated_raid_partitions->el[i].size / 1024);
2584 newtListboxAppendEntry(listbox, tmp, keylist[i]);
2585 mr_free(tmp);
2586 }
2587}
2588
2589
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
2599redraw_varslist(struct additional_raid_variables *additional_vars,
2600 void *keylist[], newtComponent listbox)
2601{
2602 /** long ************************************************************/
2603 long i = 0;
2604
2605 /** buffers *********************************************************/
2606 char *tmp;
2607
2608 assert(additional_vars != NULL);
2609 assert(keylist != NULL);
2610 assert(listbox != NULL);
2611
2612 newtListboxClear(listbox);
2613
2614 for (i = 0; i < ARBITRARY_MAXIMUM; i++) {
2615 keylist[i] = (void *) i;
2616 }
2617 for (i = 0; i < additional_vars->entries; i++) {
2618 mr_asprintf(&tmp, "%-32s %-8s", additional_vars->el[i].label,
2619 additional_vars->el[i].value);
2620 newtListboxAppendEntry(listbox, tmp, keylist[i]);
2621 mr_free(tmp);
2622 }
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
2634read_variableINT_and_remove_from_raidvars(struct
2635 OSSWAP (raid_device_record,
2636 vinum_volume) * raidrec,
2637 char *label)
2638{
2639 /** int ***************************************************************/
2640 int i = 0;
2641 int res = 0;
2642
2643
2644 assert(raidrec != NULL);
2645 assert(label != NULL);
2646
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--;
2660 }
2661 return (res);
2662}
2663#endif
2664
2665
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 */
2673void rejig_partition_name_in_raidlist_if_necessary(struct raidlist_itself
2674 *raidlist,
2675 char *old_dev,
2676 char *new_dev)
2677{
2678
2679 /** int ************************************************************/
2680 int pos = 0;
2681 int j = 0;
2682
2683 assert(raidlist != NULL);
2684 assert_string_is_neither_NULL_nor_zerolength(old_dev);
2685 assert_string_is_neither_NULL_nor_zerolength(new_dev);
2686
2687 pos = which_raid_device_is_using_this_partition(raidlist, old_dev);
2688 if (pos < 0) {
2689 log_it("No need to rejig %s in raidlist: it's not listed.",
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 }
2707#ifndef __FreeBSD__
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 }
2720#endif
2721 else {
2722 log_it("%s is supposed to be listed in this raid dev but it's not...",
2723 old_dev);
2724 }
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 */
2736void remove_essential_additionalvars(struct raid_device_record *raidrec)
2737{
2738
2739 /** int **************************************************************/
2740 int res = 0;
2741
2742 assert(raidrec != NULL);
2743
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");
2755}
2756
2757
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
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)
2773{
2774 void *curr_choice = NULL;
2775
2776 /** structures ********************************************************/
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;
2781
2782 /** newt **************************************************************/
2783 newtComponent myForm = NULL;
2784 newtComponent bAdd = NULL;
2785 newtComponent bDelete = NULL;
2786 newtComponent bOK = NULL;
2787 newtComponent bCancel = NULL;
2788 newtComponent b_res = NULL;
2789 newtComponent partitionsListbox = NULL;
2790 newtComponent headerMsg = NULL;
2791
2792 /** buffers **********************************************************/
2793 void *keylist[ARBITRARY_MAXIMUM];
2794 char *tmp = NULL;
2795 char *help_text = NULL;
2796 char *title_of_window = NULL;
2797 char *sz_res = NULL;
2798 char *header_text = NULL;
2799
2800 /** int **************************************************************/
2801 int i = 0;
2802 int currline = 0;
2803
2804 assert(mountlist_dontedit != NULL);
2805 assert(raidlist != NULL);
2806 assert(raidrec != NULL);
2807 assert(description_of_list != NULL);
2808 assert(disklist != NULL);
2809
2810 iamhere("malloc'ing");
2811 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));
2815
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));
2822
2823 iamhere("Post-malloc");
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);
2829 newtPushHelpLine(help_text);
2830 mr_free(help_text);
2831
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;
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"));
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 */
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.
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) {
2860 log_to_screen(_("I don't know what that button does!"));
2861 } else {
2862 currline = i;
2863 if (b_res == bAdd) {
2864 log_it(_("Making list of unallocated RAID slices"));
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
2870 (_
2871 ("There are no unallocated partitions marked for RAID."));
2872 } else {
2873 log_it
2874 (_
2875 ("Done. The user may add one or more of the above to RAID device"));
2876 add_disklist_entry(disklist, raidrec->raid_device,
2877 unallocated_raid_partitions);
2878 log_it(_
2879 ("I have finished adding a disklist entry."));
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 {
2888 mr_asprintf(&tmp, _("%s's index is %d. What should it be?"),
2889 raidrec->raid_device,
2890 disklist->el[currline].index);
2891 malloc_string(sz_res);
2892 sprintf(sz_res, "%d", disklist->el[currline].index);
2893 if (popup_and_get_string
2894 (_("Set index"), tmp, sz_res, 10)) {
2895 disklist->el[currline].index = atoi(sz_res);
2896 }
2897 mr_free(tmp);
2898 mr_free(sz_res);
2899
2900 redraw_disklist(disklist, keylist, partitionsListbox);
2901 }
2902 }
2903 }
2904 newtFormDestroy(myForm);
2905 newtPopWindow();
2906 }
2907 mr_free(title_of_window);
2908 mr_free(header_text);
2909
2910 newtPopHelpLine();
2911 if (b_res == bCancel) {
2912 memcpy((void *) raidlist, (void *) bkp_raidlist,
2913 sizeof(struct raidlist_itself));
2914 memcpy((void *) raidrec, (void *) bkp_raidrec,
2915 sizeof(struct raid_device_record));
2916 memcpy((void *) disklist, (void *) bkp_disklist,
2917 sizeof(struct list_of_disks));
2918 }
2919 mr_free(bkp_raidrec);
2920 mr_free(bkp_disklist);
2921 mr_free(bkp_raidlist);
2922 mr_free(unallocated_raid_partitions);
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 */
2932char which_restore_mode()
2933{
2934
2935 /** char *************************************************************/
2936 char output = '\0';
2937 char *tmp = NULL;
2938 size_t n = 0;
2939
2940 /** newt *************************************************************/
2941
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
2952 (_
2953 ("Which mode - (A)utomatic, (I)nteractive, \n(C)ompare only, or (E)xit to shell?\n--> "));
2954 mr_getline(&tmp, &n, stdin);
2955 }
2956 mr_free(tmp);
2957 return (output);
2958 }
2959
2960 newtPushHelpLine
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"));
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);
2987}
Note: See TracBrowser for help on using the repository browser.