source: MondoRescue/branches/2.2.10/mondo/src/mondorestore/mondo-rstr-newt.c@ 2508

Last change on this file since 2508 was 2508, checked in by Bruno Cornec, 14 years ago

r3287@localhost (orig r2285): bruno | 2009-07-20 11:36:47 +0200

r3285@localhost: bruno | 2009-07-20 11:17:35 +0200
Apply fix in 2.2.10 around multi USB device handling to 2.2.9 as well


r3291@localhost (orig r2288): bruno | 2009-07-21 16:48:31 +0200
Copy 2.2.10 test script in to 2.2.9 for memory problm analysis


r3293@localhost (orig r2290): bruno | 2009-07-22 14:03:44 +0200

  • Fix a printing error in mindi for the tar command
  • Fix all mr_asprintf which had no second param as a string


r3295@localhost (orig r2292): bruno | 2009-07-22 16:55:00 +0200

  • Fix #160 and #346 by rewriting the message.txt file with more valid information gathered in mindi


r3300@localhost (orig r2294): bruno | 2009-07-23 01:58:08 +0200

Man pages patch from Joe Ross (joe.ross_at_gmail.com)


r3303@localhost (orig r2297): bruno | 2009-07-23 17:43:49 +0200
Fix a remaining display error for 2.2.9. That version has been tested OK in a lab.


r3304@localhost (orig r2298): bruno | 2009-07-23 18:18:27 +0200

  • Remove memory leak for the last modification


r3308@localhost (orig r2302): bruno | 2009-07-24 21:18:50 +0200
Improve logging of mountlist.txt


r3310@localhost (orig r2304): bruno | 2009-07-27 19:45:10 +0200

  • popup_and_get_string needs an allocated buffer for the moment so fixing the calls with dyn. ones
  • Fix a bug in mem.c for mr_strcat, which wasn't modifying the right pointer level


r3311@localhost (orig r2305): bruno | 2009-07-27 19:49:35 +0200
Avoid a memory leak in the previous patch


r3314@localhost (orig r2308): bruno | 2009-07-27 20:59:06 +0200
Fix a bug in mr_strcat backported from 2.2.10. Should solve our seg faults.


r3315@localhost (orig r2309): bruno | 2009-07-28 02:14:23 +0200
Cosmetic changes to allow for quality to not giv false positive


r3343@localhost (orig r2311): bruno | 2009-08-18 02:13:43 +0200
Fix for initramfs detection with 2.6.30 (Hugo Vanwoerkom hvw59601_at_care2.com)


r3367@localhost (orig r2333): bruno | 2009-08-18 16:26:26 +0200
Adds a precision for -U option in man page on raw device usage and not partition name


r3373@localhost (orig r2336): bruno | 2009-08-20 17:37:41 +0200

  • Precise the combined usage of -E and -I in mondoarchive (Case 4601017223)


r3379@localhost (orig r2342): bruno | 2009-08-21 16:27:10 +0200


r3383@localhost (orig r2344): bruno | 2009-08-24 13:37:09 +0200

r3382@localhost: bruno | 2009-08-24 13:30:25 +0200
In NFS mode also propose access to expert, interactive, ... entry at boot prompt


r3388@localhost (orig r2346): bruno | 2009-08-27 11:41:16 +0200
Adds fdisk -l result in Log File at restore time


r3389@localhost (orig r2347): bruno | 2009-08-27 13:51:00 +0200

  • Solve tmp dir creation which sometimes was trying to create /%xx dirs. Should fix #293 for good


r3390@localhost (orig r2348): bruno | 2009-08-27 13:54:25 +0200
Improve logging (minor)


r3394@localhost (orig r2350): bruno | 2009-08-28 02:24:19 +0200
Change inerface of evaluate_mountlist and spread_flaws_across_three_lines in order to solve bugs linked to strings management in these functions. May fix a restoration crash seen by some customers


r3397@localhost (orig r2353): bruno | 2009-08-28 19:03:45 +0200

  • Addition of a nomd option to avoid starting mdadm
  • mpath is now already started if there was a mpath entry in mountlist


