Changeset 3879 in MondoRescue for branches/3.3/mondo/src/mondorestore/mondo-rstr-newt.c
- Timestamp:
- Mar 9, 2024, 3:10:04 AM (3 months ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/3.3/mondo/src/mondorestore/mondo-rstr-newt.c
r3856 r3879 10 10 #endif 11 11 12 #include "mondo-rstr-newt.h" 12 #include "my-stuff.h" 13 #include "mondostructures.h" 13 14 #include "mr_mem.h" 14 15 #include "mr_str.h" 16 #include "libmondo-raid-EXT.h" 17 #include "libmondo-mountlist-EXT.h" 18 #include "libmondo-string-EXT.h" 19 #include "libmondo-tools-EXT.h" 20 #include "libmondo-files-EXT.h" 21 #include "libmondo-filelist-EXT.h" 22 #include "newt-specific-EXT.h" 15 23 16 24 //static char cvsid[] = "$Id$"; … … 18 26 extern bool popup_with_buttons(char *p, char *button1, char *button2); 19 27 extern char err_log_lines[NOOF_ERR_LINES][MAX_STR_LEN]; 28 29 static char g_strings_of_flist_window[ARBITRARY_MAXIMUM][MAX_STR_LEN]; 30 static bool g_is_path_selected[ARBITRARY_MAXIMUM]; 31 static bool g_is_path_expanded[ARBITRARY_MAXIMUM]; 32 static char tmpnopath[MAX_STR_LEN + 2]; 33 static char tmpprevpath[MAX_STR_LEN + 2]; 34 35 // from mondo-rstr-mountlist.c 36 extern void make_list_of_unallocated_raid_partitions(struct mountlist_itself *, struct mountlist_itself *, struct raidlist_itself *); 37 38 extern bool g_text_mode; 39 20 40 21 41 /** … … 36 56 37 57 /** 38 * @addtogroup restoreGuiGroup 39 * @{ 40 */ 58 * Redraw the list of unallocated RAID partitions. 59 * @param unallocated_raid_partitions The mountlist containing unallocated RAID partitions. 60 * @param keylist The list of keys for @p listbox. 61 * @param listbox The Newt listbox component to redraw. 62 * @ingroup restoreGuiDisklist 63 */ 64 void redraw_unallocpartnslist(struct mountlist_itself 65 *unallocated_raid_partitions, 66 void *keylist[ARBITRARY_MAXIMUM], 67 newtComponent listbox) 68 { 69 70 /** long *************************************************************/ 71 long i = 0; 72 73 /** buffers **********************************************************/ 74 char tmp[MAX_STR_LEN]; 75 76 assert(unallocated_raid_partitions != NULL); 77 assert(keylist != NULL); 78 assert(listbox != NULL); 79 80 newtListboxClear(listbox); 81 for (i = 0; i < ARBITRARY_MAXIMUM; i++) { 82 keylist[i] = (void *) i; 83 } 84 for (i = 0; i < unallocated_raid_partitions->entries; i++) { 85 sprintf(tmp, "%-22s %8lld", 86 unallocated_raid_partitions->el[i].device, 87 unallocated_raid_partitions->el[i].size / 1024L); 88 newtListboxAppendEntry(listbox, tmp, keylist[i]); 89 } 90 } 91 92 93 /** 94 * Find the next free location to place a disk in @p disklist. 95 * @param disklist The disklist to operate on. 96 * @return The next free location (starting from 0). 97 * @ingroup restoreGuiDisklist 98 */ 99 int find_next_free_index_in_disklist(struct list_of_disks *disklist) 100 { 101 102 /** int ***************************************************************/ 103 int index = -1; 104 int pos = 0; 105 106 /** bool **************************************************************/ 107 bool done; 108 109 assert(disklist != NULL); 110 111 for (done = FALSE; !done;) { 112 for (pos = 0; 113 pos < disklist->entries && disklist->el[pos].index <= index; 114 pos++); 115 if (pos >= disklist->entries) { 116 done = TRUE; 117 } else { 118 index = disklist->el[pos].index; 119 } 120 } 121 return (index + 1); 122 } 123 124 125 41 126 /** 42 127 * Add an entry in @p disklist from the list in @p unallocated_raid_partitions. … … 118 203 119 204 120 121 122 /** 123 * Add an entry to @p mountlist. 124 * @param mountlist The mountlist to add an entry to. 125 * @param raidlist The raidlist that accompanies @p mountlist. 126 * @param listbox The listbox component in the mountlist editor. 127 * @param currline The line selected in @p listbox. 205 /** 206 * Locate @p device in @p raidlist. 207 * @param raidlist The raidlist ot search in. 208 * @param device The RAID device to search for. 209 * @return The index of the device, or -1 if it could not be found. 210 * @ingroup restoreGuiMountlist 211 */ 212 int 213 find_raid_device_in_raidlist(struct raidlist_itself *raidlist, 214 char *device) 215 { 216 217 /** int ***************************************************************/ 218 int i = 0; 219 #ifdef __FreeBSD__ 220 char *vdev = NULL; 221 int res = 0; 222 #else 223 // Linux 224 #endif 225 226 assert(raidlist != NULL); 227 assert_string_is_neither_NULL_nor_zerolength(device); 228 229 #ifdef __FreeBSD__ 230 for (i = 0; i < raidlist->entries; i++) { 231 mr_asprintf(vdev, "/dev/vinum/%s", raidlist->el[i].volname); 232 res = strcmp(device, vdev); 233 mr_free(vdev); 234 235 if (!res) 236 break; 237 } 238 #else 239 240 for (i = 0; 241 strcmp(raidlist->el[i].raid_device, device) 242 && i < raidlist->entries; i++); 243 #endif 244 if (i == raidlist->entries) { 245 return (-1); 246 } else { 247 return (i); 248 } 249 } 250 251 252 /** 253 * Redraw the disklist. 254 * @param disklist The disklist to read from. 128 255 * @param keylist The list of keys for @p listbox. 256 * @param listbox The Newt listbox component to redraw. 257 * @ingroup restoreGuiDisklist 258 */ 259 void 260 redraw_disklist(struct list_of_disks *disklist, 261 void *keylist[ARBITRARY_MAXIMUM], newtComponent listbox) 262 { 263 264 /** long **************************************************************/ 265 long i = 0; 266 char *tmp = NULL; 267 268 assert(disklist != NULL); 269 assert(keylist != NULL); 270 assert(listbox != NULL); 271 272 newtListboxClear(listbox); 273 274 for (i = 0; i < ARBITRARY_MAXIMUM; i++) { 275 keylist[i] = (void *) i; 276 } 277 for (i = 0; i < disklist->entries; i++) { 278 tmp = disklist_entry_to_string(disklist, i); 279 newtListboxAppendEntry(listbox, tmp, keylist[i]); 280 mr_free(tmp); 281 } 282 } 283 284 285 286 /** 287 * Delete entry number @p currline from @p disklist. 288 * @param disklist The disklist to remove the entry from. 289 * @param raid_device The RAID device containing the partition we're removing. 290 * Used only in the popup "are you sure?" box. 291 * @param currline The line number (starting from 0) of the item to delete. 292 * @ingroup restoreGuiDisklist 293 */ 294 void 295 delete_disklist_entry(struct list_of_disks *disklist, char *raid_device, 296 int currline) 297 { 298 299 /** int ***************************************************************/ 300 int pos = 0; 301 int res = 0; 302 303 /** buffers ***********************************************************/ 304 char *tmp = NULL; 305 306 assert(disklist != NULL); 307 assert_string_is_neither_NULL_nor_zerolength(raid_device); 308 309 mr_asprintf(tmp, "Delete %s from RAID device %s - are you sure?", disklist->el[currline].device, raid_device); 310 res = ask_me_yes_or_no(tmp); 311 mr_free(tmp); 312 313 if (!res) { 314 return; 315 } 316 for (pos = currline; pos < disklist->entries - 1; pos++) { 317 strcpy(disklist->el[pos].device, disklist->el[pos + 1].device); 318 } 319 disklist->entries--; 320 } 321 322 323 324 /** 325 * Select the RAID disks to use in @p raidrec. 326 * @param mountlist_dontedit The mountlist (will not be edited). 327 * @param raidlist The raidlist to modify. 328 * @param raidrec The RAID device record in @p raidlist to work on. 329 * @param description_of_list The type of disks we're selecting (e.g. "data"). 330 * @param disklist The disklist to put the user-selected disks in. 129 331 * @ingroup restoreGuiMountlist 130 332 */ 131 333 void 132 add_mountlist_entry(struct mountlist_itself *mountlist, 133 struct raidlist_itself *raidlist, 134 newtComponent listbox, int currline, void *keylist[]) 334 select_raid_disks(struct mountlist_itself *mountlist_dontedit, 335 struct raidlist_itself *raidlist, 336 struct raid_device_record *raidrec, 337 char *description_of_list, 338 struct list_of_disks *disklist) 339 { 340 void *curr_choice; 341 342 /** ??? ***************************************************************/ 343 344 /** structures ********************************************************/ 345 struct raidlist_itself *bkp_raidlist; 346 struct raid_device_record *bkp_raidrec; 347 struct list_of_disks *bkp_disklist; 348 struct mountlist_itself *unallocated_raid_partitions; 349 350 /** newt **************************************************************/ 351 newtComponent myForm = NULL; 352 newtComponent bAdd = NULL; 353 newtComponent bDelete = NULL; 354 newtComponent bOK = NULL; 355 newtComponent bCancel = NULL; 356 newtComponent b_res = NULL; 357 newtComponent partitionsListbox = NULL; 358 newtComponent headerMsg = NULL; 359 360 /** buffers **********************************************************/ 361 void *keylist[ARBITRARY_MAXIMUM]; 362 char *tmp = NULL; 363 char *help_text = NULL; 364 char *title_of_window = NULL; 365 char sz_res[MAX_STR_LEN]; 366 char *header_text = NULL; 367 368 /** int **************************************************************/ 369 int i = 0; 370 int currline = 0; 371 372 assert(mountlist_dontedit != NULL); 373 assert(raidlist != NULL); 374 assert(raidrec != NULL); 375 assert(description_of_list != NULL); 376 assert(disklist != NULL); 377 378 log_it("malloc'ing"); 379 bkp_raidrec = mr_malloc(sizeof(struct raid_device_record)); 380 bkp_disklist = mr_malloc(sizeof(struct list_of_disks)); 381 bkp_raidlist = mr_malloc(sizeof(struct raidlist_itself)); 382 unallocated_raid_partitions = mr_malloc(sizeof(struct mountlist_itself)); 383 384 memcpy((void *) bkp_raidlist, (void *) raidlist, sizeof(struct raidlist_itself)); 385 memcpy((void *) bkp_raidrec, (void *) raidrec, sizeof(struct raid_device_record)); 386 memcpy((void *) bkp_disklist, (void *) disklist, sizeof(struct list_of_disks)); 387 388 log_it("Post-malloc"); 389 mr_asprintf(help_text, " Edit this RAID device's list of partitions. Choose OK or Cancel when done."); 390 mr_asprintf(header_text, "%-24s %s", "Device", "Index"); 391 mr_asprintf(title_of_window, "%s contains...", raidrec->raid_device); 392 newtPushHelpLine(help_text); 393 for (b_res = (newtComponent) 12345; b_res != bOK && b_res != bCancel;) { 394 headerMsg = newtLabel(1, 1, header_text); 395 partitionsListbox = 396 newtListbox(1, 2, 6, NEWT_FLAG_SCROLL | NEWT_FLAG_RETURNEXIT); 397 redraw_disklist(disklist, keylist, partitionsListbox); 398 i = 1; 399 bAdd = newtCompactButton(i, 9, " Add "); 400 bDelete = newtCompactButton(i += 8, 9, "Delete"); 401 bOK = newtCompactButton(i += 9, 9, " OK "); 402 bCancel = newtCompactButton(i += 9, 9, "Cancel"); 403 newtOpenWindow(21, 7, 38, 10, title_of_window); 404 myForm = newtForm(NULL, NULL, 0); 405 if (disklist->entries == 0) { 406 newtFormAddComponents(myForm, headerMsg, bAdd, bDelete, bOK, 407 bCancel, NULL); 408 } else { 409 newtFormAddComponents(myForm, headerMsg, partitionsListbox, 410 bAdd, bDelete, bOK, bCancel, NULL); 411 } 412 b_res = newtRunForm(myForm); 413 if (b_res == bOK || b_res == bCancel) { /* do nothing */ 414 // That's OK. At the end of this subroutine (after this do/while loop), 415 // we'll throw away the changes if Cancel was pushed. 416 } else { 417 curr_choice = newtListboxGetCurrent(partitionsListbox); 418 for (i = 0; i < disklist->entries && keylist[i] != curr_choice; 419 i++); 420 if (i == disklist->entries && disklist->entries > 0) { 421 log_to_screen("I don't know what that button does!"); 422 } else { 423 currline = i; 424 if (b_res == bAdd) { 425 log_it("Making list of unallocated RAID slices"); 426 make_list_of_unallocated_raid_partitions 427 (unallocated_raid_partitions, mountlist_dontedit, 428 raidlist); 429 if (unallocated_raid_partitions->entries <= 0) { 430 popup_and_OK 431 ("There are no unallocated partitions marked for RAID."); 432 } else { 433 log_it 434 ("Done. The user may add one or more of the above to RAID device"); 435 add_disklist_entry(disklist, raidrec->raid_device, 436 unallocated_raid_partitions); 437 log_it("I have finished adding a disklist entry."); 438 redraw_disklist(disklist, keylist, 439 partitionsListbox); 440 } 441 } else if (b_res == bDelete) { 442 delete_disklist_entry(disklist, raidrec->raid_device, 443 currline); 444 redraw_disklist(disklist, keylist, partitionsListbox); 445 } else { 446 mr_asprintf(tmp, "%s's index is %d. What should it be?", raidrec->raid_device, disklist->el[currline].index); 447 sprintf(sz_res, "%d", disklist->el[currline].index); 448 if (popup_and_get_string("Set index", tmp, sz_res, 10)) { 449 disklist->el[currline].index = atoi(sz_res); 450 } 451 mr_free(tmp); 452 453 redraw_disklist(disklist, keylist, partitionsListbox); 454 } 455 } 456 } 457 newtFormDestroy(myForm); 458 newtPopWindow(); 459 } 460 newtPopHelpLine(); 461 mr_free(help_text); 462 mr_free(header_text); 463 mr_free(title_of_window); 464 465 if (b_res == bCancel) { 466 memcpy((void *) raidlist, (void *) bkp_raidlist, sizeof(struct raidlist_itself)); 467 memcpy((void *) raidrec, (void *) bkp_raidrec, sizeof(struct raid_device_record)); 468 memcpy((void *) disklist, (void *) bkp_disklist, sizeof(struct list_of_disks)); 469 } 470 mr_free(bkp_raidrec); 471 mr_free(bkp_disklist); 472 mr_free(bkp_raidlist); 473 mr_free(unallocated_raid_partitions); 474 } 475 476 477 #ifndef __FreeBSD__ 478 /** 479 * Insert the RAID variables not stored in the "additional RAID variables" list there too. 480 * @param raidrec The RAID device record to operate on. 481 * @ingroup restoreGuiVarslist 482 */ 483 void insert_essential_additionalvars(struct raid_device_record *raidrec) 135 484 { 136 485 137 486 /** int **************************************************************/ 487 int items = 0; 488 489 assert(raidrec != NULL); 490 491 items = raidrec->additional_vars.entries; 492 write_variableINT_to_raid_var_line(raidrec, items++, 493 "persistent-superblock", 494 raidrec->persistent_superblock); 495 write_variableINT_to_raid_var_line(raidrec, items++, "chunk-size", 496 raidrec->chunk_size); 497 raidrec->additional_vars.entries = items; 498 } 499 500 #endif 501 502 503 #ifndef __FreeBSD__ 504 /** 505 * Redraw the list of additional RAID variables. 506 * @param additional_vars The list of additional RAID varibals. 507 * @param keylist The list of keys for @p listbox. 508 * @param listbox The Newt listbox component to redraw. 509 * @ingroup restoreGuiVarslist 510 */ 511 void 512 redraw_varslist(struct additional_raid_variables *additional_vars, 513 void *keylist[], newtComponent listbox) 514 { 515 /** long ************************************************************/ 516 long i = 0; 517 518 /** buffers *********************************************************/ 519 char tmp[MAX_STR_LEN]; 520 521 assert(additional_vars != NULL); 522 assert(keylist != NULL); 523 assert(listbox != NULL); 524 525 newtListboxClear(listbox); 526 527 for (i = 0; i < ARBITRARY_MAXIMUM; i++) { 528 keylist[i] = (void *) i; 529 } 530 for (i = 0; i < additional_vars->entries; i++) { 531 sprintf(tmp, "%-32s %-8s", additional_vars->el[i].label, 532 additional_vars->el[i].value); 533 newtListboxAppendEntry(listbox, tmp, keylist[i]); 534 } 535 } 536 537 #endif 538 539 540 #ifndef __FreeBSD__ 541 /** 542 * Remove variable @p label from the RAID variables list in @p raidrec. 543 * @param raidrec The RAID device record to remove the variable from. 544 * @param label The variable name to remove. 545 * @return The value of the variable removed. 546 * @ingroup restoreUtilityGroup 547 */ 548 int 549 read_variableINT_and_remove_from_raidvars(struct 550 OSSWAP (raid_device_record, 551 vinum_volume) * raidrec, 552 char *label) 553 { 554 /** int ***************************************************************/ 138 555 int i = 0; 139 140 /** newt *************************************************************/ 141 newtComponent myForm; 556 int res = 0; 557 558 559 assert(raidrec != NULL); 560 assert(label != NULL); 561 562 for (i = 0; 563 i < raidrec->additional_vars.entries 564 && strcmp(raidrec->additional_vars.el[i].label, label); i++); 565 if (i == raidrec->additional_vars.entries) { 566 res = -1; 567 } else { 568 res = atoi(raidrec->additional_vars.el[i].value); 569 for (i++; i < raidrec->additional_vars.entries; i++) { 570 memcpy((void *) &raidrec->additional_vars.el[i - 1], 571 (void *) &raidrec->additional_vars.el[i], 572 sizeof(struct raid_var_line)); 573 } 574 raidrec->additional_vars.entries--; 575 } 576 return (res); 577 } 578 #endif 579 580 #ifndef __FreeBSD__ 581 /** 582 * Remove the essential RAID variables from the "additional variables" section. 583 * If they have been changed, set them in their normal locations too. 584 * @param raidrec The RAID device record to operate on. 585 * @ingroup restoreUtilityVarslist 586 */ 587 void remove_essential_additionalvars(struct raid_device_record *raidrec) 588 { 589 590 /** int **************************************************************/ 591 int res = 0; 592 593 assert(raidrec != NULL); 594 595 res = 596 read_variableINT_and_remove_from_raidvars(raidrec, 597 "persistent-superblock"); 598 if (res > 0) { 599 raidrec->persistent_superblock = res; 600 } 601 res = read_variableINT_and_remove_from_raidvars(raidrec, "chunk-size"); 602 if (res > 0) { 603 raidrec->chunk_size = res; 604 } 605 res = read_variableINT_and_remove_from_raidvars(raidrec, "block-size"); 606 } 607 608 #endif 609 610 611 612 /** 613 * Choose the RAID level for the RAID device record in @p raidrec. 614 * @param raidrec The RAID device record to set the RAID level of. 615 * @ingroup restoreGuiMountlist 616 */ 617 void 618 choose_raid_level(struct OSSWAP (raid_device_record, vinum_plex) * raidrec) 619 { 620 621 #ifdef __FreeBSD__ 622 623 /** int ***************************************************************/ 624 int res = 0; 625 int out = 0; 626 627 /** buffers ***********************************************************/ 628 char tmp[MAX_STR_LEN]; 629 char *prompt = NULL; 630 char sz[MAX_STR_LEN]; 631 632 mr_asprintf(prompt, "Please enter the RAID level you want. (concat, striped, raid5)"); 633 if (raidrec->raidlevel == -1) { 634 strcpy(tmp, "concat"); 635 } else if (raidrec->raidlevel == 0) { 636 strcpy(tmp, "striped"); 637 } else { 638 sprintf(tmp, "raid%i", raidrec->raidlevel); 639 } 640 for (out = 999; out == 999;) { 641 res = popup_and_get_string("Specify RAID level", prompt, tmp, 10); 642 if (!res) { 643 mr_free(prompt); 644 return; 645 } 646 strip_spaces(tmp); 647 if (tmp[0] == '[' && tmp[strlen(tmp) - 1] == ']') { 648 strcpy(sz, tmp); 649 strncpy(tmp, sz + 1, strlen(sz) - 2); 650 tmp[strlen(sz) - 2] = '\0'; 651 } 652 if (!strcmp(tmp, "concat")) { 653 out = -1; 654 } else if (!strcmp(tmp, "striped")) { 655 out = 0; 656 } else if (!strcmp(tmp, "raid5")) { 657 out = 5; 658 } 659 log_it(tmp); 660 if (is_this_raid_personality_registered(out)) { 661 log_it("Groovy. You've picked a RAID personality which is registered."); 662 } else { 663 if (ask_me_yes_or_no("You have chosen a RAID personality which is not registered with the kernel. Make another selection?")) 664 { 665 out = 999; 666 } 667 } 668 } 669 mr_free(prompt); 670 671 raidrec->raidlevel = out; 672 #else 673 /** buffers ***********************************************************/ 674 char tmp[MAX_STR_LEN]; 675 char *personalities = NULL; 676 char *prompt = NULL; 677 char sz[MAX_STR_LEN]; 678 int out = 0; 679 int res = 0; 680 681 682 assert(raidrec != NULL); 683 paranoid_system("grep Pers /proc/mdstat > /tmp/raid-personalities.txt 2> /dev/null"); 684 mr_asprintf(personalities, "%s", last_line_of_file("/tmp/raid-personalities.txt")); 685 mr_asprintf(prompt, "Please enter the RAID level you want. %s", personalities); 686 mr_free(personalities); 687 688 if (raidrec->raid_level == -1) { 689 strcpy(tmp, "linear"); 690 } else { 691 sprintf(tmp, "%d", raidrec->raid_level); 692 } 693 for (out = 999; 694 out != -1 && out != 0 && out != 1 && out != 4 && out != 5 695 && out != 10;) { 696 res = popup_and_get_string("Specify RAID level", prompt, tmp, 10); 697 if (!res) { 698 return; 699 } 700 strip_spaces(tmp); 701 if (tmp[0] == '[' && tmp[strlen(tmp) - 1] == ']') { 702 strcpy(sz, tmp); 703 strncpy(tmp, sz + 1, strlen(sz) - 2); 704 tmp[strlen(sz) - 2] = '\0'; 705 } 706 if (!strcmp(tmp, "linear")) { 707 out = -1; 708 } else if (!strncmp(tmp, "raid", 4)) { 709 out = atoi(tmp + 4); 710 } else { 711 out = atoi(tmp); 712 } 713 log_it(tmp); 714 if (is_this_raid_personality_registered(out)) { 715 log_it("Groovy. You've picked a RAID personality which is registered."); 716 } else { 717 if (ask_me_yes_or_no("You have chosen a RAID personality which is not registered with the kernel. Make another selection?")) { 718 out = 999; 719 } 720 } 721 } 722 mr_free(prompt); 723 724 raidrec->raid_level = out; 725 #endif 726 } 727 728 729 #ifdef __FreeBSD__ 730 731 /** 732 * Edit the plex @p raidrec in @p raidlist. 733 * @param mountlist The mountlist to get some of the information from. 734 * @param raidlist The raidlist containing information about RAID devices. 735 * @param raidrec The plex to edit. 736 * @param currline The line number (starting from 0) of the RAID device in @p mountlist. 737 * @param currline2 The line number (starting from 0) of the plex within the RAID device. 738 * @author Joshua Oreman 739 * @ingroup restoreGuiMountlist 740 */ 741 void 742 edit_raidlist_plex(struct mountlist_itself *mountlist, 743 struct raidlist_itself *raidlist, 744 struct vinum_plex *raidrec, int currline, int currline2) 745 { 746 747 /** structures ********************************************************/ 748 struct vinum_plex bkp_raidrec; 749 750 751 /** buffers ***********************************************************/ 752 char *title_of_editraidForm_window = NULL; 753 754 /** newt **************************************************************/ 755 newtComponent editraidForm; 142 756 newtComponent bOK; 143 757 newtComponent bCancel; 758 newtComponent bEdit; 759 newtComponent bAdd; 760 newtComponent bDelete; 144 761 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"); 762 newtComponent unallocListbox, allocListbox; 763 newtComponent bLevel, sLevel; 764 newtComponent bStripeSize, sStripeSize; 765 newtComponent bAlloc, bUnalloc; 766 767 void *keylist[ARBITRARY_MAXIMUM]; 768 void *curr_choice_a, *curr_choice_u; 769 int currline_a, currline_u; 770 771 char *p = NULL; 772 char *tmp = NULL; 773 char *entry = NULL; 774 775 struct mountlist_itself *unallocparts; 776 777 unallocparts = malloc(sizeof(struct mountlist_itself)); 778 779 log_it("Started edit_raidlist_entry"); 780 memcpy((void *) &bkp_raidrec, (void *) raidrec, 781 sizeof(struct vinum_plex)); 782 mr_asprintf(title_of_editraidForm_window, "%s.p%i", raidlist->el[currline].volname, currline2); 783 newtPushHelpLine 784 (" Please select a subdisk to edit, or edit this plex's parameters"); 785 newtOpenWindow(13, 3, 54, 18, title_of_editraidForm_window); 786 mr_free(title_of_editraidForm_window); 787 788 for (;;) { 789 int i; 790 791 switch (raidrec->raidlevel) { 792 case -1: 793 mr_asprintf(tmp, "concat"); 794 break; 795 case 0: 796 mr_asprintf(tmp, "striped"); 797 break; 798 case 5: 799 mr_asprintf(tmp, "raid5"); 800 break; 801 default: 802 mr_asprintf(tmp, "unknown (%i)", raidrec->raidlevel); 803 break; 804 } 805 bLevel = newtCompactButton(2, 2, " RAID level "); 806 sLevel = newtLabel(19, 2, tmp); 807 mr_free(tmp); 808 809 if (raidrec->raidlevel >= 0) { 810 mr_asprintf(tmp, "%ik", raidrec->stripesize); 811 bStripeSize = newtCompactButton(2, 4, " Stripe size "); 812 } else { 813 mr_asprintf(tmp, "N/A"); 814 bStripeSize = newtLabel(2, 4, "Stripe size:"); 815 } 816 sStripeSize = newtLabel(19, 4, tmp); 817 mr_free(tmp); 818 819 bOK = newtCompactButton(2, 16, " OK "); 820 bCancel = newtCompactButton(12, 16, "Cancel"); 821 bAdd = newtCompactButton(22, 16, " Add "); 822 bEdit = newtCompactButton(32, 16, " Edit "); 823 bDelete = newtCompactButton(42, 16, "Delete"); 824 825 826 unallocListbox = 827 newtListbox(2, 7, 7, NEWT_FLAG_SCROLL | NEWT_FLAG_RETURNEXIT); 828 allocListbox = 829 newtListbox(33, 7, 7, NEWT_FLAG_SCROLL | NEWT_FLAG_RETURNEXIT); 830 bAlloc = newtButton(23, 7, " -> "); 831 bUnalloc = newtButton(23, 11, " <- "); 832 833 editraidForm = newtForm(NULL, NULL, 0); 834 835 newtListboxClear(allocListbox); 836 newtListboxClear(unallocListbox); 837 bzero(unallocparts, sizeof(struct mountlist_itself)); 838 make_list_of_unallocated_raid_partitions(unallocparts, mountlist, 839 raidlist); 840 for (i = 0; i < ARBITRARY_MAXIMUM; ++i) { 841 keylist[i] = (void *) i; 842 if (i < raidrec->subdisks) { 843 mr_asprintf(entry, "%-17s", find_dev_entry_for_raid_device_name(raidlist, raidrec->sd[i].which_device)); 844 newtListboxAppendEntry(allocListbox, entry, keylist[i]); 845 mr_free(entry); 846 } 847 if (i < unallocparts->entries) { 848 mr_asprintf(entry, "%-17s", unallocparts->el[i].device); 849 newtListboxAppendEntry(unallocListbox, entry, keylist[i]); 850 mr_free(entry); 851 } 852 } 853 854 #define COMP(x) newtFormAddComponent (editraidForm, x) 855 #define UCOMP(x) if (unallocparts->entries > 0) COMP(x) 856 #define ACOMP(x) if (raidrec->subdisks > 0) COMP(x) 857 editraidForm = newtForm(NULL, NULL, 0); 858 UCOMP(unallocListbox); 859 UCOMP(bAlloc); 860 ACOMP(allocListbox); 861 ACOMP(bUnalloc); 862 COMP(bOK); 863 COMP(bCancel); 864 COMP(bLevel); 865 COMP(sLevel); 866 if (raidrec->raidlevel != -1) { 867 COMP(bStripeSize); 868 COMP(sStripeSize); 869 } 870 #undef COMP 871 #undef UCOMP 872 #undef ACOMP 873 874 newtDrawForm(editraidForm); 875 newtRefresh(); 876 b_res = newtRunForm(editraidForm); 877 if (b_res == bOK || b_res == bCancel) { 878 break; 879 } 880 881 curr_choice_a = (raidrec->subdisks > 0) ? 882 newtListboxGetCurrent(allocListbox) : (void *) 1234; 883 curr_choice_u = (unallocparts->entries > 0) ? 884 newtListboxGetCurrent(unallocListbox) : (void *) 1234; 885 for (currline_a = 0; currline_a < raidrec->subdisks; ++currline_a) { 886 if (currline_a > ARBITRARY_MAXIMUM) 887 break; 888 if (keylist[currline_a] == curr_choice_a) 889 break; 890 } 891 for (currline_u = 0; currline_u < unallocparts->entries; 892 ++currline_u) { 893 if (currline_u > ARBITRARY_MAXIMUM) 894 break; 895 if (keylist[currline_u] == curr_choice_u) 896 break; 897 } 898 if (b_res == bLevel) { 899 choose_raid_level(raidrec); 900 } else if (b_res == bStripeSize) { 901 char tmp1[64]; 902 sprintf(tmp1, "%i", raidrec->stripesize); 903 if (popup_and_get_string 904 ("Stripe size", 905 "Please enter the stripe size in kilobytes.", tmp1, 20)) { 906 raidrec->stripesize = atoi(tmp1); 907 } 908 } else if ((b_res == bAlloc) || (b_res == unallocListbox)) { 909 if (currline_u <= unallocparts->entries) 910 add_raid_subdisk(raidlist, raidrec, 911 unallocparts->el[currline_u].device); 912 } else if ((b_res == bUnalloc) || (b_res == allocListbox)) { 913 if (currline_a <= raidrec->subdisks) { 914 memcpy((void *) &raidrec->sd[currline_a], 915 (void *) &raidrec->sd[raidrec->subdisks - 1], 916 sizeof(struct vinum_subdisk)); 917 raidrec->subdisks--; 918 } 919 } 920 newtFormDestroy(editraidForm); 921 newtRefresh(); 922 } 923 924 if (b_res == bCancel) { 925 memcpy((void *) raidrec, (void *) &bkp_raidrec, sizeof(struct vinum_plex)); 926 } 927 newtPopWindow(); 928 newtPopHelpLine(); 929 } 177 930 #else 178 mr_asprintf(format_str, "ext3"); 931 /** 932 * Edit additional RAID variable number @p lino. 933 * @param raidrec The RAID device record to edit the variable in. 934 * @param lino The line number (starting from 0) of the variable to edit. 935 * @ingroup restoreGuiVarslist 936 */ 937 void edit_varslist_entry(struct raid_device_record *raidrec, int lino) 938 { 939 940 /** buffers ***********************************************************/ 941 char *header = NULL; 942 char *comment = NULL; 943 char sz_out[MAX_STR_LEN]; 944 945 assert(raidrec != 0); 946 assert(lino >= 0); 947 948 strcpy(sz_out, raidrec->additional_vars.el[lino].value); 949 mr_asprintf(header, "Edit %s", raidrec->additional_vars.el[lino].label); 950 mr_asprintf(comment, "Please set %s's value (currently '%s')", raidrec->additional_vars.el[lino].label, sz_out); 951 if (popup_and_get_string(header, comment, sz_out, MAX_STR_LEN)) { 952 strip_spaces(sz_out); 953 strcpy(raidrec->additional_vars.el[lino].value, sz_out); 954 } 955 mr_free(header); 956 mr_free(comment); 957 } 179 958 #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 newtPushHelpLine192 ("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 device_str = mr_strip_spaces(device_here);201 202 mr_free(mountpoint_str);203 mountpoint_str = mr_strip_spaces(mountpoint_here);204 205 mr_free(format_str);206 format_str = mr_strip_spaces(format_here);207 208 mr_free(size_str);209 size_str = mr_strip_spaces(size_here);210 211 if (b_res == bOK) {212 if (device_str[strlen(device_str) - 1] == '/') {213 popup_and_OK("You left the device nearly blank!");214 b_res = NULL;215 }216 if (size_of_specific_device_in_mountlist(mountlist, device_str) >= 0) {217 popup_and_OK("Can't add this - you've got one already!");218 b_res = NULL;219 }220 }221 }222 newtFormDestroy(myForm);223 newtPopHelpLine();224 newtPopWindow();225 if (b_res == bCancel) {226 return;227 }228 mr_asprintf(drive_to_add, "%s", device_str);229 for (i = strlen(drive_to_add); isdigit(drive_to_add[i - 1]); i--);230 mr_free(drive_to_add);231 232 currline = mountlist->entries;233 strcpy(mountlist->el[currline].device, device_str);234 strcpy(mountlist->el[currline].mountpoint, mountpoint_str);235 mr_free(mountpoint_str);236 237 strcpy(mountlist->el[currline].format, format_str);238 mr_free(format_str);239 240 mountlist->el[currline].size = atol(size_str) * 1024L;241 mr_free(size_str);242 243 mountlist->entries++;244 if (strstr(mountlist->el[currline].device, RAID_DEVICE_STUB)) {245 initiate_new_raidlist_entry(raidlist, mountlist, currline, device_str);246 }247 mr_free(device_str);248 249 redraw_mountlist(mountlist, keylist, listbox);250 }251 959 252 960 … … 289 997 } 290 998 #endif 999 1000 1001 #ifndef __FreeBSD__ 1002 /** 1003 * Delete entry number @p lino in the additional RAID variables section of @p raidrec. 1004 * @param raidrec The RAID device record containing the RAID variable to delete. 1005 * @param lino The line number (starting from 0) of the variable to delete. 1006 * @ingroup restoreGuiVarslist 1007 */ 1008 void delete_varslist_entry(struct raid_device_record *raidrec, int lino) 1009 { 1010 1011 /** buffers ************************************************************/ 1012 char *tmp = NULL; 1013 int res = 0; 1014 1015 /** structures *********************************************************/ 1016 struct additional_raid_variables *av; 1017 1018 assert(raidrec != NULL); 1019 1020 av = &raidrec->additional_vars; 1021 mr_asprintf(tmp, "Delete %s - are you sure?", av->el[lino].label); 1022 res = ask_me_yes_or_no(tmp); 1023 mr_free(tmp); 1024 1025 if (res) { 1026 if (!strcmp(av->el[lino].label, "persistent-superblock") 1027 || !strcmp(av->el[lino].label, "chunk-size")) { 1028 mr_asprintf(tmp, "%s must not be deleted. It would be bad.", av->el[lino].label); 1029 popup_and_OK(tmp); 1030 mr_free(tmp); 1031 } else { 1032 memcpy((void *) &av->el[lino], (void *) &av->el[av->entries--], 1033 sizeof(struct raid_var_line)); 1034 } 1035 } 1036 } 1037 #endif 1038 1039 1040 1041 #ifndef __FreeBSD__ 1042 /** 1043 * Edit the additional RAID variables in @p raidrec. 1044 * @param raidrec The RAID device record to edit the RAID variables in. 1045 * @ingroup restoreGuiVarslist 1046 */ 1047 void edit_raidrec_additional_vars(struct raid_device_record *raidrec) 1048 { 1049 1050 /** structure *********************************************************/ 1051 struct raid_device_record bkp_raidrec; 1052 1053 /** newt **************************************************************/ 1054 newtComponent myForm; 1055 newtComponent bAdd; 1056 newtComponent bEdit; 1057 newtComponent bDelete; 1058 newtComponent bOK; 1059 newtComponent bCancel; 1060 newtComponent b_res; 1061 newtComponent varsListbox; 1062 newtComponent headerMsg; 1063 1064 /** ?? ***************************************************************/ 1065 void *keylist[ARBITRARY_MAXIMUM], *curr_choice; 1066 1067 /** buffers **********************************************************/ 1068 char title_of_window[MAX_STR_LEN]; 1069 1070 /** int **************************************************************/ 1071 int i = 0; 1072 int currline = 0; 1073 1074 1075 assert(raidrec != NULL); 1076 1077 memcpy((void *) &bkp_raidrec, (void *) raidrec, 1078 sizeof(struct raid_device_record)); 1079 sprintf(title_of_window, "Additional variables"); 1080 newtPushHelpLine 1081 (" Edit the additional fields to your heart's content, then click OK or Cancel."); 1082 headerMsg = newtLabel(1, 1, "Label Value"); 1083 varsListbox = 1084 newtListbox(1, 2, 6, NEWT_FLAG_SCROLL | NEWT_FLAG_RETURNEXIT); 1085 i = 1; 1086 bAdd = newtCompactButton(i, 9, " Add "); 1087 bEdit = newtCompactButton(i += 8, 9, " Edit "); 1088 bDelete = newtCompactButton(i += 9, 9, "Delete"); 1089 bOK = newtCompactButton(i += 9, 9, " OK "); 1090 bCancel = newtCompactButton(i += 9, 9, "Cancel"); 1091 newtOpenWindow(17, 7, 46, 10, title_of_window); 1092 myForm = newtForm(NULL, NULL, 0); 1093 newtFormAddComponents(myForm, headerMsg, varsListbox, bAdd, bEdit, 1094 bDelete, bOK, bCancel, NULL); 1095 insert_essential_additionalvars(raidrec); 1096 redraw_varslist(&raidrec->additional_vars, keylist, varsListbox); 1097 for (b_res = NULL; b_res != bOK && b_res != bCancel;) { 1098 b_res = newtRunForm(myForm); 1099 curr_choice = newtListboxGetCurrent(varsListbox); 1100 for (currline = 0; 1101 currline < raidrec->additional_vars.entries 1102 && keylist[currline] != curr_choice; currline++); 1103 if (currline == raidrec->additional_vars.entries 1104 && raidrec->additional_vars.entries > 0) { 1105 log_it("Warning - I don't know what this button does"); 1106 } 1107 if (b_res == bOK) { /* do nothing */ 1108 } else if (b_res == bCancel) { /* do nothing */ 1109 } else if (b_res == bAdd) { 1110 add_varslist_entry(raidrec); 1111 } else if (b_res == bDelete) { 1112 delete_varslist_entry(raidrec, currline); 1113 } else { 1114 edit_varslist_entry(raidrec, currline); 1115 } 1116 redraw_varslist(&raidrec->additional_vars, keylist, varsListbox); 1117 } 1118 remove_essential_additionalvars(raidrec); 1119 newtFormDestroy(myForm); 1120 newtPopWindow(); 1121 newtPopHelpLine(); 1122 if (b_res == bCancel) { 1123 memcpy((void *) raidrec, (void *) &bkp_raidrec, 1124 sizeof(struct raid_device_record)); 1125 } 1126 return; 1127 } 1128 #endif 1129 291 1130 292 1131 /** … … 445 1284 446 1285 /** 447 * Choose the RAID level for the RAID device record in @p raidrec. 448 * @param raidrec The RAID device record to set the RAID level of. 1286 * Edit the entry for @p raidrec in @p raidlist. 1287 * @param mountlist The mountlist to get some information from. 1288 * @param raidlist The raidlist containing information about RAID devices. 1289 * @param raidrec The RAID device record for this partition. 1290 * @param currline The line number (starting from 0) in the mountlist of the RAID device. 449 1291 * @ingroup restoreGuiMountlist 450 1292 */ 1293 void edit_raidlist_entry(struct mountlist_itself *mountlist, 1294 struct raidlist_itself *raidlist, 1295 struct OSSWAP (raid_device_record, 1296 vinum_volume) * raidrec, int currline) 1297 { 1298 1299 #ifdef __FreeBSD__ 1300 /** structures ********************************************************/ 1301 struct vinum_volume bkp_raidrec; 1302 1303 1304 /** buffers ***********************************************************/ 1305 char title_of_editraidForm_window[MAX_STR_LEN]; 1306 1307 /** newt **************************************************************/ 1308 newtComponent editraidForm; 1309 newtComponent bOK; 1310 newtComponent bCancel; 1311 newtComponent bEdit; 1312 newtComponent bAdd; 1313 newtComponent bDelete; 1314 newtComponent b_res; 1315 newtComponent plexesListbox; 1316 newtComponent plexesHeader; 1317 1318 void *keylist[10]; 1319 void *curr_choice; 1320 char *raidlevel = NULL; 1321 char *chunksize = NULL; 1322 char *msg = NULL; 1323 1324 int currline2 = 0; 1325 int res = 0; 1326 1327 log_it("Started edit_raidlist_entry"); 1328 memcpy((void *) &bkp_raidrec, (void *) raidrec, 1329 sizeof(struct vinum_volume)); 1330 sprintf(title_of_editraidForm_window, "Plexes on %s", 1331 raidrec->volname); 1332 newtPushHelpLine(" Please select a plex to edit"); 1333 newtOpenWindow(13, 5, 54, 15, title_of_editraidForm_window); 1334 for (;;) { 1335 int i; 1336 char *headerstr = NULL; 1337 mr_asprintf(headerstr, "%-14s %-8s %11s %8s", "Plex", "Level", "Stripe Size", "Subdisks"); 1338 1339 bOK = newtCompactButton(2, 13, " OK "); 1340 bCancel = newtCompactButton(12, 13, "Cancel"); 1341 bAdd = newtCompactButton(22, 13, " Add "); 1342 bEdit = newtCompactButton(32, 13, " Edit "); 1343 bDelete = newtCompactButton(42, 13, "Delete"); 1344 1345 plexesListbox = 1346 newtListbox(2, 3, 9, NEWT_FLAG_SCROLL | NEWT_FLAG_RETURNEXIT); 1347 plexesHeader = newtLabel(2, 2, headerstr); 1348 mr_free(headerstr); 1349 editraidForm = newtForm(NULL, NULL, 0); 1350 1351 newtListboxClear(plexesListbox); 1352 for (i = 0; i < 10; ++i) { 1353 keylist[i] = (void *) i; 1354 if (i < raidrec->plexes) { 1355 char *pname; 1356 char *entry; 1357 switch (raidrec->plex[i].raidlevel) { 1358 case -1: 1359 mr_asprintf(raidlevel, "concat"); 1360 break; 1361 case 0: 1362 mr_asprintf(raidlevel, "striped"); 1363 break; 1364 case 5: 1365 mr_asprintf(raidlevel, "raid5"); 1366 break; 1367 default: 1368 mr_asprintf(raidlevel, "raid%i", raidrec->plex[i].raidlevel); 1369 break; 1370 } 1371 1372 if (raidrec->plex[i].raidlevel == -1) { 1373 mr_asprintf(chunksize, "N/A"); 1374 } else { 1375 mr_asprintf(chunksize, "%dk", raidrec->plex[i].stripesize); 1376 } 1377 mr_asprintf(pname, "%s.p%i", raidrec->volname, i); 1378 mr_asprintf(entry, "%-14s %-8s %11s %8d", pname, raidlevel, chunksize, raidrec->plex[i].subdisks); 1379 mr_free(pname); 1380 mr_free(raidlevel); 1381 mr_free(chunksize); 1382 1383 newtListboxAppendEntry(plexesListbox, entry, keylist[i]); 1384 mr_free(entry); 1385 } 1386 } 1387 1388 newtFormAddComponents(editraidForm, bOK, bCancel, bAdd, bEdit, 1389 bDelete, plexesListbox, plexesHeader, NULL); 1390 1391 b_res = newtRunForm(editraidForm); 1392 if (b_res == bOK || b_res == bCancel) { 1393 break; 1394 } 1395 1396 curr_choice = newtListboxGetCurrent(plexesListbox); 1397 for (currline2 = 0; currline2 < raidrec->plexes; ++currline2) { 1398 if (currline2 > 9) 1399 break; 1400 if (keylist[currline2] == curr_choice) 1401 break; 1402 } 1403 1404 if (b_res == bDelete) { 1405 mr_asprintf(msg, "Are you sure you want to delete %s.p%i?", raidrec->volname, currline2); 1406 res = ask_me_yes_or_no(msg); 1407 mr_free(msg); 1408 1409 if (res) { 1410 log_it("Deleting RAID plex"); 1411 memcpy((void *) &raidrec->plex[currline2], 1412 (void *) &raidrec->plex[raidrec->plexes - 1], 1413 sizeof(struct vinum_plex)); 1414 raidrec->plexes--; 1415 } 1416 continue; 1417 } 1418 if (b_res == bAdd) { 1419 raidrec->plex[raidrec->plexes].raidlevel = 0; 1420 raidrec->plex[raidrec->plexes].stripesize = 279; 1421 raidrec->plex[raidrec->plexes].subdisks = 0; 1422 currline2 = raidrec->plexes++; 1423 } 1424 edit_raidlist_plex(mountlist, raidlist, &raidrec->plex[currline2], 1425 currline, currline2); 1426 newtFormDestroy(editraidForm); 1427 } 1428 if (b_res == bCancel) { 1429 memcpy((void *) raidrec, (void *) &bkp_raidrec, 1430 sizeof(struct vinum_volume)); 1431 } 1432 newtPopHelpLine(); 1433 newtPopWindow(); 1434 mountlist->el[currline].size = 1435 calculate_raid_device_size(mountlist, raidlist, raidrec->volname); 1436 #else 1437 /** structures ********************************************************/ 1438 struct raid_device_record *bkp_raidrec; 1439 1440 1441 /** buffers ***********************************************************/ 1442 char *title_of_editraidForm_window; 1443 char *sz_raid_level = NULL; 1444 char *sz_data_disks = NULL; 1445 char *sz_spare_disks = NULL; 1446 char *sz_parity_disks = NULL; 1447 char *sz_failed_disks = NULL; 1448 1449 /** newt **************************************************************/ 1450 newtComponent editraidForm; 1451 newtComponent bOK; 1452 newtComponent bCancel; 1453 newtComponent bAdditional; 1454 newtComponent bChangeRaid; 1455 newtComponent bSelectData; 1456 newtComponent bSelectSpare; 1457 newtComponent bSelectParity; 1458 newtComponent bSelectFailed; 1459 newtComponent b_res; 1460 1461 assert(mountlist != NULL); 1462 assert(raidlist != NULL); 1463 assert(raidrec != NULL); 1464 1465 bkp_raidrec = mr_malloc(sizeof(struct raid_device_record)); 1466 log_it("Started edit_raidlist_entry"); 1467 1468 memcpy((void *) bkp_raidrec, (void *) raidrec, sizeof(struct raid_device_record)); 1469 mr_asprintf(title_of_editraidForm_window, "%s", raidrec->raid_device); 1470 log_msg(2, "Opening newt window"); 1471 newtOpenWindow(20, 5, 40, 14, title_of_editraidForm_window); 1472 for (;;) { 1473 log_msg(2, "Main loop"); 1474 mr_free(title_of_editraidForm_window); 1475 mr_asprintf(title_of_editraidForm_window, "Edit %s", raidrec->raid_device); 1476 sz_raid_level = turn_raid_level_number_to_string(raidrec->raid_level); 1477 sz_data_disks = number_of_disks_as_string(raidrec->data_disks.entries, "data"); 1478 sz_spare_disks = number_of_disks_as_string(raidrec->spare_disks.entries, "spare"); 1479 sz_parity_disks = number_of_disks_as_string(raidrec->parity_disks.entries, "parity"); 1480 sz_failed_disks = number_of_disks_as_string(raidrec->failed_disks.entries, "failed"); 1481 bSelectData = newtButton(1, 1, sz_data_disks); 1482 bSelectSpare = newtButton(20, 1, sz_spare_disks); 1483 bSelectParity = newtButton(1, 5, sz_parity_disks); 1484 bSelectFailed = newtButton(20, 5, sz_failed_disks); 1485 bChangeRaid = newtButton(1, 9, sz_raid_level); 1486 bOK = newtButton(16 + (raidrec->raid_level == -1), 9, " OK "); 1487 bCancel = newtButton(28, 9, "Cancel"); 1488 bAdditional = 1489 newtCompactButton(1, 13, 1490 "Additional settings and information"); 1491 newtPushHelpLine 1492 (" Edit the RAID device's settings to your heart's content, then hit OK/Cancel."); 1493 editraidForm = newtForm(NULL, NULL, 0); 1494 newtFormAddComponents(editraidForm, bSelectData, bSelectParity, 1495 bChangeRaid, bSelectSpare, bSelectFailed, 1496 bOK, bCancel, bAdditional); 1497 b_res = newtRunForm(editraidForm); 1498 if (b_res == bChangeRaid) { 1499 choose_raid_level(raidrec); 1500 } else if (b_res == bSelectData) { 1501 select_raid_disks(mountlist, raidlist, raidrec, "data", &raidrec->data_disks); 1502 } else if (b_res == bSelectSpare) { 1503 select_raid_disks(mountlist, raidlist, raidrec, "spare", &raidrec->spare_disks); 1504 } else if (b_res == bSelectParity) { 1505 select_raid_disks(mountlist, raidlist, raidrec, "parity", &raidrec->parity_disks); 1506 } else if (b_res == bSelectFailed) { 1507 select_raid_disks(mountlist, raidlist, raidrec, "failed", &raidrec->failed_disks); 1508 } else if (b_res == bAdditional) { 1509 edit_raidrec_additional_vars(raidrec); 1510 } 1511 newtFormDestroy(editraidForm); 1512 if (b_res == bOK || b_res == bCancel) { 1513 break; 1514 } 1515 mr_free(sz_data_disks); 1516 mr_free(sz_spare_disks); 1517 mr_free(sz_parity_disks); 1518 mr_free(sz_failed_disks); 1519 } 1520 if (b_res == bCancel) { 1521 memcpy((void *) raidrec, (void *) bkp_raidrec, sizeof(struct raid_device_record)); 1522 } 1523 newtPopHelpLine(); 1524 newtPopWindow(); 1525 mountlist->el[currline].size = calculate_raid_device_size(mountlist, raidlist, raidrec->raid_device); 1526 mr_free(title_of_editraidForm_window); 1527 mr_free(sz_raid_level); 1528 paranoid_free(bkp_raidrec); 1529 #endif 1530 } 1531 1532 1533 /** 1534 * Create a new raidtab entry for @p device in @p raidlist. 1535 * @param raidlist The raidlist to add the device to. 1536 * @param mountlist The mountlist containing information about the user's partitions. 1537 * @param currline The selected line in the mountlist. 1538 * @param device The RAID device (e.g. /dev/md0) to use. 1539 * @ingroup restoreGuiMountlist 1540 */ 451 1541 void 452 choose_raid_level(struct OSSWAP (raid_device_record, vinum_plex) * raidrec) 453 { 454 1542 initiate_new_raidlist_entry(struct raidlist_itself *raidlist, 1543 struct mountlist_itself *mountlist, 1544 int currline, char *device) 1545 { 1546 1547 /** structure *********************************************************/ 1548 struct OSSWAP (raid_device_record, vinum_volume) * raidrec; 1549 1550 /** int ***************************************************************/ 1551 int pos_in_raidlist = 0; 1552 1553 assert(raidlist != NULL); 1554 assert(mountlist != NULL); 1555 assert_string_is_neither_NULL_nor_zerolength(device); 1556 1557 pos_in_raidlist = 1558 find_raid_device_in_raidlist(raidlist, 1559 mountlist->el[currline].device); 1560 if (pos_in_raidlist >= 0) { 1561 fatal_error("Sorry, that RAID device already exists. Weird."); 1562 } 1563 pos_in_raidlist = raidlist->entries++; 1564 raidrec = &raidlist->el[pos_in_raidlist]; 1565 initialize_raidrec(raidrec); 1566 strcpy(raidrec->OSSWAP(raid_device, volname), OSSWAP(device, basename(device))); 1567 #ifndef __FreeBSD__ 1568 choose_raid_level(raidrec); 1569 select_raid_disks(mountlist, raidlist, raidrec, "data", 1570 &raidrec->data_disks); 1571 #endif 1572 edit_raidlist_entry(mountlist, raidlist, raidrec, currline); 1573 } 1574 1575 1576 /** 1577 * Redraw the mountlist. 1578 * @param mountlist The mountlist to read from. 1579 * @param keylist The list of keys for @p listbox. 1580 * @param listbox The Newt listbox component to redraw. 1581 * @ingroup restoreGuiMountlist 1582 */ 1583 void 1584 redraw_mountlist(struct mountlist_itself *mountlist, 1585 void *keylist[ARBITRARY_MAXIMUM], newtComponent listbox) 1586 { 1587 1588 /** long **************************************************************/ 1589 long i = 0; 1590 char * tmp = NULL; 1591 1592 assert(mountlist != NULL); 1593 assert(keylist != NULL); 1594 assert(listbox != NULL); 1595 1596 newtListboxClear(listbox); 1597 // sort_mountlist_by_device (mountlist); 1598 for (i = 0; i < ARBITRARY_MAXIMUM; i++) { 1599 keylist[i] = (void *) i; 1600 } 1601 for (i = 0; i < mountlist->entries; i++) { 1602 tmp = mountlist_entry_to_string(mountlist, i); 1603 newtListboxAppendEntry(listbox, tmp, keylist[i]); 1604 mr_free(tmp); 1605 } 1606 } 1607 1608 1609 1610 1611 /** 1612 * Add an entry to @p mountlist. 1613 * @param mountlist The mountlist to add an entry to. 1614 * @param raidlist The raidlist that accompanies @p mountlist. 1615 * @param listbox The listbox component in the mountlist editor. 1616 * @param currline The line selected in @p listbox. 1617 * @param keylist The list of keys for @p listbox. 1618 * @ingroup restoreGuiMountlist 1619 */ 1620 void 1621 add_mountlist_entry(struct mountlist_itself *mountlist, 1622 struct raidlist_itself *raidlist, 1623 newtComponent listbox, int currline, void *keylist[]) 1624 { 1625 1626 /** int **************************************************************/ 1627 int i = 0; 1628 1629 /** newt *************************************************************/ 1630 newtComponent myForm; 1631 newtComponent bOK; 1632 newtComponent bCancel; 1633 newtComponent b_res; 1634 newtComponent mountpointComp; 1635 newtComponent label0; 1636 newtComponent label1; 1637 newtComponent label2; 1638 newtComponent label3; 1639 newtComponent sizeComp; 1640 newtComponent deviceComp; 1641 newtComponent formatComp; 1642 1643 /** buffers **********************************************************/ 1644 char *drive_to_add = NULL; 1645 char *mountpoint_str = NULL; 1646 char *size_str = NULL; 1647 char *device_str = NULL; 1648 char *format_str = NULL; 1649 1650 /** pointers *********************************************************/ 1651 char *mountpoint_here; 1652 char *size_here; 1653 char *device_here; 1654 char *format_here; 1655 1656 assert(mountlist != NULL); 1657 assert(raidlist != NULL); 1658 assert(listbox != NULL); 1659 assert(keylist != NULL); 1660 1661 mr_asprintf(device_str, "/dev/"); 1662 mr_asprintf(mountpoint_str, "/"); 1663 mr_asprintf(size_str, ""); 455 1664 #ifdef __FreeBSD__ 456 457 /** int ***************************************************************/ 458 int res = 0; 459 int out = 0; 460 461 /** buffers ***********************************************************/ 462 char tmp[MAX_STR_LEN]; 463 char *prompt = NULL; 464 char sz[MAX_STR_LEN]; 465 466 mr_asprintf(prompt, "Please enter the RAID level you want. (concat, striped, raid5)"); 467 if (raidrec->raidlevel == -1) { 468 strcpy(tmp, "concat"); 469 } else if (raidrec->raidlevel == 0) { 470 strcpy(tmp, "striped"); 471 } else { 472 sprintf(tmp, "raid%i", raidrec->raidlevel); 473 } 474 for (out = 999; out == 999;) { 475 res = popup_and_get_string("Specify RAID level", prompt, tmp, 10); 476 if (!res) { 477 mr_free(prompt); 478 return; 479 } 480 strip_spaces(tmp); 481 if (tmp[0] == '[' && tmp[strlen(tmp) - 1] == ']') { 482 strcpy(sz, tmp); 483 strncpy(tmp, sz + 1, strlen(sz) - 2); 484 tmp[strlen(sz) - 2] = '\0'; 485 } 486 if (!strcmp(tmp, "concat")) { 487 out = -1; 488 } else if (!strcmp(tmp, "striped")) { 489 out = 0; 490 } else if (!strcmp(tmp, "raid5")) { 491 out = 5; 492 } 493 log_it(tmp); 494 if (is_this_raid_personality_registered(out)) { 495 log_it("Groovy. You've picked a RAID personality which is registered."); 496 } else { 497 if (ask_me_yes_or_no("You have chosen a RAID personality which is not registered with the kernel. Make another selection?")) 498 { 499 out = 999; 1665 mr_asprintf(format_str, "ufs"); 1666 #else 1667 mr_asprintf(format_str, "ext3"); 1668 #endif 1669 newtOpenWindow(20, 5, 48, 10, "Add entry"); 1670 label0 = newtLabel(2, 1, "Device: "); 1671 label1 = newtLabel(2, 2, "Mountpoint:"); 1672 label2 = newtLabel(2, 3, "Size (MB): "); 1673 label3 = newtLabel(2, 4, "Format: "); 1674 deviceComp = newtEntry(14, 1, device_str, 30, (void *) &device_here, 0); 1675 mountpointComp = newtEntry(14, 2, mountpoint_str, 30, (void *) &mountpoint_here, 0); 1676 formatComp = newtEntry(14, 4, format_str, 15, (void *) &format_here, 0); 1677 sizeComp = newtEntry(14, 3, size_str, 10, (void *) &size_here, 0); 1678 bOK = newtButton(5, 6, " OK "); 1679 bCancel = newtButton(17, 6, "Cancel"); 1680 newtPushHelpLine 1681 ("To add an entry to the mountlist, please fill in these fields and then hit 'OK'"); 1682 myForm = newtForm(NULL, NULL, 0); 1683 newtFormAddComponents(myForm, deviceComp, mountpointComp, sizeComp, 1684 formatComp, label0, label1, label2, label3, bOK, 1685 bCancel, NULL); 1686 for (b_res = NULL; b_res != bOK && b_res != bCancel;) { 1687 b_res = newtRunForm(myForm); 1688 mr_free(device_str); 1689 device_str = mr_strip_spaces(device_here); 1690 1691 mr_free(mountpoint_str); 1692 mountpoint_str = mr_strip_spaces(mountpoint_here); 1693 1694 mr_free(format_str); 1695 format_str = mr_strip_spaces(format_here); 1696 1697 mr_free(size_str); 1698 size_str = mr_strip_spaces(size_here); 1699 1700 if (b_res == bOK) { 1701 if (device_str[strlen(device_str) - 1] == '/') { 1702 popup_and_OK("You left the device nearly blank!"); 1703 b_res = NULL; 500 1704 } 501 } 502 } 503 mr_free(prompt); 504 505 raidrec->raidlevel = out; 506 #else 507 /** buffers ***********************************************************/ 508 char tmp[MAX_STR_LEN]; 509 char *personalities = NULL; 510 char *prompt = NULL; 511 char sz[MAX_STR_LEN]; 512 int out = 0; 513 int res = 0; 514 515 516 assert(raidrec != NULL); 517 paranoid_system("grep Pers /proc/mdstat > /tmp/raid-personalities.txt 2> /dev/null"); 518 mr_asprintf(personalities, "%s", last_line_of_file("/tmp/raid-personalities.txt")); 519 mr_asprintf(prompt, "Please enter the RAID level you want. %s", personalities); 520 mr_free(personalities); 521 522 if (raidrec->raid_level == -1) { 523 strcpy(tmp, "linear"); 524 } else { 525 sprintf(tmp, "%d", raidrec->raid_level); 526 } 527 for (out = 999; 528 out != -1 && out != 0 && out != 1 && out != 4 && out != 5 529 && out != 10;) { 530 res = popup_and_get_string("Specify RAID level", prompt, tmp, 10); 531 if (!res) { 532 return; 533 } 534 strip_spaces(tmp); 535 if (tmp[0] == '[' && tmp[strlen(tmp) - 1] == ']') { 536 strcpy(sz, tmp); 537 strncpy(tmp, sz + 1, strlen(sz) - 2); 538 tmp[strlen(sz) - 2] = '\0'; 539 } 540 if (!strcmp(tmp, "linear")) { 541 out = -1; 542 } else if (!strncmp(tmp, "raid", 4)) { 543 out = atoi(tmp + 4); 544 } else { 545 out = atoi(tmp); 546 } 547 log_it(tmp); 548 if (is_this_raid_personality_registered(out)) { 549 log_it("Groovy. You've picked a RAID personality which is registered."); 550 } else { 551 if (ask_me_yes_or_no("You have chosen a RAID personality which is not registered with the kernel. Make another selection?")) { 552 out = 999; 1705 if (size_of_specific_device_in_mountlist(mountlist, device_str) >= 0) { 1706 popup_and_OK("Can't add this - you've got one already!"); 1707 b_res = NULL; 553 1708 } 554 1709 } 555 1710 } 556 mr_free(prompt); 557 558 raidrec->raid_level = out; 559 #endif 1711 newtFormDestroy(myForm); 1712 newtPopHelpLine(); 1713 newtPopWindow(); 1714 if (b_res == bCancel) { 1715 return; 1716 } 1717 mr_asprintf(drive_to_add, "%s", device_str); 1718 for (i = strlen(drive_to_add); isdigit(drive_to_add[i - 1]); i--); 1719 mr_free(drive_to_add); 1720 1721 currline = mountlist->entries; 1722 strcpy(mountlist->el[currline].device, device_str); 1723 strcpy(mountlist->el[currline].mountpoint, mountpoint_str); 1724 mr_free(mountpoint_str); 1725 1726 strcpy(mountlist->el[currline].format, format_str); 1727 mr_free(format_str); 1728 1729 mountlist->el[currline].size = atol(size_str) * 1024L; 1730 mr_free(size_str); 1731 1732 mountlist->entries++; 1733 if (strstr(mountlist->el[currline].device, RAID_DEVICE_STUB)) { 1734 initiate_new_raidlist_entry(raidlist, mountlist, currline, device_str); 1735 } 1736 mr_free(device_str); 1737 1738 redraw_mountlist(mountlist, keylist, listbox); 560 1739 } 561 1740 … … 601 1780 602 1781 603 604 /**605 * Delete entry number @p currline from @p disklist.606 * @param disklist The disklist to remove the entry from.607 * @param raid_device The RAID device containing the partition we're removing.608 * Used only in the popup "are you sure?" box.609 * @param currline The line number (starting from 0) of the item to delete.610 * @ingroup restoreGuiDisklist611 */612 void613 delete_disklist_entry(struct list_of_disks *disklist, char *raid_device,614 int currline)615 {616 617 /** int ***************************************************************/618 int pos = 0;619 int res = 0;620 621 /** buffers ***********************************************************/622 char *tmp = NULL;623 624 assert(disklist != NULL);625 assert_string_is_neither_NULL_nor_zerolength(raid_device);626 627 mr_asprintf(tmp, "Delete %s from RAID device %s - are you sure?", disklist->el[currline].device, raid_device);628 res = ask_me_yes_or_no(tmp);629 mr_free(tmp);630 631 if (!res) {632 return;633 }634 for (pos = currline; pos < disklist->entries - 1; pos++) {635 strcpy(disklist->el[pos].device, disklist->el[pos + 1].device);636 }637 disklist->entries--;638 }639 640 641 642 /**643 * Delete entry number @p currline from @p mountlist.644 * @param mountlist The mountlist to delete the entry from.645 * @param raidlist The raidlist that goes with @p mountlist.646 * @param listbox The Newt listbox component in the mountlist editor.647 * @param currline The line number (starting from 0) of the item to delete.648 * @param keylist The list of keys for @p listbox.649 * @ingroup restoreGuiMountlist650 */651 void652 delete_mountlist_entry(struct mountlist_itself *mountlist,653 struct raidlist_itself *raidlist,654 newtComponent listbox, int currline,655 void *keylist[])656 {657 658 /** int ***************************************************************/659 int pos = 0;660 int res = 0;661 662 /** buffers ***********************************************************/663 char *tmp = NULL;664 char *device = NULL;665 666 667 assert(mountlist != NULL);668 assert(raidlist != NULL);669 assert(listbox != NULL);670 assert(keylist != NULL);671 672 pos = which_raid_device_is_using_this_partition(raidlist, mountlist->el[currline].device);673 if (pos >= 0) {674 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));675 popup_and_OK(tmp);676 mr_free(tmp);677 return;678 }679 mr_asprintf(tmp, "Delete %s - are you sure?", mountlist->el[currline].device);680 res = ask_me_yes_or_no(tmp);681 mr_free(tmp);682 683 if (!res) {684 return;685 }686 if (strstr(mountlist->el[currline].device, RAID_DEVICE_STUB)) {687 mr_asprintf(device, "%s", mountlist->el[currline].device);688 delete_raidlist_entry(mountlist, raidlist, device);689 for (currline = 0;690 currline < mountlist->entries691 && strcmp(mountlist->el[currline].device, device);692 currline++);693 mr_free(device);694 695 if (currline == mountlist->entries) {696 log_it("Dev is gone. I can't delete it. Ho-hum");697 return;698 }699 }700 memcpy((void *) &mountlist->el[currline],701 (void *) &mountlist->el[mountlist->entries - 1],702 sizeof(struct mountlist_line));703 mountlist->entries--;704 redraw_mountlist(mountlist, keylist, listbox);705 }706 707 708 1782 /** 709 1783 * Delete @p device from @p raidlist. … … 713 1787 * @ingroup restoreGuiMountlist 714 1788 */ 715 void 716 delete_raidlist_entry(struct mountlist_itself *mountlist, 1789 void delete_raidlist_entry(struct mountlist_itself *mountlist, 717 1790 struct raidlist_itself *raidlist, char *device) 718 1791 { … … 783 1856 784 1857 785 #ifndef __FreeBSD__ 786 /** 787 * Delete entry number @p lino in the additional RAID variables section of @p raidrec. 788 * @param raidrec The RAID device record containing the RAID variable to delete. 789 * @param lino The line number (starting from 0) of the variable to delete. 790 * @ingroup restoreGuiVarslist 791 */ 792 void delete_varslist_entry(struct raid_device_record *raidrec, int lino) 793 { 794 795 /** buffers ************************************************************/ 1858 1859 /** 1860 * Delete entry number @p currline from @p mountlist. 1861 * @param mountlist The mountlist to delete the entry from. 1862 * @param raidlist The raidlist that goes with @p mountlist. 1863 * @param listbox The Newt listbox component in the mountlist editor. 1864 * @param currline The line number (starting from 0) of the item to delete. 1865 * @param keylist The list of keys for @p listbox. 1866 * @ingroup restoreGuiMountlist 1867 */ 1868 void 1869 delete_mountlist_entry(struct mountlist_itself *mountlist, 1870 struct raidlist_itself *raidlist, 1871 newtComponent listbox, int currline, 1872 void *keylist[]) 1873 { 1874 1875 /** int ***************************************************************/ 1876 int pos = 0; 1877 int res = 0; 1878 1879 /** buffers ***********************************************************/ 796 1880 char *tmp = NULL; 797 int res = 0; 798 799 /** structures *********************************************************/ 800 struct additional_raid_variables *av; 801 802 assert(raidrec != NULL); 803 804 av = &raidrec->additional_vars; 805 mr_asprintf(tmp, "Delete %s - are you sure?", av->el[lino].label); 1881 char *device = NULL; 1882 1883 1884 assert(mountlist != NULL); 1885 assert(raidlist != NULL); 1886 assert(listbox != NULL); 1887 assert(keylist != NULL); 1888 1889 pos = which_raid_device_is_using_this_partition(raidlist, mountlist->el[currline].device); 1890 if (pos >= 0) { 1891 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)); 1892 popup_and_OK(tmp); 1893 mr_free(tmp); 1894 return; 1895 } 1896 mr_asprintf(tmp, "Delete %s - are you sure?", mountlist->el[currline].device); 806 1897 res = ask_me_yes_or_no(tmp); 807 1898 mr_free(tmp); 808 1899 809 if (res) { 810 if (!strcmp(av->el[lino].label, "persistent-superblock") 811 || !strcmp(av->el[lino].label, "chunk-size")) { 812 mr_asprintf(tmp, "%s must not be deleted. It would be bad.", av->el[lino].label); 813 popup_and_OK(tmp); 814 mr_free(tmp); 1900 if (!res) { 1901 return; 1902 } 1903 if (strstr(mountlist->el[currline].device, RAID_DEVICE_STUB)) { 1904 mr_asprintf(device, "%s", mountlist->el[currline].device); 1905 delete_raidlist_entry(mountlist, raidlist, device); 1906 for (currline = 0; 1907 currline < mountlist->entries 1908 && strcmp(mountlist->el[currline].device, device); 1909 currline++); 1910 mr_free(device); 1911 1912 if (currline == mountlist->entries) { 1913 log_it("Dev is gone. I can't delete it. Ho-hum"); 1914 return; 1915 } 1916 } 1917 memcpy((void *) &mountlist->el[currline], 1918 (void *) &mountlist->el[mountlist->entries - 1], 1919 sizeof(struct mountlist_line)); 1920 mountlist->entries--; 1921 redraw_mountlist(mountlist, keylist, listbox); 1922 } 1923 1924 1925 /** 1926 * Strip a path to the bare minimum (^ pointing to the directory above, plus filename). 1927 * @param tmp The path to strip. 1928 * @return The stripped path. 1929 * @author Conor Daly 1930 * @ingroup restoreUtilityGroup 1931 */ 1932 char *strip_path(char *tmp) 1933 { 1934 1935 int i = 0, j = 0, slashcount = 0; 1936 int slashloc = 0, lastslashloc = 0; 1937 1938 while (tmp[i] != '\0') { /* Count the slashes in tmp 1939 1 slash per dir */ 1940 if (tmp[i] == '/') { 1941 slashcount++; 1942 lastslashloc = slashloc; 1943 slashloc = i; 1944 if (tmp[i + 1] == '\0') { /* if this slash is last char, back off */ 1945 slashcount--; 1946 slashloc = lastslashloc; 1947 } 1948 } 1949 i++; 1950 } 1951 if (slashcount > 0) 1952 slashcount--; /* Keep one slash 'cos Hugh does... */ 1953 1954 for (i = 0; i < slashcount; i++) { /* Replace each dir with a space char */ 1955 tmpnopath[i] = ' '; 1956 } 1957 1958 i = slashloc; 1959 j = slashcount; 1960 while (tmp[i] != '\0') { /* Now add what's left of tmp */ 1961 if ((tmpprevpath[j] == ' ' || tmpprevpath[j] == '^') 1962 && tmp[i] == '/' && tmpnopath[j - 1] != '^' && j != 0) { /* Add a pointer upwards if this is not in the same dir as line above */ 1963 tmpnopath[j - 1] = '^'; 815 1964 } else { 816 memcpy((void *) &av->el[lino], (void *) &av->el[av->entries--], 817 sizeof(struct raid_var_line)); 818 } 819 } 820 } 821 #endif 1965 tmpnopath[j++] = tmp[i++]; 1966 } 1967 } 1968 tmpnopath[j] = '\0'; 1969 1970 strcpy(tmpprevpath, tmpnopath); /* Make a copy for next iteration */ 1971 1972 return (tmpnopath); 1973 } 1974 822 1975 823 1976 … … 924 2077 return (0); 925 2078 } 926 }927 928 929 /**930 * Strip a path to the bare minimum (^ pointing to the directory above, plus filename).931 * @param tmp The path to strip.932 * @return The stripped path.933 * @author Conor Daly934 * @ingroup restoreUtilityGroup935 */936 char *strip_path(char *tmp)937 {938 939 int i = 0, j = 0, slashcount = 0;940 int slashloc = 0, lastslashloc = 0;941 942 while (tmp[i] != '\0') { /* Count the slashes in tmp943 1 slash per dir */944 if (tmp[i] == '/') {945 slashcount++;946 lastslashloc = slashloc;947 slashloc = i;948 if (tmp[i + 1] == '\0') { /* if this slash is last char, back off */949 slashcount--;950 slashloc = lastslashloc;951 }952 }953 i++;954 }955 if (slashcount > 0)956 slashcount--; /* Keep one slash 'cos Hugh does... */957 958 for (i = 0; i < slashcount; i++) { /* Replace each dir with a space char */959 tmpnopath[i] = ' ';960 }961 962 i = slashloc;963 j = slashcount;964 while (tmp[i] != '\0') { /* Now add what's left of tmp */965 if ((tmpprevpath[j] == ' ' || tmpprevpath[j] == '^')966 && tmp[i] == '/' && tmpnopath[j - 1] != '^' && j != 0) { /* Add a pointer upwards if this is not in the same dir as line above */967 tmpnopath[j - 1] = '^';968 } else {969 tmpnopath[j++] = tmp[i++];970 }971 }972 tmpnopath[j] = '\0';973 974 strcpy(tmpprevpath, tmpnopath); /* Make a copy for next iteration */975 976 return (tmpnopath);977 2079 } 978 2080 … … 1113 2215 1114 2216 /** 2217 * Change all RAID devices to use @p new_dev instead of @p old_dev. 2218 * @param raidlist The raidlist to make the changes in. 2219 * @param old_dev The old name of the device (what it used to be). 2220 * @param new_dev The new name of the device (what it is now). 2221 * @ingroup restoreGuiMountlist 2222 */ 2223 void rejig_partition_name_in_raidlist_if_necessary(struct raidlist_itself 2224 *raidlist, 2225 char *old_dev, 2226 char *new_dev) 2227 { 2228 /** int ************************************************************/ 2229 int pos = 0; 2230 int j = 0; 2231 2232 assert(raidlist != NULL); 2233 assert_string_is_neither_NULL_nor_zerolength(old_dev); 2234 assert_string_is_neither_NULL_nor_zerolength(new_dev); 2235 2236 pos = which_raid_device_is_using_this_partition(raidlist, old_dev); 2237 if (pos < 0) { 2238 log_it("No need to rejig %s in raidlist: it's not listed.", old_dev); 2239 } else { 2240 if ((j = 2241 where_in_drivelist_is_drive(&raidlist-> 2242 OSSWAP(el[pos].data_disks, disks), 2243 old_dev)) >= 0) { 2244 strcpy(raidlist->OSSWAP(el[pos].data_disks, disks).el[j].device, new_dev); 2245 } else 2246 if ((j = 2247 where_in_drivelist_is_drive(&raidlist-> 2248 OSSWAP(el[pos].spare_disks, 2249 spares), 2250 old_dev)) >= 0) { 2251 strcpy(raidlist->OSSWAP(el[pos].spare_disks, spares).el[j].device, new_dev); 2252 } 2253 #ifndef __FreeBSD__ 2254 else if ((j = 2255 where_in_drivelist_is_drive(&raidlist->el[pos]. 2256 parity_disks, 2257 old_dev)) >= 0) { 2258 strcpy(raidlist->el[pos].parity_disks.el[j].device, new_dev); 2259 } else 2260 if ((j = 2261 where_in_drivelist_is_drive(&raidlist->el[pos]. 2262 failed_disks, 2263 old_dev)) >= 0) { 2264 strcpy(raidlist->el[pos].failed_disks.el[j].device, new_dev); 2265 } 2266 #endif 2267 else { 2268 log_it("%s is supposed to be listed in this raid dev but it's not...", old_dev); 2269 } 2270 } 2271 } 2272 2273 2274 /** 1115 2275 * Edit an entry in @p mountlist. 1116 2276 * @param mountlist The mountlist containing information about the user's partitions. … … 1380 2540 struct vinum_plex *raidrec, int currline, 1381 2541 int currline2); 1382 1383 #endif1384 1385 1386 /**1387 * Edit the entry for @p raidrec in @p raidlist.1388 * @param mountlist The mountlist to get some information from.1389 * @param raidlist The raidlist containing information about RAID devices.1390 * @param raidrec The RAID device record for this partition.1391 * @param currline The line number (starting from 0) in the mountlist of the RAID device.1392 * @ingroup restoreGuiMountlist1393 */1394 void1395 edit_raidlist_entry(struct mountlist_itself *mountlist,1396 struct raidlist_itself *raidlist,1397 struct OSSWAP (raid_device_record,1398 vinum_volume) * raidrec, int currline)1399 {1400 1401 #ifdef __FreeBSD__1402 /** structures ********************************************************/1403 struct vinum_volume bkp_raidrec;1404 1405 1406 /** buffers ***********************************************************/1407 char title_of_editraidForm_window[MAX_STR_LEN];1408 1409 /** newt **************************************************************/1410 newtComponent editraidForm;1411 newtComponent bOK;1412 newtComponent bCancel;1413 newtComponent bEdit;1414 newtComponent bAdd;1415 newtComponent bDelete;1416 newtComponent b_res;1417 newtComponent plexesListbox;1418 newtComponent plexesHeader;1419 1420 void *keylist[10];1421 void *curr_choice;1422 char *raidlevel = NULL;1423 char *chunksize = NULL;1424 char *msg = NULL;1425 1426 int currline2 = 0;1427 int res = 0;1428 1429 log_it("Started edit_raidlist_entry");1430 memcpy((void *) &bkp_raidrec, (void *) raidrec,1431 sizeof(struct vinum_volume));1432 sprintf(title_of_editraidForm_window, "Plexes on %s",1433 raidrec->volname);1434 newtPushHelpLine(" Please select a plex to edit");1435 newtOpenWindow(13, 5, 54, 15, title_of_editraidForm_window);1436 for (;;) {1437 int i;1438 char *headerstr = NULL;1439 mr_asprintf(headerstr, "%-14s %-8s %11s %8s", "Plex", "Level", "Stripe Size", "Subdisks");1440 1441 bOK = newtCompactButton(2, 13, " OK ");1442 bCancel = newtCompactButton(12, 13, "Cancel");1443 bAdd = newtCompactButton(22, 13, " Add ");1444 bEdit = newtCompactButton(32, 13, " Edit ");1445 bDelete = newtCompactButton(42, 13, "Delete");1446 1447 plexesListbox =1448 newtListbox(2, 3, 9, NEWT_FLAG_SCROLL | NEWT_FLAG_RETURNEXIT);1449 plexesHeader = newtLabel(2, 2, headerstr);1450 mr_free(headerstr);1451 editraidForm = newtForm(NULL, NULL, 0);1452 1453 newtListboxClear(plexesListbox);1454 for (i = 0; i < 10; ++i) {1455 keylist[i] = (void *) i;1456 if (i < raidrec->plexes) {1457 char *pname;1458 char *entry;1459 switch (raidrec->plex[i].raidlevel) {1460 case -1:1461 mr_asprintf(raidlevel, "concat");1462 break;1463 case 0:1464 mr_asprintf(raidlevel, "striped");1465 break;1466 case 5:1467 mr_asprintf(raidlevel, "raid5");1468 break;1469 default:1470 mr_asprintf(raidlevel, "raid%i", raidrec->plex[i].raidlevel);1471 break;1472 }1473 1474 if (raidrec->plex[i].raidlevel == -1) {1475 mr_asprintf(chunksize, "N/A");1476 } else {1477 mr_asprintf(chunksize, "%dk", raidrec->plex[i].stripesize);1478 }1479 mr_asprintf(pname, "%s.p%i", raidrec->volname, i);1480 mr_asprintf(entry, "%-14s %-8s %11s %8d", pname, raidlevel, chunksize, raidrec->plex[i].subdisks);1481 mr_free(pname);1482 mr_free(raidlevel);1483 mr_free(chunksize);1484 1485 newtListboxAppendEntry(plexesListbox, entry, keylist[i]);1486 mr_free(entry);1487 }1488 }1489 1490 newtFormAddComponents(editraidForm, bOK, bCancel, bAdd, bEdit,1491 bDelete, plexesListbox, plexesHeader, NULL);1492 1493 b_res = newtRunForm(editraidForm);1494 if (b_res == bOK || b_res == bCancel) {1495 break;1496 }1497 1498 curr_choice = newtListboxGetCurrent(plexesListbox);1499 for (currline2 = 0; currline2 < raidrec->plexes; ++currline2) {1500 if (currline2 > 9)1501 break;1502 if (keylist[currline2] == curr_choice)1503 break;1504 }1505 1506 if (b_res == bDelete) {1507 mr_asprintf(msg, "Are you sure you want to delete %s.p%i?", raidrec->volname, currline2);1508 res = ask_me_yes_or_no(msg);1509 mr_free(msg);1510 1511 if (res) {1512 log_it("Deleting RAID plex");1513 memcpy((void *) &raidrec->plex[currline2],1514 (void *) &raidrec->plex[raidrec->plexes - 1],1515 sizeof(struct vinum_plex));1516 raidrec->plexes--;1517 }1518 continue;1519 }1520 if (b_res == bAdd) {1521 raidrec->plex[raidrec->plexes].raidlevel = 0;1522 raidrec->plex[raidrec->plexes].stripesize = 279;1523 raidrec->plex[raidrec->plexes].subdisks = 0;1524 currline2 = raidrec->plexes++;1525 }1526 edit_raidlist_plex(mountlist, raidlist, &raidrec->plex[currline2],1527 currline, currline2);1528 newtFormDestroy(editraidForm);1529 }1530 if (b_res == bCancel) {1531 memcpy((void *) raidrec, (void *) &bkp_raidrec,1532 sizeof(struct vinum_volume));1533 }1534 newtPopHelpLine();1535 newtPopWindow();1536 mountlist->el[currline].size =1537 calculate_raid_device_size(mountlist, raidlist, raidrec->volname);1538 #else1539 /** structures ********************************************************/1540 struct raid_device_record *bkp_raidrec;1541 1542 1543 /** buffers ***********************************************************/1544 char *title_of_editraidForm_window;1545 char *sz_raid_level = NULL;1546 char *sz_data_disks = NULL;1547 char *sz_spare_disks = NULL;1548 char *sz_parity_disks = NULL;1549 char *sz_failed_disks = NULL;1550 1551 /** newt **************************************************************/1552 newtComponent editraidForm;1553 newtComponent bOK;1554 newtComponent bCancel;1555 newtComponent bAdditional;1556 newtComponent bChangeRaid;1557 newtComponent bSelectData;1558 newtComponent bSelectSpare;1559 newtComponent bSelectParity;1560 newtComponent bSelectFailed;1561 newtComponent b_res;1562 1563 assert(mountlist != NULL);1564 assert(raidlist != NULL);1565 assert(raidrec != NULL);1566 1567 bkp_raidrec = mr_malloc(sizeof(struct raid_device_record));1568 log_it("Started edit_raidlist_entry");1569 1570 memcpy((void *) bkp_raidrec, (void *) raidrec, sizeof(struct raid_device_record));1571 mr_asprintf(title_of_editraidForm_window, "%s", raidrec->raid_device);1572 log_msg(2, "Opening newt window");1573 newtOpenWindow(20, 5, 40, 14, title_of_editraidForm_window);1574 for (;;) {1575 log_msg(2, "Main loop");1576 mr_free(title_of_editraidForm_window);1577 mr_asprintf(title_of_editraidForm_window, "Edit %s", raidrec->raid_device);1578 sz_raid_level = turn_raid_level_number_to_string(raidrec->raid_level);1579 sz_data_disks = number_of_disks_as_string(raidrec->data_disks.entries, "data");1580 sz_spare_disks = number_of_disks_as_string(raidrec->spare_disks.entries, "spare");1581 sz_parity_disks = number_of_disks_as_string(raidrec->parity_disks.entries, "parity");1582 sz_failed_disks = number_of_disks_as_string(raidrec->failed_disks.entries, "failed");1583 bSelectData = newtButton(1, 1, sz_data_disks);1584 bSelectSpare = newtButton(20, 1, sz_spare_disks);1585 bSelectParity = newtButton(1, 5, sz_parity_disks);1586 bSelectFailed = newtButton(20, 5, sz_failed_disks);1587 bChangeRaid = newtButton(1, 9, sz_raid_level);1588 bOK = newtButton(16 + (raidrec->raid_level == -1), 9, " OK ");1589 bCancel = newtButton(28, 9, "Cancel");1590 bAdditional =1591 newtCompactButton(1, 13,1592 "Additional settings and information");1593 newtPushHelpLine1594 (" Edit the RAID device's settings to your heart's content, then hit OK/Cancel.");1595 editraidForm = newtForm(NULL, NULL, 0);1596 newtFormAddComponents(editraidForm, bSelectData, bSelectParity,1597 bChangeRaid, bSelectSpare, bSelectFailed,1598 bOK, bCancel, bAdditional);1599 b_res = newtRunForm(editraidForm);1600 if (b_res == bChangeRaid) {1601 choose_raid_level(raidrec);1602 } else if (b_res == bSelectData) {1603 select_raid_disks(mountlist, raidlist, raidrec, "data", &raidrec->data_disks);1604 } else if (b_res == bSelectSpare) {1605 select_raid_disks(mountlist, raidlist, raidrec, "spare", &raidrec->spare_disks);1606 } else if (b_res == bSelectParity) {1607 select_raid_disks(mountlist, raidlist, raidrec, "parity", &raidrec->parity_disks);1608 } else if (b_res == bSelectFailed) {1609 select_raid_disks(mountlist, raidlist, raidrec, "failed", &raidrec->failed_disks);1610 } else if (b_res == bAdditional) {1611 edit_raidrec_additional_vars(raidrec);1612 }1613 newtFormDestroy(editraidForm);1614 if (b_res == bOK || b_res == bCancel) {1615 break;1616 }1617 mr_free(sz_data_disks);1618 mr_free(sz_spare_disks);1619 mr_free(sz_parity_disks);1620 mr_free(sz_failed_disks);1621 }1622 if (b_res == bCancel) {1623 memcpy((void *) raidrec, (void *) bkp_raidrec, sizeof(struct raid_device_record));1624 }1625 newtPopHelpLine();1626 newtPopWindow();1627 mountlist->el[currline].size = calculate_raid_device_size(mountlist, raidlist, raidrec->raid_device);1628 mr_free(title_of_editraidForm_window);1629 mr_free(sz_raid_level);1630 paranoid_free(bkp_raidrec);1631 #endif1632 }1633 1634 #ifdef __FreeBSD__1635 1636 /**1637 * Edit the plex @p raidrec in @p raidlist.1638 * @param mountlist The mountlist to get some of the information from.1639 * @param raidlist The raidlist containing information about RAID devices.1640 * @param raidrec The plex to edit.1641 * @param currline The line number (starting from 0) of the RAID device in @p mountlist.1642 * @param currline2 The line number (starting from 0) of the plex within the RAID device.1643 * @author Joshua Oreman1644 * @ingroup restoreGuiMountlist1645 */1646 void1647 edit_raidlist_plex(struct mountlist_itself *mountlist,1648 struct raidlist_itself *raidlist,1649 struct vinum_plex *raidrec, int currline, int currline2)1650 {1651 1652 /** structures ********************************************************/1653 struct vinum_plex bkp_raidrec;1654 1655 1656 /** buffers ***********************************************************/1657 char *title_of_editraidForm_window = NULL;1658 1659 /** newt **************************************************************/1660 newtComponent editraidForm;1661 newtComponent bOK;1662 newtComponent bCancel;1663 newtComponent bEdit;1664 newtComponent bAdd;1665 newtComponent bDelete;1666 newtComponent b_res;1667 newtComponent unallocListbox, allocListbox;1668 newtComponent bLevel, sLevel;1669 newtComponent bStripeSize, sStripeSize;1670 newtComponent bAlloc, bUnalloc;1671 1672 void *keylist[ARBITRARY_MAXIMUM];1673 void *curr_choice_a, *curr_choice_u;1674 int currline_a, currline_u;1675 1676 char *p = NULL;1677 char *tmp = NULL;1678 char *entry = NULL;1679 1680 struct mountlist_itself *unallocparts;1681 1682 unallocparts = malloc(sizeof(struct mountlist_itself));1683 1684 log_it("Started edit_raidlist_entry");1685 memcpy((void *) &bkp_raidrec, (void *) raidrec,1686 sizeof(struct vinum_plex));1687 mr_asprintf(title_of_editraidForm_window, "%s.p%i", raidlist->el[currline].volname, currline2);1688 newtPushHelpLine1689 (" Please select a subdisk to edit, or edit this plex's parameters");1690 newtOpenWindow(13, 3, 54, 18, title_of_editraidForm_window);1691 mr_free(title_of_editraidForm_window);1692 1693 for (;;) {1694 int i;1695 1696 switch (raidrec->raidlevel) {1697 case -1:1698 mr_asprintf(tmp, "concat");1699 break;1700 case 0:1701 mr_asprintf(tmp, "striped");1702 break;1703 case 5:1704 mr_asprintf(tmp, "raid5");1705 break;1706 default:1707 mr_asprintf(tmp, "unknown (%i)", raidrec->raidlevel);1708 break;1709 }1710 bLevel = newtCompactButton(2, 2, " RAID level ");1711 sLevel = newtLabel(19, 2, tmp);1712 mr_free(tmp);1713 1714 if (raidrec->raidlevel >= 0) {1715 mr_asprintf(tmp, "%ik", raidrec->stripesize);1716 bStripeSize = newtCompactButton(2, 4, " Stripe size ");1717 } else {1718 mr_asprintf(tmp, "N/A");1719 bStripeSize = newtLabel(2, 4, "Stripe size:");1720 }1721 sStripeSize = newtLabel(19, 4, tmp);1722 mr_free(tmp);1723 1724 bOK = newtCompactButton(2, 16, " OK ");1725 bCancel = newtCompactButton(12, 16, "Cancel");1726 bAdd = newtCompactButton(22, 16, " Add ");1727 bEdit = newtCompactButton(32, 16, " Edit ");1728 bDelete = newtCompactButton(42, 16, "Delete");1729 1730 1731 unallocListbox =1732 newtListbox(2, 7, 7, NEWT_FLAG_SCROLL | NEWT_FLAG_RETURNEXIT);1733 allocListbox =1734 newtListbox(33, 7, 7, NEWT_FLAG_SCROLL | NEWT_FLAG_RETURNEXIT);1735 bAlloc = newtButton(23, 7, " -> ");1736 bUnalloc = newtButton(23, 11, " <- ");1737 1738 editraidForm = newtForm(NULL, NULL, 0);1739 1740 newtListboxClear(allocListbox);1741 newtListboxClear(unallocListbox);1742 bzero(unallocparts, sizeof(struct mountlist_itself));1743 make_list_of_unallocated_raid_partitions(unallocparts, mountlist,1744 raidlist);1745 for (i = 0; i < ARBITRARY_MAXIMUM; ++i) {1746 keylist[i] = (void *) i;1747 if (i < raidrec->subdisks) {1748 mr_asprintf(entry, "%-17s", find_dev_entry_for_raid_device_name(raidlist, raidrec->sd[i].which_device));1749 newtListboxAppendEntry(allocListbox, entry, keylist[i]);1750 mr_free(entry);1751 }1752 if (i < unallocparts->entries) {1753 mr_asprintf(entry, "%-17s", unallocparts->el[i].device);1754 newtListboxAppendEntry(unallocListbox, entry, keylist[i]);1755 mr_free(entry);1756 }1757 }1758 1759 #define COMP(x) newtFormAddComponent (editraidForm, x)1760 #define UCOMP(x) if (unallocparts->entries > 0) COMP(x)1761 #define ACOMP(x) if (raidrec->subdisks > 0) COMP(x)1762 editraidForm = newtForm(NULL, NULL, 0);1763 UCOMP(unallocListbox);1764 UCOMP(bAlloc);1765 ACOMP(allocListbox);1766 ACOMP(bUnalloc);1767 COMP(bOK);1768 COMP(bCancel);1769 COMP(bLevel);1770 COMP(sLevel);1771 if (raidrec->raidlevel != -1) {1772 COMP(bStripeSize);1773 COMP(sStripeSize);1774 }1775 #undef COMP1776 #undef UCOMP1777 #undef ACOMP1778 1779 newtDrawForm(editraidForm);1780 newtRefresh();1781 b_res = newtRunForm(editraidForm);1782 if (b_res == bOK || b_res == bCancel) {1783 break;1784 }1785 1786 curr_choice_a = (raidrec->subdisks > 0) ?1787 newtListboxGetCurrent(allocListbox) : (void *) 1234;1788 curr_choice_u = (unallocparts->entries > 0) ?1789 newtListboxGetCurrent(unallocListbox) : (void *) 1234;1790 for (currline_a = 0; currline_a < raidrec->subdisks; ++currline_a) {1791 if (currline_a > ARBITRARY_MAXIMUM)1792 break;1793 if (keylist[currline_a] == curr_choice_a)1794 break;1795 }1796 for (currline_u = 0; currline_u < unallocparts->entries;1797 ++currline_u) {1798 if (currline_u > ARBITRARY_MAXIMUM)1799 break;1800 if (keylist[currline_u] == curr_choice_u)1801 break;1802 }1803 if (b_res == bLevel) {1804 choose_raid_level(raidrec);1805 } else if (b_res == bStripeSize) {1806 char tmp1[64];1807 sprintf(tmp1, "%i", raidrec->stripesize);1808 if (popup_and_get_string1809 ("Stripe size",1810 "Please enter the stripe size in kilobytes.", tmp1, 20)) {1811 raidrec->stripesize = atoi(tmp1);1812 }1813 } else if ((b_res == bAlloc) || (b_res == unallocListbox)) {1814 if (currline_u <= unallocparts->entries)1815 add_raid_subdisk(raidlist, raidrec,1816 unallocparts->el[currline_u].device);1817 } else if ((b_res == bUnalloc) || (b_res == allocListbox)) {1818 if (currline_a <= raidrec->subdisks) {1819 memcpy((void *) &raidrec->sd[currline_a],1820 (void *) &raidrec->sd[raidrec->subdisks - 1],1821 sizeof(struct vinum_subdisk));1822 raidrec->subdisks--;1823 }1824 }1825 newtFormDestroy(editraidForm);1826 newtRefresh();1827 }1828 1829 if (b_res == bCancel) {1830 memcpy((void *) raidrec, (void *) &bkp_raidrec, sizeof(struct vinum_plex));1831 }1832 newtPopWindow();1833 newtPopHelpLine();1834 }1835 #else1836 /**1837 * Edit additional RAID variable number @p lino.1838 * @param raidrec The RAID device record to edit the variable in.1839 * @param lino The line number (starting from 0) of the variable to edit.1840 * @ingroup restoreGuiVarslist1841 */1842 void edit_varslist_entry(struct raid_device_record *raidrec, int lino)1843 {1844 1845 /** buffers ***********************************************************/1846 char *header = NULL;1847 char *comment = NULL;1848 char sz_out[MAX_STR_LEN];1849 1850 assert(raidrec != 0);1851 assert(lino >= 0);1852 1853 strcpy(sz_out, raidrec->additional_vars.el[lino].value);1854 mr_asprintf(header, "Edit %s", raidrec->additional_vars.el[lino].label);1855 mr_asprintf(comment, "Please set %s's value (currently '%s')", raidrec->additional_vars.el[lino].label, sz_out);1856 if (popup_and_get_string(header, comment, sz_out, MAX_STR_LEN)) {1857 strip_spaces(sz_out);1858 strcpy(raidrec->additional_vars.el[lino].value, sz_out);1859 }1860 mr_free(header);1861 mr_free(comment);1862 }1863 2542 1864 2543 #endif … … 2048 2727 } 2049 2728 2050 2051 2052 2053 #ifndef __FreeBSD__2054 /**2055 * Edit the additional RAID variables in @p raidrec.2056 * @param raidrec The RAID device record to edit the RAID variables in.2057 * @ingroup restoreGuiVarslist2058 */2059 void edit_raidrec_additional_vars(struct raid_device_record *raidrec)2060 {2061 2062 /** structure *********************************************************/2063 struct raid_device_record bkp_raidrec;2064 2065 /** newt **************************************************************/2066 newtComponent myForm;2067 newtComponent bAdd;2068 newtComponent bEdit;2069 newtComponent bDelete;2070 newtComponent bOK;2071 newtComponent bCancel;2072 newtComponent b_res;2073 newtComponent varsListbox;2074 newtComponent headerMsg;2075 2076 /** ?? ***************************************************************/2077 void *keylist[ARBITRARY_MAXIMUM], *curr_choice;2078 2079 /** buffers **********************************************************/2080 char title_of_window[MAX_STR_LEN];2081 2082 /** int **************************************************************/2083 int i = 0;2084 int currline = 0;2085 2086 2087 assert(raidrec != NULL);2088 2089 memcpy((void *) &bkp_raidrec, (void *) raidrec,2090 sizeof(struct raid_device_record));2091 sprintf(title_of_window, "Additional variables");2092 newtPushHelpLine2093 (" Edit the additional fields to your heart's content, then click OK or Cancel.");2094 headerMsg = newtLabel(1, 1, "Label Value");2095 varsListbox =2096 newtListbox(1, 2, 6, NEWT_FLAG_SCROLL | NEWT_FLAG_RETURNEXIT);2097 i = 1;2098 bAdd = newtCompactButton(i, 9, " Add ");2099 bEdit = newtCompactButton(i += 8, 9, " Edit ");2100 bDelete = newtCompactButton(i += 9, 9, "Delete");2101 bOK = newtCompactButton(i += 9, 9, " OK ");2102 bCancel = newtCompactButton(i += 9, 9, "Cancel");2103 newtOpenWindow(17, 7, 46, 10, title_of_window);2104 myForm = newtForm(NULL, NULL, 0);2105 newtFormAddComponents(myForm, headerMsg, varsListbox, bAdd, bEdit,2106 bDelete, bOK, bCancel, NULL);2107 insert_essential_additionalvars(raidrec);2108 redraw_varslist(&raidrec->additional_vars, keylist, varsListbox);2109 for (b_res = NULL; b_res != bOK && b_res != bCancel;) {2110 b_res = newtRunForm(myForm);2111 curr_choice = newtListboxGetCurrent(varsListbox);2112 for (currline = 0;2113 currline < raidrec->additional_vars.entries2114 && keylist[currline] != curr_choice; currline++);2115 if (currline == raidrec->additional_vars.entries2116 && raidrec->additional_vars.entries > 0) {2117 log_it("Warning - I don't know what this button does");2118 }2119 if (b_res == bOK) { /* do nothing */2120 } else if (b_res == bCancel) { /* do nothing */2121 } else if (b_res == bAdd) {2122 add_varslist_entry(raidrec);2123 } else if (b_res == bDelete) {2124 delete_varslist_entry(raidrec, currline);2125 } else {2126 edit_varslist_entry(raidrec, currline);2127 }2128 redraw_varslist(&raidrec->additional_vars, keylist, varsListbox);2129 }2130 remove_essential_additionalvars(raidrec);2131 newtFormDestroy(myForm);2132 newtPopWindow();2133 newtPopHelpLine();2134 if (b_res == bCancel) {2135 memcpy((void *) raidrec, (void *) &bkp_raidrec,2136 sizeof(struct raid_device_record));2137 }2138 return;2139 }2140 #endif2141 2142 2143 /**2144 * Find the next free location to place a disk in @p disklist.2145 * @param disklist The disklist to operate on.2146 * @return The next free location (starting from 0).2147 * @ingroup restoreGuiDisklist2148 */2149 int find_next_free_index_in_disklist(struct list_of_disks *disklist)2150 {2151 2152 /** int ***************************************************************/2153 int index = -1;2154 int pos = 0;2155 2156 /** bool **************************************************************/2157 bool done;2158 2159 assert(disklist != NULL);2160 2161 for (done = FALSE; !done;) {2162 for (pos = 0;2163 pos < disklist->entries && disklist->el[pos].index <= index;2164 pos++);2165 if (pos >= disklist->entries) {2166 done = TRUE;2167 } else {2168 index = disklist->el[pos].index;2169 }2170 }2171 return (index + 1);2172 }2173 2174 2175 2176 /**2177 * Locate @p device in @p raidlist.2178 * @param raidlist The raidlist ot search in.2179 * @param device The RAID device to search for.2180 * @return The index of the device, or -1 if it could not be found.2181 * @ingroup restoreGuiMountlist2182 */2183 int2184 find_raid_device_in_raidlist(struct raidlist_itself *raidlist,2185 char *device)2186 {2187 2188 /** int ***************************************************************/2189 int i = 0;2190 #ifdef __FreeBSD__2191 char *vdev = NULL;2192 int res = 0;2193 #else2194 // Linux2195 #endif2196 2197 assert(raidlist != NULL);2198 assert_string_is_neither_NULL_nor_zerolength(device);2199 2200 #ifdef __FreeBSD__2201 for (i = 0; i < raidlist->entries; i++) {2202 mr_asprintf(vdev, "/dev/vinum/%s", raidlist->el[i].volname);2203 res = strcmp(device, vdev);2204 mr_free(vdev);2205 2206 if (!res)2207 break;2208 }2209 #else2210 2211 for (i = 0;2212 strcmp(raidlist->el[i].raid_device, device)2213 && i < raidlist->entries; i++);2214 #endif2215 if (i == raidlist->entries) {2216 return (-1);2217 } else {2218 return (i);2219 }2220 }2221 2222 2223 /**2224 * Create a new raidtab entry for @p device in @p raidlist.2225 * @param raidlist The raidlist to add the device to.2226 * @param mountlist The mountlist containing information about the user's partitions.2227 * @param currline The selected line in the mountlist.2228 * @param device The RAID device (e.g. /dev/md0) to use.2229 * @ingroup restoreGuiMountlist2230 */2231 void2232 initiate_new_raidlist_entry(struct raidlist_itself *raidlist,2233 struct mountlist_itself *mountlist,2234 int currline, char *device)2235 {2236 2237 /** structure *********************************************************/2238 struct OSSWAP (raid_device_record, vinum_volume) * raidrec;2239 2240 /** int ***************************************************************/2241 int pos_in_raidlist = 0;2242 2243 assert(raidlist != NULL);2244 assert(mountlist != NULL);2245 assert_string_is_neither_NULL_nor_zerolength(device);2246 2247 pos_in_raidlist =2248 find_raid_device_in_raidlist(raidlist,2249 mountlist->el[currline].device);2250 if (pos_in_raidlist >= 0) {2251 fatal_error("Sorry, that RAID device already exists. Weird.");2252 }2253 pos_in_raidlist = raidlist->entries++;2254 raidrec = &raidlist->el[pos_in_raidlist];2255 initialize_raidrec(raidrec);2256 strcpy(raidrec->OSSWAP(raid_device, volname), OSSWAP(device, basename(device)));2257 #ifndef __FreeBSD__2258 choose_raid_level(raidrec);2259 select_raid_disks(mountlist, raidlist, raidrec, "data",2260 &raidrec->data_disks);2261 #endif2262 edit_raidlist_entry(mountlist, raidlist, raidrec, currline);2263 }2264 2265 2266 #ifndef __FreeBSD__2267 /**2268 * Insert the RAID variables not stored in the "additional RAID variables" list there too.2269 * @param raidrec The RAID device record to operate on.2270 * @ingroup restoreGuiVarslist2271 */2272 void insert_essential_additionalvars(struct raid_device_record *raidrec)2273 {2274 2275 /** int **************************************************************/2276 int items = 0;2277 2278 assert(raidrec != NULL);2279 2280 items = raidrec->additional_vars.entries;2281 write_variableINT_to_raid_var_line(raidrec, items++,2282 "persistent-superblock",2283 raidrec->persistent_superblock);2284 write_variableINT_to_raid_var_line(raidrec, items++, "chunk-size",2285 raidrec->chunk_size);2286 raidrec->additional_vars.entries = items;2287 }2288 2289 #endif2290 2291 2729 /** 2292 2730 * Dummy function that proves that we can get to the point where Mondo is run. … … 2314 2752 newtPopHelpLine(); 2315 2753 } 2316 2317 2318 2319 /**2320 * Redraw the disklist.2321 * @param disklist The disklist to read from.2322 * @param keylist The list of keys for @p listbox.2323 * @param listbox The Newt listbox component to redraw.2324 * @ingroup restoreGuiDisklist2325 */2326 void2327 redraw_disklist(struct list_of_disks *disklist,2328 void *keylist[ARBITRARY_MAXIMUM], newtComponent listbox)2329 {2330 2331 /** long **************************************************************/2332 long i = 0;2333 char *tmp = NULL;2334 2335 assert(disklist != NULL);2336 assert(keylist != NULL);2337 assert(listbox != NULL);2338 2339 newtListboxClear(listbox);2340 2341 for (i = 0; i < ARBITRARY_MAXIMUM; i++) {2342 keylist[i] = (void *) i;2343 }2344 for (i = 0; i < disklist->entries; i++) {2345 tmp = disklist_entry_to_string(disklist, i);2346 newtListboxAppendEntry(listbox, tmp, keylist[i]);2347 mr_free(tmp);2348 }2349 }2350 2351 2352 /**2353 * Redraw the mountlist.2354 * @param mountlist The mountlist to read from.2355 * @param keylist The list of keys for @p listbox.2356 * @param listbox The Newt listbox component to redraw.2357 * @ingroup restoreGuiMountlist2358 */2359 void2360 redraw_mountlist(struct mountlist_itself *mountlist,2361 void *keylist[ARBITRARY_MAXIMUM], newtComponent listbox)2362 {2363 2364 /** long **************************************************************/2365 long i = 0;2366 char * tmp = NULL;2367 2368 assert(mountlist != NULL);2369 assert(keylist != NULL);2370 assert(listbox != NULL);2371 2372 newtListboxClear(listbox);2373 // sort_mountlist_by_device (mountlist);2374 for (i = 0; i < ARBITRARY_MAXIMUM; i++) {2375 keylist[i] = (void *) i;2376 }2377 for (i = 0; i < mountlist->entries; i++) {2378 tmp = mountlist_entry_to_string(mountlist, i);2379 newtListboxAppendEntry(listbox, tmp, keylist[i]);2380 mr_free(tmp);2381 }2382 }2383 2384 2385 2386 2387 /**2388 * Redraw the list of unallocated RAID partitions.2389 * @param unallocated_raid_partitions The mountlist containing unallocated RAID partitions.2390 * @param keylist The list of keys for @p listbox.2391 * @param listbox The Newt listbox component to redraw.2392 * @ingroup restoreGuiDisklist2393 */2394 void redraw_unallocpartnslist(struct mountlist_itself2395 *unallocated_raid_partitions,2396 void *keylist[ARBITRARY_MAXIMUM],2397 newtComponent listbox)2398 {2399 2400 /** long *************************************************************/2401 long i = 0;2402 2403 /** buffers **********************************************************/2404 char tmp[MAX_STR_LEN];2405 2406 assert(unallocated_raid_partitions != NULL);2407 assert(keylist != NULL);2408 assert(listbox != NULL);2409 2410 newtListboxClear(listbox);2411 for (i = 0; i < ARBITRARY_MAXIMUM; i++) {2412 keylist[i] = (void *) i;2413 }2414 for (i = 0; i < unallocated_raid_partitions->entries; i++) {2415 sprintf(tmp, "%-22s %8lld",2416 unallocated_raid_partitions->el[i].device,2417 unallocated_raid_partitions->el[i].size / 1024L);2418 newtListboxAppendEntry(listbox, tmp, keylist[i]);2419 }2420 }2421 2422 #ifndef __FreeBSD__2423 /**2424 * Redraw the list of additional RAID variables.2425 * @param additional_vars The list of additional RAID varibals.2426 * @param keylist The list of keys for @p listbox.2427 * @param listbox The Newt listbox component to redraw.2428 * @ingroup restoreGuiVarslist2429 */2430 void2431 redraw_varslist(struct additional_raid_variables *additional_vars,2432 void *keylist[], newtComponent listbox)2433 {2434 /** long ************************************************************/2435 long i = 0;2436 2437 /** buffers *********************************************************/2438 char tmp[MAX_STR_LEN];2439 2440 assert(additional_vars != NULL);2441 assert(keylist != NULL);2442 assert(listbox != NULL);2443 2444 newtListboxClear(listbox);2445 2446 for (i = 0; i < ARBITRARY_MAXIMUM; i++) {2447 keylist[i] = (void *) i;2448 }2449 for (i = 0; i < additional_vars->entries; i++) {2450 sprintf(tmp, "%-32s %-8s", additional_vars->el[i].label,2451 additional_vars->el[i].value);2452 newtListboxAppendEntry(listbox, tmp, keylist[i]);2453 }2454 }2455 2456 2457 /**2458 * Remove variable @p label from the RAID variables list in @p raidrec.2459 * @param raidrec The RAID device record to remove the variable from.2460 * @param label The variable name to remove.2461 * @return The value of the variable removed.2462 * @ingroup restoreUtilityGroup2463 */2464 int2465 read_variableINT_and_remove_from_raidvars(struct2466 OSSWAP (raid_device_record,2467 vinum_volume) * raidrec,2468 char *label)2469 {2470 /** int ***************************************************************/2471 int i = 0;2472 int res = 0;2473 2474 2475 assert(raidrec != NULL);2476 assert(label != NULL);2477 2478 for (i = 0;2479 i < raidrec->additional_vars.entries2480 && strcmp(raidrec->additional_vars.el[i].label, label); i++);2481 if (i == raidrec->additional_vars.entries) {2482 res = -1;2483 } else {2484 res = atoi(raidrec->additional_vars.el[i].value);2485 for (i++; i < raidrec->additional_vars.entries; i++) {2486 memcpy((void *) &raidrec->additional_vars.el[i - 1],2487 (void *) &raidrec->additional_vars.el[i],2488 sizeof(struct raid_var_line));2489 }2490 raidrec->additional_vars.entries--;2491 }2492 return (res);2493 }2494 #endif2495 2496 /**2497 * Change all RAID devices to use @p new_dev instead of @p old_dev.2498 * @param raidlist The raidlist to make the changes in.2499 * @param old_dev The old name of the device (what it used to be).2500 * @param new_dev The new name of the device (what it is now).2501 * @ingroup restoreGuiMountlist2502 */2503 void rejig_partition_name_in_raidlist_if_necessary(struct raidlist_itself2504 *raidlist,2505 char *old_dev,2506 char *new_dev)2507 {2508 /** int ************************************************************/2509 int pos = 0;2510 int j = 0;2511 2512 assert(raidlist != NULL);2513 assert_string_is_neither_NULL_nor_zerolength(old_dev);2514 assert_string_is_neither_NULL_nor_zerolength(new_dev);2515 2516 pos = which_raid_device_is_using_this_partition(raidlist, old_dev);2517 if (pos < 0) {2518 log_it("No need to rejig %s in raidlist: it's not listed.", old_dev);2519 } else {2520 if ((j =2521 where_in_drivelist_is_drive(&raidlist->2522 OSSWAP(el[pos].data_disks, disks),2523 old_dev)) >= 0) {2524 strcpy(raidlist->OSSWAP(el[pos].data_disks, disks).el[j].device, new_dev);2525 } else2526 if ((j =2527 where_in_drivelist_is_drive(&raidlist->2528 OSSWAP(el[pos].spare_disks,2529 spares),2530 old_dev)) >= 0) {2531 strcpy(raidlist->OSSWAP(el[pos].spare_disks, spares).el[j].device, new_dev);2532 }2533 #ifndef __FreeBSD__2534 else if ((j =2535 where_in_drivelist_is_drive(&raidlist->el[pos].2536 parity_disks,2537 old_dev)) >= 0) {2538 strcpy(raidlist->el[pos].parity_disks.el[j].device, new_dev);2539 } else2540 if ((j =2541 where_in_drivelist_is_drive(&raidlist->el[pos].2542 failed_disks,2543 old_dev)) >= 0) {2544 strcpy(raidlist->el[pos].failed_disks.el[j].device, new_dev);2545 }2546 #endif2547 else {2548 log_it("%s is supposed to be listed in this raid dev but it's not...", old_dev);2549 }2550 }2551 }2552 2553 2554 #ifndef __FreeBSD__2555 /**2556 * Remove the essential RAID variables from the "additional variables" section.2557 * If they have been changed, set them in their normal locations too.2558 * @param raidrec The RAID device record to operate on.2559 * @ingroup restoreUtilityVarslist2560 */2561 void remove_essential_additionalvars(struct raid_device_record *raidrec)2562 {2563 2564 /** int **************************************************************/2565 int res = 0;2566 2567 assert(raidrec != NULL);2568 2569 res =2570 read_variableINT_and_remove_from_raidvars(raidrec,2571 "persistent-superblock");2572 if (res > 0) {2573 raidrec->persistent_superblock = res;2574 }2575 res = read_variableINT_and_remove_from_raidvars(raidrec, "chunk-size");2576 if (res > 0) {2577 raidrec->chunk_size = res;2578 }2579 res = read_variableINT_and_remove_from_raidvars(raidrec, "block-size");2580 }2581 2582 /**2583 * Select the RAID disks to use in @p raidrec.2584 * @param mountlist_dontedit The mountlist (will not be edited).2585 * @param raidlist The raidlist to modify.2586 * @param raidrec The RAID device record in @p raidlist to work on.2587 * @param description_of_list The type of disks we're selecting (e.g. "data").2588 * @param disklist The disklist to put the user-selected disks in.2589 * @ingroup restoreGuiMountlist2590 */2591 void2592 select_raid_disks(struct mountlist_itself *mountlist_dontedit,2593 struct raidlist_itself *raidlist,2594 struct raid_device_record *raidrec,2595 char *description_of_list,2596 struct list_of_disks *disklist)2597 {2598 void *curr_choice;2599 2600 /** ??? ***************************************************************/2601 2602 /** structures ********************************************************/2603 struct raidlist_itself *bkp_raidlist;2604 struct raid_device_record *bkp_raidrec;2605 struct list_of_disks *bkp_disklist;2606 struct mountlist_itself *unallocated_raid_partitions;2607 2608 /** newt **************************************************************/2609 newtComponent myForm = NULL;2610 newtComponent bAdd = NULL;2611 newtComponent bDelete = NULL;2612 newtComponent bOK = NULL;2613 newtComponent bCancel = NULL;2614 newtComponent b_res = NULL;2615 newtComponent partitionsListbox = NULL;2616 newtComponent headerMsg = NULL;2617 2618 /** buffers **********************************************************/2619 void *keylist[ARBITRARY_MAXIMUM];2620 char *tmp = NULL;2621 char *help_text = NULL;2622 char *title_of_window = NULL;2623 char sz_res[MAX_STR_LEN];2624 char *header_text = NULL;2625 2626 /** int **************************************************************/2627 int i = 0;2628 int currline = 0;2629 2630 assert(mountlist_dontedit != NULL);2631 assert(raidlist != NULL);2632 assert(raidrec != NULL);2633 assert(description_of_list != NULL);2634 assert(disklist != NULL);2635 2636 log_it("malloc'ing");2637 bkp_raidrec = mr_malloc(sizeof(struct raid_device_record));2638 bkp_disklist = mr_malloc(sizeof(struct list_of_disks));2639 bkp_raidlist = mr_malloc(sizeof(struct raidlist_itself));2640 unallocated_raid_partitions = mr_malloc(sizeof(struct mountlist_itself));2641 2642 memcpy((void *) bkp_raidlist, (void *) raidlist, sizeof(struct raidlist_itself));2643 memcpy((void *) bkp_raidrec, (void *) raidrec, sizeof(struct raid_device_record));2644 memcpy((void *) bkp_disklist, (void *) disklist, sizeof(struct list_of_disks));2645 2646 log_it("Post-malloc");2647 mr_asprintf(help_text, " Edit this RAID device's list of partitions. Choose OK or Cancel when done.");2648 mr_asprintf(header_text, "%-24s %s", "Device", "Index");2649 mr_asprintf(title_of_window, "%s contains...", raidrec->raid_device);2650 newtPushHelpLine(help_text);2651 for (b_res = (newtComponent) 12345; b_res != bOK && b_res != bCancel;) {2652 headerMsg = newtLabel(1, 1, header_text);2653 partitionsListbox =2654 newtListbox(1, 2, 6, NEWT_FLAG_SCROLL | NEWT_FLAG_RETURNEXIT);2655 redraw_disklist(disklist, keylist, partitionsListbox);2656 i = 1;2657 bAdd = newtCompactButton(i, 9, " Add ");2658 bDelete = newtCompactButton(i += 8, 9, "Delete");2659 bOK = newtCompactButton(i += 9, 9, " OK ");2660 bCancel = newtCompactButton(i += 9, 9, "Cancel");2661 newtOpenWindow(21, 7, 38, 10, title_of_window);2662 myForm = newtForm(NULL, NULL, 0);2663 if (disklist->entries == 0) {2664 newtFormAddComponents(myForm, headerMsg, bAdd, bDelete, bOK,2665 bCancel, NULL);2666 } else {2667 newtFormAddComponents(myForm, headerMsg, partitionsListbox,2668 bAdd, bDelete, bOK, bCancel, NULL);2669 }2670 b_res = newtRunForm(myForm);2671 if (b_res == bOK || b_res == bCancel) { /* do nothing */2672 // That's OK. At the end of this subroutine (after this do/while loop),2673 // we'll throw away the changes if Cancel was pushed.2674 } else {2675 curr_choice = newtListboxGetCurrent(partitionsListbox);2676 for (i = 0; i < disklist->entries && keylist[i] != curr_choice;2677 i++);2678 if (i == disklist->entries && disklist->entries > 0) {2679 log_to_screen("I don't know what that button does!");2680 } else {2681 currline = i;2682 if (b_res == bAdd) {2683 log_it("Making list of unallocated RAID slices");2684 make_list_of_unallocated_raid_partitions2685 (unallocated_raid_partitions, mountlist_dontedit,2686 raidlist);2687 if (unallocated_raid_partitions->entries <= 0) {2688 popup_and_OK2689 ("There are no unallocated partitions marked for RAID.");2690 } else {2691 log_it2692 ("Done. The user may add one or more of the above to RAID device");2693 add_disklist_entry(disklist, raidrec->raid_device,2694 unallocated_raid_partitions);2695 log_it("I have finished adding a disklist entry.");2696 redraw_disklist(disklist, keylist,2697 partitionsListbox);2698 }2699 } else if (b_res == bDelete) {2700 delete_disklist_entry(disklist, raidrec->raid_device,2701 currline);2702 redraw_disklist(disklist, keylist, partitionsListbox);2703 } else {2704 mr_asprintf(tmp, "%s's index is %d. What should it be?", raidrec->raid_device, disklist->el[currline].index);2705 sprintf(sz_res, "%d", disklist->el[currline].index);2706 if (popup_and_get_string("Set index", tmp, sz_res, 10)) {2707 disklist->el[currline].index = atoi(sz_res);2708 }2709 mr_free(tmp);2710 2711 redraw_disklist(disklist, keylist, partitionsListbox);2712 }2713 }2714 }2715 newtFormDestroy(myForm);2716 newtPopWindow();2717 }2718 newtPopHelpLine();2719 mr_free(help_text);2720 mr_free(header_text);2721 mr_free(title_of_window);2722 2723 if (b_res == bCancel) {2724 memcpy((void *) raidlist, (void *) bkp_raidlist, sizeof(struct raidlist_itself));2725 memcpy((void *) raidrec, (void *) bkp_raidrec, sizeof(struct raid_device_record));2726 memcpy((void *) disklist, (void *) bkp_disklist, sizeof(struct list_of_disks));2727 }2728 mr_free(bkp_raidrec);2729 mr_free(bkp_disklist);2730 mr_free(bkp_raidlist);2731 mr_free(unallocated_raid_partitions);2732 }2733 #endif2734 2735 2736 2754 2737 2755 /**
Note:
See TracChangeset
for help on using the changeset viewer.