1 /* $NetBSD: partman.c,v 1.43 2019/10/06 00:05:10 mrg Exp $ */ 2 3 /* 4 * Copyright 2012 Eugene Lozovoy 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. The name of Eugene Lozovoy may not be used to endorse 16 * or promote products derived from this software without specific prior 17 * written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY PIERMONT INFORMATION SYSTEMS INC. ``AS IS'' 20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL PIERMONT INFORMATION SYSTEMS INC. BE 23 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 29 * THE POSSIBILITY OF SUCH DAMAGE. 30 * 31 */ 32 33 /* 34 * Copyright 2010 The NetBSD Foundation, Inc. 35 * All rights reserved. 36 * 37 * Redistribution and use in source and binary forms, with or without 38 * modification, are permitted provided that the following conditions 39 * are met: 40 * 1. Redistributions of source code must retain the above copyright 41 * notice, this list of conditions and the following disclaimer. 42 * 2. Redistributions in binary form must reproduce the above copyright 43 * notice, this list of conditions and the following disclaimer in the 44 * documentation and/or other materials provided with the distribution. 45 * 46 * THIS SOFTWARE IS PROVIDED BY PIERMONT INFORMATION SYSTEMS INC. ``AS IS'' 47 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 48 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 49 * ARE DISCLAIMED. IN NO EVENT SHALL PIERMONT INFORMATION SYSTEMS INC. BE 50 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 51 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 52 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 53 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 54 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 55 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 56 * THE POSSIBILITY OF SUCH DAMAGE. 57 * 58 */ 59 60 /* partman.c - extended partitioning */ 61 62 #include <assert.h> 63 #include <fcntl.h> 64 #include <errno.h> 65 #include <libgen.h> 66 #include <stdio.h> 67 #include <stdlib.h> 68 #include <unistd.h> 69 #include <util.h> 70 71 #include "defs.h" 72 #include "msg_defs.h" 73 #include "menu_defs.h" 74 75 /* XXX: replace all MAX_* defines with vars that depend on kernel settings */ 76 #define MAX_ENTRIES 96 77 78 #define MAX_RAID 8 79 #define MAX_IN_RAID 48 80 struct raid_comp { 81 char name[SSTRSIZE]; /* display name for this component */ 82 struct disk_partitions *parts; /* where is this on? */ 83 part_id id; /* which partition in parts */ 84 bool is_spare; /* is this a spare component? */ 85 }; 86 struct raid_desc { 87 int enabled; 88 int blocked; 89 int node; /* the N in raid${N} */ 90 int numRow, numCol, numSpare; 91 int sectPerSU, SUsPerParityUnit, SUsPerReconUnit, raid_level; 92 daddr_t total_size; 93 struct raid_comp comp[MAX_IN_RAID]; 94 }; 95 struct raid_desc *raids; 96 97 #define MAX_VND 4 98 struct vnd_desc { 99 int enabled; 100 int blocked; 101 int node; /* the N in vnd${N} */ 102 char filepath[STRSIZE]; 103 daddr_t size; 104 int readonly; 105 int is_exist; 106 int manual_geom; 107 int secsize, nsectors, ntracks, ncylinders; 108 struct pm_devs *pm; /* device this is on */ 109 part_id pm_part; /* which partition (in pm->parts) */ 110 }; 111 struct vnd_desc *vnds; 112 113 #define MAX_CGD 4 114 struct cgd_desc { 115 int enabled; 116 int blocked; 117 int node; /* the N in cgd${N} */ 118 char pm_name[SSTRSIZE]; 119 const char *keygen_type; 120 const char *verify_type; 121 const char *enc_type; 122 const char *iv_type; 123 int key_size; 124 struct pm_devs *pm; /* device this is on */ 125 part_id pm_part; /* which partition (in pm->parts) */ 126 }; 127 struct cgd_desc *cgds; 128 129 #define MAX_LVM_VG 16 130 #define MAX_LVM_PV 255 131 #define MAX_LVM_LV 255 132 typedef struct pv_t { 133 struct pm_devs *pm; 134 char pm_name[SSTRSIZE]; 135 part_id pm_part; 136 int metadatasize; 137 int metadatacopies; 138 int labelsector; 139 int setphysicalvolumesize; 140 } pv_t; 141 typedef struct lv_t { 142 int blocked; 143 daddr_t size; 144 char name[SSTRSIZE]; 145 int readonly; 146 int contiguous; 147 char extents[SSTRSIZE]; 148 int minor; 149 int mirrors; 150 int regionsize; 151 int persistent; 152 int readahead; 153 int stripes; 154 int stripesize; 155 int zero; 156 } lv_t; 157 typedef struct lvms_t { 158 int enabled; 159 int blocked; 160 char name[SSTRSIZE]; 161 int maxlogicalvolumes; 162 int maxphysicalvolumes; 163 int physicalextentsize; 164 daddr_t total_size; 165 pv_t pv[MAX_LVM_PV]; 166 lv_t lv[MAX_LVM_LV]; 167 } lvms_t; 168 lvms_t *lvms; 169 170 typedef struct structinfo_t { 171 int max; 172 uint entry_size; 173 uint parent_size; 174 void *entry_first; 175 void *entry_enabled; 176 void *entry_blocked; 177 void *entry_node; 178 } structinfo_t; 179 structinfo_t raids_t_info, vnds_t_info, cgds_t_info, lvms_t_info, lv_t_info; 180 181 typedef struct pm_upddevlist_adv_t { 182 const char *create_msg; 183 int pe_type; 184 structinfo_t *s; 185 int sub_num; 186 struct pm_upddevlist_adv_t *sub; 187 } pm_upddevlist_adv_t; 188 189 #define MAX_MNTS 48 190 struct { 191 char dev[STRSIZE]; 192 const char *mnt_opts, *on; 193 } *mnts; 194 195 int cursel; /* Number of selected entry in main menu */ 196 int changed; /* flag indicating that we have unsaved changes */ 197 int raid_curspare; /* XXX: replace by true way */ 198 199 enum { /* RAIDframe menu enum */ 200 PMR_MENU_DEVS, PMR_MENU_DEVSSPARE, PMR_MENU_RAIDLEVEL, PMR_MENU_NUMROW, 201 PMR_MENU_NUMCOL, PMR_MENU_NUMSPARE, PMR_MENU_SECTPERSU, PMR_MENU_SUSPERPARITYUNIT, 202 PMR_MENU_SUSPERRECONUNIT, PMR_MENU_REMOVE, PMR_MENU_END 203 }; 204 205 enum { /* VND menu enum */ 206 PMV_MENU_FILEPATH, PMV_MENU_EXIST, PMV_MENU_SIZE, PMV_MENU_RO, PMV_MENU_MGEOM, 207 PMV_MENU_SECSIZE, PMV_MENU_NSECTORS, PMV_MENU_NTRACKS, PMV_MENU_NCYLINDERS, 208 PMV_MENU_REMOVE, PMV_MENU_END 209 }; 210 211 enum { /* CGD menu enum */ 212 PMC_MENU_DEV, PMC_MENU_ENCTYPE, PMC_MENU_KEYSIZE, PMC_MENU_IVTYPE, 213 PMC_MENU_KEYGENTYPE, PMC_MENU_VERIFYTYPE, PMC_MENU_REMOVE, PMC_MENU_END 214 }; 215 216 enum { /* LVM menu enum */ 217 PML_MENU_PV, PML_MENU_NAME, PML_MENU_MAXLOGICALVOLUMES, 218 PML_MENU_MAXPHYSICALVOLUMES, PML_MENU_PHYSICALEXTENTSIZE, 219 PML_MENU_REMOVE, PML_MENU_END 220 }; 221 222 enum { /* LVM submenu (logical volumes) enum */ 223 PMLV_MENU_NAME, PMLV_MENU_SIZE, PMLV_MENU_READONLY, PMLV_MENU_CONTIGUOUS, 224 PMLV_MENU_EXTENTS, PMLV_MENU_MINOR, PMLV_MENU_PERSISTENT, 225 PMLV_MENU_MIRRORS, PMLV_MENU_REGIONSIZE, PMLV_MENU_READAHEAD, 226 PMLV_MENU_STRIPES, PMLV_MENU_STRIPESIZE, PMLV_MENU_ZERO, 227 PMLV_MENU_REMOVE, PMLV_MENU_END 228 }; 229 230 struct part_entry pm_dev_list(int); 231 static int pm_raid_disk_add(menudesc *, void *); 232 static int pm_raid_disk_del(menudesc *, void *); 233 static int pm_cgd_disk_set(struct cgd_desc *, struct part_entry *); 234 static int pm_mount(struct pm_devs *, int); 235 static int pm_upddevlist(menudesc *, void *); 236 static void pm_select(struct pm_devs *); 237 238 static void 239 pm_edit_size_value(msg prompt_msg, daddr_t cylsec, daddr_t *size) 240 { 241 242 char answer[16], dflt[16]; 243 daddr_t new_size_val, mult; 244 245 snprintf(dflt, sizeof dflt, "%" PRIu64 "%s", *size / sizemult, 246 multname); 247 248 msg_prompt_win(prompt_msg, -1, 18, 0, 0, dflt, answer, sizeof answer); 249 250 mult = sizemult; 251 new_size_val = parse_disk_pos(answer, &mult, cylsec, NULL); 252 253 if (new_size_val > 0) 254 *size = new_size_val; 255 } 256 257 static const char * 258 pm_get_mount(struct pm_devs *p, part_id id) 259 { 260 261 if (p->mounted == NULL) 262 return NULL; 263 if (id >= p->parts->num_part) 264 return NULL; 265 return p->mounted[id]; 266 } 267 268 bool pm_set_mount(struct pm_devs *p, part_id id, const char *path); 269 270 bool 271 pm_set_mount(struct pm_devs *p, part_id id, const char *path) 272 { 273 274 if (p->parts == NULL || id >= p->parts->num_part) 275 return false; 276 277 if (p->mounted == NULL) { 278 p->mounted = calloc(p->parts->num_part, sizeof(char*)); 279 if (p->mounted == NULL) 280 return false; 281 } 282 free(p->mounted[id]); 283 p->mounted[id] = strdup(path); 284 return p->mounted[id] != NULL; 285 } 286 287 /* Universal menu for RAID/VND/CGD/LVM entry edit */ 288 static int 289 pm_edit(int menu_entries_count, void (*menu_fmt)(menudesc *, int, void *), 290 int (*action)(menudesc *, void *), int (*check_fun)(void *), 291 void (*entry_init)(void *, void *), void *entry_init_arg, 292 void *dev_ptr, int dev_ptr_delta, structinfo_t *s) 293 { 294 int i, ok = 0; 295 menu_ent *menu_entries; 296 297 if (dev_ptr == NULL) { 298 /* We should create new device */ 299 for (i = 0; i < s->max && !ok; i++) 300 if (*(int*)((char*)s->entry_enabled + dev_ptr_delta + s->entry_size * i) == 0) { 301 dev_ptr = (char*)s->entry_first + dev_ptr_delta + s->entry_size * i; 302 entry_init(dev_ptr, entry_init_arg); 303 ok = 1; 304 } 305 if (!ok) { 306 /* We do not have free device slots */ 307 hit_enter_to_continue(NULL, MSG_limitcount); 308 return -1; 309 } 310 } 311 312 menu_entries = calloc(menu_entries_count, sizeof *menu_entries); 313 for (i = 0; i < menu_entries_count - 1; i++) 314 menu_entries[i] = (menu_ent) { .opt_action=action }; 315 menu_entries[i] = (menu_ent) { .opt_name=MSG_fremove, 316 .opt_flags=OPT_EXIT, 317 .opt_action=action }; 318 319 int menu_no = -1; 320 menu_no = new_menu(NULL, menu_entries, menu_entries_count, 321 -1, -1, 0, 40, MC_NOCLEAR | MC_SCROLL, 322 NULL, menu_fmt, NULL, NULL, MSG_DONE); 323 324 process_menu(menu_no, dev_ptr); 325 free_menu(menu_no); 326 free(menu_entries); 327 328 return check_fun(dev_ptr); 329 } 330 331 /* Show filtered partitions menu */ 332 struct part_entry 333 pm_dev_list(int type) 334 { 335 int dev_num = -1, num_devs = 0; 336 bool ok; 337 part_id i; 338 int menu_no; 339 struct disk_part_info info; 340 menu_ent menu_entries[MAX_DISKS*MAXPARTITIONS]; 341 struct part_entry disk_entries[MAX_DISKS*MAXPARTITIONS]; 342 struct pm_devs *pm_i; 343 344 SLIST_FOREACH(pm_i, &pm_head, l) 345 for (i = 0; i < pm_i->parts->num_part; i++) { 346 ok = false; 347 if (!pm_i->parts->pscheme->get_part_info(pm_i->parts, 348 i, &info)) 349 continue; 350 if (info.flags & 351 (PTI_WHOLE_DISK|PTI_PSCHEME_INTERNAL|PTI_RAW_PART)) 352 continue; 353 switch (type) { 354 case PM_RAID: 355 if (info.fs_type == FS_RAID) 356 ok = 1; 357 break; 358 case PM_CGD: 359 if (info.fs_type == FS_CGD) 360 ok = 1; 361 break; 362 case PM_LVM: 363 // XXX if (pm_i->bsdlabel[i].lvmpv) 364 // ok = 1; 365 break; 366 } 367 if (!ok) 368 continue; 369 if (pm_partusage(pm_i, i, 0) != 0) 370 continue; 371 372 disk_entries[num_devs].dev_ptr = pm_i; 373 disk_entries[num_devs].id = i; 374 disk_entries[num_devs].parts = pm_i->parts; 375 376 pm_i->parts->pscheme->get_part_device( 377 pm_i->parts, i, disk_entries[num_devs].fullname, 378 sizeof disk_entries[num_devs].fullname, 379 NULL, plain_name, false); 380 381 menu_entries[num_devs] = (struct menu_ent) { 382 .opt_name = disk_entries[num_devs].fullname, 383 .opt_action = set_menu_select, 384 .opt_flags = OPT_EXIT, 385 }; 386 num_devs++; 387 } 388 389 menu_no = new_menu(MSG_avdisks, 390 menu_entries, num_devs, -1, -1, (num_devs+1<3)?3:num_devs+1, 13, 391 MC_SCROLL | MC_NOCLEAR, NULL, NULL, NULL, NULL, NULL); 392 if (menu_no == -1) 393 return (struct part_entry) { .retvalue = -1, }; 394 process_menu(menu_no, &dev_num); 395 free_menu(menu_no); 396 397 if (dev_num < 0 || dev_num >= num_devs) 398 return (struct part_entry) { .retvalue = -1, }; 399 400 disk_entries[dev_num].retvalue = dev_num; 401 return disk_entries[dev_num]; 402 } 403 404 /* Get unused raid*, cgd* or vnd* device */ 405 static int 406 pm_manage_getfreenode(void *node, const char *d, structinfo_t *s) 407 { 408 int i, ii, ok; 409 char buf[SSTRSIZE]; 410 struct pm_devs *pm_i; 411 412 *(int*)node = -1; 413 for (i = 0; i < s->max; i++) { 414 ok = 1; 415 /* Check that node is not already reserved */ 416 for (ii = 0; ii < s->max; ii++) 417 if (*(int*)((char*)s->entry_node + s->entry_size * ii) == i) { 418 ok = 0; 419 break; 420 } 421 if (! ok) 422 continue; 423 /* Check that node is not in the device list */ 424 snprintf(buf, SSTRSIZE, "%s%d", d, i); 425 SLIST_FOREACH(pm_i, &pm_head, l) 426 if (! strcmp(pm_i->diskdev, buf)) { 427 ok = 0; 428 break; 429 } 430 if (ok) { 431 *(int*)node = i; 432 return i; 433 } 434 } 435 hit_enter_to_continue(NULL, MSG_nofreedev); 436 return -1; 437 } 438 439 /* 440 * Show a line for a device, usually with full size in the right 441 * column, alternatively (if != NULL) with no_size_display 442 * instead in paranthesis (used for error displays or to note 443 * a action that can be done to this device. 444 */ 445 static void 446 pm_fmt_disk_line(WINDOW *w, const char *line, const char *on, 447 daddr_t total, const char *no_size_display) 448 { 449 char out[STRSIZE], human[6]; 450 451 if (on != NULL) { 452 snprintf(out, sizeof out, "%s %s %s", line, 453 msg_string(MSG_pm_menu_on), on); 454 line = out; 455 } 456 if (no_size_display != NULL) { 457 wprintw(w, " %-56s (%s)", line, no_size_display); 458 } else { 459 humanize_number(human, sizeof(human), 460 total * 512, "", 461 HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL); 462 wprintw(w, " %-56s %s", line, human); 463 } 464 } 465 466 /*** 467 RAIDs 468 ***/ 469 470 static void 471 pm_raid_menufmt(menudesc *m, int opt, void *arg) 472 { 473 int i, ok = 0; 474 char buf[STRSIZE], rdev[STRSIZE], level[STRSIZE], *line; 475 struct raid_desc *dev_ptr = ((struct part_entry *)arg)[opt].dev_ptr; 476 477 if (dev_ptr->enabled == 0) 478 return; 479 buf[0] = '\0'; 480 sprintf(rdev, "raid%d", dev_ptr->node); 481 for (i = 0; i < MAX_IN_RAID; i++) { 482 if (dev_ptr->comp[i].parts != NULL) { 483 strlcat(buf, dev_ptr->comp[i].name, sizeof buf); 484 strlcat(buf, " ", sizeof buf); 485 ok = 1; 486 } 487 } 488 if (ok) { 489 sprintf(level, "%u", dev_ptr->raid_level); 490 const char *args[] = { rdev, level }; 491 line = str_arg_subst(msg_string(MSG_raid_menufmt), 492 __arraycount(args), args); 493 pm_fmt_disk_line(m->mw, line, buf, dev_ptr->total_size, NULL); 494 free(line); 495 } else { 496 pm_fmt_disk_line(m->mw, buf, NULL, 0, 497 msg_string(MSG_raid_err_menufmt)); 498 } 499 } 500 501 static void 502 pm_raid_edit_menufmt(menudesc *m, int opt, void *arg) 503 { 504 int i; 505 char buf[STRSIZE]; 506 struct raid_desc *dev_ptr = arg; 507 508 buf[0] = '\0'; 509 switch (opt) { 510 case PMR_MENU_DEVS: 511 strlcpy(buf, msg_string(MSG_raid_disks_fmt), 512 sizeof buf); 513 strlcpy(buf, ": ", sizeof buf); 514 for (i = 0; i < MAX_IN_RAID; i++) { 515 if (dev_ptr->comp[i].parts == NULL || 516 dev_ptr->comp[i].is_spare) 517 continue; 518 strlcat(buf, " ", sizeof buf); 519 strlcat(buf, dev_ptr->comp[i].name, sizeof buf); 520 } 521 wprintw(m->mw, "%s", buf); 522 break; 523 case PMR_MENU_DEVSSPARE: 524 strlcpy(buf, msg_string(MSG_raid_spares_fmt), 525 sizeof buf); 526 strlcpy(buf, ": ", sizeof buf); 527 for (i = 0; i < MAX_IN_RAID; i++) { 528 if (dev_ptr->comp[i].parts == NULL || 529 !dev_ptr->comp[i].is_spare) 530 continue; 531 strlcat(buf, " ", sizeof buf); 532 strlcat(buf, dev_ptr->comp[i].name, sizeof buf); 533 } 534 wprintw(m->mw, "%s", buf); 535 break; 536 case PMR_MENU_RAIDLEVEL: 537 wprintw(m->mw, "%s: %u", 538 msg_string(MSG_raid_level_fmt), 539 dev_ptr->raid_level); 540 break; 541 case PMR_MENU_NUMROW: 542 wprintw(m->mw, "%s: %u", 543 msg_string(MSG_raid_numrow_fmt), dev_ptr->numRow); 544 break; 545 case PMR_MENU_NUMCOL: 546 wprintw(m->mw, "%s: %u", 547 msg_string(MSG_raid_numcol_fmt), dev_ptr->numCol); 548 break; 549 case PMR_MENU_NUMSPARE: 550 wprintw(m->mw, "%s: %u", 551 msg_string(MSG_raid_numspare_fmt), 552 dev_ptr->numSpare); 553 break; 554 case PMR_MENU_SECTPERSU: 555 wprintw(m->mw, "%s: %u", 556 msg_string(MSG_raid_sectpersu_fmt), 557 dev_ptr->sectPerSU); 558 break; 559 case PMR_MENU_SUSPERPARITYUNIT: 560 wprintw(m->mw, "%s: %u", 561 msg_string(MSG_raid_superpar_fmt), 562 dev_ptr->SUsPerParityUnit); 563 break; 564 case PMR_MENU_SUSPERRECONUNIT: 565 wprintw(m->mw, "%s: %u", 566 msg_string(MSG_raid_superrec_fmt), 567 dev_ptr->SUsPerReconUnit); 568 break; 569 } 570 } 571 572 static int 573 pm_raid_set_value(menudesc *m, void *arg) 574 { 575 int retvalue = -1; 576 int *out_var = NULL; 577 char buf[SSTRSIZE]; 578 const char *msg_to_show = NULL; 579 struct raid_desc *dev_ptr = arg; 580 581 static menu_ent menuent_disk_adddel[] = { 582 { .opt_name=MSG_add, .opt_flags=OPT_EXIT, 583 .opt_action=pm_raid_disk_add }, 584 { .opt_name=MSG_remove, .opt_flags=OPT_EXIT, 585 .opt_action=pm_raid_disk_del } 586 }; 587 static int menu_disk_adddel = -1; 588 if (menu_disk_adddel == -1) { 589 menu_disk_adddel = new_menu(NULL, menuent_disk_adddel, 590 __arraycount(menuent_disk_adddel), 591 -1, -1, 0, 10, MC_NOCLEAR, NULL, NULL, NULL, NULL, 592 NULL); 593 } 594 595 switch (m->cursel) { 596 case PMR_MENU_DEVS: 597 raid_curspare = 0; 598 process_menu(menu_disk_adddel, dev_ptr); 599 return 0; 600 case PMR_MENU_DEVSSPARE: 601 raid_curspare = 1; 602 process_menu(menu_disk_adddel, dev_ptr); 603 return 0; 604 case PMR_MENU_RAIDLEVEL: 605 process_menu(MENU_raidlevel, &retvalue); 606 if (retvalue >= 0) 607 dev_ptr->raid_level = retvalue; 608 return 0; 609 case PMR_MENU_NUMROW: 610 hit_enter_to_continue(NULL, MSG_raid_nomultidim); 611 return 0; 612 #if 0 /* notyet */ 613 msg_to_show = MSG_raid_numrow_ask; 614 out_var = &(dev_ptr->numRow); 615 break; 616 #endif 617 case PMR_MENU_NUMCOL: 618 msg_to_show = MSG_raid_numcol_ask; 619 out_var = &(dev_ptr->numCol); 620 break; 621 case PMR_MENU_NUMSPARE: 622 msg_to_show = MSG_raid_numspare_ask; 623 out_var = &(dev_ptr->numSpare); 624 break; 625 case PMR_MENU_SECTPERSU: 626 msg_to_show = MSG_raid_sectpersu_ask; 627 out_var = &(dev_ptr->sectPerSU); 628 break; 629 case PMR_MENU_SUSPERPARITYUNIT: 630 msg_to_show = MSG_raid_superpar_ask; 631 out_var = &(dev_ptr->SUsPerParityUnit); 632 break; 633 case PMR_MENU_SUSPERRECONUNIT: 634 msg_to_show = MSG_raid_superrec_ask; 635 out_var = &(dev_ptr->SUsPerReconUnit); 636 break; 637 case PMR_MENU_REMOVE: 638 dev_ptr->enabled = 0; 639 return 0; 640 } 641 if (out_var == NULL || msg_to_show == NULL) 642 return -1; 643 snprintf(buf, SSTRSIZE, "%d", *out_var); 644 msg_prompt_win(msg_to_show, -1, 18, 0, 0, buf, buf, SSTRSIZE); 645 if (atoi(buf) >= 0) 646 *out_var = atoi(buf); 647 return 0; 648 } 649 650 static void 651 pm_raid_init(void *arg, void *none) 652 { 653 struct raid_desc *dev_ptr = arg; 654 memset(dev_ptr, 0, sizeof(*dev_ptr)); 655 *dev_ptr = (struct raid_desc) { 656 .enabled = 1, 657 .blocked = 0, 658 .sectPerSU = 32, 659 .SUsPerParityUnit = 1, 660 .SUsPerReconUnit = 1, 661 }; 662 } 663 664 static int 665 pm_raid_check(void *arg) 666 { 667 size_t i, dev_num = 0; 668 daddr_t min_size = 0, cur_size = 0; 669 struct raid_desc *dev_ptr = arg; 670 struct disk_part_info info; 671 struct disk_partitions *parts; 672 673 if (dev_ptr->blocked) 674 return 0; 675 676 for (i = 0; i < MAX_IN_RAID; i++) { 677 if (dev_ptr->comp[i].parts != NULL) { 678 parts = dev_ptr->comp[i].parts; 679 if (!parts->pscheme->get_part_info(parts, 680 dev_ptr->comp[i].id, &info)) 681 continue; 682 cur_size = info.size; 683 if (cur_size < min_size || dev_num == 0) 684 min_size = cur_size; 685 if (dev_ptr->comp[i].is_spare) 686 continue; 687 dev_num++; 688 } 689 } 690 691 /* Calculate sum of available space */ 692 if (dev_num > 0) { 693 switch (dev_ptr->raid_level) { 694 case 0: 695 dev_ptr->total_size = min_size * dev_num; 696 break; 697 case 1: 698 dev_ptr->total_size = min_size; 699 break; 700 case 4: 701 case 5: 702 dev_ptr->total_size = min_size * (dev_num - 1); 703 break; 704 } 705 pm_manage_getfreenode(&(dev_ptr->node), "raid", &raids_t_info); 706 if (dev_ptr->node < 0) 707 dev_ptr->enabled = 0; 708 } 709 else 710 dev_ptr->enabled = 0; 711 return dev_ptr->enabled; 712 } 713 714 static int 715 pm_raid_disk_add(menudesc *m, void *arg) 716 { 717 int i; 718 struct raid_desc *dev_ptr = arg; 719 struct part_entry disk_entrie = pm_dev_list(PM_RAID); 720 if (disk_entrie.retvalue < 0) 721 return disk_entrie.retvalue; 722 723 for (i = 0; i < MAX_IN_RAID; i++) 724 if (dev_ptr->comp[i].parts == NULL) { 725 dev_ptr->comp[i].parts = disk_entrie.parts; 726 dev_ptr->comp[i].id = disk_entrie.id; 727 dev_ptr->comp[i].is_spare = raid_curspare; 728 strlcpy(dev_ptr->comp[i].name, disk_entrie.fullname, 729 sizeof dev_ptr->comp[i].name); 730 if (raid_curspare) 731 dev_ptr->numSpare++; 732 else 733 dev_ptr->numCol++; 734 dev_ptr->numRow = 1; 735 break; 736 } 737 return 0; 738 } 739 740 static int 741 pm_raid_disk_del(menudesc *m, void *arg) 742 { 743 int retvalue = -1, num_devs = 0; 744 int i, pm_cur; 745 int menu_no; 746 struct raid_desc *dev_ptr = arg; 747 menu_ent menu_entries[MAX_IN_RAID]; 748 struct part_entry submenu_args[MAX_IN_RAID]; 749 750 for (i = 0; i < MAX_IN_RAID; i++) { 751 if (dev_ptr->comp[i].parts == NULL || 752 dev_ptr->comp[i].is_spare != raid_curspare) 753 continue; 754 menu_entries[num_devs] = (struct menu_ent) { 755 .opt_name = dev_ptr->comp[i].name, 756 .opt_action = set_menu_select, 757 .opt_flags = OPT_EXIT, 758 }; 759 submenu_args[num_devs].dev_ptr = dev_ptr; 760 submenu_args[num_devs].index = i; 761 num_devs++; 762 } 763 764 menu_no = new_menu(MSG_raid_disks, 765 menu_entries, num_devs, -1, -1, (num_devs+1<3)?3:num_devs+1, 13, 766 MC_SCROLL | MC_NOCLEAR, NULL, NULL, NULL, NULL, NULL); 767 if (menu_no == -1) 768 return -1; 769 process_menu(menu_no, &retvalue); 770 free_menu(menu_no); 771 772 if (retvalue < 0 || retvalue >= num_devs) 773 return -1; 774 775 pm_cur = submenu_args[retvalue].index; 776 777 if (dev_ptr->comp[pm_cur].is_spare) 778 dev_ptr->numSpare--; 779 else 780 dev_ptr->numCol--; 781 dev_ptr->numRow = (dev_ptr->numCol)?1:0; 782 dev_ptr->comp[pm_cur].parts = NULL; 783 784 return 0; 785 } 786 787 static int 788 pm_raid_commit(void) 789 { 790 int i, ii; 791 FILE *f; 792 char f_name[STRSIZE]; 793 794 for (i = 0; i < MAX_RAID; i++) { 795 if (! pm_raid_check(&raids[i])) 796 continue; 797 798 /* Generating configure file for our raid */ 799 snprintf(f_name, SSTRSIZE, "/tmp/raid.%d.conf", raids[i].node); 800 f = fopen(f_name, "w"); 801 if (f == NULL) { 802 endwin(); 803 (void)fprintf(stderr, 804 "Could not open %s for writing\n", f_name); 805 if (logfp) 806 (void)fprintf(logfp, 807 "Could not open %s for writing\n", f_name); 808 return 1; 809 } 810 scripting_fprintf(NULL, "cat <<EOF >%s\n", f_name); 811 scripting_fprintf(f, "START array\n%d %d %d\n", 812 raids[i].numRow, raids[i].numCol, raids[i].numSpare); 813 814 scripting_fprintf(f, "\nSTART disks\n"); 815 for (ii = 0; ii < MAX_IN_RAID; ii++) 816 if (raids[i].comp[ii].parts != NULL && 817 !raids[i].comp[ii].is_spare) { 818 scripting_fprintf(f, "/dev/%s\n", 819 raids[i].comp[ii].name); 820 } 821 822 scripting_fprintf(f, "\nSTART spare\n"); 823 for (ii = 0; ii < MAX_IN_RAID; ii++) 824 if (raids[i].comp[ii].parts != NULL && 825 raids[i].comp[ii].is_spare) { 826 scripting_fprintf(f, "/dev/%s\n", 827 raids[i].comp[ii].name); 828 } 829 830 scripting_fprintf(f, "\nSTART layout\n%d %d %d %d\n", 831 raids[i].sectPerSU, raids[i].SUsPerParityUnit, 832 raids[i].SUsPerReconUnit, raids[i].raid_level); 833 834 scripting_fprintf(f, "\nSTART queue\nfifo 100\n\n"); 835 scripting_fprintf(NULL, "EOF\n"); 836 fclose (f); 837 fflush(NULL); 838 839 /* Raid initialization */ 840 if (run_program(RUN_DISPLAY | RUN_PROGRESS, 841 "raidctl -C %s raid%d", f_name, raids[i].node) == 0 && 842 run_program(RUN_DISPLAY | RUN_PROGRESS, 843 "raidctl -I %d raid%d", rand(), raids[i].node) == 0 && 844 run_program(RUN_DISPLAY | RUN_PROGRESS, 845 "raidctl -vi raid%d", raids[i].node) == 0 && 846 run_program(RUN_DISPLAY | RUN_PROGRESS, 847 "raidctl -v -A yes raid%d", raids[i].node) == 0) { 848 /* 849 * RAID creation done, remove it from list to 850 * prevent its repeated reinitialization 851 */ 852 raids[i].blocked = 1; 853 } 854 } 855 return 0; 856 } 857 858 /*** 859 VND 860 ***/ 861 862 static void 863 pm_vnd_menufmt(menudesc *m, int opt, void *arg) 864 { 865 struct vnd_desc *dev_ptr = ((struct part_entry *)arg)[opt].dev_ptr; 866 char dev[STRSIZE]; 867 868 if (dev_ptr->enabled == 0) 869 return; 870 sprintf(dev, "vnd%d", dev_ptr->node); 871 if (strlen(dev_ptr->filepath) < 1) 872 pm_fmt_disk_line(m->mw, dev, NULL, 873 0, msg_string(MSG_vnd_err_menufmt)); 874 else if (dev_ptr->is_exist) 875 pm_fmt_disk_line(m->mw, dev, dev_ptr->filepath, 876 0, msg_string(MSG_vnd_assign)); 877 else 878 pm_fmt_disk_line(m->mw, dev, dev_ptr->filepath, 879 dev_ptr->size, NULL); 880 } 881 882 static int 883 max_msg_length(const msg *p, size_t cnt) 884 { 885 int len, m = 0; 886 887 while (cnt > 0) { 888 len = strlen(msg_string(*p)); 889 if (len > m) 890 m = len; 891 cnt--; p++; 892 } 893 894 return m; 895 } 896 897 static void 898 pm_vnd_edit_menufmt(menudesc *m, int opt, void *arg) 899 { 900 struct vnd_desc *dev_ptr = arg; 901 char buf[SSTRSIZE]; 902 strcpy(buf, "-"); 903 static int lcol_width; 904 if (lcol_width == 0) { 905 static const msg labels[] = { 906 MSG_vnd_path_fmt, MSG_vnd_assign_fmt, MSG_vnd_size_fmt, 907 MSG_vnd_ro_fmt, MSG_vnd_geom_fmt, MSG_vnd_bps_fmt, 908 MSG_vnd_spt_fmt, MSG_vnd_tpc_fmt, MSG_vnd_cyl_fmt 909 }; 910 lcol_width = max_msg_length(labels, __arraycount(labels)) + 3; 911 } 912 913 switch (opt) { 914 case PMV_MENU_FILEPATH: 915 wprintw(m->mw, "%*s %s", -lcol_width, 916 msg_string(MSG_vnd_path_fmt), dev_ptr->filepath); 917 break; 918 case PMV_MENU_EXIST: 919 wprintw(m->mw, "%*s %s", -lcol_width, 920 msg_string(MSG_vnd_assign_fmt), 921 dev_ptr->is_exist? 922 msg_string(MSG_No) : msg_string(MSG_Yes)); 923 break; 924 case PMV_MENU_SIZE: 925 if (!dev_ptr->is_exist) 926 snprintf(buf, SSTRSIZE, "%" PRIu64, 927 dev_ptr->size); 928 wprintw(m->mw, "%*s %s", -lcol_width, 929 msg_string(MSG_vnd_size_fmt), buf); 930 break; 931 case PMV_MENU_RO: 932 wprintw(m->mw, "%*s %s", -lcol_width, 933 msg_string(MSG_vnd_ro_fmt), 934 dev_ptr->readonly? 935 msg_string(MSG_Yes) : msg_string(MSG_No)); 936 break; 937 case PMV_MENU_MGEOM: 938 if (!dev_ptr->is_exist) 939 snprintf(buf, SSTRSIZE, "%s", 940 dev_ptr->manual_geom? 941 msg_string(MSG_Yes) : msg_string(MSG_No)); 942 wprintw(m->mw, "%*s %s", -lcol_width, 943 msg_string(MSG_vnd_geom_fmt), buf); 944 break; 945 case PMV_MENU_SECSIZE: 946 if (dev_ptr->manual_geom && !dev_ptr->is_exist) 947 snprintf(buf, SSTRSIZE, "%d", dev_ptr->secsize); 948 wprintw(m->mw, "%*s %s", -lcol_width, 949 msg_string(MSG_vnd_bps_fmt), buf); 950 break; 951 case PMV_MENU_NSECTORS: 952 if (dev_ptr->manual_geom && !dev_ptr->is_exist) 953 snprintf(buf, SSTRSIZE, "%d", 954 dev_ptr->nsectors); 955 wprintw(m->mw, "%*s %s", -lcol_width, 956 msg_string(MSG_vnd_spt_fmt), buf); 957 break; 958 case PMV_MENU_NTRACKS: 959 if (dev_ptr->manual_geom && !dev_ptr->is_exist) 960 snprintf(buf, SSTRSIZE, "%d", dev_ptr->ntracks); 961 wprintw(m->mw, "%*s %s", -lcol_width, 962 msg_string(MSG_vnd_tpc_fmt), buf); 963 break; 964 case PMV_MENU_NCYLINDERS: 965 if (dev_ptr->manual_geom && !dev_ptr->is_exist) 966 snprintf(buf, SSTRSIZE, "%d", 967 dev_ptr->ncylinders); 968 wprintw(m->mw, "%*s %s", -lcol_width, 969 msg_string(MSG_vnd_cyl_fmt), buf); 970 break; 971 } 972 } 973 974 static int 975 pm_vnd_set_value(menudesc *m, void *arg) 976 { 977 struct vnd_desc *dev_ptr = arg; 978 char buf[STRSIZE]; 979 const char *msg_to_show = NULL; 980 int *out_var = NULL; 981 982 switch (m->cursel) { 983 case PMV_MENU_FILEPATH: 984 msg_prompt_win(MSG_vnd_path_ask, -1, 18, 0, 0, 985 dev_ptr->filepath, dev_ptr->filepath, STRSIZE); 986 if (dev_ptr->filepath[0] != '/') { 987 strlcpy(buf, dev_ptr->filepath, MOUNTLEN); 988 snprintf(dev_ptr->filepath, MOUNTLEN, "/%s", 989 buf); 990 } 991 if (dev_ptr->filepath[strlen(dev_ptr->filepath) - 1] 992 == '/') 993 dev_ptr->filepath[strlen(dev_ptr->filepath) 994 - 1] = '\0'; 995 return 0; 996 case PMV_MENU_EXIST: 997 dev_ptr->is_exist = !dev_ptr->is_exist; 998 return 0; 999 case PMV_MENU_SIZE: 1000 if (dev_ptr->is_exist) 1001 return 0; 1002 1003 pm_edit_size_value(MSG_vnd_size_ask, pm->dlcylsize, 1004 &dev_ptr->size); 1005 1006 break; 1007 case PMV_MENU_RO: 1008 dev_ptr->readonly = !dev_ptr->readonly; 1009 return 0; 1010 case PMV_MENU_MGEOM: 1011 if (dev_ptr->is_exist) 1012 return 0; 1013 dev_ptr->manual_geom = !dev_ptr->manual_geom; 1014 return 0; 1015 case PMV_MENU_SECSIZE: 1016 if (!dev_ptr->manual_geom || dev_ptr->is_exist) 1017 return 0; 1018 msg_to_show = MSG_vnd_bps_ask; 1019 out_var = &(dev_ptr->secsize); 1020 break; 1021 case PMV_MENU_NSECTORS: 1022 if (!dev_ptr->manual_geom || dev_ptr->is_exist) 1023 return 0; 1024 msg_to_show = MSG_vnd_spt_ask; 1025 out_var = &(dev_ptr->nsectors); 1026 break; 1027 case PMV_MENU_NTRACKS: 1028 if (!dev_ptr->manual_geom || dev_ptr->is_exist) 1029 return 0; 1030 msg_to_show = MSG_vnd_tpc_ask; 1031 out_var = &(dev_ptr->ntracks); 1032 break; 1033 case PMV_MENU_NCYLINDERS: 1034 if (!dev_ptr->manual_geom || dev_ptr->is_exist) 1035 return 0; 1036 msg_to_show = MSG_vnd_cyl_ask; 1037 out_var = &(dev_ptr->ncylinders); 1038 break; 1039 case PMV_MENU_REMOVE: 1040 dev_ptr->enabled = 0; 1041 return 0; 1042 } 1043 if (out_var == NULL || msg_to_show == NULL) 1044 return -1; 1045 snprintf(buf, SSTRSIZE, "%d", *out_var); 1046 msg_prompt_win(msg_to_show, -1, 18, 0, 0, buf, buf, SSTRSIZE); 1047 if (atoi(buf) >= 0) 1048 *out_var = atoi(buf); 1049 return 0; 1050 } 1051 1052 static void 1053 pm_vnd_init(void *arg, void *none) 1054 { 1055 struct vnd_desc *dev_ptr = arg; 1056 memset(dev_ptr, 0, sizeof(*dev_ptr)); 1057 *dev_ptr = (struct vnd_desc) { 1058 .enabled = 1, 1059 .blocked = 0, 1060 .filepath[0] = '\0', 1061 .is_exist = 0, 1062 .size = 1024, 1063 .readonly = 0, 1064 .manual_geom = 0, 1065 .secsize = 512, 1066 .nsectors = 18, 1067 .ntracks = 2, 1068 .ncylinders = 80 1069 }; 1070 } 1071 1072 static int 1073 pm_vnd_check(void *arg) 1074 { 1075 struct vnd_desc *dev_ptr = arg; 1076 1077 if (dev_ptr->blocked) 1078 return 0; 1079 if (strlen(dev_ptr->filepath) < 1 || 1080 dev_ptr->size < 1) 1081 dev_ptr->enabled = 0; 1082 else { 1083 pm_manage_getfreenode(&(dev_ptr->node), "vnd", &vnds_t_info); 1084 if (dev_ptr->node < 0) 1085 dev_ptr->enabled = 0; 1086 } 1087 return dev_ptr->enabled; 1088 } 1089 1090 /* XXX: vndconfig always return 0? */ 1091 static int 1092 pm_vnd_commit(void) 1093 { 1094 int i, error; 1095 char r_o[3], buf[MOUNTLEN+3], resultpath[STRSIZE]; 1096 const char *mpath, *mp_suit = NULL, *rp; 1097 struct pm_devs *pm_i, *pm_suit = NULL; 1098 part_id id, part_suit = NO_PART; 1099 struct disk_part_info info; 1100 1101 for (i = 0; i < MAX_VND; i++) { 1102 error = 0; 1103 if (! pm_vnd_check(&vnds[i])) 1104 continue; 1105 1106 /* Trying to assign target device */ 1107 SLIST_FOREACH(pm_i, &pm_head, l) { 1108 for (id = 0; id < pm_i->parts->num_part; id++) { 1109 if (!pm_i->parts->pscheme->get_part_info( 1110 pm_i->parts, id, &info)) 1111 continue; 1112 if (info.flags & (PTI_SEC_CONTAINER| 1113 PTI_WHOLE_DISK|PTI_PSCHEME_INTERNAL| 1114 PTI_RAW_PART)) 1115 continue; 1116 if (info.last_mounted == NULL || 1117 info.last_mounted[0] == 0) 1118 continue; 1119 mpath = info.last_mounted; 1120 strcpy(buf, mpath); 1121 if (buf[strlen(buf)-1] != '/') 1122 strcat(buf, "/"); 1123 if (strstr(vnds[i].filepath, buf) != 1124 vnds[i].filepath) 1125 continue; 1126 if (part_suit == NO_PART || pm_suit == NULL || 1127 strlen(buf) > strlen(mp_suit)) { 1128 part_suit = id; 1129 pm_suit = pm_i; 1130 mp_suit = mpath; 1131 } 1132 } 1133 } 1134 if (part_suit == NO_PART || pm_suit == NULL || 1135 mp_suit == NULL) 1136 continue; 1137 1138 /* Mounting assigned partition and try to get real file path*/ 1139 if (pm_mount(pm_suit, part_suit) != 0) 1140 continue; 1141 rp = pm_get_mount(pm_suit, part_suit); 1142 snprintf(resultpath, STRSIZE, "%s/%s", 1143 rp, 1144 &(vnds[i].filepath[strlen(rp)])); 1145 1146 strcpy(r_o, vnds[i].readonly?"-r":""); 1147 /* If this is a new image */ 1148 if (!vnds[i].is_exist) { 1149 run_program(RUN_DISPLAY | RUN_PROGRESS, "mkdir -p %s ", 1150 dirname(resultpath)); 1151 if (error == 0) 1152 error = run_program(RUN_DISPLAY | RUN_PROGRESS, 1153 "dd if=/dev/zero of=%s bs=1m " 1154 "count=% " PRIi64 " progress=100 " 1155 "msgfmt=human", 1156 resultpath, vnds[i].size*(MEG/512)); 1157 } 1158 if (error) 1159 continue; 1160 1161 /* If this is a new image with manual geometry */ 1162 if (!vnds[i].is_exist && vnds[i].manual_geom) 1163 error = run_program(RUN_DISPLAY | RUN_PROGRESS, 1164 "vndconfig %s vnd%d %s %d %d %d %d", 1165 r_o, vnds[i].node, 1166 resultpath, vnds[i].secsize, 1167 vnds[i].nsectors, 1168 vnds[i].ntracks, vnds[i].ncylinders); 1169 else 1170 /* If this is a existing image or image without manual 1171 * geometry */ 1172 error = run_program(RUN_DISPLAY | RUN_PROGRESS, 1173 "vndconfig %s vnd%d %s", 1174 r_o, vnds[i].node, resultpath); 1175 1176 if (error == 0) { 1177 vnds[i].blocked = 1; 1178 vnds[i].pm_part = part_suit; 1179 vnds[i].pm = pm_suit; 1180 vnds[i].pm->blocked++; 1181 } 1182 } 1183 return 0; 1184 } 1185 1186 /*** 1187 CGD 1188 ***/ 1189 1190 static void 1191 pm_cgd_menufmt(menudesc *m, int opt, void *arg) 1192 { 1193 struct cgd_desc *dev_ptr = ((struct part_entry *)arg)[opt].dev_ptr; 1194 char desc[STRSIZE]; 1195 struct disk_part_info info; 1196 1197 if (dev_ptr->enabled == 0) 1198 return; 1199 if (dev_ptr->pm == NULL) 1200 wprintw(m->mw, "%s", msg_string(MSG_cgd_err_menufmt)); 1201 else { 1202 snprintf(desc, sizeof desc, "cgd%d (%s-%d)", 1203 dev_ptr->node, dev_ptr->enc_type, dev_ptr->key_size); 1204 dev_ptr->pm->parts->pscheme->get_part_info(dev_ptr->pm->parts, 1205 dev_ptr->pm_part, &info); 1206 pm_fmt_disk_line(m->mw, desc, dev_ptr->pm_name, 1207 info.size, NULL); 1208 } 1209 } 1210 1211 static void 1212 pm_cgd_edit_menufmt(menudesc *m, int opt, void *arg) 1213 { 1214 struct cgd_desc *dev_ptr = arg; 1215 switch (opt) { 1216 case PMC_MENU_DEV: 1217 wprintw(m->mw, "%-15s: %s", 1218 msg_string(MSG_cgd_dev_fmt), dev_ptr->pm_name); 1219 break; 1220 case PMC_MENU_ENCTYPE: 1221 wprintw(m->mw, "%-15s: %s", 1222 msg_string(MSG_cgd_enc_fmt), dev_ptr->enc_type); 1223 break; 1224 case PMC_MENU_KEYSIZE: 1225 wprintw(m->mw, "%-15s: %d", 1226 msg_string(MSG_cgd_key_fmt), dev_ptr->key_size); 1227 break; 1228 case PMC_MENU_IVTYPE: 1229 wprintw(m->mw, "%-15s: %s", 1230 msg_string(MSG_cgd_iv_fmt), dev_ptr->iv_type); 1231 break; 1232 case PMC_MENU_KEYGENTYPE: 1233 wprintw(m->mw, "%-15s: %s", 1234 msg_string(MSG_cgd_keygen_fmt), dev_ptr->keygen_type); 1235 break; 1236 case PMC_MENU_VERIFYTYPE: 1237 wprintw(m->mw, "%-15s: %s", 1238 msg_string(MSG_cgd_verif_fmt), dev_ptr->verify_type); 1239 break; 1240 } 1241 } 1242 1243 static int 1244 pm_cgd_set_value(menudesc *m, void *arg) 1245 { 1246 char *retstring; 1247 struct cgd_desc *dev_ptr = arg; 1248 1249 switch (m->cursel) { 1250 case PMC_MENU_DEV: 1251 pm_cgd_disk_set(dev_ptr, NULL); 1252 return 0; 1253 case PMC_MENU_ENCTYPE: 1254 process_menu(MENU_cgd_enctype, &retstring); 1255 dev_ptr->enc_type = retstring; 1256 if (! strcmp(retstring, "aes-xts")) 1257 dev_ptr->key_size = 256; 1258 if (! strcmp(retstring, "aes-cbc")) 1259 dev_ptr->key_size = 192; 1260 if (! strcmp(retstring, "blowfish-cbc")) 1261 dev_ptr->key_size = 128; 1262 if (! strcmp(retstring, "3des-cbc")) 1263 dev_ptr->key_size = 192; 1264 return 0; 1265 case PMC_MENU_KEYSIZE: 1266 if (! strcmp(dev_ptr->enc_type, "aes-xts")) 1267 dev_ptr->key_size += 1268 (dev_ptr->key_size < 512)? 256 : -256; 1269 if (! strcmp(dev_ptr->enc_type, "aes-cbc")) 1270 dev_ptr->key_size += 1271 (dev_ptr->key_size < 256)? 64 : -128; 1272 if (! strcmp(dev_ptr->enc_type, "blowfish-cbc")) 1273 dev_ptr->key_size = 128; 1274 if (! strcmp(dev_ptr->enc_type, "3des-cbc")) 1275 dev_ptr->key_size = 192; 1276 return 0; 1277 case PMC_MENU_IVTYPE: 1278 process_menu(MENU_cgd_ivtype, &retstring); 1279 dev_ptr->iv_type = retstring; 1280 return 0; 1281 case PMC_MENU_KEYGENTYPE: 1282 process_menu(MENU_cgd_keygentype, &retstring); 1283 dev_ptr->keygen_type = retstring; 1284 return 0; 1285 case PMC_MENU_VERIFYTYPE: 1286 process_menu(MENU_cgd_verifytype, &retstring); 1287 dev_ptr->verify_type = retstring; 1288 return 0; 1289 case PMC_MENU_REMOVE: 1290 dev_ptr->enabled = 0; 1291 return 0; 1292 } 1293 return -1; 1294 } 1295 1296 static void 1297 pm_cgd_init(void *arg1, void *arg2) 1298 { 1299 struct cgd_desc *dev_ptr = arg1; 1300 struct part_entry *disk_entrie = arg2; 1301 1302 memset(dev_ptr, 0, sizeof(*dev_ptr)); 1303 *dev_ptr = (struct cgd_desc) { 1304 .enabled = 1, 1305 .blocked = 0, 1306 .pm = NULL, 1307 .pm_name[0] = '\0', 1308 .pm_part = 0, 1309 .keygen_type = "pkcs5_pbkdf2/sha1", 1310 .verify_type = "disklabel", 1311 .enc_type = "aes-xts", 1312 .iv_type = "encblkno1", 1313 .key_size = 256, 1314 }; 1315 if (disk_entrie != NULL) { 1316 disk_entrie->parts->pscheme->get_part_device( 1317 disk_entrie->parts, disk_entrie->id, 1318 disk_entrie->fullname, sizeof(disk_entrie->fullname), 1319 NULL, logical_name, false); 1320 pm_cgd_disk_set(dev_ptr, disk_entrie); 1321 } 1322 } 1323 1324 static int 1325 pm_cgd_check(void *arg) 1326 { 1327 struct cgd_desc *dev_ptr = arg; 1328 1329 if (dev_ptr->blocked) 1330 return 0; 1331 if (dev_ptr->pm == NULL) 1332 dev_ptr->enabled = 0; 1333 else { 1334 pm_manage_getfreenode(&(dev_ptr->node), "cgd", &cgds_t_info); 1335 if (dev_ptr->node < 0) 1336 dev_ptr->enabled = 0; 1337 } 1338 return dev_ptr->enabled; 1339 } 1340 1341 static int 1342 pm_cgd_disk_set(struct cgd_desc *dev_ptr, struct part_entry *disk_entrie) 1343 { 1344 int alloc_disk_entrie = 0; 1345 1346 if (disk_entrie == NULL) { 1347 alloc_disk_entrie = 1; 1348 disk_entrie = malloc (sizeof(struct part_entry)); 1349 if (disk_entrie == NULL) 1350 return -2; 1351 *disk_entrie = pm_dev_list(PM_CGD); 1352 if (disk_entrie->retvalue < 0) { 1353 free(disk_entrie); 1354 return -1; 1355 } 1356 } 1357 dev_ptr->pm = disk_entrie->dev_ptr; 1358 dev_ptr->pm_part = disk_entrie->id; 1359 strlcpy(dev_ptr->pm_name, disk_entrie->fullname, SSTRSIZE); 1360 1361 if (alloc_disk_entrie) 1362 free(disk_entrie); 1363 return 0; 1364 } 1365 1366 int 1367 pm_cgd_edit(void *dev_ptr, struct part_entry *disk_entrie) 1368 { 1369 if (disk_entrie != NULL) 1370 dev_ptr = NULL; 1371 return pm_edit(PMC_MENU_END, pm_cgd_edit_menufmt, 1372 pm_cgd_set_value, pm_cgd_check, pm_cgd_init, 1373 disk_entrie, dev_ptr, 0, &cgds_t_info); 1374 } 1375 1376 static int 1377 pm_cgd_commit(void) 1378 { 1379 int i, error = 0; 1380 for (i = 0; i < MAX_CGD; i++) { 1381 if (! pm_cgd_check(&cgds[i])) 1382 continue; 1383 if (run_program(RUN_DISPLAY | RUN_PROGRESS, 1384 "cgdconfig -g -i %s -k %s -o /tmp/cgd.%d.conf %s %d", 1385 cgds[i].iv_type, cgds[i].keygen_type, cgds[i].node, 1386 cgds[i].enc_type, cgds[i].key_size) != 0) { 1387 error++; 1388 continue; 1389 } 1390 if (run_program(RUN_DISPLAY | RUN_PROGRESS, 1391 "cgdconfig -V re-enter cgd%d /dev/%s /tmp/cgd.%d.conf", 1392 cgds[i].node, cgds[i].pm_name, cgds[i].node) != 0) { 1393 error++; 1394 continue; 1395 } 1396 cgds[i].pm->blocked++; 1397 cgds[i].blocked = 1; 1398 } 1399 return error; 1400 } 1401 1402 /*** 1403 LVM 1404 ***/ 1405 1406 /* Add lvm logical volumes to pm list */ 1407 /* XXX: rewrite */ 1408 static void 1409 pm_lvm_find(void) 1410 { 1411 int i, ii, already_found; 1412 char dev[STRSIZE]; 1413 struct pm_devs *pm_i; 1414 1415 for (i = 0; i < MAX_LVM_VG; i++) { 1416 if (! lvms[i].blocked) 1417 continue; 1418 for (ii = 0; ii < MAX_LVM_LV; ii++) { 1419 if (! lvms[i].lv[ii].blocked || lvms[i].lv[ii].size < 1) 1420 continue; 1421 snprintf(dev, STRSIZE, "%s/%s", lvms[i].name, 1422 lvms[i].lv[ii].name); 1423 already_found = 0; 1424 SLIST_FOREACH(pm_i, &pm_head, l) 1425 if (!already_found && strcmp(pm_i->diskdev, 1426 dev) == 0) { 1427 pm_i->found = 1; 1428 already_found = 1; 1429 } 1430 if (already_found) 1431 /* We already added this device, skipping */ 1432 continue; 1433 pm_new->found = 1; 1434 pm_new->ptstart = 0; 1435 pm_new->ptsize = 0; 1436 pm_new->no_part = true; 1437 pm_new->refdev = &lvms[i].lv[ii]; 1438 pm_new->sectorsize = 1; 1439 pm_new->dlcylsize = MEG; 1440 strlcpy(pm_new->diskdev, dev, SSTRSIZE); 1441 strlcpy(pm_new->diskdev_descr, dev, STRSIZE); 1442 1443 if (SLIST_EMPTY(&pm_head)) 1444 SLIST_INSERT_HEAD(&pm_head, pm_new, l); 1445 else 1446 SLIST_INSERT_AFTER(pm_i, pm_new, l); 1447 pm_new = malloc(sizeof (struct pm_devs)); 1448 memset(pm_new, 0, sizeof *pm_new); 1449 } 1450 } 1451 } 1452 1453 static int 1454 pm_lvm_disk_add(menudesc *m, void *arg) 1455 { 1456 int i; 1457 lvms_t *dev_ptr = arg; 1458 struct part_entry disk_entrie = pm_dev_list(PM_LVM); 1459 if (disk_entrie.retvalue < 0) 1460 return disk_entrie.retvalue; 1461 1462 for (i = 0; i < MAX_LVM_PV; i++) 1463 if (dev_ptr->pv[i].pm == NULL) { 1464 dev_ptr->pv[i].pm = disk_entrie.dev_ptr; 1465 dev_ptr->pv[i].pm_part = disk_entrie.id; 1466 strlcpy(dev_ptr->pv[i].pm_name, disk_entrie.fullname, 1467 sizeof(dev_ptr->pv[i].pm_name)); 1468 break; 1469 } 1470 return 0; 1471 } 1472 1473 static int 1474 pm_lvm_disk_del(menudesc *m, void *arg) 1475 { 1476 int retvalue = -1, num_devs = 0; 1477 size_t i; 1478 int menu_no; 1479 lvms_t *dev_ptr = arg; 1480 menu_ent menu_entries[MAX_LVM_PV]; 1481 struct part_entry submenu_args[MAX_LVM_PV]; 1482 1483 for (i = 0; i < MAX_LVM_PV; i++) { 1484 if (dev_ptr->pv[i].pm == NULL) 1485 continue; 1486 menu_entries[num_devs] = (struct menu_ent) { 1487 .opt_name = dev_ptr->pv[i].pm_name, 1488 .opt_action = set_menu_select, 1489 .opt_flags = OPT_EXIT, 1490 }; 1491 submenu_args[num_devs].index = i; 1492 num_devs++; 1493 } 1494 1495 menu_no = new_menu(MSG_lvm_disks, 1496 menu_entries, num_devs, -1, -1, (num_devs+1<3)?3:num_devs+1, 13, 1497 MC_SCROLL | MC_NOCLEAR, NULL, NULL, NULL, NULL, NULL); 1498 if (menu_no == -1) 1499 return -1; 1500 process_menu(menu_no, &retvalue); 1501 free_menu(menu_no); 1502 1503 if (retvalue < 0 || retvalue >= num_devs) 1504 return -1; 1505 1506 dev_ptr->pv[submenu_args[retvalue].index].pm = NULL; 1507 1508 return 0; 1509 } 1510 1511 static void 1512 pm_lvm_menufmt(menudesc *m, int opt, void *arg) 1513 { 1514 int i, ok = 0; 1515 daddr_t used_size = 0; 1516 char buf1[STRSIZE]; buf1[0] = 0; 1517 char buf2[STRSIZE]; buf2[0] = 0; 1518 char devs[STRSIZE]; devs[0] = 0; 1519 lvms_t *dev_ptr = ((struct part_entry *)arg)[opt].dev_ptr; 1520 1521 if (dev_ptr->enabled == 0) 1522 return; 1523 snprintf(buf1, STRSIZE, "VG '%s'", dev_ptr->name); 1524 for (i = 0; i < MAX_LVM_PV; i++) 1525 if (dev_ptr->pv[i].pm != NULL) { 1526 strlcat(devs, dev_ptr->pv[i].pm_name, STRSIZE); 1527 strlcat(devs, " ", STRSIZE); 1528 ok = 1; 1529 } 1530 for (i = 0; i < MAX_LVM_LV; i++) 1531 used_size += dev_ptr->lv[i].size; 1532 if (ok) { 1533 snprintf(buf2, STRSIZE, "%" PRIi64 "/%" PRIi64, 1534 dev_ptr->total_size - used_size, dev_ptr->total_size); 1535 pm_fmt_disk_line(m->mw, buf1, devs, 0, buf2); 1536 } else { 1537 pm_fmt_disk_line(m->mw, buf1, NULL, 0, 1538 msg_string(MSG_lvm_err_menufmt)); 1539 } 1540 } 1541 1542 static void 1543 pm_lvm_edit_menufmt(menudesc *m, int opt, void *arg) 1544 { 1545 int i; 1546 char buf[STRSIZE]; 1547 lvms_t *dev_ptr = arg; 1548 strlcpy(buf, msg_string(MSG_auto), sizeof buf); 1549 1550 switch (opt) { 1551 case PML_MENU_PV: 1552 buf[0] = '\0'; 1553 for (i = 0; i < MAX_LVM_PV; i++) { 1554 if (dev_ptr->pv[i].pm != NULL) { 1555 strlcat(buf, " ", sizeof buf); 1556 strlcat(buf, dev_ptr->pv[i].pm_name, 1557 sizeof buf); 1558 } 1559 } 1560 wprintw(m->mw, "%-20s: %s", 1561 msg_string(MSG_lvm_disks_fmt), buf); 1562 break; 1563 case PML_MENU_NAME: 1564 wprintw(m->mw, "%-20s: %s", 1565 msg_string(MSG_lvm_name_fmt), dev_ptr->name); 1566 break; 1567 case PML_MENU_MAXLOGICALVOLUMES: 1568 if (dev_ptr->maxlogicalvolumes > 0) 1569 snprintf(buf, STRSIZE, "%d", 1570 dev_ptr->maxlogicalvolumes); 1571 wprintw(m->mw, "%-20s: %s", 1572 msg_string(MSG_lvm_maxlv_fmt), buf); 1573 break; 1574 case PML_MENU_MAXPHYSICALVOLUMES: 1575 if (dev_ptr->maxphysicalvolumes > 0) 1576 snprintf(buf, STRSIZE, "%d", 1577 dev_ptr->maxphysicalvolumes); 1578 wprintw(m->mw, "%-20s: %s", 1579 msg_string(MSG_lvm_maxpv_fmt), buf); 1580 break; 1581 case PML_MENU_PHYSICALEXTENTSIZE: 1582 if (dev_ptr->physicalextentsize > 0) 1583 snprintf(buf, STRSIZE, "%dM", 1584 dev_ptr->physicalextentsize); 1585 wprintw(m->mw, "%-20s: %s", 1586 msg_string(MSG_lvm_extsiz_fmt), buf); 1587 break; 1588 } 1589 } 1590 1591 static int 1592 pm_lvm_set_value(menudesc *m, void *arg) 1593 { 1594 char buf[STRSIZE]; 1595 const char *msg_to_show = NULL; 1596 int *out_var = NULL; 1597 lvms_t *dev_ptr = arg; 1598 1599 static menu_ent menuent_disk_adddel[] = { 1600 { .opt_name=MSG_add, .opt_flags=OPT_EXIT, 1601 .opt_action=pm_lvm_disk_add }, 1602 { .opt_name=MSG_remove, .opt_flags=OPT_EXIT, 1603 .opt_action=pm_lvm_disk_del } 1604 }; 1605 static int menu_disk_adddel = -1; 1606 if (menu_disk_adddel == -1) { 1607 menu_disk_adddel = new_menu(NULL, menuent_disk_adddel, 1608 __arraycount(menuent_disk_adddel), 1609 -1, -1, 0, 10, MC_NOCLEAR, NULL, NULL, NULL, NULL, 1610 NULL); 1611 } 1612 1613 switch (m->cursel) { 1614 case PML_MENU_PV: 1615 process_menu(menu_disk_adddel, arg); 1616 return 0; 1617 case PML_MENU_NAME: 1618 msg_prompt_win(MSG_lvm_name_ask, -1, 18, 0, 0, 1619 dev_ptr->name, dev_ptr->name, SSTRSIZE); 1620 return 0; 1621 case PML_MENU_MAXLOGICALVOLUMES: 1622 msg_to_show = MSG_lvm_maxlv_ask; 1623 out_var = &(dev_ptr->maxlogicalvolumes); 1624 break; 1625 case PML_MENU_MAXPHYSICALVOLUMES: 1626 msg_to_show = MSG_lvm_maxpv_ask; 1627 out_var = &(dev_ptr->maxphysicalvolumes); 1628 break; 1629 case PML_MENU_PHYSICALEXTENTSIZE: 1630 msg_to_show = MSG_lvm_extsiz_ask; 1631 out_var = &(dev_ptr->physicalextentsize); 1632 break; 1633 case PML_MENU_REMOVE: 1634 dev_ptr->enabled = 0; 1635 return 0; 1636 } 1637 if (out_var == NULL || msg_to_show == NULL) 1638 return -1; 1639 snprintf(buf, SSTRSIZE, "%d", *out_var); 1640 msg_prompt_win(msg_to_show, -1, 18, 0, 0, buf, buf, SSTRSIZE); 1641 if (atoi(buf) >= 0) 1642 *out_var = atoi(buf); 1643 return 0; 1644 } 1645 1646 static void 1647 pm_lvm_init(void *arg, void* none) 1648 { 1649 lvms_t *dev_ptr = arg; 1650 1651 memset(dev_ptr, 0, sizeof *dev_ptr); 1652 *dev_ptr = (struct lvms_t) { 1653 .enabled = 1, 1654 .blocked = 0, 1655 .maxlogicalvolumes = MAX_LVM_PV, 1656 .maxphysicalvolumes = MAX_LVM_LV, 1657 .physicalextentsize = -1, 1658 }; 1659 sprintf(dev_ptr->name, "vg%.2d", rand()%100); 1660 } 1661 1662 static int 1663 pm_lvm_check(void *arg) 1664 { 1665 size_t i; 1666 bool ok = false; 1667 lvms_t *dev_ptr = arg; 1668 dev_ptr->total_size = 0; 1669 struct disk_part_info info; 1670 1671 for (i = 0; i < MAX_LVM_PV; i++) { 1672 if (dev_ptr->pv[i].pm != NULL) { 1673 if (!dev_ptr->pv[i].pm->parts->pscheme->get_part_info( 1674 dev_ptr->pv[i].pm->parts, dev_ptr->pv[i].pm_part, 1675 &info)) 1676 continue; 1677 ok = 1; 1678 dev_ptr->total_size += info.size; 1679 } 1680 } 1681 if (!ok) 1682 dev_ptr->enabled = 0; 1683 return dev_ptr->enabled; 1684 } 1685 1686 static void 1687 pm_lvmlv_menufmt(menudesc *m, int opt, void *arg) 1688 { 1689 char buf[STRSIZE]; 1690 lv_t *dev_ptr = ((struct part_entry *)arg)[opt].dev_ptr; 1691 1692 if (dev_ptr->size > 0) { 1693 snprintf(buf, STRSIZE, "'%s'", dev_ptr->name); 1694 pm_fmt_disk_line(m->mw, buf, NULL, dev_ptr->size, NULL); 1695 } 1696 } 1697 1698 static void 1699 pm_lvmlv_edit_menufmt(menudesc *m, int opt, void *arg) 1700 { 1701 1702 lv_t *dev_ptr = arg; 1703 char buf[STRSIZE]; 1704 strlcpy(buf, msg_string(MSG_auto), STRSIZE); 1705 1706 switch (opt) { 1707 case PMLV_MENU_NAME: 1708 wprintw(m->mw, "%-20s: %s", 1709 msg_string(MSG_lvmlv_name_fmt), dev_ptr->name); 1710 break; 1711 case PMLV_MENU_SIZE: 1712 wprintw(m->mw, "%-20s: %" PRIi64, 1713 msg_string(MSG_lvmlv_size_fmt), dev_ptr->size); 1714 break; 1715 case PMLV_MENU_READONLY: 1716 wprintw(m->mw, "%-20s: %s", 1717 msg_string(MSG_lvmlv_ro_fmt), 1718 dev_ptr->readonly? msg_string(MSG_Yes) : msg_string(MSG_No)); 1719 break; 1720 case PMLV_MENU_CONTIGUOUS: 1721 wprintw(m->mw, "%-20s: %s", 1722 msg_string(MSG_lvmlv_cont_fmt), 1723 dev_ptr->contiguous? msg_string(MSG_Yes) : msg_string(MSG_No)); 1724 break; 1725 case PMLV_MENU_EXTENTS: 1726 wprintw(m->mw, "%-20s: %s", 1727 msg_string(MSG_lvmlv_extnum_fmt), 1728 (strlen(dev_ptr->extents) > 0) ? 1729 dev_ptr->extents : msg_string(MSG_auto)); 1730 break; 1731 case PMLV_MENU_MINOR: 1732 if (dev_ptr->minor > 0) 1733 snprintf(buf, STRSIZE, "%dK", dev_ptr->minor); 1734 wprintw(m->mw, "%-20s: %s", 1735 msg_string(MSG_lvmlv_minor_fmt), buf); 1736 break; 1737 case PMLV_MENU_MIRRORS: 1738 wprintw(m->mw, "%-20s: %d", 1739 msg_string(MSG_lvmlv_mirrors_fmt), 1740 dev_ptr->mirrors); 1741 break; 1742 case PMLV_MENU_REGIONSIZE: 1743 if (dev_ptr->regionsize > 0) 1744 snprintf(buf, STRSIZE, "%dM", 1745 dev_ptr->regionsize); 1746 wprintw(m->mw, "%-20s: %s", 1747 msg_string(MSG_lvmlv_regsiz_fmt), buf); 1748 break; 1749 case PMLV_MENU_PERSISTENT: 1750 wprintw(m->mw, "%-20s: %s", 1751 msg_string(MSG_lvmlv_pers_fmt), 1752 dev_ptr->persistent ? 1753 msg_string(MSG_Yes) : msg_string(MSG_No)); 1754 break; 1755 case PMLV_MENU_READAHEAD: 1756 if (dev_ptr->readahead > 0) 1757 snprintf(buf, STRSIZE, "%d", 1758 dev_ptr->readahead); 1759 wprintw(m->mw, "%-20s: %s", 1760 msg_string(MSG_lvmlv_readahsect_fmt), buf); 1761 break; 1762 case PMLV_MENU_STRIPES: 1763 if (dev_ptr->stripes > 0) 1764 snprintf(buf, STRSIZE, "%d", dev_ptr->stripes); 1765 wprintw(m->mw, "%-20s: %s", 1766 msg_string(MSG_lvmlv_stripes_fmt), buf); 1767 break; 1768 case PMLV_MENU_STRIPESIZE: 1769 if (dev_ptr->stripesize > 0) 1770 snprintf(buf, STRSIZE, "%dK", dev_ptr->stripesize); 1771 wprintw(m->mw, "%-20s: %s", 1772 msg_string(MSG_lvmlv_stripesiz_fmt), buf); 1773 break; 1774 case PMLV_MENU_ZERO: 1775 wprintw(m->mw, "%-20s: %s", 1776 msg_string(MSG_lvmlv_zero_fmt), 1777 dev_ptr->zero ? 1778 msg_string(MSG_Yes) : msg_string(MSG_No)); 1779 break; 1780 } 1781 } 1782 1783 static int 1784 pm_lvmlv_set_value(menudesc *m, void *arg) 1785 { 1786 char buf[STRSIZE]; 1787 const char *msg_to_show = NULL; 1788 int *out_var = NULL; 1789 lv_t *dev_ptr = arg; 1790 1791 switch (m->cursel) { 1792 case PMLV_MENU_NAME: 1793 msg_prompt_win(MSG_lvmlv_name_ask, -1, 18, 0, 0, 1794 dev_ptr->name, dev_ptr->name, SSTRSIZE); 1795 return 0; 1796 case PMLV_MENU_SIZE: 1797 pm_edit_size_value(MSG_lvmlv_size_ask, 1798 pm->dlcylsize, &dev_ptr->size); /* XXX cylsize? */ 1799 break; 1800 case PMLV_MENU_READONLY: 1801 dev_ptr->readonly = !dev_ptr->readonly; 1802 return 0; 1803 case PMLV_MENU_CONTIGUOUS: 1804 dev_ptr->contiguous = !dev_ptr->contiguous; 1805 return 0; 1806 case PMLV_MENU_EXTENTS: 1807 msg_prompt_win(MSG_lvmlv_extnum_ask, -1, 18, 0, 0, 1808 dev_ptr->extents, dev_ptr->extents, SSTRSIZE); 1809 return 0; 1810 case PMLV_MENU_MINOR: 1811 msg_to_show = MSG_lvmlv_minor_ask; 1812 out_var = &(dev_ptr->minor); 1813 break; 1814 case PMLV_MENU_MIRRORS: 1815 msg_to_show = MSG_lvmlv_mirrors_ask; 1816 out_var = &(dev_ptr->mirrors); 1817 break; 1818 case PMLV_MENU_REGIONSIZE: 1819 msg_to_show = MSG_lvmlv_regsiz_ask; 1820 out_var = &(dev_ptr->regionsize); 1821 break; 1822 case PMLV_MENU_PERSISTENT: 1823 dev_ptr->persistent = !dev_ptr->persistent; 1824 return 0; 1825 case PMLV_MENU_READAHEAD: 1826 msg_to_show = MSG_lvmlv_readahsect_ask; 1827 out_var = &(dev_ptr->readahead); 1828 break; 1829 case PMLV_MENU_STRIPES: 1830 msg_to_show = MSG_lvmlv_stripes_ask; 1831 out_var = &(dev_ptr->stripes); 1832 break; 1833 case PMLV_MENU_STRIPESIZE: 1834 if (dev_ptr->stripesize << 1 > 512) 1835 dev_ptr->stripesize = 4; 1836 else 1837 dev_ptr->stripesize <<= 1; 1838 return 0; 1839 case PMLV_MENU_ZERO: 1840 dev_ptr->zero = !dev_ptr->zero; 1841 return 0; 1842 case PMLV_MENU_REMOVE: 1843 dev_ptr->size = 0; 1844 return 0; 1845 } 1846 if (out_var == NULL || msg_to_show == NULL) 1847 return -1; 1848 snprintf(buf, SSTRSIZE, "%d", *out_var); 1849 msg_prompt_win(msg_to_show, -1, 18, 0, 0, buf, buf, SSTRSIZE); 1850 if (atoi(buf) >= 0) 1851 *out_var = atoi(buf); 1852 return 0; 1853 } 1854 1855 static void 1856 pm_lvmlv_init(void *arg, void *none) 1857 { 1858 lv_t *dev_ptr = arg; 1859 memset(dev_ptr, 0, sizeof *(dev_ptr)); 1860 *dev_ptr = (struct lv_t) { 1861 .blocked = 0, 1862 .size = 1024, 1863 .stripesize = 64, 1864 }; 1865 sprintf (dev_ptr->name, "lvol%.2d", rand()%100); 1866 } 1867 1868 static int 1869 pm_lvmlv_check(void *arg) 1870 { 1871 lv_t *dev_ptr = arg; 1872 if (dev_ptr->size > 0 && strlen(dev_ptr->name) > 0) 1873 return 1; 1874 else { 1875 dev_ptr->size = 0; 1876 return 0; 1877 } 1878 } 1879 1880 static int 1881 pm_lvm_commit(void) 1882 { 1883 int i, ii, error; 1884 uint used_size = 0; 1885 char params[STRSIZE*3], devs[STRSIZE*3], arg[STRSIZE]; 1886 1887 for (i = 0; i < MAX_LVM_VG; i++) { 1888 /* Stage 0: checks */ 1889 if (! pm_lvm_check(&lvms[i])) 1890 continue; 1891 for (ii = 0; ii < MAX_LVM_LV; ii++) 1892 used_size += lvms[i].lv[ii].size; 1893 if (used_size > lvms[i].total_size) 1894 continue; 1895 1896 params[0] = '\0'; 1897 devs[0] = '\0'; 1898 error = 0; 1899 /* Stage 1: creating Physical Volumes (PV's) */ 1900 for (ii = 0; ii < MAX_LVM_PV && ! error; ii++) 1901 if (lvms[i].pv[ii].pm != NULL) { 1902 run_program(RUN_SILENT | RUN_ERROR_OK, 1903 "lvm pvremove -ffy /dev/r%s", 1904 (char*)lvms[i].pv[ii].pm_name); 1905 error += run_program(RUN_DISPLAY | RUN_PROGRESS, 1906 "lvm pvcreate -ffy /dev/r%s", 1907 (char*)lvms[i].pv[ii].pm_name); 1908 if (error) 1909 break; 1910 strlcat(devs, " /dev/r", sizeof devs); 1911 strlcat(devs, lvms[i].pv[ii].pm_name, 1912 sizeof devs); 1913 } 1914 if (error) 1915 continue; 1916 /* Stage 2: creating Volume Groups (VG's) */ 1917 if (lvms[i].maxlogicalvolumes > 0) { 1918 snprintf(arg, sizeof arg, " -l %d", 1919 lvms[i].maxlogicalvolumes); 1920 strlcat(params, arg, sizeof params); 1921 } 1922 if (lvms[i].maxphysicalvolumes > 0) { 1923 snprintf(arg, sizeof arg, " -p %d", 1924 lvms[i].maxphysicalvolumes); 1925 strlcat(params, arg, sizeof params); 1926 } 1927 if (lvms[i].physicalextentsize > 0) { 1928 snprintf(arg, sizeof arg, " -s %d", 1929 lvms[i].physicalextentsize); 1930 strlcat(params, arg, sizeof params); 1931 } 1932 error += run_program(RUN_DISPLAY | RUN_PROGRESS, 1933 "lvm vgcreate %s %s %s", params, lvms[i].name, devs); 1934 if (error) 1935 continue; 1936 /* Stage 3: creating Logical Volumes (LV's) */ 1937 for (ii = 0; ii < MAX_LVM_LV; ii++) { 1938 if (lvms[i].lv[ii].size <= 0) 1939 continue; 1940 1941 params[0] = '\0'; 1942 snprintf(arg, sizeof arg, " -C %c", 1943 lvms[i].lv[ii].contiguous?'y':'n'); 1944 strlcat(params, arg, sizeof params); 1945 snprintf(arg, sizeof arg, " -M %c", 1946 lvms[i].lv[ii].persistent?'y':'n'); 1947 strlcat(params, arg, sizeof params); 1948 snprintf(arg, sizeof arg, " -p %s", 1949 lvms[i].lv[ii].readonly?"r":"rw"); 1950 strlcat(params, arg, sizeof params); 1951 snprintf(arg, sizeof arg, " -Z %c", 1952 lvms[i].lv[ii].zero?'y':'n'); 1953 strlcat(params, arg, sizeof params); 1954 if (strlen(lvms[i].lv[ii].name) > 0) { 1955 snprintf(arg, sizeof arg, " -n %s", 1956 lvms[i].lv[ii].name); 1957 strlcat(params, arg, sizeof params); 1958 } 1959 if (strlen(lvms[i].lv[ii].extents) > 0) { 1960 snprintf(arg, sizeof arg, " -l %s", 1961 lvms[i].lv[ii].extents); 1962 strlcat(params, arg, sizeof params); 1963 } 1964 if (lvms[i].lv[ii].minor > 0) { 1965 snprintf(arg, sizeof arg, " --minor %d", 1966 lvms[i].lv[ii].minor); 1967 strlcat(params, arg, sizeof params); 1968 } 1969 if (lvms[i].lv[ii].mirrors > 0) { 1970 snprintf(arg, sizeof arg, " -m %d", 1971 lvms[i].lv[ii].mirrors); 1972 strlcat(params, arg, sizeof params); 1973 if (lvms[i].lv[ii].regionsize > 0) { 1974 snprintf(arg, sizeof arg, " -R %d", 1975 lvms[i].lv[ii].regionsize); 1976 strlcat(params, arg, sizeof params); 1977 } 1978 } 1979 if (lvms[i].lv[ii].readahead > 0) { 1980 snprintf(arg, sizeof arg, " -r %d", 1981 lvms[i].lv[ii].readahead); 1982 strlcat(params, arg, sizeof params); 1983 } 1984 if (lvms[i].lv[ii].stripes > 0) { 1985 snprintf(arg, sizeof arg, " -i %d", 1986 lvms[i].lv[ii].stripes); 1987 strlcat(params, arg, sizeof params); 1988 if (lvms[i].lv[ii].stripesize > 0) { 1989 snprintf(arg, sizeof arg, " -I %d", 1990 lvms[i].lv[ii].stripesize); 1991 strlcat(params, arg, sizeof params); 1992 } 1993 } 1994 snprintf(arg, sizeof arg, " -L %" PRIi64 "M", 1995 lvms[i].lv[ii].size); 1996 strlcat(params, arg, sizeof params); 1997 1998 error += run_program(RUN_DISPLAY | RUN_PROGRESS, 1999 "lvm lvcreate %s %s", params, lvms[i].name); 2000 } 2001 if (! error) { 2002 lvms[i].blocked = 1; 2003 for (ii = 0; ii < MAX_LVM_PV; ii++) 2004 if (lvms[i].pv[ii].pm != NULL) 2005 lvms[i].pv[ii].pm->blocked++; 2006 for (ii = 0; ii < MAX_LVM_LV; ii++) 2007 if (lvms[i].lv[ii].size > 0) 2008 lvms[i].lv[ii].blocked = 1; 2009 } 2010 } 2011 2012 return 0; 2013 } 2014 2015 /*** 2016 Partman generic functions 2017 ***/ 2018 2019 int 2020 pm_getrefdev(struct pm_devs *pm_cur) 2021 { 2022 int i, ii, dev_num, num_devs, num_devs_s; 2023 char descr[SSTRSIZE], dev[SSTRSIZE] = ""; 2024 2025 pm_cur->refdev = NULL; 2026 if (! strncmp(pm_cur->diskdev, "cgd", 3)) { 2027 dev_num = pm_cur->diskdev[3] - '0'; 2028 for (i = 0; i < MAX_CGD; i++) 2029 if (cgds[i].blocked && cgds[i].node == dev_num) { 2030 pm_cur->refdev = &cgds[i]; 2031 snprintf(descr, sizeof descr, 2032 " (%s, %s-%d)", cgds[i].pm_name, 2033 cgds[i].enc_type, cgds[i].key_size); 2034 strlcat(pm_cur->diskdev_descr, descr, 2035 sizeof(pm_cur->diskdev_descr)); 2036 break; 2037 } 2038 } else if (! strncmp(pm_cur->diskdev, "vnd", 3)) { 2039 dev_num = pm_cur->diskdev[3] - '0'; 2040 for (i = 0; i < MAX_VND; i++) 2041 if (vnds[i].blocked && vnds[i].node == dev_num) { 2042 pm_cur->refdev = &vnds[i]; 2043 vnds[i].pm->parts->pscheme->get_part_device( 2044 vnds[i].pm->parts, vnds[i].pm_part, 2045 dev, sizeof dev, NULL, plain_name, false); 2046 snprintf(descr, sizeof descr, " (%s, %s)", 2047 dev, vnds[i].filepath); 2048 strlcat(pm_cur->diskdev_descr, descr, 2049 sizeof(pm_cur->diskdev_descr)); 2050 break; 2051 } 2052 } else if (! strncmp(pm_cur->diskdev, "raid", 4)) { 2053 dev_num = pm_cur->diskdev[4] - '0'; 2054 for (i = 0; i < MAX_RAID; i++) 2055 if (raids[i].blocked && raids[i].node == dev_num) { 2056 pm_cur->refdev = &raids[i]; 2057 num_devs = 0; num_devs_s = 0; 2058 for (ii = 0; ii < MAX_IN_RAID; ii++) 2059 if (raids[i].comp[ii].parts != NULL) { 2060 if(raids[i].comp[ii].is_spare) 2061 num_devs_s++; 2062 else 2063 num_devs++; 2064 } 2065 snprintf(descr, sizeof descr, 2066 " (lvl %d, %d disks, %d spare)", 2067 raids[i].raid_level, num_devs, 2068 num_devs_s); 2069 strlcat(pm_cur->diskdev_descr, descr, 2070 sizeof(pm_cur->diskdev_descr)); 2071 break; 2072 } 2073 } else 2074 return -1; 2075 return 0; 2076 } 2077 2078 /* Detect that partition is in use */ 2079 int 2080 pm_partusage(struct pm_devs *pm_cur, int part_num, int do_del) 2081 { 2082 int i, ii, retvalue = 0; 2083 struct disk_part_info info; 2084 part_id id; 2085 2086 if (part_num < 0) { 2087 /* Check all partitions on device */ 2088 for (id = 0; id < pm_cur->parts->num_part; id++) { 2089 if (!pm_cur->parts->pscheme->get_part_info( 2090 pm_cur->parts, id, &info)) 2091 continue; 2092 if (info.flags & (PTI_SEC_CONTAINER| 2093 PTI_WHOLE_DISK|PTI_PSCHEME_INTERNAL| 2094 PTI_RAW_PART)) 2095 continue; 2096 retvalue += pm_partusage(pm_cur, id, do_del); 2097 } 2098 return retvalue; 2099 } 2100 2101 id = (part_id)part_num; 2102 if (id >= pm_cur->parts->num_part) 2103 return 0; 2104 2105 for (i = 0; i < MAX_CGD; i++) 2106 if (cgds[i].enabled && 2107 cgds[i].pm == pm_cur && 2108 cgds[i].pm_part == id) { 2109 if (do_del) { 2110 cgds[i].pm = NULL; 2111 cgds[i].pm_name[0] = '\0'; 2112 } 2113 return 1; 2114 } 2115 for (i = 0; i < MAX_RAID; i++) 2116 for (ii = 0; ii < MAX_IN_RAID; ii++) 2117 if (raids[i].enabled && 2118 raids[i].comp[ii].parts == pm_cur->parts && 2119 raids[i].comp[ii].id == id) { 2120 if (do_del) 2121 raids[i].comp[ii].parts = NULL; 2122 return 1; 2123 } 2124 for (i = 0; i < MAX_LVM_VG; i++) 2125 for (ii = 0; ii < MAX_LVM_PV; ii++) 2126 if (lvms[i].enabled && 2127 lvms[i].pv[ii].pm == pm_cur && 2128 lvms[i].pv[ii].pm_part == id) { 2129 if (do_del) 2130 lvms[i].pv[ii].pm = NULL; 2131 return 1; 2132 } 2133 2134 return 0; 2135 } 2136 2137 static void 2138 pm_destroy_one(struct pm_devs *pm_i) 2139 { 2140 part_id i; 2141 2142 if (pm_i->parts != NULL) { 2143 if (pm_i->mounted != NULL) { 2144 for (i = 0; i < pm_i->parts->num_part; i++) 2145 free(pm_i->mounted[i]); 2146 } 2147 2148 pm_i->parts->pscheme->free(pm_i->parts); 2149 } 2150 free(pm_i); 2151 } 2152 2153 /* Clean up removed devices */ 2154 static int 2155 pm_clean(void) 2156 { 2157 int count = 0; 2158 struct pm_devs *pm_i, *tmp; 2159 2160 SLIST_FOREACH_SAFE(pm_i, &pm_head, l, tmp) 2161 if (! pm_i->found) { 2162 count++; 2163 SLIST_REMOVE(&pm_head, pm_i, pm_devs, l); 2164 pm_destroy_one(pm_i); 2165 } 2166 return count; 2167 } 2168 2169 /* Free all pm storage */ 2170 void 2171 pm_destroy_all(void) 2172 { 2173 struct pm_devs *pm_i, *tmp; 2174 2175 if (pm_new != pm) 2176 pm_destroy_one(pm_new); 2177 SLIST_FOREACH_SAFE(pm_i, &pm_head, l, tmp) { 2178 SLIST_REMOVE(&pm_head, pm_i, pm_devs, l); 2179 pm_destroy_one(pm_i); 2180 } 2181 } 2182 2183 void 2184 pm_setfstype(struct pm_devs *pm_cur, part_id id, int fstype, int fs_subtype) 2185 { 2186 struct disk_part_info info; 2187 2188 if (!pm_cur->parts->pscheme->get_part_info(pm_cur->parts, id, &info)) 2189 return; 2190 2191 info.nat_type = pm_cur->parts->pscheme->get_fs_part_type(fstype, fs_subtype); 2192 if (info.nat_type == NULL) 2193 return; 2194 info.fs_type = fstype; 2195 info.fs_sub_type = fs_subtype; 2196 pm_cur->parts->pscheme->set_part_info(pm_cur->parts, id, &info, NULL); 2197 } 2198 2199 static void 2200 pm_select(struct pm_devs *pm_devs_in) 2201 { 2202 pm = pm_devs_in; 2203 if (logfp) 2204 (void)fprintf(logfp, "Partman device: %s\n", pm->diskdev); 2205 } 2206 2207 void 2208 pm_rename(struct pm_devs *pm_cur) 2209 { 2210 #if 0 // XXX - convert to custom attribute or handle similar 2211 pm_select(pm_cur); 2212 msg_prompt_win(MSG_packname, -1, 18, 0, 0, pm_cur->bsddiskname, 2213 pm_cur->bsddiskname, sizeof pm_cur->bsddiskname); 2214 #ifndef NO_DISKLABEL 2215 (void) savenewlabel(pm_cur->bsdlabel, MAXPARTITIONS); 2216 #endif 2217 #endif 2218 } 2219 2220 int 2221 pm_editpart(int part_num) 2222 { 2223 //XXX partinfo backup = pm->bsdlabel[part_num]; 2224 2225 edit_ptn(&(struct menudesc){.cursel = part_num}, NULL); 2226 if (checkoverlap(pm->parts)) { 2227 hit_enter_to_continue(MSG_cantsave, NULL); 2228 //XXX pm->bsdlabel[part_num] = backup; 2229 return -1; 2230 } 2231 pm->unsaved = 1; 2232 return 0; 2233 } 2234 2235 /* Safe erase of disk */ 2236 int 2237 pm_shred(struct pm_devs *pm_cur, int part, int shredtype) 2238 { 2239 int error = -1; 2240 char dev[SSTRSIZE]; 2241 part_id id; 2242 2243 if (part < 0) 2244 return -1; 2245 2246 id = part; 2247 pm_cur->parts->pscheme->get_part_device(pm_cur->parts, id, dev, 2248 sizeof dev, NULL, plain_name, false); 2249 switch(shredtype) { 2250 case SHRED_ZEROS: 2251 error += run_program(RUN_DISPLAY | RUN_PROGRESS, 2252 "dd of=/dev/%s if=/dev/zero bs=1m progress=100 msgfmt=human", 2253 dev); 2254 break; 2255 case SHRED_RANDOM: 2256 error += run_program(RUN_DISPLAY | RUN_PROGRESS, 2257 "dd of=/dev/%s if=/dev/urandom bs=1m progress=100 msgfmt=human", 2258 dev); 2259 break; 2260 case SHRED_CRYPTO: 2261 error += run_program(RUN_DISPLAY | RUN_PROGRESS, 2262 "sh -c 'cgdconfig -s cgd0 /dev/%s aes-cbc 128 < /dev/urandom'", 2263 dev); /* XXX: cgd0?! */ 2264 if (! error) { 2265 error += run_program(RUN_DISPLAY | RUN_PROGRESS, 2266 "dd of=/dev/rcgd0d if=/dev/urandom bs=1m progress=100 msgfmt=human"); 2267 error += run_program(RUN_DISPLAY | RUN_PROGRESS, 2268 "cgdconfig -u cgd0"); 2269 } 2270 break; 2271 default: 2272 return -1; 2273 } 2274 pm_partusage(pm_cur, -1, 1); 2275 //XXX memset(&pm_cur->oldlabel, 0, sizeof pm_cur->oldlabel); 2276 //XXX memset(&pm_cur->bsdlabel, 0, sizeof pm_cur->bsdlabel); 2277 return error; 2278 } 2279 2280 #if 0 // XXX 2281 static int 2282 pm_mountall_sort(const void *a, const void *b) 2283 { 2284 return strcmp(mnts[*(const int *)a].on, mnts[*(const int *)b].on); 2285 } 2286 #endif 2287 2288 /* Mount all available partitions */ 2289 static int 2290 pm_mountall(void) 2291 { 2292 #if 0 // XXX 2293 int num_devs = 0; 2294 int mnts_order[MAX_MNTS]; 2295 int i, ii, error, ok; 2296 char dev[SSTRSIZE]; dev[0] = '\0'; 2297 struct pm_devs *pm_i; 2298 2299 localfs_dev[0] = '\0'; 2300 if (mnts == NULL) 2301 mnts = calloc(MAX_MNTS, sizeof(*mnts)); 2302 2303 SLIST_FOREACH(pm_i, &pm_head, l) { 2304 ok = 0; 2305 for (i = 0; i < MAXPARTITIONS; i++) { 2306 if (!(pm_i->bsdlabel[i].pi_flags & PIF_MOUNT && 2307 pm_i->bsdlabel[i].mnt_opts != NULL)) 2308 continue; 2309 mnts[num_devs].mnt_opts = pm_i->bsdlabel[i].mnt_opts; 2310 if (strlen(pm_i->bsdlabel[i].mounted) > 0) { 2311 /* Device is already mounted. So, doing mount_null */ 2312 strlcpy(mnts[num_devs].dev, pm_i->bsdlabel[i].mounted, MOUNTLEN); 2313 mnts[num_devs].mnt_opts = "-t null"; 2314 } else { 2315 pm_getdevstring(dev, SSTRSIZE, pm_i, i); 2316 snprintf(mnts[num_devs].dev, STRSIZE, "/dev/%s", dev); 2317 } 2318 mnts[num_devs].on = pm_i->bsdlabel[i].pi_mount; 2319 if (strcmp(pm_i->bsdlabel[i].pi_mount, "/") == 0) { 2320 if (pm_i->no_part) 2321 pm_i->bootable = 1; 2322 /* Use disk with / as a default if the user has 2323 the sets on a local disk */ 2324 strlcpy(localfs_dev, pm_i->diskdev, SSTRSIZE); 2325 } 2326 num_devs++; 2327 ok = 1; 2328 } 2329 if (ok) 2330 md_pre_mount(NULL, 0); 2331 } 2332 if (strlen(localfs_dev) < 1) { 2333 hit_enter_to_continue(MSG_noroot, NULL); 2334 return -1; 2335 } 2336 for (i = 0; i < num_devs; i++) 2337 mnts_order[i] = i; 2338 qsort(mnts_order, num_devs, sizeof mnts_order[0], pm_mountall_sort); 2339 2340 for (i = 0; i < num_devs; i++) { 2341 ii = mnts_order[i]; 2342 make_target_dir(mnts[ii].on); 2343 error = target_mount_do(mnts[ii].mnt_opts, mnts[ii].dev, mnts[ii].on); 2344 if (error) 2345 return error; 2346 } 2347 #endif 2348 return 0; 2349 } 2350 2351 /* Mount partition bypassing ordinary order */ 2352 static int 2353 pm_mount(struct pm_devs *pm_cur, int part_num) 2354 { 2355 int error = 0; 2356 #if 0 // XXX 2357 char buf[MOUNTLEN]; 2358 2359 if (strlen(pm_cur->bsdlabel[part_num].mounted) > 0) 2360 return 0; 2361 2362 snprintf(buf, sizeof(buf), "/tmp/%s%c", pm_cur->diskdev, 2363 part_num + 'a'); 2364 if (! dir_exists_p(buf)) 2365 run_program(RUN_DISPLAY | RUN_PROGRESS, "/bin/mkdir -p %s", buf); 2366 if (pm_cur->bsdlabel[part_num].pi_flags & PIF_MOUNT && 2367 pm_cur->bsdlabel[part_num].mnt_opts != NULL && 2368 strlen(pm_cur->bsdlabel[part_num].mounted) < 1) 2369 error += run_program(RUN_DISPLAY | RUN_PROGRESS, "/sbin/mount %s /dev/%s%c %s", 2370 pm_cur->bsdlabel[part_num].mnt_opts, 2371 pm_cur->diskdev, part_num + 'a', buf); 2372 2373 if (error) 2374 pm_cur->bsdlabel[part_num].mounted[0] = '\0'; 2375 else { 2376 strlcpy(pm_cur->bsdlabel[part_num].mounted, buf, MOUNTLEN); 2377 pm_cur->blocked++; 2378 } 2379 #endif 2380 return error; 2381 } 2382 2383 void 2384 pm_umount(struct pm_devs *pm_cur, int part_num) 2385 { 2386 char buf[SSTRSIZE]; buf[0] = '\0'; 2387 part_id id; 2388 2389 if (part_num < 0) 2390 return; 2391 id = (part_id)part_num; 2392 2393 pm_cur->parts->pscheme->get_part_device(pm_cur->parts, id, buf, 2394 sizeof buf, NULL, plain_name, false); 2395 2396 if (run_program(RUN_DISPLAY | RUN_PROGRESS, 2397 "umount -f /dev/%s", buf) == 0) { 2398 free(pm_cur->mounted[id]); 2399 pm_cur->mounted[id] = NULL; 2400 if (pm_cur->blocked > 0) 2401 pm_cur->blocked--; 2402 } 2403 } 2404 2405 int 2406 pm_unconfigure(struct pm_devs *pm_cur) 2407 { 2408 int error = 0; 2409 if (! strncmp(pm_cur->diskdev, "cgd", 3)) { 2410 error = run_program(RUN_DISPLAY | RUN_PROGRESS, "cgdconfig -u %s", pm_cur->diskdev); 2411 if (! error && pm_cur->refdev != NULL) { 2412 ((struct cgd_desc*)pm_cur->refdev)->pm->blocked--; 2413 ((struct cgd_desc*)pm_cur->refdev)->blocked = 0; 2414 } 2415 } else if (! strncmp(pm_cur->diskdev, "vnd", 3)) { 2416 error = run_program(RUN_DISPLAY | RUN_PROGRESS, "vndconfig -u %s", pm_cur->diskdev); 2417 if (! error && pm_cur->refdev != NULL) { 2418 ((struct vnd_desc*)pm_cur->refdev)->pm->blocked--; 2419 ((struct vnd_desc*)pm_cur->refdev)->blocked = 0; 2420 } 2421 } else if (! strncmp(pm_cur->diskdev, "raid", 4)) { 2422 error = run_program(RUN_DISPLAY | RUN_PROGRESS, "raidctl -u %s", pm_cur->diskdev); 2423 if (! error && pm_cur->refdev != NULL) { 2424 ((struct raid_desc*)pm_cur->refdev)->blocked = 0; 2425 #if 0 // XXX 2426 for (i = 0; i < MAX_IN_RAID; i++) 2427 if (((struct raid_desc*)pm_cur->refdev)->comp[i].parts != NULL) 2428 ((raids_t*)pm_cur->refdev)->pm[i]->blocked--; 2429 #endif 2430 } 2431 } else if (! strncmp(pm_cur->diskdev, "dk", 2)) { 2432 if (pm_cur->refdev == NULL) 2433 return -2; 2434 /* error = */ 2435 run_program(RUN_DISPLAY | RUN_PROGRESS, "dkctl %s delwedge %s", 2436 ((struct pm_devs*)pm_cur->refdev)->diskdev, pm_cur->diskdev); 2437 #if 0 // XXX 2438 if (! error) { 2439 if (pm_cur->refdev != NULL && ((struct pm_devs*)pm_cur->refdev)->blocked > 0) 2440 ((struct pm_devs*)pm_cur->refdev)->blocked--; 2441 sscanf(pm_cur->diskdev, "dk%d", &num); 2442 if (num >= 0 && num < MAX_WEDGES) 2443 wedges[num].allocated = 0; 2444 } 2445 #endif 2446 } /* XXX: lvm */ 2447 else 2448 error = run_program(RUN_DISPLAY | RUN_PROGRESS, "eject -t disk /dev/%sd", 2449 pm_cur->diskdev); 2450 if (!error) 2451 pm_cur->found = 0; 2452 return error; 2453 } 2454 2455 /* Last checks before leaving partition manager */ 2456 static int 2457 pm_lastcheck(void) 2458 { 2459 FILE *file_tmp = fopen(concat_paths(targetroot_mnt, "/etc/fstab"), "r"); 2460 if (file_tmp == NULL) 2461 return 1; 2462 fclose(file_tmp); 2463 return 0; 2464 } 2465 2466 /* Are there unsaved changes? */ 2467 static int 2468 pm_needsave(void) 2469 { 2470 struct pm_devs *pm_i; 2471 SLIST_FOREACH(pm_i, &pm_head, l) 2472 if (pm_i->unsaved) { 2473 /* Oops, we have unsaved changes */ 2474 changed = 1; 2475 msg_display(MSG_saveprompt); 2476 return ask_yesno(NULL); 2477 } 2478 return 0; 2479 } 2480 2481 /* Write all changes to disk */ 2482 static int 2483 pm_commit(menudesc *m, void *arg) 2484 { 2485 int retcode; 2486 struct pm_devs *pm_i; 2487 struct install_partition_desc install; 2488 2489 if (m != NULL && arg != NULL) 2490 ((struct part_entry *)arg)[0].retvalue = m->cursel + 1; 2491 2492 SLIST_FOREACH(pm_i, &pm_head, l) { 2493 if (! pm_i->unsaved) 2494 continue; 2495 pm_select(pm_i); 2496 install_desc_from_parts(&install, pm_i->parts); 2497 2498 if (pm_i->no_part) { 2499 if (make_filesystems(&install) != 0) { 2500 if (logfp) 2501 fprintf(logfp, "Special disk %s preparing error\n", pm_i->diskdev); 2502 goto next; 2503 } 2504 pm_i->unsaved = 0; 2505 } else if (pm_i->parts != NULL) { 2506 2507 if (!pm_i->parts->pscheme->write_to_disk(pm_i->parts) || 2508 set_swap_if_low_ram(NULL) != 0 || 2509 md_post_disklabel(&install, pm_i->parts) != 0 || /* Enable swap and check badblock */ 2510 make_filesystems(&install) != 0 /* Create filesystems with newfs */ 2511 ) { 2512 /* Oops, something failed... */ 2513 if (logfp) 2514 fprintf(logfp, "Disk %s preparing error\n", pm_i->diskdev); 2515 goto next; 2516 } 2517 pm_i->unsaved = 0; 2518 } 2519 next: 2520 free_install_desc(&install); 2521 } 2522 2523 /* Call all functions that may create new devices */ 2524 if ((retcode = pm_raid_commit()) != 0) { 2525 if (logfp) 2526 fprintf(logfp, "RAIDframe configuring error #%d\n", retcode); 2527 return -1; 2528 } 2529 if ((retcode = pm_cgd_commit()) != 0) { 2530 if (logfp) 2531 fprintf(logfp, "CGD configuring error #%d\n", retcode); 2532 return -1; 2533 } 2534 if ((retcode = pm_lvm_commit()) != 0) { 2535 if (logfp) 2536 fprintf(logfp, "LVM configuring error #%d\n", retcode); 2537 return -1; 2538 } 2539 if ((retcode = pm_vnd_commit()) != 0) { 2540 if (logfp) 2541 fprintf(logfp, "VND configuring error #%d\n", retcode); 2542 return -1; 2543 } 2544 if (m != NULL && arg != NULL) 2545 pm_upddevlist(m, arg); 2546 if (logfp) 2547 fflush (logfp); 2548 return 0; 2549 } 2550 2551 static int 2552 pm_savebootsector(void) 2553 { 2554 #if 0 // XXX 2555 struct pm_devs *pm_i; 2556 SLIST_FOREACH(pm_i, &pm_head, l) 2557 if (pm_i->bootable) { 2558 if (! strncmp("raid", pm_i->diskdev, 4)) 2559 if (run_program(RUN_DISPLAY | RUN_PROGRESS, 2560 "raidctl -v -A root %s", pm_i->diskdev) != 0) { 2561 if (logfp) 2562 fprintf(logfp, "Error writting RAID bootsector to %s\n", 2563 pm_i->diskdev); 2564 continue; 2565 } 2566 if (pm_i->no_part) { 2567 if (pm_i->rootpart < 0 || 2568 run_program(RUN_DISPLAY | RUN_PROGRESS, 2569 "gpt biosboot -i %d %s", 2570 pm_i->rootpart + 1, pm_i->diskdev) != 0) { 2571 if (logfp) 2572 fprintf(logfp, "Error writting GPT bootsector to %s\n", 2573 pm_i->diskdev); 2574 continue; 2575 } 2576 } else { 2577 pm_select(pm_i); 2578 if ( 2579 #ifndef NO_DISKLABEL 2580 !check_partitions(pm_i, pm_i->parts) || 2581 #endif 2582 md_post_newfs() != 0) { 2583 if (logfp) 2584 fprintf(logfp, "Error writting bootsector to %s\n", 2585 pm_i->diskdev); 2586 continue; 2587 } 2588 } 2589 } 2590 #endif 2591 return 0; 2592 } 2593 2594 /* Function for 'Enter'-menu */ 2595 static int 2596 pm_submenu(menudesc *m, void *arg) 2597 { 2598 int part_num = -1; 2599 struct pm_devs *pm_cur = NULL; 2600 ((struct part_entry *)arg)[0].retvalue = m->cursel + 1; 2601 2602 switch (((struct part_entry *)arg)[m->cursel].type) { 2603 case PM_DISK: 2604 case PM_PART: 2605 case PM_SPEC: 2606 if (((struct part_entry *)arg)[m->cursel].dev_ptr != NULL) { 2607 pm_cur = ((struct part_entry *)arg)[m->cursel].dev_ptr; 2608 if (pm_cur == NULL) 2609 return -1; 2610 if (pm_cur->blocked) { 2611 msg_display(MSG_wannaunblock); 2612 if (!ask_noyes(NULL)) 2613 return -2; 2614 pm_cur->blocked = 0; 2615 } 2616 pm_select(pm_cur); 2617 } 2618 default: 2619 break; 2620 } 2621 2622 switch (((struct part_entry *)arg)[m->cursel].type) { 2623 case PM_DISK: 2624 if (pm_cur != NULL 2625 && pm_cur->parts == NULL) { 2626 2627 #ifndef NO_DISKLABEL 2628 struct install_partition_desc install = { 0 }; 2629 #endif 2630 const struct disk_partitioning_scheme *ps = 2631 select_part_scheme(pm_cur, NULL, false, 2632 NULL); 2633 if (!ps) 2634 return 0; 2635 2636 struct disk_partitions *parts = 2637 (*ps->create_new_for_disk)(pm_cur->diskdev, 2638 0, pm_cur->dlsize, pm_cur->dlsize, false); 2639 if (!parts) 2640 return 0; 2641 2642 pm_cur->parts = parts; 2643 if (pm->dlsize > ps->size_limit) 2644 pm->dlsize = ps->size_limit; 2645 2646 if (pm_cur->parts == NULL) 2647 break; 2648 wclear(stdscr); 2649 wrefresh(stdscr); 2650 #ifndef NO_DISKLABEL 2651 install_desc_from_parts(&install, pm->parts); 2652 make_bsd_partitions(&install); 2653 free_install_desc(&install); 2654 #endif 2655 } 2656 // XXX 2657 // if (pm_cur != NULL 2658 // && pm_cur->label_type == PM_LABEL_GPT) { 2659 // process_menu(MENU_pmgptentry, &part_num); 2660 // pm_wedges_fill(pm_cur); 2661 // } else { 2662 process_menu(MENU_pmdiskentry, &part_num); 2663 // } 2664 break; 2665 case PM_PART: 2666 part_num = ((struct part_entry *)arg)[m->cursel].id; 2667 process_menu(MENU_pmpartentry, &part_num); 2668 // if (pm_cur != NULL && pm_cur->label_type == PM_LABEL_GPT) 2669 // pm_wedges_fill(pm_cur); 2670 break; 2671 case PM_SPEC: 2672 part_num = 0; 2673 process_menu(MENU_pmpartentry, &part_num); 2674 break; 2675 case PM_RAID: 2676 return pm_edit(PMR_MENU_END, pm_raid_edit_menufmt, 2677 pm_raid_set_value, pm_raid_check, pm_raid_init, 2678 NULL, ((struct part_entry *)arg)[m->cursel].dev_ptr, 0, &raids_t_info); 2679 case PM_VND: 2680 return pm_edit(PMV_MENU_END, pm_vnd_edit_menufmt, 2681 pm_vnd_set_value, pm_vnd_check, pm_vnd_init, 2682 NULL, ((struct part_entry *)arg)[m->cursel].dev_ptr, 0, &vnds_t_info); 2683 case PM_CGD: 2684 return pm_cgd_edit(((struct part_entry *)arg)[m->cursel].dev_ptr, 2685 NULL); 2686 case PM_LVM: 2687 return pm_edit(PML_MENU_END, pm_lvm_edit_menufmt, 2688 pm_lvm_set_value, pm_lvm_check, pm_lvm_init, 2689 NULL, ((struct part_entry *)arg)[m->cursel].dev_ptr, 0, &lvms_t_info); 2690 case PM_LVMLV: 2691 return pm_edit(PMLV_MENU_END, pm_lvmlv_edit_menufmt, 2692 pm_lvmlv_set_value, pm_lvmlv_check, pm_lvmlv_init, 2693 NULL, ((struct part_entry *)arg)[m->cursel].dev_ptr, 2694 ((struct part_entry *)arg)[m->cursel].dev_ptr_delta, &lv_t_info); 2695 } 2696 return 0; 2697 } 2698 2699 /* Functions that generate menu entries text */ 2700 static void 2701 pm_menufmt(menudesc *m, int opt, void *arg) 2702 { 2703 const char *dev_status = ""; 2704 char buf[STRSIZE], dev[STRSIZE]; 2705 part_id part_num = ((struct part_entry *)arg)[opt].id; 2706 struct pm_devs *pm_cur = ((struct part_entry *)arg)[opt].dev_ptr; 2707 struct disk_partitions *parts = ((struct part_entry *)arg)[opt].parts; 2708 struct disk_part_info info; 2709 const char *mount_point, *fstype; 2710 2711 switch (((struct part_entry *)arg)[opt].type) { 2712 case PM_DISK: 2713 if (pm_cur->blocked) 2714 dev_status = msg_string(MSG_pmblocked); 2715 else if (! pm_cur->unsaved) 2716 dev_status = msg_string(MSG_pmunchanged); 2717 else if (pm_cur->bootable) 2718 dev_status = msg_string(MSG_pmsetboot); 2719 else 2720 dev_status = msg_string(MSG_pmused); 2721 wprintw(m->mw, "%-33.32s %33.32s", 2722 pm_cur->diskdev_descr, 2723 dev_status); 2724 break; 2725 case PM_PART: 2726 if (parts->pscheme->get_part_device != NULL) 2727 parts->pscheme->get_part_device( 2728 parts, part_num, 2729 dev, sizeof dev, NULL, plain_name, false); 2730 else 2731 strcpy(dev, "-"); 2732 parts->pscheme->get_part_info(parts, 2733 part_num, &info); 2734 if (pm_cur->mounted != NULL && 2735 pm_cur->mounted[part_num] != NULL && 2736 pm_cur->mounted[part_num][0] != 0) 2737 mount_point = msg_string(MSG_pmmounted); 2738 else 2739 mount_point = msg_string(MSG_pmunused); 2740 fstype = getfslabelname(info.fs_type, 2741 info.fs_sub_type); 2742 if (info.last_mounted != NULL) { 2743 snprintf(buf, STRSIZE, "%s (%s) %s", 2744 info.last_mounted, fstype, 2745 mount_point); 2746 pm_fmt_disk_line(m->mw, dev, buf, 2747 info.size, NULL); 2748 } else { 2749 if (fstype != NULL) { 2750 strlcat(dev, " (", sizeof(dev)); 2751 strlcat(dev, fstype, sizeof(dev)); 2752 strlcat(dev, ")", sizeof(dev)); 2753 } 2754 pm_fmt_disk_line(m->mw, dev, NULL, 2755 info.size, NULL); 2756 } 2757 break; 2758 case PM_SPEC: 2759 /* XXX ? */ 2760 pm_fmt_disk_line(m->mw, pm_cur->diskdev_descr, NULL, 2761 pm_cur->dlsize, NULL); 2762 break; 2763 case PM_RAID: 2764 pm_raid_menufmt(m, opt, arg); 2765 break; 2766 case PM_VND: 2767 pm_vnd_menufmt(m, opt, arg); 2768 break; 2769 case PM_CGD: 2770 pm_cgd_menufmt(m, opt, arg); 2771 break; 2772 case PM_LVM: 2773 pm_lvm_menufmt(m, opt, arg); 2774 break; 2775 case PM_LVMLV: 2776 pm_lvmlv_menufmt(m, opt, arg); 2777 break; 2778 } 2779 } 2780 2781 /* Submenu for RAID/LVM/CGD/VND */ 2782 static void 2783 pm_upddevlist_adv(menudesc *m, void *arg, int *i, 2784 pm_upddevlist_adv_t *d) 2785 { 2786 int ii; 2787 if (d->create_msg != NULL) { 2788 /* We want to have menu entry that creates a new device */ 2789 ((struct part_entry *)arg)[*i].type = d->pe_type; 2790 ((struct part_entry *)arg)[*i].dev_ptr = NULL; 2791 ((struct part_entry *)arg)[*i].dev_ptr_delta = d->s->parent_size * d->sub_num; 2792 m->opts[(*i)++] = (struct menu_ent) { 2793 .opt_name = d->create_msg, 2794 .opt_action = pm_submenu, 2795 }; 2796 } 2797 for (ii = 0; ii < d->s->max; ii++) { 2798 if (d->s->entry_enabled == NULL || 2799 d->s->entry_blocked == NULL || 2800 *(int*)((char*)d->s->entry_enabled + d->s->entry_size * ii + 2801 d->s->parent_size * d->sub_num) == 0 || 2802 *(int*)((char*)d->s->entry_blocked + d->s->entry_size * ii + 2803 d->s->parent_size * d->sub_num) != 0) 2804 continue; 2805 /* We have a entry for displaying */ 2806 changed = 1; 2807 m->opts[*i] = (struct menu_ent) { 2808 .opt_name = NULL, 2809 .opt_action = pm_submenu, 2810 }; 2811 ((struct part_entry *)arg)[*i].type = d->pe_type; 2812 ((struct part_entry *)arg)[*i].dev_ptr = (char*)d->s->entry_first + 2813 d->s->entry_size * ii + d->s->parent_size * d->sub_num; 2814 (*i)++; 2815 /* We should show submenu for current entry */ 2816 if (d->sub != NULL) { 2817 d->sub->sub_num = ii; 2818 pm_upddevlist_adv(m, arg, i, d->sub); 2819 } 2820 } 2821 } 2822 2823 /* Update partman main menu with devices list */ 2824 static int 2825 pm_upddevlist(menudesc *m, void *arg) 2826 { 2827 int i = 0; 2828 size_t ii; 2829 struct pm_devs *pm_i; 2830 struct disk_partitions *secondary; 2831 const struct disk_partitioning_scheme *ps; 2832 struct disk_part_info info; 2833 2834 if (arg != NULL) 2835 ((struct part_entry *)arg)[0].retvalue = m->cursel + 1; 2836 2837 changed = 0; 2838 /* Mark all devices as not found */ 2839 SLIST_FOREACH(pm_i, &pm_head, l) { 2840 if (pm_i->parts != NULL) { 2841 pm_i->parts->pscheme->free(pm_i->parts); 2842 pm_i->parts = NULL; 2843 } 2844 if (pm_i->found > 0) 2845 pm_i->found = 0; 2846 } 2847 2848 /* Detect all present devices */ 2849 (void)find_disks("partman", false); 2850 if (have_lvm) 2851 pm_lvm_find(); 2852 pm_clean(); 2853 2854 if (m == NULL || arg == NULL) 2855 return -1; 2856 2857 SLIST_FOREACH(pm_i, &pm_head, l) { 2858 memset(&m->opts[i], 0, sizeof m->opts[i]); 2859 m->opts[i].opt_action = pm_submenu; 2860 ((struct part_entry *)arg)[i].dev_ptr = pm_i; 2861 ((struct part_entry *)arg)[i].id = NO_PART; 2862 if (pm_i->no_part) 2863 ((struct part_entry *)arg)[i].type = PM_SPEC; 2864 else { 2865 ps = pm_i->parts != NULL ? pm_i->parts->pscheme : NULL; 2866 secondary = NULL; 2867 2868 ((struct part_entry *)arg)[i].type = PM_DISK; 2869 2870 for (ii = 0; pm_i->parts != NULL && 2871 ii < pm_i->parts->num_part; ii++) { 2872 if (!ps->get_part_info( 2873 pm_i->parts, ii, &info)) 2874 continue; 2875 if (info.flags & PTI_SEC_CONTAINER) { 2876 if (secondary == NULL && 2877 ps->secondary_scheme != NULL) 2878 secondary = ps-> 2879 secondary_partitions( 2880 pm_i->parts, 2881 info.start, false); 2882 continue; 2883 } 2884 if (info.flags & (PTI_WHOLE_DISK| 2885 PTI_PSCHEME_INTERNAL|PTI_RAW_PART)) 2886 continue; 2887 if (info.fs_type == FS_UNUSED) 2888 continue; 2889 if (i >= MAX_ENTRIES) 2890 break; 2891 i++; 2892 memset(&m->opts[i], 0, sizeof m->opts[i]); 2893 m->opts[i].opt_action = pm_submenu; 2894 ((struct part_entry *)arg)[i].parts = 2895 pm_i->parts; 2896 ((struct part_entry *)arg)[i].dev_ptr = pm_i; 2897 ((struct part_entry *)arg)[i].id = ii; 2898 ((struct part_entry *)arg)[i].type = PM_PART; 2899 } 2900 2901 for (ii = 0; secondary != NULL && 2902 ii < secondary->num_part; ii++) { 2903 if (!secondary->pscheme->get_part_info( 2904 secondary, ii, &info)) 2905 continue; 2906 if (info.flags & (PTI_WHOLE_DISK| 2907 PTI_PSCHEME_INTERNAL|PTI_RAW_PART)) 2908 continue; 2909 if (info.fs_type == FS_UNUSED) 2910 continue; 2911 if (i >= MAX_ENTRIES) 2912 break; 2913 i++; 2914 memset(&m->opts[i], 0, sizeof m->opts[i]); 2915 m->opts[i].opt_action = pm_submenu; 2916 ((struct part_entry *)arg)[i].parts = secondary; 2917 ((struct part_entry *)arg)[i].dev_ptr = pm_i; 2918 ((struct part_entry *)arg)[i].id = ii; 2919 ((struct part_entry *)arg)[i].type = PM_PART; 2920 } 2921 } 2922 i++; 2923 } 2924 if (have_cgd) { 2925 pm_upddevlist_adv(m, arg, &i, 2926 &(pm_upddevlist_adv_t) {MSG_create_cgd, PM_CGD, &cgds_t_info, 0, NULL}); 2927 } 2928 if (have_lvm) { 2929 pm_upddevlist_adv(m, arg, &i, 2930 &(pm_upddevlist_adv_t) {MSG_create_cnd, PM_VND, &vnds_t_info, 0, NULL}); 2931 pm_upddevlist_adv(m, arg, &i, 2932 &(pm_upddevlist_adv_t) {MSG_create_vg, PM_LVM, &lvms_t_info, 0, 2933 &(pm_upddevlist_adv_t) {MSG_create_lv, PM_LVMLV, &lv_t_info, 0, NULL}}); 2934 } 2935 if (have_raid) { 2936 pm_upddevlist_adv(m, arg, &i, 2937 &(pm_upddevlist_adv_t) {MSG_create_raid, PM_RAID, &raids_t_info, 0, NULL}); 2938 } 2939 2940 m->opts[i++] = (struct menu_ent) { 2941 .opt_name = MSG_updpmlist, 2942 .opt_action = pm_upddevlist, 2943 }; 2944 m->opts[i ] = (struct menu_ent) { 2945 .opt_name = MSG_savepm, 2946 .opt_action = pm_commit, 2947 }; 2948 for (ii = 0; ii <= (size_t)i; ii++) { 2949 m->opts[ii].opt_flags = OPT_EXIT; 2950 } 2951 2952 if (((struct part_entry *)arg)[0].retvalue >= 0) 2953 m->cursel = ((struct part_entry *)arg)[0].retvalue - 1; 2954 return i; 2955 } 2956 2957 static void 2958 pm_menuin(menudesc *m, void *arg) 2959 { 2960 if (cursel > m->numopts) 2961 m->cursel = m->numopts; 2962 else if (cursel < 0) 2963 m->cursel = 0; 2964 else 2965 m->cursel = cursel; 2966 } 2967 2968 static void 2969 pm_menuout(menudesc *m, void *arg) 2970 { 2971 cursel = m->cursel; 2972 } 2973 2974 /* Main partman function */ 2975 int 2976 partman(void) 2977 { 2978 int menu_no, menu_num_entries; 2979 static int firstrun = 1; 2980 menu_ent menu_entries[MAX_ENTRIES+6]; 2981 struct part_entry args[MAX_ENTRIES]; 2982 2983 if (firstrun) { 2984 check_available_binaries(); 2985 2986 if (!have_raid) 2987 remove_raid_options(); 2988 else if (!(raids = calloc(MAX_RAID, sizeof(*raids)))) 2989 have_raid = 0; 2990 2991 #define remove_vnd_options() (void)0 2992 if (!have_vnd) 2993 remove_vnd_options(); 2994 else if (!(vnds = calloc(MAX_VND, sizeof(*vnds)))) 2995 have_vnd = 0; 2996 2997 if (!have_cgd) 2998 remove_cgd_options(); 2999 else if (!(cgds = calloc(MAX_CGD, sizeof(*cgds)))) 3000 have_cgd = 0; 3001 3002 if (!have_lvm) 3003 remove_lvm_options(); 3004 else if (!(lvms = calloc(MAX_LVM_VG, sizeof(*lvms)))) 3005 have_lvm = 0; 3006 3007 if (!have_gpt) 3008 remove_gpt_options(); 3009 3010 raids_t_info = (structinfo_t) { 3011 .max = MAX_RAID, 3012 .entry_size = sizeof raids[0], 3013 .entry_first = &raids[0], 3014 .entry_enabled = &(raids[0].enabled), 3015 .entry_blocked = &(raids[0].blocked), 3016 .entry_node = &(raids[0].node), 3017 }; 3018 vnds_t_info = (structinfo_t) { 3019 .max = MAX_VND, 3020 .entry_size = sizeof vnds[0], 3021 .entry_first = &vnds[0], 3022 .entry_enabled = &(vnds[0].enabled), 3023 .entry_blocked = &(vnds[0].blocked), 3024 .entry_node = &(vnds[0].node), 3025 }; 3026 cgds_t_info = (structinfo_t) { 3027 .max = MAX_CGD, 3028 .entry_size = sizeof cgds[0], 3029 .entry_first = &cgds[0], 3030 .entry_enabled = &(cgds[0].enabled), 3031 .entry_blocked = &(cgds[0].blocked), 3032 .entry_node = &(cgds[0].node), 3033 }; 3034 lvms_t_info = (structinfo_t) { 3035 .max = MAX_LVM_VG, 3036 .entry_size = sizeof lvms[0], 3037 .entry_first = &lvms[0], 3038 .entry_enabled = &(lvms[0].enabled), 3039 .entry_blocked = &(lvms[0].blocked), 3040 .entry_node = NULL, 3041 }; 3042 lv_t_info = (structinfo_t) { 3043 .max = MAX_LVM_LV, 3044 .entry_size = sizeof lvms[0].lv[0], 3045 .entry_first = &lvms[0].lv[0], 3046 .entry_enabled = &(lvms[0].lv[0].size), 3047 .entry_blocked = &(lvms[0].lv[0].blocked), 3048 .parent_size = sizeof lvms[0], 3049 }; 3050 3051 cursel = 0; 3052 changed = 0; 3053 firstrun = 0; 3054 } 3055 3056 do { 3057 menu_num_entries = pm_upddevlist(&(menudesc){.opts = menu_entries}, args); 3058 menu_no = new_menu(MSG_partman_header, 3059 menu_entries, menu_num_entries+1, 1, 1, 0, 75, /* Fixed width */ 3060 MC_ALWAYS_SCROLL | MC_NOBOX | MC_NOCLEAR, 3061 pm_menuin, pm_menufmt, pm_menuout, NULL, MSG_finishpm); 3062 if (menu_no == -1) 3063 args[0].retvalue = -1; 3064 else { 3065 args[0].retvalue = 0; 3066 clear(); 3067 refresh(); 3068 process_menu(menu_no, &args); 3069 free_menu(menu_no); 3070 } 3071 3072 if (args[0].retvalue == 0 && pm->parts != NULL) { 3073 struct install_partition_desc install; 3074 3075 install_desc_from_parts(&install, pm->parts); 3076 if (pm_needsave()) 3077 pm_commit(NULL, NULL); 3078 if (pm_mountall() != 0 || 3079 make_fstab(&install) != 0 || 3080 pm_lastcheck() != 0 || 3081 pm_savebootsector() != 0) { 3082 msg_display(MSG_wannatry); 3083 args[0].retvalue = (ask_yesno(NULL)) ? 1:-1; 3084 } 3085 free_install_desc(&install); 3086 } 3087 } while (args[0].retvalue > 0); 3088 3089 /* retvalue <0 - error, retvalue ==0 - user quits, retvalue >0 - all ok */ 3090 return (args[0].retvalue >= 0)?0:-1; 3091 } 3092 3093 void 3094 update_wedges(const char *disk) 3095 { 3096 check_available_binaries(); 3097 3098 if (!have_dk) 3099 return; 3100 3101 run_program(RUN_SILENT | RUN_ERROR_OK, 3102 "dkctl %s makewedges", disk); 3103 } 3104 3105