r3399@localhost (orig r2355): bruno | 2009-08-29 00:56:50 +0200
Remove function spread_flaws_across_three_lines and expand it at the single place where it was useful, and fix memory allocation issues in it.


r3402@localhost (orig r2358): bruno | 2009-09-01 19:02:35 +0200
P2V doc updated (Lester Wade lester.wade_at_hp.com)


r3404@localhost (orig r2360): bruno | 2009-09-01 19:26:53 +0200
Website update to refer to new P2V document


r3405@localhost (orig r2361): bruno | 2009-09-03 13:54:25 +0200

  • Fix a case where the NFS dir in restore mode was mounted rw (linked to bug #291 could create a huge problem)


r3407@localhost (orig r2363): bruno | 2009-09-03 14:46:46 +0200
More verbose at installation of additional tools


r3409@localhost (orig r2365): bruno | 2009-09-03 18:08:32 +0200

  • New update from Lester Wade (lester.wade_at_hp.com) for P2V doc


r3410@localhost (orig r2366): bruno | 2009-09-05 01:28:18 +0200
place the code of mondo_makefilelist before its call



r3411@localhost (orig r2367): bruno | 2009-09-06 01:51:26 +0200

  • Advertising for project-builder on the website added


r3412@localhost (orig r2368): bruno | 2009-09-07 15:36:23 +0200
Fix compilation issue


r3413@localhost (orig r2369): bruno | 2009-09-07 18:03:40 +0200
Another compilation issue fixed.


r3415@localhost (orig r2371): bruno | 2009-09-08 13:40:25 +0200

  • Fix a problem a error detection in evaluate_mountlist which casued nuke mode to abort. Error string should also be better now.


r3417@localhost (orig r2373): bruno | 2009-09-08 13:55:31 +0200
Avoid asking the Prefix name in NFS mode twice


r3418@localhost (orig r2374): bruno | 2009-09-08 20:04:07 +0200

  • Try to fix garbled screen progression in text mode based on 2.2.10 modifications which are working


r3424@localhost (orig r2380): bruno | 2009-09-09 20:30:47 +0200

  • Change NFS support into a NetFS support to allow for multiple protocol in addition to NFS (NEEDS TESTING)
  • Better logging to detect a potential nuke issue


r3425@localhost (orig r2381): bruno | 2009-09-10 02:05:55 +0200
Fix a missing param for sshfs call


r3428@localhost (orig r2384): bruno | 2009-09-10 13:02:56 +0200

  • Remove separate function look_for_duplicate_mountpoints used only once and whose interface created problems with caller


r3430@localhost (orig r2386): bruno | 2009-09-10 16:06:52 +0200
Be compatible on backup type by making old nfs recognized as netfs and proto forced


r3431@localhost (orig r2387): bruno | 2009-09-10 18:40:47 +0200
Fix a problem in netfs analysis in mondoarchive


r3432@localhost (orig r2388): bruno | 2009-09-10 20:25:13 +0200
Fix mondoarchive CLI analysis for NETFS type of requests


r3434@localhost (orig r2390): bruno | 2009-09-11 03:05:20 +0200

  • Adds ext3 initrd support for 2.6.30


r3437@localhost (orig r2393): bruno | 2009-09-11 11:56:52 +0200

  • Tries to add support for bzip2 and lzma initramfs (preliminary, not tested) for 2.6.30


r3438@localhost (orig r2394): bruno | 2009-09-12 02:53:02 +0200
Fix interface of evaluate_mountlist (remove 2nd param useless) and fix nuke mode which wasn't working.


r3441@localhost (orig r2397): bruno | 2009-09-14 18:54:34 +0200
Fix a format issue in text mode on percentage


r3452@localhost (orig r2398): bruno | 2009-09-15 16:00:13 +0200

  • Fix a bug where flaws_str could be NULL and wasn't tested correctly.


r3453@localhost (orig r2399): bruno | 2009-09-15 19:28:39 +0200

  • Use protocol name when displaying restore progress instead of netfs
  • Ask for network protocol name at restore time


r3455@localhost (orig r2401): bruno | 2009-09-15 19:34:19 +0200
Wrong structure member name was used


r3456@localhost (orig r2402): bruno | 2009-09-16 13:04:17 +0200
Use dir for shell related commands and dir1 for C related actions in open_and_list_dir to avoid missing some files with { in names e.g.


r3457@localhost (orig r2403): bruno | 2009-09-16 16:32:03 +0200

  • At restore time read the netfs protocol in the conf file


r3462@localhost (orig r2408): bruno | 2009-09-18 15:17:08 +0200
Remove useless script


r3463@localhost (orig r2409): bruno | 2009-09-18 15:25:35 +0200

  • Split deplist.txt into multiple conf files under deplist.d in the conf dir. This will allow to have a minimal.conf file for initrd content to analyze to improve support of new embedded feature in the future (sshfs, live install). The other conf files contain the additional commands to put in the all.tar.gz. For the moment, mindi is still working the same. THis infra will allow that support in a near future. deplist.txt is now reserved for the admin additional commands.


r3465@localhost (orig r2410): bruno | 2009-09-18 19:10:54 +0200

  • Better list of mandatory tools
  • Adds fuse and sshfs support in initrd


r3466@localhost (orig r2411): bruno | 2009-09-18 20:32:47 +0200
sshfs also needs ssh at restore time in initrd


r3478@localhost (orig r2418): bruno | 2009-09-23 23:22:39 +0200
Modify getfattr call to have all extended attributes, including non user ones. (patch from Kevin Ritzenthaler Kevin.Ritzenthaler_at_hp.com) and fix #357


r3479@localhost (orig r2419): bruno | 2009-09-23 23:50:34 +0200
star only supports ACL when used with exustar mode. Fix #356.


r3482@localhost (orig r2422): bruno | 2009-09-24 16:53:24 +0200

  • Adds support for bnx2x (BL 460 G6) and auth_rpcgss (Debian 2.6.31)


r3485@localhost (orig r2423): bruno | 2009-09-25 16:38:40 +0200
Fix an issue in is_this_device_mounted (string freed before last usage)


r3486@localhost (orig r2424): bruno | 2009-09-25 18:44:01 +0200

  • analyze-my-lvm now removes excluded devices from list coming from mondoarchive
  • new mr_make_devlist_from_pathlist which handle the new bkpinfo->exclude_devs field containing the excluded devices and remove corresponding code from libmondo-cli.c
  • Move DSF code into libmondo-devices.c for coherency, and only the previous function is made externally available
  • Remove dev_to_exclude in libmondo-archive.c which wasn't working correctly and replace it with bkpinfo->exclude_devs


r3487@localhost (orig r2425): bruno | 2009-09-25 18:58:23 +0200

  • Improving ssh support at restore time by providing a shadow file


r3489@localhost (orig r2426): bruno | 2009-09-25 19:42:09 +0200

  • Attempt to stay backward compatible without protocol for -n option


r3490@localhost (orig r2427): bruno | 2009-09-28 02:08:06 +0200
Avoids null param for excludes_devs for mindi call


r3492@localhost (orig r2429): bruno | 2009-09-28 11:46:16 +0200

  • Simplify GetInitrdFilesystemToUse which doesn't need to detect everything, but just know if it's initramfs (new mode) or a compressed FS ext2/3 (older mode) as initrd is anyway re-made by mindi. Should fix #353


r3494@localhost (orig r2431): bruno | 2009-09-28 13:16:18 +0200

  • Use only the AWK veriable everywhere and not the awk command


r3495@localhost (orig r2432): bruno | 2009-09-28 14:16:31 +0200
Warning emited in case of duplicate mountpoints or devices in fstab found


r3496@localhost (orig r2433): bruno | 2009-09-28 15:55:17 +0200
ssh in the restore env needs some dlopened libs (libnss_compat|files)


r3497@localhost (orig r2434): bruno | 2009-09-28 16:33:14 +0200
Compiler warning fixed


r3498@localhost (orig r2435): bruno | 2009-09-28 17:55:26 +0200
Improve user management for NetFS cases


r3499@localhost (orig r2436): bruno | 2009-09-29 01:48:32 +0200

  • Improve deplist.d/* files
  • adds libnss for ssh support in boot disk
  • Solve a memory management issue in DSF module (strtok => mr_strtok)
  • DSF now also supports partitions in addition to full disks
  • Adds debug in open_and_list_dir


r3500@localhost (orig r2437): bruno | 2009-09-29 10:41:56 +0200

  • Fix udev support in init for Mandriva 2009.1 (udevadm settle is blocking)


r3501@localhost (orig r2438): bruno | 2009-09-29 14:41:36 +0200

  • Improvements on sshfs/ssh management in restore mode
  • Include now all minimal requirements for sshfs


r3502@localhost (orig r2439): bruno | 2009-09-29 18:46:08 +0200

  • Avoids error message if some ssh conf files do not exist


r3503@localhost (orig r2440): bruno | 2009-09-29 18:57:13 +0200

  • Avoids comment analysis in the new code handling deplist.d


r3504@localhost (orig r2441): bruno | 2009-09-29 19:34:34 +0200

  • fuse device is needed at restore time for sshfs


r3505@localhost (orig r2442): bruno | 2009-09-29 20:02:36 +0200

  • Improves udev timeout handling


r3506@localhost (orig r2443): bruno | 2009-09-29 20:43:38 +0200

  • priority given to env var for tmpdir
  • fuse FS excluded from tmpdir computation


r3518@localhost (orig r2447): bruno | 2009-10-04 01:58:08 +0200

  • Iprove USB log in case of error by adding the conf file


r3519@localhost (orig r2448): bruno | 2009-10-05 11:06:13 +0200


r3520@localhost (orig r2449): bruno | 2009-10-06 01:10:35 +0200

  • Adds support for grub2 conf file grub.cfg in addition to menu.lst


r3521@localhost (orig r2450): bruno | 2009-10-06 01:24:02 +0200

  • Fix a mr_asprintf usage without & causing a seg fault.


r3523@localhost (orig r2452): bruno | 2009-10-06 12:47:56 +0200
CIFS mounts shouldn't be part of the mountlist analysis (should help solving #288)


r3524@localhost (orig r2453): bruno | 2009-10-07 10:17:03 +0200

  • Fix a bug in handling of -E option with real devices (bad report in function mr_make_devlist_from_pathlist of the test between -E and -I)


r3525@localhost (orig r2454): bruno | 2009-10-07 10:19:02 +0200

  • Fix an error in the test for grub conf files (or used instead of and)


r3526@localhost (orig r2455): bruno | 2009-10-07 16:14:59 +0200
afio is under /bin on Debian


r3527@localhost (orig r2456): bruno | 2009-10-07 17:31:26 +0200

  • Adds support for libcrc32c (needed by bnx2x)


r3532@localhost (orig r2457): bruno | 2009-10-09 13:33:44 +0200

  • Apply path from Matthew Cline (matt_at_nightrealms.com) in order to fix #359


r3533@localhost (orig r2458): bruno | 2009-10-09 13:41:02 +0200
Adds a conf file example for mindi and fix #360


r3535@localhost (orig r2459): bruno | 2009-10-09 15:13:01 +0200
MOde of conf file


r3546@localhost (orig r2461): bruno | 2009-10-14 01:12:24 +0200

  • umount freshly created VFAT partition on USB key as Ubunu has an automounter mounting it as soon as created (Steffen Neumann sneumann_at_ipb-halle.de)


r3566@localhost (orig r2463): bruno | 2009-10-26 01:34:16 +0100

  • Reset an error counter before blanking a DVD to avoid always returning an error (Vincent Raman vincent.raman_at_macqel.eu)


r3567@localhost (orig r2464): bruno | 2009-10-26 13:57:14 +0100
bzip2 is under /bin on Debian


r3568@localhost (orig r2465): bruno | 2009-10-28 01:46:30 +0100
some distro hold lvm commands under /usr/sbin


r3595@localhost (orig r2469): bruno | 2009-11-10 12:22:10 +0100
/dev/shm is now part of the default exclude list


r3596@localhost (orig r2470): bruno | 2009-11-10 12:32:40 +0100
Remove useless pb_log and MONDO_TRACEFILE


r3597@localhost (orig r2471): bruno | 2009-11-10 12:57:58 +0100
Improve analysis of kernel modules by printing whether it's a live or extra module which has not been found (Matthew Cline) as reported in #362


r3598@localhost (orig r2472): bruno | 2009-11-10 13:21:46 +0100

  • Default to DVD size when in iso or netfs mode


r3599@localhost (orig r2473): bruno | 2009-11-10 14:13:10 +0100

  • Fix #363 where exclude_paths was extended up to memory limit dumping core


r3600@localhost (orig r2474): bruno | 2009-11-10 14:31:14 +0100

  • Update deplist for Debian support


r3602@localhost (orig r2476): bruno | 2009-11-11 02:44:42 +0100

  • small improvement for loging in USB case


r3603@localhost (orig r2477): bruno | 2009-11-11 13:29:27 +0100

  • Adds a nolvm boot option at restore time


r3604@localhost (orig r2478): bruno | 2009-11-11 19:54:51 +0100

  • Fix #367 - the for loop doesn't make any test now, as it was computed before entering the loop, leading to an error, and was also made inside the loop anyway.


r3605@localhost (orig r2479): bruno | 2009-11-12 00:32:45 +0100

  • Add support for diskdumplib driver useful for RHEL 3 and IBM xseries 336


r3606@localhost (orig r2480): bruno | 2009-11-12 01:09:40 +0100

  • If using nolvm, mondorestore should also not nalyze and handle i-want-my-lvm


r3608@localhost (orig r2482): bruno | 2009-11-14 12:54:11 +0100
Fix bunzip2 on debian as well


r3610@localhost (orig r2484): bruno | 2009-11-15 00:44:19 +0100

  • Adds support for variable serial port console, with defalut to /dev/ttyS0, and a boot param to change it with serial=/dev/ttySx


r3615@localhost (orig r2485): bruno | 2009-11-15 01:34:33 +0100

r3614@localhost: bruno | 2009-11-15 01:34:12 +0100
Adds a space in exclude paths


r3623@localhost (orig r2487): bruno | 2009-11-18 20:41:40 +0100

r3620@localhost: bruno | 2009-11-18 10:31:36 +0100

  • Only link /dev/tty to serial port when there is indeed a serial port. If not breaks mondorestore on normal console


r3631@localhost (orig r2490): bruno | 2009-11-24 01:48:29 +0100
Put news below in the main page to make it more readable


r3648@localhost (orig r2492): bruno | 2009-11-25 23:50:13 +0100

r3647@localhost: bruno | 2009-11-25 23:49:11 +0100

  • Add warning for -f and SW Raid as in 2.2.10


r3650@localhost (orig r2493): bruno | 2009-11-26 00:19:52 +0100

r3649@localhost: bruno | 2009-11-26 00:18:27 +0100

  • Addition of the german translation made by Magnus Rasche (Magnus.rasche_at_gmx.de) and Website inclusion


r3652@localhost (orig r2495): bruno | 2009-11-27 15:55:55 +0100
cosmetic display fix
r3659@localhost (orig r2498): bruno | 2009-12-05 17:53:03 +0100
nfsopt restore boot time option added to support custom mount options for network restore


r3684@localhost (orig r2501): bruno | 2009-12-17 00:35:08 +0100
Fix #375 mondo will segfault if the partition in sensibly_set_tmpdir_and_scratchdir() is read-only (cylau)


r3685@localhost (orig r2502): bruno | 2009-12-17 01:02:47 +0100

  • Fix an issue in the function listing kernel modules when not found


r3686@localhost (orig r2503): bruno | 2009-12-17 01:15:01 +0100
Adds scsi_dump_register to mindi SCSI_MODS for RHEL3 + IBM servers


r3701@localhost (orig r2504): bruno | 2009-12-23 02:24:33 +0100

  • Addition of the Lab for Mondorescue


r3702@localhost (orig r2505): bruno | 2009-12-23 02:41:17 +0100
Web site update for Lab MondoRescue delivery


r3706@localhost (orig r2506): bruno | 2010-01-04 11:31:53 +0100

  • Fix a bug when isodir is / only when splitting it in iso_path and iso_mnt


r3707@localhost (orig r2507): bruno | 2010-01-04 13:22:49 +0100

  • Fix #377: Segfault in pause_and_ask_for_cdr() (ggeens)


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